Using the Timer in SDL

Discussion in 'Indie Basics' started by esrix, Aug 15, 2005.

  1. esrix

    Original Member

    Joined:
    Aug 11, 2005
    Messages:
    143
    Likes Received:
    0
    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?
     
  2. ggambett

    Moderator Original Member Indie Author

    Joined:
    Jul 26, 2004
    Messages:
    1,982
    Likes Received:
    6
    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.
     
  3. Rainer Deyke

    Indie Author

    Joined:
    Jul 28, 2004
    Messages:
    380
    Likes Received:
    0
    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.
     
  4. mahlzeit

    Original Member

    Joined:
    Sep 26, 2004
    Messages:
    852
    Likes Received:
    1
    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();
    }
    
     
  5. esrix

    Original Member

    Joined:
    Aug 11, 2005
    Messages:
    143
    Likes Received:
    0
    Thanks. I'll probably use something close to ggambett's code.
     
  6. Sol_HSA

    Indie Author

    Joined:
    Feb 27, 2005
    Messages:
    470
    Likes Received:
    1
    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".
     

Share This Page

  • About Indie Gamer

    When the original Dexterity Forums closed in 2004, Indie Gamer was born and a diverse community has grown out of a passion for creating great games. Here you will find over 10 years of in-depth discussion on game design, the business of game development, and marketing/sales. Indie Gamer also provides a friendly place to meet up with other Developers, Artists, Composers and Writers.
  • Buy us a beer!

    Indie Gamer is delicately held together by a single poor bastard who thankfully gets help from various community volunteers. If you frequent this site or have found value in something you've learned here, help keep the site running by donating a few dollars (for beer of course)!

    Sure, I'll Buy You a Beer