Search code examples
c++sdl-2

SDL game doesn't work properly without cout


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.


Solution

  • 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:

    1. Rely on vertical sync.
    2. Write a loop that looks like this:
      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.