I've been trying to draw a label (sf::Text) for a couple hour and my program has been crashing for a reason I can't tell. I used to print a few labels for information output with the same font and within the same class even, but now, it crashes when I draw the sf::Text and ouputs Violation access error.
Can sombebody see my mistake ?
**update, I have found a way to not crash my program, but more problems occur, see lower down
Clas definition
class Body
{
public:
Body();
Body(RenderWindow&, Color aFillColor, float aRadius, double true_radius, double aMass, Vector2<double> aSpeed, float anOrientation, Vector2<double> aPosition, string aName);
~Body();
CircleShape getCricle();
Derivative initialDerivative(State, double delta_time, vector<Body>);
Derivative nextDerivative(State, Derivative, double delta_time, vector<Body>);
Vector2<double> calc_acceleration(State aState, double delta_time, vector<Body>);
void update(vector<Body> list_of_bodies, double delta_time);
void draw();
bool collide(Body const& aBody);
//GET
string getName();
Vector2<double> getPosition();
float getRadius();
//SET
void setPosition(Vector2f);
//operators
void operator=(Body const& b);
bool operator==(Body const& a);
bool operator>(Body const& a);
private:
RenderWindow& myWin;
CircleShape circle;
string myName;
double mass;
float radius;
Vector2<double> mySpeed;
Vector2<double> position;
Vector2<double> acceleration;
State myState;
double last_chrono;
double true_radius;
double f;
double a;
Font myFont;
Text label;
float orientation;
Color fillColor;
int cpt;
Clock myClock;
Clock utility_clock;
double time;
};
Constructor
Body::Body(RenderWindow &win, Color aFillColor, float aRadius, double t_radius, double aMass, Vector2<double> aSpeed, float anOrientation, Vector2<double> aPosition, string aName)
:myWin(win), fillColor(aFillColor), radius(aRadius), true_radius(t_radius), mySpeed(aSpeed), mass(aMass), orientation(anOrientation), position(aPosition), myName(aName)
{
acceleration = Vector2<double>(0,0);
myState = State(position.x, position.y, mySpeed.x, mySpeed.y);
circle.setPosition(position.x, position.y);
circle.setFillColor(fillColor);
circle.setRadius(true_radius/dist_adjust);
if(!myFont.loadFromFile("ressources/Fonts/arial.ttf")){ //Font loading IS successfull
cout << "problem!!" << endl;
}
label.setFont(myFont);
label.setCharacterSize(12);
label.setColor(Color::Black);
label.setString(myName);
cout << true_radius/dist_adjust << endl;
circle.setOrigin(circle.getLocalBounds().width/2,circle.getLocalBounds().height/2);
last_chrono = 0;
myClock.restart();
}
Draw function
void Body::draw()
{
circle.setRadius(radius);
circle.setPosition(Vector2f(myState.x, myState.y));
myWin.draw(circle);
label.setPosition(myState.x - radius, myState.y - radius - label.getLocalBounds().height);
myWin.draw(label); //THE PROGRAM CRASHES HERE!
}
And for whoever wonders, here is when I call the draw function
for(vector<Body>::iterator it_bodies = myBodies.begin(); it_bodies != myBodies.end(); ++it_bodies){
if(!myPause){
it_bodies->setPosition(Vector2f(it_bodies->getPosition().x - temp_position.x, it_bodies->getPosition().y - temp_position.y));
}
it_bodies->draw();
}
any abvious mistake? Am I victim of the randomly crashing fonts ?
please help!
More testing :
I tried to draw the Text in the constructor and the program did not crash :
Body::Body(RenderWindow &win, Color aFillColor, float aRadius, double t_radius, double aMass, Vector2<double> aSpeed, float anOrientation, Vector2<double> aPosition, string aName)
:myWin(win), fillColor(aFillColor), radius(aRadius), true_radius(t_radius), mySpeed(aSpeed), mass(aMass), orientation(anOrientation), position(aPosition), myName(aName)
{
acceleration = Vector2<double>(0,0);
myState = State(position.x, position.y, mySpeed.x, mySpeed.y);
circle.setPosition(position.x, position.y);
circle.setFillColor(fillColor);
circle.setRadius(true_radius/dist_adjust);
if(!myFont.loadFromFile("ressources/Fonts/arial.ttf")){
cout << "problem!!" << endl;
}
label.setFont(myFont);
label.setCharacterSize(12);
label.setColor(Color::Black);
label.setString(myName);
myWin.draw(label); //HERE IS WHERE MY TEXT IS DRAWN
cout << true_radius/dist_adjust << endl;
circle.setOrigin(circle.getLocalBounds().width/2,circle.getLocalBounds().height/2);
last_chrono = 0;
myClock.restart();
}
Further testing brings up more questions : When I comment or uncomment those lines, in the constructor of the Body class, my FPS goes from 70+ when commented to 2 when uncommented. ?!?!? Note that I am not drawing the sf::Text, I am only initiating some of it's attributes. For the record, I only have 9 of these objects, 1 for the sun, and 8 for planets (yes, it is a solar system simulation)
label.setFont(myFont);
label.setCharacterSize(12);
label.setColor(Color::Black);
label.setString(myName);
ok... One last update : I tried setting up the attributes within the draw function instead of the constructor, SURPSIE! my program doesn't crash! Nevertheless, it still drops the FPS drastically. Of course, I would normally not do that because setting atributes multiple times with the same value is a waste of ressources.
void Body::draw()
{
circle.setRadius(radius);
circle.setPosition(Vector2f(myState.x, myState.y));
myWin.draw(circle);
label.setPosition(myState.x - radius, myState.y - radius - label.getLocalBounds().height);
label.setFont(myFont);
label.setCharacterSize(12);
label.setColor(Color::Black);
label.setString(myName);
myWin.draw(label);
}
This is never ending, here is another update... I found one line of code that slows down my program by a lot :
for(vector<Body>::iterator it_bodies = myBodies.begin(); it_bodies != myBodies.end(); ++it_bodies){
if(!myPause){
it_bodies->update(myBodies,delta_time * timing_var); //THIS LINE SUCKS THE JUICE
if(it_bodies->getName() == "Earth"){
temp_position = Vector2<double>(it_bodies->getPosition().x - temp_position.x, it_bodies->getPosition().y - temp_position.y);
}
}
}
you will never guess what is in that function...... COMMENTS!!! yes, only comments.... no actual line of code. Nevertheless, calling that function brings my fps from 1500, down to 700 even if I have only one object in that vector................ ??? ??? ??? ??? ???
Here is the code in case anybody cares :
void Body::update(vector<Body> theBodies, double delta_t)
{
/*
Derivative derivative_a = initialDerivative(myState, delta_t, theBodies);
Derivative derivative_b = nextDerivative(myState, derivative_a, delta_t * 0.5, theBodies);
Derivative derivative_c = nextDerivative(myState, derivative_b, delta_t * 0.5, theBodies);
Derivative derivative_d = nextDerivative(myState, derivative_c, delta_t, theBodies);
double one_over_six = 1.f/6.f;
double dxdt = one_over_six * (derivative_a.vx + 2.f * (derivative_b.vx + derivative_c.vx) + derivative_d.vx);
double dydt = one_over_six * (derivative_a.vy + 2.f * (derivative_b.vy + derivative_c.vy) + derivative_d.vy);
double dvxdt = one_over_six * (derivative_a.ax + 2.f * (derivative_b.ax + derivative_c.ax) + derivative_d.ax);
double dvydt =one_over_six * (derivative_a.ay + 2.f * (derivative_b.ay + derivative_c.ay) + derivative_d.ay);
//UPDATING SPEED AND POSITION (position in pixels, and speed in meters / seconds)
myState.x += dxdt * delta_t / dist_adjust;
myState.y += dydt * delta_t / dist_adjust;
myState.vx += dvxdt * delta_t;
myState.vy += dvydt * delta_t;
*/
/*
if(myName == "Earth"){
stringstream str_a;
stringstream str_g;
stringstream str_r;
stringstream str_f;
stringstream str_speed_x;
stringstream str_speed_y;
stringstream str_speed;
stringstream str_correction_x;
str_g << fixed << setprecision( 20 ) << gravity;
str_f << fixed << setprecision( 20 ) << f;
str_a << fixed << setprecision( 20 ) << a;
str_speed_x << fixed << setprecision( 20 ) << myState.vx;
str_speed_y << fixed << setprecision( 20 ) << myState.vy;
str_speed << fixed << setprecision( 20 ) << sqrt(myState.vy * myState.vy + myState.vx * myState.vx);
Text planete;
planete.setPosition(0,0);
planete.setColor(Color::Black);
planete.setCharacterSize(15);
planete.setFont(font);
planete.setString(" x = " + to_string(myState.x) + ", y = " + to_string(myState.y));
planete.setPosition(0,20);
myWin.draw(planete);
planete.setString("ratio = " + to_string((py - position.y)/(px - position.x)));
planete.setPosition(0,40);
myWin.draw(planete);
planete.setString("delta_time = " + to_string(time_temp));
planete.setPosition(0,60);
myWin.draw(planete);
planete.setString("vitesse x = " + str_speed_x.str());
planete.setPosition(300,0);
myWin.draw(planete);
planete.setString("vitesse y = " + str_speed_y.str());
planete.setPosition(300,20);
myWin.draw(planete);
planete.setString("Vitesse totale = " + str_speed.str());
planete.setPosition(300,40);
myWin.draw(planete);
planete.setString("accélération = " + str_a.str());
planete.setPosition(300,60);
myWin.draw(planete);
planete.setString("distance = " + str_r.str());
planete.setPosition(300,80);
myWin.draw(planete);
planete.setString("force = " + str_f.str());
planete.setPosition(700,0);
myWin.draw(planete);
}*/
}
Here is the minimal code, and the exact lines and situation that slows down my program drastically :
for(vector<Body>::iterator it_bodies = myBodies.begin(); it_bodies != myBodies.end(); ++it_bodies){
it_bodies->update(myBodies,delta_time * timing_var);
}
for(vector<Body>::iterator it_bodies = myBodies.begin(); it_bodies != myBodies.end(); ++it_bodies){
it_bodies->draw();
}
Here is the content of those 2 functions (comments were erased for readability.....)
void Body::update(vector<Body> theBodies, double delta_t)
{
}
void Body::draw()
{
label.setFont(myFont);
myWin.draw(label);
}
Here are the 2 possibilities that my program is not slowed down :
for(vector<Body>::iterator it_bodies = myBodies.begin(); it_bodies != myBodies.end(); ++it_bodies){
//it_bodies->update(myBodies,delta_time * timing_var);
}
for(vector<Body>::iterator it_bodies = myBodies.begin(); it_bodies != myBodies.end(); ++it_bodies){
it_bodies->draw();
}
for(vector<Body>::iterator it_bodies = myBodies.begin(); it_bodies != myBodies.end(); ++it_bodies){
it_bodies->update(myBodies,delta_time * timing_var);
}
for(vector<Body>::iterator it_bodies = myBodies.begin(); it_bodies != myBodies.end(); ++it_bodies){
//it_bodies->draw();
}
I point out that if I don't setFont() in my draw() function but still drawing the label (sf::Text), I get 3000 fps. If I don't draw the label but still do the setFont(), I also get 3000 fps. If I do both while updating my body (only one in the vector), I get 800 fps.
Also, If I don't update my body, I can do the draw function with both setFont() and draw() and I get 3000 fps.
I have attached a picture to show what it looks like (not much to be seen unfortunately)
All right, I was able to minimize my code I guess. Anybody should be able to copy paste this into a project and run it as it is EXCEPT for the font. You're gonna have to load a font of your own. I tried 2 diffrent ones, so I guess any font will reproduce the problem. This being said, comment the update line, the one that contains
it_bodies->update(myBodies,delta_time);
and your FPS should go up quite a bit. The FPS_manager class found in the code is only there to display the framerate in the console. It can also be used to "regulate" whatever movement you're dealing with, depending on how fast you're computer process the code. I have used it before and has not caused me any problem even if it is not my own work.
#include <sfml/system.hpp>
#include <sfml/graphics.hpp>
#include <sfml/window.hpp>
#include <iostream>
using namespace std;
using namespace sf;
class FPS_manager
{
private:
float frameCount;
Clock frameClock;
float frameSpeed;
float speedFactor;
public:
FPS_manager();
virtual ~FPS_manager();
void DisplayFrameRate();
void CalculateFrameRate();
float GetSpeedFactor();
protected:
};
FPS_manager::FPS_manager()
{
frameClock.restart();
frameCount = 0;
frameSpeed = 0.0f;
speedFactor = 0.0f;
}
FPS_manager::~FPS_manager()
{
}
void FPS_manager::DisplayFrameRate()
{
frameCount++;
if(frameClock.getElapsedTime().asSeconds() >= 1.0f)
{
frameSpeed = (float)(1 / frameCount);
speedFactor = (float)(60 / frameCount);
std::cout << "FPS: " << frameCount << " TF: " << frameSpeed << " SF: " << speedFactor << std::endl;
frameCount = 0;
frameClock.restart();
}
}
void FPS_manager::CalculateFrameRate()
{
frameCount++;
if(frameClock.getElapsedTime().asSeconds() >= 1.0f)
{
frameSpeed = (float)(1 / frameCount);
speedFactor = (float)(60 / frameCount);
frameCount = 0;
frameClock.restart();
}
}
float FPS_manager::GetSpeedFactor()
{
return speedFactor;
}
class Body
{
public:
Body();
Body(RenderWindow&, Color aFillColor, float aRadius, double true_radius, double aMass, Vector2<double> aSpeed, float anOrientation, Vector2<double> aPosition, string aName);
~Body();
void update(vector<Body> list_of_bodies, double delta_time);
void draw();
private:
RenderWindow& myWin;
string myName;
double mass;
float radius;
Vector2<double> mySpeed;
Vector2<double> position;
Vector2<double> acceleration;
Font myFont;
Text label1;
double true_radius;
float orientation;
Color fillColor;
};
class Intro
{
public:
Intro(RenderWindow&);
~Intro();
void update();
void initBodies();
private:
RenderWindow& myWin;
Clock chrono;
vector<Body> myBodies;
};
Body::Body(RenderWindow &win, Color aFillColor, float aRadius, double t_radius, double aMass, Vector2<double> aSpeed, float anOrientation, Vector2<double> aPosition, string aName)
:myWin(win), fillColor(aFillColor), radius(aRadius), true_radius(t_radius), mySpeed(aSpeed), mass(aMass), orientation(anOrientation), position(aPosition), myName(aName)
{
if(!myFont.loadFromFile("ressources/Fonts/arial.ttf")){
cout << "problem!!" << endl;
}
}
Body::~Body()
{}
void Body::draw()
{
label1.setFont(myFont);
myWin.draw(label1);
}
void Body::update(vector<Body> theBodies, double delta_t)
{
}
Intro::Intro(RenderWindow &win)
:myWin(win)
{
initBodies();
}
Intro::~Intro()
{}
void Intro::initBodies()
{
//EARTH
myBodies.push_back(
Body(myWin, Color::Blue, 2, 6371000, 0, Vector2<double>(0,29800), 0, Vector2<double>(0,0), "Earth"));
}
void Intro::update()
{
double delta_time = chrono.getElapsedTime().asSeconds();
chrono.restart();
for(vector<Body>::iterator it_bodies = myBodies.begin(); it_bodies != myBodies.end(); ++it_bodies){
it_bodies->update(myBodies,delta_time);
}
for(vector<Body>::iterator it_bodies = myBodies.begin(); it_bodies != myBodies.end(); ++it_bodies){
it_bodies->draw();
}
}
int main()
{
ContextSettings settings;
RenderWindow window(VideoMode(1600,1024,32),"Whatever", Style::Default,settings);
FPS_manager mFps;
Intro myIntro(window);
while(true)
{
mFps.DisplayFrameRate();
window.clear();
myIntro.update();
window.display();
}
return 0;
}
Anybody can tell me what is going on?