0
\$\begingroup\$

I am using SDL/Glew to create an engine for a game I want to make. I am trying to set a constant framerate of like around 60 (once every 17ish ms). I don't know the best way to do this so I do attempted to do it with a timer.

//Main Loop
int EngineLoop(int interval, CEngine* engine)
{
    Input->Poll();
}
//---------

void CEngine::Start()
{
    _running = true;

    SDL_AddTimer(17, (SDL_TimerCallback)EngineLoop, this);
}

The input poll is this:

void CInput::Poll()
{
    SDL_Event evnt;

    while (SDL_PollEvent(&evnt))
    {
        switch (evnt.type)
        {
        case SDL_MOUSEMOTION:
            *(Rect*)(&MousePosition) = Rect(evnt.motion.x, evnt.motion.y);
            *(Rect*)(&MouseDelta)    = Rect(evnt.motion.xrel, evnt.motion.yrel);

            break;

        case SDL_MOUSEBUTTONDOWN:
            _mouseButtons[evnt.button.button - 1] = true;
            break;

        case SDL_MOUSEBUTTONUP:
            _mouseButtons[evnt.button.button - 1] = false;
            break;
        }
    }
}

This system works perfectly when I put it in some random class function to pump as much as it'd like. But when I introduced the timer, nothing works, no input is taken and the window freezes up. Is it because I am not Polling the events quick enough or?

I tried using a separate timer function that called the class function to poll the input because maybe having it on a different thread is the reason, that didn't work either.

So why didn't this work?
What other approach should I take if necessary?

\$\endgroup\$
  • \$\begingroup\$ Unrelated, but this *(Rect*)(&MousePosition) looks extremely fishy (and is certainly UB). What is going on there? \$\endgroup\$ – Quentin Dec 22 '17 at 12:22
2
\$\begingroup\$

SDL_AddTimer is a problem here. SDL_AddTimer spawns a new thread, and things won't work like you expect when using multiple threads. When you call SDL_Init(), you likely do it from the main thread, and that's where your event queue is, so when you call SDL_PollEvent() from your timer thread, it won't have access to the internal SDL event queue, and thus will not return your events.

As for resolving this issue, you could change your code to keep everything on one single thread (e.g. each loop, check how much time execution took and sleep for whatever time is left). Or take a look at the SDL_AddTimer documentation, it has some specific recommendations about how to resolve this issue: https://wiki.libsdl.org/SDL_AddTimer

In any case though, you can only poll for events from the same thread that initialized SDL.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.