Capping & Calculating FPS in SDL? - c++

I have written this code to cap the SDL game to 60 fps, is this the correct way of implementing an fps count?
int fps=60;
int desiredDelta=1000/fps; //desired time b/w frames
while (gameRunning)
{
int starttick=SDL_GetTicks();
// Get our controls and events
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
gameRunning = false;
}
window.Clear();
for(Entity& e: entities)
{
window.Render(e);
}
window.Display();
int delta=SDL_GetTicks()-starttick; //actual time b/w frames
int avgFPS=1000/(desiredDelta-delta); //calculating FPS HERE
if(delta<desiredDelta)
{
SDL_Delay(desiredDelta-delta);
}
std::cout<<avgFPS<<std::endl;
}

In games there are usually two "framerates" to worry about: the framerate of the display and the framerate of your game physics. Ideally, you draw at the native framerate of the display. To do this, ensure you pass the SDL_RENDERER_PRESENTVSYNC flag to SDL_CreateRenderer().
For the physics of your game, you can either measure the time between two rendered frames, and use that as your physics time step, so that you basically match the display framerate. The advantage is that your rates are naturally synced, but the disadvantage is that the physics of the game might suffer from accuracy problems, especially during times when rendering takes so long that the display framerate drops to low values.
Alternatively, you use a fixed framerate for your physics. However, if you do the latter then you have to some how deal with the two framerates not being in sync, but this is not solved by adding SDL_Delay()s. The usual approach is to have the rendering thread interpolate animations based on physics as necessary.
A more practical issue in your code is that SDL_GetTicks() gives you the time in milliseconds. That is not very accurate; if your display runs at 60 fps, then one frame takes 16.66666... milliseconds. Your calculation will have an error of up to 1 ms, which is 6.25% of the length of one frame. Depending on the type of game, this can actually be noticable!

Related

Is it okay to call SDL_RenderCopy() for each sprite?

This is a followup to my question here: Is it okay to have a SDL_Surface and SDL_Texture for each sprite?
I made an class called entity each having a SDL_Texture, which is set in the constructor and then a member function render() is called for every onscreen entity in a vector, which uses SDL_RenderCopy() to draw to the renderer.
This render() function includes generating rectangles for each sprite based on their position/cameradata
Is this okay? Is there a faster way?
I made a testlevel with 96 sprites that each take up 2% of the screen with tons of overdraw and ft is 15ms (~65fps)at a resolution of1600x900. Seems a little slow for just some sprites, and my computer breathes much heavier then when playing a full game such as spelunky or isaac.
Prefer frame time over FPS
You want to measure and judge your performance based on the frame time not FPS. Because the relation between the two is not linear. Going from 20 FPS to 30 FPS needs about 16.7 ms worth of optimization. That is the same amount of performance gain in optimization it takes to get from 30 FPS to 60 FPS. So if you judge performance based on FPS you would come to conclusion that a particular "optimization" that increased the FPS from 30 to 60 is better that the one that made a 20 FPS scene run 31 FPS. while the latter is actually a better optimization.
Batch your draws
If you pack all your textures into one and store each individual image's coordinates, you can use the same texture to draw many of your objects. This is limited by the size and number of your textures and also the maximum texture size supported in your environment. In my experiences 4096x4096 is safe but I prefer to use 2048x2048 "texture atlases". There are many utility programs to make such textures. You can easily find a suitable one by doing a Google search.
In this setup in addition to a SDL texture, each sprite also has the x, y, width and height of the region in the "big" texture containing the particular image needed. You can make a TextureRegion class. Each sprite then has a TextureRegion. This whole process is often referred to as batching. Look it up. The whole idea is to minimize state changes. I am not sure if it applies to software rendering or to all of SDL2 backends.
Cache your transformations
Batching your sprites will increase the performance in the GPU side. The CPU bound code is another optimization opportunity. Instead of calculating the parameters of SDL_RenderCopy in each frame, calculate them once and cache them. Then when the position/rotation of the camera or object changes, recalculate the cache. You can do this in "accessors" of your entity class (like setPosition, setRotaion, etc..). Note that instead of directly recalculating transform as soon as a position or rotation changes your want to flag the object as "dirty" and check for the dirty flag in the your render function. if this->isDirty Then recalculate and cache the transform. This prevents redundant calculations when you do this:
//if dirty flag is not used each of the following function calls
//would have resulted in a recalculation of transforms. However by
//using the dirty flag they will be calculated only once before
//the rendering of next frame in the render() function.
player->setPostion(start_x,start_y);
player->setRotation(0);
camera->reset();
So, I've done some more testing by examining the memory/cpu usage of this program at full screen with a "demanding" level and managed to make it similar to other games by enforcing a framerate cap with SDL_Wait()
float g_max_framerate = 60;
float g_max_frametime = 1/g_max_framerate * 1000;
...
while (!quit) {
lastticks = ticks;
ticks = SDL_GetTicks();
elapsed = ticks - lastticks;
...
SDL_RenderPresent(renderer);
//lock framerate
if(elapsed < g_max_frametime) {
SDL_Delay(g_max_frametime - elapsed);
}
}
With this limitation it is appropriatly lowspec.

