[SDL] SDL_WaitEventTimeout

tfolzdon at student.umass.edu tfolzdon at student.umass.edu
Sat Nov 1 11:15:01 PST 2003


Bob Pendleton pointed out a bug in my sample code.  Should have been:
(in pseudocode)
while(!done){
	gotone = SDL_WaitEventTimeout(e, nextick - SDL_GetTicks());
	if(gotone){
		execute_user_input(e);
	}
	if((time = SDL_GetTicks()) >= nextick){
		if(time >= nextick + ticklen)
			nextick = time + ticklen;      
		else
			nextick += TICKLEN;
		do_once_per_tick_stuff();
	}
}

Neil Brown writes:
> ...I dont see why you think input
> should be handled instantly instead of once per frame.  For even a
> simple 20fps game, can the player really tell the difference
> between "instantly" and (on average) 1/40th of a second later?
  Yes, taking all the input that occurs during one frame and processing it 
all in a batch before the next would look just like if the input had been 
dealt with as it occured.
  The problem is when your game is simple enough not to need any internal 
concept of framerate.  In a tetris, you don't need to repeatedly render the 
same picture ten times before the game drops the piece itself if the user 
doesn't press a button, as would happen if it was rendered at 20fps and the 
piece drop delay was 200ms, which is just about as short as is playable for 
me.
  My users have noted a delay between pressing buttons and things happening.  
The event loop I'm using looks (kinda) like this (pre-rewrite):

  do{ /* main loop */
    looptime=SDL_GetTicks();
    while(SDL_PollEvent(&ev))
      execute_user_input(ev);
    if(!paused)
      timer++;
    if(timer = ticks_to_drop_the_piece){
      piece_height--;
      timer = 0;
      do_stuff_if_the_piece_is_on_the_ground();
    }
    draw_to_screen();
    if(SDL_GetTicks() < looptime + 50)
      SDL_Delay(looptime + 50 - SDL_GetTicks());
  } while (!done);

  Now, actually, my tetris *does* need to draw every 50ms, because it 
changes the colors of everything every 50ms (red=sin(t), green=sin(t+2pi/3), 
blue=sin(t+4pi/3)).  A framerate of 20fps is sufficient for the drawing, but 
apparently not for my users.  Should I increase the framerate, which will 
only increase CPU usage?
  And suppose I supported classical coloration of tetris pieces, like I am 
trying to with my rewrite?  (besides trying to make the code non-butt-ugly)  
Classical tetris piece coloration will only require a "framerate" of however 
long it takes for (1) the user to press a button, or (2) the time until a 
piece drops without the user doing anything.
  The point of moving that bit of code into the library instead of it being 
in my game (and in the other SDL tetris game I saw, and probably in many 
other SDL games) is to make a more efficient implementation possible.  The 
hack that I wrote for SDL is perhaps not the most efficient way of writing 
it, I'm going to look more thoroughly into the way libsdl handles events 
when I get back from raking leaves.


> As to the first issue; low frame rates, you could get around that by 
> running input in a separate thread, timestamping the events as you 
> receive them. That way - if you're on a reasonably nice OS - you can 
> have the game process events at the right logic time, even if the 
> rendering (and thus, the actual event/logic processing) doesn't keep 
> up.
  As I understand it, libSDL keeps a thread for input of it's own.  So, I 
would be interposing a thread between libSDL's event thread and my 
application's thread that actually does stuff, a gratuitous waste of system 
resources.
  Another problem with multithreading is correctness.  In Quake, drawing is 
done as quickly as possible, churning out frames.  The logic is rather 
independent of the drawing, doing AI here and noting that an explosion 
occurs over there, and informing the drawing routine thereof.  And input 
happens when it happens.  I don't know if ID Software actually implemented 
Quake as a multithreaded application, in fact, as it runs under MacOS, I 
rather doubt that Quake is multithreaded.  But it would make sense to 
multithread it.  However, input, logic and drawing are not asynchronous in 
Tetris.  Nor are they asynchronous in Space Invaders, PacMan, or a variety 
of other types of program.
  Which is why I think such an function is necessary to at least my game's 
logic, and why I think most APIs (UNIX, MacOS, 'doze, etc.) include such a 
call.




More information about the SDL mailing list