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