Unreal C++ Controller Input: Yaw Rotation

I'm setting my game character camera via c++, and I came across this, and even though it works, I don't understand why the code uses DeltaTime. What is the function of GetDeltaSeconds actually doing?
void AWizardCharater::LookX(float Value)
{
AddControllerYawInput(Sensitivity * Value * GetWorld()->GetDeltaSeconds());
}
Here is the api ref : https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/GameFramework/APawn/AddControllerYawInput/index.html
Thanks
Using delta time, multiplied by some sensitivity value, is a standard method used throughout games to provide a consistent movement rate, independent of framerate.
Consider the following code, without using delta time:
AddControllerYawInput(1);
If you had a framerate of 10 FPS then you'd be doing 10 degrees per second. If the framerate increases to 100 FPS, you'd be doing 100 degrees per second.
Using delta time makes the movement consistent regardless of framerate, as the time between frames decreases with faster framerate, slowing down the movement.

How to reduce OpenGL CPU usage and/or how to use OpenGL properly

I'm working a on a Micromouse simulation application built with OpenGL, and I have a hunch that I'm not doing things properly. In particular, I'm suspicious about the way I am getting my (mostly static) graphics to refresh at a close-to-constant framerate (60 FPS). My approach is as follows:
1) Start a timer
2) Draw my shapes and text (about a thousand of them):
glBegin(GL_POLYGON);
for (Cartesian vertex : polygon.getVertices()) {
std::pair<float, float> coordinates = getOpenGlCoordinates(vertex);
glVertex2f(coordinates.first, coordinates.second);
}
glEnd();
and
glPushMatrix();
glScalef(scaleX, scaleY, 0);
glTranslatef(coordinates.first * 1.0/scaleX, coordinates.second * 1.0/scaleY, 0);
for (int i = 0; i < text.size(); i += 1) {
glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, text.at(i));
}
glPopMatrix();
3) Call
glFlush();
4) Stop the timer
5) Sleep for (1/FPS - duration) seconds
6) Call
glutPostRedisplay();
The "problem" is that the above approach really hogs my CPU - the process is using something like 96-100%. I know that there isn't anything inherently wrong with using lots of CPU, but I feel like I shouldn't be using that much all of the time.
The kicker is that most of the graphics don't change from frame to frame. It's really just a single polygon moving over (and covering up) some static shapes. Is there any way to tell OpenGL to only redraw what has changed since the previous frame (with the hope it would reduce the number of glxxx calls, which I've deemed to be the source of the "problem")? Or, better yet, is my approach to getting my graphics to refresh even correct?
First and foremost the biggest CPU hog with OpenGL is immediate modeā€¦ and you're using it (glBegin, glEnd). The problem with IM is, that every single vertex requires a whole couple of OpenGL calls being made; and because OpenGL uses a thread local state this means that each and every OpenGL call must go through some indirection. So the first step would be getting rid of that.
The next issue is with how you're timing your display. If low latency between user input and display is not your ultimate goal the standard approach would setting up the window for double buffering, enabling V-Sync, set a swap interval of 1 and do a buffer swap (glutSwapBuffers) once the frame is rendered. The exact timings what and where things will block are implementation dependent (unfortunately), but you're more or less guaranteed to exactly hit your screen refresh frequency, as long as your renderer is able to keep up (i.e. rendering a frame takes less time that a screen refresh interval).
glutPostRedisplay merely sets a flag for the main loop to call the display function if no further events are pending, so timing a frame redraw through that is not very accurate.
Last but not least you may be simply mocked by the way Windows does account CPU time (time spent in driver context, which includes blocking, waiting for V-Sync) will be accouted to the consumed CPU time, while it's in fact interruptible sleep. However you wrote, that you already do a sleep in your code, which would rule that out, because the go-to approach to get a more reasonable accounting would be adding a Sleep(1) before or after the buffer swap.
I found that by putting render thread to sleep helps reducing cpu usage from (my case) 26% to around 8%
#include <chrono>
#include <thread>
void render_loop(){
...
auto const start_time = std::chrono::steady_clock::now();
auto const wait_time = std::chrono::milliseconds{ 17 };
auto next_time = start_time + wait_time;
while(true){
...
// execute once after thread wakes up every 17ms which is theoretically 60 frames per
// second
auto then = std::chrono::high_resolution_clock::now();
std::this_thread::sleep_until(next_time);
...rendering jobs
auto elasped_time =
std::chrono::duration_cast<std::chrono::milliseconds> (std::chrono::high_resolution_clock::now() - then);
std::cout << "ms: " << elasped_time.count() << '\n';
next_time += wait_time;
}
}
I thought about attempting to measure the frame rate while the thread is asleep but there isn't any reason for my use case to attempt that. The result was averaging around 16ms so I thought it was good enough
Inspired by this post

Replay system for cocos2d with FPS correction

I'm building a replay system for my cocos2d-x game, it uses box2d too.
The game is nondeterministic so I can't store the user actions and replay them, so what I'm doing is storing position and angle of a sprite for each time step into a stream.
Now I have replay files that are in the following format
x,y,angle\r\n
Each line represents the state of the sprite at a given time step.
Now when I replay it back on the same device, it's all perfect, but of course life isn't this easy, so the problem arises if i want to play it back on different frame rates, how can this happen ?
is there a smart way to handle this issue ?
I don't have a fixed time step too, I'll implement this soon so you can consider a fixed time step in your answer :)
Thanks !
Ok, you record the delta time along with each recorded frame. Best to start recording the first frame with a delta time of 0 and assume the same for the first frame of the playback.
Then in your update method accumulate the current delta time:
-(void) update:(ccTime)delta
{
if (firstFrame)
{
totalTime = 0;
totalRecordedTime = 0;
firstFrame = NO;
}
else
{
totalTime += delta;
}
totalRecordedTime += [self getRecordedDeltaForFrameIndex:recordedFrameIndex];
if (totalTime > totalRecordedTime)
{
[self advanceRecordedFrameIndex];
}
// alternative:
id recordedFrameData = [self getRecordedFrameForDeltaTime:totalTime];
// apply recorded data ...
}
Alternative: create a method that returns or "applies" the recorded frame based on the current time delta. Pick the frame whose recorded total delta time is equal or lower the current total delta time.
To make searching for the frame faster, remember the most recent recorded frame's index and start searching from there (compare each frame's delta time), always including the most recent frame as well.
Occassionally this will display the same recorded frame multiple times, or it may skip recorded frames - depending on the actual device framerate and the framerate during recording.

