Re: Double clicking the mouse

Search this archive.

From: Russell Marks (russell.marks@dtn.ntl.com)
Date: Sun 19 Mar 2000 - 15:32:22 IST


Never tried any double-click stuff, but...

> And speaking of timers, what have some of you done in regard to games, etc.?
> How have you keep speeds consistent across different processors?

The most basic approach is to use usleep() each frame (I did this in
zblast, IIRC), but that's a bit inaccurate, especially if your
per-frame processing takes non-zero time. :-) A better way, which I've
used in z81 and I'm also using in a port of the old Windoze game
Hyperoid which I'm playing around with (anyone happen to know the
author's current email address, BTW?), is to use setitimer() to set a
flag at given intervals. Here's an example of what's needed:


volatile int timer_flag=0;


void sighandler(int foo)
{
timer_flag=1;
}


void start_timer(void)
{
struct sigaction sa;
struct itimerval itv;
int tmp=1000000/20;	/* 20 ints/sec */

sigemptyset(&sa.sa_mask);
sa.sa_handler=sighandler;
sa.sa_flags=SA_RESTART;
sigaction(SIGALRM,&sa,NULL);

itv.it_value.tv_sec=itv.it_interval.tv_sec=tmp/1000000;
itv.it_value.tv_usec=itv.it_interval.tv_usec=tmp%1000000;
setitimer(ITIMER_REAL,&itv,NULL);
}


void wait_for_timer(void)
{
sigset_t mask,oldmask;

sigemptyset(&mask);
sigaddset(&mask,SIGALRM);

/* The procmask stuff is to avoid a race condition (not actually
 * a big deal, would just rarely lose an interrupt, but FWIW...).
 */
sigprocmask(SIG_BLOCK,&mask,&oldmask);
if(!timer_flag)
  while(!timer_flag)
    sigsuspend(&oldmask);
sigprocmask(SIG_UNBLOCK,&mask,NULL);

timer_flag=0;
}


And FWIW, here's an example of how you might use this:


start_timer();

while(!quit)
  {
  wait_for_timer();
  
  do_a_frame();
  }


The advantage of not calling do_a_frame() directly from sighandler()
is twofold - there's *very* little you can do safely in a signal
handler, and the `polling' approach means you degrade gracefully on
machines too slow to handle the game (i.e. the game runs slow rather
than completely screwing up :-)). Also, a polling model is less hassle
than dealing with interrupts IMHO.

OTOH, the above code is fairly POSIX-me-harder; it may not be quite as
portable as just using usleep() (which in turn is probably less
portable than (ab)using select()/poll()). But that hardly matters for
svgalib stuff, and these days it probably isn't much of a problem
anyway. [1]

Oh, one final thing - you *could* explicitly stop the timer, but since
it's only setting a flag there's usually no need, you can just leave
it running.

-Rus.

[1] Though I'm not sure *BSD would like the sigaction() stuff.
Certainly ye olde BSD didn't have it. (But most of my `BSD' experience
was with SunOS 4.x, so I'm probably best ignored on this one. :-))
That'd be easy enough to replace with plain old signal() though, and
the timer wait stuff with pause().


This archive was generated by hypermail 2.1.4 : Wed 21 Jan 2004 - 22:10:23 IST