-
Hy,
I've been working on graphics application for a while, but suddenly I'm experiencing some trouble with it. Somehow the main loop is not being executed. I've managed to make a simple example which still shows my problem:
sf::Window window(sf::VideoMode(1024, 576), "First Person Shooter");
window.setVerticalSyncEnabled(true); // 60 FPS
sf::Clock c;
unsigned int fps_counter = 0;
unsigned int fps = 0;
while (true)
{
sf::Time time = c.getElapsedTime();
c.restart();
unsigned int ms = time.asMilliseconds();
fps_counter += ms;
++fps;
if(fps_counter >= FPS_REFRESH) {
char buffer[32];
int av = (int) (fps * 1000) / fps_counter;
sprintf(buffer, "%d - frames per second", av);
window.setTitle(buffer);
// reset
fps_counter = 0;
fps = 0;
}
//draw();
window.display();
}
window.close();
What I'm trying to do is to print out the frames per second. But the title of the window is never updated...
I suppose I'm overlooking something very easy... :/
Anyone a suggestion?
// edit
Forgot to mention this:
When I add one line in the loop, for example
cout << "test" << endl;
It all suddenly works.
-
Ugly code but works for me, empty window opens and it's caption keeps changing.
Maybe you're just getting consistent fps and it's udating with same non stop?
-
No, I get the intial title, being: "First Person Shooter".
And maybe just as a tip, what do find so ugly about the code?
-
while (true)
Never ever do this. It doesn't matter if it's just for testing or whatever.
sf::Time time = c.getElapsedTime();
c.restart();
unsigned int ms = time.asMilliseconds();
fps_counter += ms;
Why all those indirections?
This looks much better.
fps_counter += c.restart().asMilliseconds();
FPS_REFRESH is not defined in the code you gave us.
char buffer[32];
int av = (int) (fps * 1000) / fps_counter;
sprintf(buffer, "%d - frames per second", av);
window.setTitle(buffer);
This is positional dangerous C (and not C++) code.
You should better use a std::stringstream instead and don't use C-casts.
//draw();
window.display();
You never call window.clear(). It's a must!
As for the problem, I don't really know...
What OS do you use?
-
I use windows.
Most of the things you mention are different in my original code, but I didn't know about the stringstream, so thanks for that. :P
As for the window.clear();
Why is this a must?
-
sf::Time time = c.getElapsedTime();
c.restart();
unsigned int ms = time.asMilliseconds();
fps_counter += ms;
=>
fps_counter+=c.restart().asMilliseconds();
FPS_REFRESH
Macro in c++ = no-no (I'm guessing it's macro, I put 16 there, maybe you have your constant there wrong).
window.close();
Redundant.
sprintf(buffer, "%d - frames per second", av);
C and potentially unsafe for anything non-trivial, I use boost.format instead for printf-like formating into console, file, string streams.
std::stringstream ss;
ss<<boost::format("%1% frames per second")%some_number;
window.setTitle(ss.str());
Never ever do this. It doesn't matter if it's just for testing or whatever.
Really? Warum nicht?
Oh and static_cast<int>() instead of (int) or int() like he says.
Exploiter, you cannot clear a window, renderwindow yes but not plain window.
-
while (true) isn't good, because this will use your cpu fully.
Or at least that's what they told me :P
-
Really? Warum nicht?
Because you intentionally create an infinite loop, that your only be able to break; out of, which isn't a good design. One can discuss forever about this and I don't feel like having a big discussion now. It's the same reason, why one shouldn't use goto and use break only limited, etc.
I'm aware of the pros and cons and if you're not really experienced, it's just a nono.
And even when doing some tests, it's essential to stick to the principles, so one doesn't even have to worry about rewriting everything, once the testing is over.
while (true) isn't good, because this will use your cpu fully.
Or at least that's what they told me :P
No and yes. It will use you CPU fully, but it's not because of while(true) and to not use it at the maximum you setFramerateLimit(60).
As for the window.clear();
Why is this a must?
Exploiter, you cannot clear a window, renderwindow yes but not plain window.
Right, I didn't see, that he's using sf::Window. I usually assume people that don't know stringstreams don't even try to go the OpenGL way... :D
-
Oh, don't under estimate me :P I do have quite some experience.
I'm just new to C and C++. But yes, I am using OpenGL.
-
genzm, go check what FPS_REFRESH is, it's not declared in your code, it might be wrong.
I usually assume people that don't know stringstreams don't even try to go the OpenGL way... :D
Obviously C graphics API reqires knowledge of c++ ::) Poor Carmack and his first engines in pure C...
"First Person Shooter"
Last time I checked Evil Laurentâ„¢ didn't add any 3D features(nor did binary write that 3D magic for Tank to start that GLEW argument again)..
-
Is used:
#define FPS_REFRESH 500
-
Still works.
-
Obviously C graphics API reqires knowledge of c++ ::) Poor Carmack and his first engines in pure C...
Where's the pure C when he's using SFML, a C++ library? (I probably didn't get that joke...)
Last time I checked Evil Laurentâ„¢ didn't add any 3D features
So? You can do all the 3D magic with OpenGL and use SFML just as context creator and optional audio output. ;)
#define FPS_REFRESH 500
Don't use macros!
const int FPS_REFRESH = 500;
...works too! ;)
-
Exploiter, you cannot clear a window, renderwindow yes but not plain window.
There's glClear() for that, the parameter depends on whether you use a depth buffer or not.
I'm just new to C and C++. But yes, I am using OpenGL.
JOGL before I suppose.
-
I know I'm not supposed to use macro's, but that isn't going to solve the problem now, is it?
And yes, I used java before. But this is still my first openGL/sfml experience, so I never used JOGL.
-
I know I'm not supposed to use macro's, but that isn't going to solve the problem now, is it?
Granted that it may not solve the problem, but still it doesn't hurt. It's better to cultivate good habits than bad ones.
-
Os and compiler? Did you try using debugger to see if the code executes?
The fact that adding line to the loop fixes it makes me think you have your compiler settings wrong and it optimized out entire loop for some reason. I'm probably wrong but that'd be really cool.
So? You can do all the 3D magic with OpenGL and use SFML just as context creator and optional audio output. ;)
But then you'd not use clear(), especially not in sf::Window :)
Where's the pure C when he's using SFML, a C++ library? (I probably didn't get that joke...)
Knowing c++ isn't prerequisite for knowing OpenGL, he might be experienced C coder, migrating to c++. Joke: Carmack had around 10 years of experience in OpenGL and C and none in c++ at the point of beginning id tech 4(Doom 3, Quake 4, everything before was just C) engine that was his (company) first real c++ project.
If you want to reply to that send me a pm, enough goofing in this thread.
-
os is windows, and i'm using visual studio c++ professional 2012.
If this would be a compiler setting (which I actually would doubt), what could I do to change it?
In debugger the code does execute and updates the title.
// edit
Another thing I just realised:
If I do add a line which prints out some text, I get a very high amount of frames per second (over a 1000). even though vertical sync is set on. Shouldn't vertical sync limit it to 60 frames?
-
Use sf::Time instead of unsigned and do +=clock.restart() on it, you can compare them easily too, you can do like time<=sf::miliseconds(FPS_PDATE) or something. I suspect your loop goes over 1000x per second, miliseconds get truanced in C/C++ int way to 0 and debugger stepping slowed that down and let clock build few miliseconds up. If you don't know what change I'm talking about tell me and I'll make change for you to try.
Vsync can be forced off in setting for GPU and I think it only affects fullscreen.
-
Use sf::Time instead of unsigned and do +=clock.restart() on it, you can compare them easily too, you can do like time<=sf::miliseconds(FPS_PDATE) or something. I suspect your loop goes over 1000x per second, miliseconds get truanced in C/C++ int way to 0 and debugger stepping slowed that down and let clock build few miliseconds up. If you don't know what change I'm talking about tell me and I'll make change for you to try.
Vsync can be forced off in setting for GPU and I think it only affects fullscreen.
I'm not really sure what you want to change. But indeed, when using
window.setFramerateLimit(60);
It all works just fine. I still don't really see why this solves my problem, but I'm glad I'm getting some progress.
-
sf::Time fps_counter;
while (true)
{
fps_counter += c.restart();
++fps;
if(fps_counter >= sf::milliseconds(FPS_REFRESH)) {
char buffer[32];
int av = (int) (fps * 1000) / fps_counter.asMiliseconds();
sprintf(buffer, "%d - frames per second", av);
window.setTitle(buffer);
// reset
fps_counter = sf::Time::Zero;
fps = 0;
}
//draw();
window.display();
}
-
Oh, I see, like that :P
I tried it and it executes the loop. This is off course a better use than a simple integer.
Thanks for the tip.
But I still don't really understand why this fixed it :/
-
1. Loop is going too fast, clock gains some fraction of milisecond.
2. Get that fraction as int = rounded down to 0.
3. Reset Clock.
4. Repeat.
Console io, debugger and setFramerateLimit slowed loop down enough to build up more than fraction of milisecond in clock so it wasn't truanced to 0.
-
Ok, this would explain why the title isn't updated.
But the rest of the loop (the commented draw() function), and other steps like controls,...
They should still be executed?
-
Yes, and display() is getting executed.
-
Oh no sorry, I see.
The functions I wrote for example to check controls, all used this int to know the difference in time. Since there was no difference, nothing changed.
So, that's solved :P
Thanks for all the help everyone. I wouldn't have found it by myself.