I'm trying to use SDL_Addtimer to draw to the screen at 30 frames per second. I've looked over the documentation on using this function and I admit I'm stumped on how to go about correctly implementing it. I have a function called render which takes two SDL surfaces as it's parameters. It works if I call it within a while loop, but it runs rediculously fast. If I use SDL_Delay, I can slow it down, but the frame rate won't be very consistent. void render(SDL_Surface *screen, SDL_Surface *frame) { // Lock surface if needed if (SDL_MUSTLOCK(screen)) if (SDL_LockSurface(screen) < 0) return; if(SDL_BlitSurface(frame, NULL, screen, NULL) < 0) fprintf(stderr, "BlitSurface error: %s\n", SDL_GetError()); //SDL_UpdateRect(screen, 0, 0, image->w, image->h); // Unlock if needed if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); // Tell SDL to update the whole screen SDL_UpdateRect(screen, 0, 0, 256, 164); } Any ideas on how to call this?
I do this Code: nFrameInterval = 1000 / nFPS; nNextTicks = getMilliseconds(); nLastTicks = nNextTicks while (true) { int nTicks = getMilliseconds(); if (nTicks < nNextTicks) SDL_Delay(nNextTicks - nTicks); nTicks = getMilliseconds(); float fTime = (float)((nTicks - nLastTicks) / 1000.0); dispatchUpdate(fTime); processEvents(); updateScreen(); nNextTicks = nTicks + nFrameInterval; nLastTicks = nTicks; } You can get much fancier than that, but this works OK.
Don't use SDL_AddTimer for that. Timers run in a separate thread (or, worse, an interrupt), and SDL video calls are only legal in the main thread. Also, never blit to or from a locked surface. Locking is for direct pixel access. Also, when you do need direct pixel access, it's usually faster and always cleaner to just call SDL_LockSurface instead of using SDL_MUSTLOCK.
You *can* use a timer to schedule video redraw, but you'll have to post a custom event to the main thread. Something like this: Code: #define EVENT_REDRAW 0 SDL_TimerID redraw_timer; Uint32 redraw_timer_callback(Uint32 interval, void *param) { SDL_Event event; event.type = SDL_USEREVENT; event.user.code = EVENT_REDRAW; event.user.data1 = NULL; event.user.data2 = NULL; SDL_PushEvent(&event); return interval; } void init() { ... SDL_Init(... | SDL_INIT_TIMER); ... redraw_timer = SDL_AddTimer(20, redraw_timer_callback, NULL); ... } void done() { ... SDL_RemoveTimer(redraw_timer); ... } void gameloop() { init(); while (!finished) { SDL_WaitEvent(&event); switch (event.type) { ... case SDL_USEREVENT: switch (event.user.code) { case EVENT_REDRAW: render(); break; } break; ... } } done(); }
I've covered this, and a lot more, in my tutorial. You're most likely interested in chapter 9 at http://iki.fi/sol/gp/ch09.html "frame rate independence".