How to pause an animation with OpenGL / glut

To achieve an animation, i am just redrawing things on a loop.
However, I need to be able to pause when a key is pressed. I know the way i'm doing it now its wrong because it eats all of my cycles when the loop is going on.
Which way is better, and will allow for a key pause and resume?
I tried using a bool flag but obviously it didnt change the flag until the loop was done.
You have the correct very basic architecture sorted in that the everything needs to be updated in a loop, but you need to make your loop a lot smarter for a game (or other application requiring OpenGL animations).
However, I need to be able to pause when a key is pressed.
A basic way of doing this is to have a boolean value paused and to wrap the game into a loop.
while(!finished) {
while(!paused) {
update();
render();
}
}
Typically however you still want to do things such as look at your inventory, craft things, etc. while your game is paused, and many games still run their main loop while the game's paused, they just don't let the actors know any time has passed. For instance, it sounds like your animation frames simply have a number of game-frames to be visible for. This is a bad idea because if the animation speed increases or decreases on a different computer, the animation speed will look wrong on those computers. You can consider my answer here, and the linked samples to see how you can achieve framerate-independent animation by specifying animation frames in terms of millisecond duration and passing in the frame time in the update loop. For instance, your main game then changes to look like this:
float previousTime = 0.0f;
float thisTime = 0.0f;
float framePeriod = 0.0f;
while(!finished) {
thisTime = getTimeInMilliseconds();
framePeriod = previousTime - thisTime;
update(framePeriod);
render();
previousTime = thisTime;
}
Now, everything in the game that gets updated will know how much time has passed since the previous frame. This is helpful for all your physics calculations as all of our physical formulae are in terms of time + starting factors + decay factors (for instance, the SUVAT equations). The same information can be used for your animations to make them framerate independent as I have described with some links to examples here.
To answer the next part of the question:
it eats all of my cycles when the loop is going on.
This is because you're using 100% of the CPU and never going to sleep. If we consider that we want for instance 30fps on the target device (and we know that this is possible) then we know the period of one frame is 1/30th of a second. We've just calculated the time it takes to update and render our game, so we can sleep for any of the spare time:
float previousTime = 0.0f;
float thisTime = 0.0f;
float framePeriod = 0.0f;
float availablePeriod = 1 / 30.0f;
while (!finished) {
thisTime = getTimeInMilliseconds();
framePeriod = previousTime - thisTime;
update(framePeriod);
render();
previousTime = thisTime;
if (framePeriod < availablePeriod)
sleep(availablePeriod - framePeriod);
}
This technique is called framerate governance as you are manually controlling the rate at which you are rendering and updating.