I'm C++ beginner, and I am currently following a tutorial to make a game with SDL2. In the process of configurating delta time to allow user control of an object, I seem to have a problem with the smoothness of the object's movement: it is only smooth when cout is added, without which the object seems almost unresponsive. Here's my code:
#include <iostream>
#include <SDL.h>
int objectDir;
int Input() {
const Uint8* state = SDL_GetKeyboardState(NULL);
objectDir = 0;
if(state[SDL_SCANCODE_W]) {
objectDir -=1;
}
if (state[SDL_SCANCODE_S]) {
objectDir += 1;
}
return 0;
}
int Update() {
if (objectDir != 0) {
objectPos.y += objectDir*50*deltaTime;
}
return 0;
}
int Loop() {
while (gameRunning)
{
if (!SDL_TICKS_PASSED(SDL_GetTicks(), tick + 0.033f)) {continue;}
deltaTime = SDL_GetTicks() - tick;
if (deltaTime > 0.05f) {
deltaTime = 0.05f;
}
Input();
Update();
Output();
tick = SDL_GetTicks();
}
return 0;
}
int main(int argc, char* argv[]) {
Loop();
}
I've tried removing the conditional line (SDL_TICKS_PASSED()), but nothing changed.
I think you are misunderstanding the return value of SDL_GetTicks()
: it returns an integer value representing the number of millisecond that have passed since the start of the program. It doesn't return a floating point number.
Basically, your if (!SDL_TICKS_PASSED(SDL_GetTicks(), tick + 0.033f)) {continue;}
statement will cause it to wait at most one millisecond. Then afterwards, deltaTime = SDL_GetTicks() - tick
will for sure be equal to 1 or to an even larger integer. So then you always cap deltaTtime
to 0.05, regardless of how much time actually passed.
Printing to std::cout
might take a bit more than 1 millisecond perhaps, which allows more ticks to pass between iterations of your while
-loop, which causes your game to behave differently. To fix it, make sure you interpret SDL_GetTicks()
correctly.
One more issue: Input()
, Update()
and Output()
take some variable time to complete. If you call tick = SDL_GetTicks()
at the end of the while
-loop, that means you will then wait for a fixed amount of time after Output()
returned. So your frame period will be that fixed amount plus the variable amount caused by the aforementioned functions. To get a steady framerate, there are options:
const Uint32 frame_time = 50; // 50 ms per frame
Uint32 next_frame = SDL_GetTicks();
while (gameRunning) {
if (!SDL_TICKS_PASSED(SDL_GetTicks(), next_frame)) {continue;}
…
next_frame += frame_time;
}
Last but not least, you are doing a busy loop waiting for the next frame. That will use 100% CPU time unnecessarily, causing more power usage and increasing the temperature of the CPU. Again, either rely on vertical sync, or use SDL_Delay()
to sleep until it's time for the next frame.