Linux game programming An introduction to the use of interval timers and asynchronous input notifications Our prior animation demo We achieved the illusion of smooth and flicker free animation by synchronizing drawing operations with Vertical Retrace But more is needed in a game that s fun Some deficiencies in our animate1 demo Ball movements tied to Vertical Retrace The viewer lacked any real time control How can we overcome these limitations Decoupling move from draw Our program loop had used logic like this do vsync delay until start of the next retrace hide ball erase the ball move ball adjust its location show ball redraw the ball count decrement a counter while count 0 So ball movement is delayed by vertical retraces Linux provides interval timers include sys time h struct itimerval itval itold itval it value tv sec 2 itval it value tv usec 0 itval it interval tv sec 0 itval it interval tv usec 10000 setitimer ITIMER REAL itval itold See the man page for additional details structs timeval and itimerval struct timeval tv sec tv usec struct itimerval it interval tv sec tv usec it value tv sec tv usec It itimerval next delay value it timeval current delay value SIGALRM When timer expires our application gets notified by being sent a signal from Linux Normally an application gets terminated if the SIGALRM signal is delivered to it But we can alter that default behavior by installing a signal handler that we design We can move the ball when SIGALRM is received regardless of Vertical Retrace Our signal handler void on alarm int signum modify these global variables ball xcoordinate xincrement ball ycoordinate yincrement The signal function installs our handler signal SIGALRM on alarm Main program loop revised We can now omit ball movement in main loop do vsync delay until start of the next retrace hide ball erase the old ball oldx newx oldy newy remember new position show ball redraw the new ball count decrement a counter while count 0 Ball movement is managed by signal handler draw versus move Signal handler Program loop The code in this signal handler takes care of all movements whenever it s time for them to occur The code in this loop handles all the actual re drawing in sync with the vertical retrace The Operating System takes care of switching the CPU between these two separate threads of control Giving the user control Linux supports asynchronous terminal i o We can reprogram the terminal console so a SIGIO signal will be sent to our program whenever the user decides to press a key And we can install a signal handler of our own design that executes if SIGIO arrives This will allow a user to control our game The tty interface tty is an acronyn for TeleTYpe terminal Such devices have a keyboard and screen Behavior emulates technology from 1950s Usually a tty operates in canonical mode Each user keystroke is echoed to screen Some editing is allowed e g backspace The keyboard input is internally buffered The ENTER key signals an end of line Programs receive input one line at a time tty customization Sometimes canonical mode isn t suitable an example animated computer games The terminal s behavior can be modified UNIX provides a convenient interface include termios h struct termios tty int tcgetattr int fd struct termios tty int tcsetattr int fd int flag struct termios tty How does the tty work SOFTWARE application User space tty driver c lflag Kernel space input handling c iflag c cc output handling c oflag terminal driver c cflag HARDWARE TeleTYpe display device struct tty c iflag c oflag c cflag c lflag c line c cc The c lflag field This field is just an array of flag bits Individual bits have symbolic names Names conform to a POSIX standard Linux names match other UNIX s names Though actual symbol values may differ Your C C program should use include termios h for portability to other UNIX environments ICANON and ECHO Normally the c lflag field has these set They can be cleared using bitwise logic tty c lflag ECHO inhibit echo tty c lflag ICANON no buffering The c cc array struct termios objects include an array The array indices have symbolic names Symbol names are standardized in UNIX Array entries are tty operating parameters Two useful ones for our purposes are tty c cc VMIN and tty c cc VTIME How to setup raw terminal mode Step 1 Use tcgetattr to get a copy of the current tty s struct termios settings Step 2 Make a working copy of that object Step 3 Modify its flags and control codes Step 4 Use tcsetattr to install changes Step 5 Perform desired raw mode input Step 6 Use tcsetattr to restore the terminal to its original default settings raw mode needs four changes tty c cc VMIN 1 so the read function will return as soon as at least one new input character is available tty c cc VTIME 0 so there will be no time delay after each new key pressed until the read function returns tty c lflag ECHO tty c lflag ICANON no echoing no buffering Demo program rawtty cpp This program may soon prove useful It shows the keyboard scancode values It demonstrates noncanonical tty mode It clears the ISIG bit in c lflags field This prevents CONTROL C from being used to abort the program the user must quit by hitting the ESCAPE key so default terminal settings will get reinstalled Noncanonical terminal i o We ve now learned how to reprogram the terminal to allow raw keyboard input include termios h struct termios tty tcgetattr 0 tty get tty settings tty c lflag ICANON ECHO ISIG tty c cc VMIN 1 tty c cc VTIME 0 tcsetattr 0 TCSAFLUSH tty install Handling a key press Here s a simple signal handler that lets a user decide to terminate our program by hitting the ESCAPE key instead of the program itself deciding to quit when a counter reaches zero void on input int signum int inch 0 read 0 inch 4 if inch ESCAPE KEY done 1 Enabling asynchronous I O Now we need to install our signal handler specify which program will receive SIGIO then enable the delivery of these signals signal SIGIO on input fcntl 0 F SETOWN getpid int flagval fcntl 0 F GETFL NULL flagval O ASYNC turn on flag bit fcntl 0 F SETFL flagval animate2 cpp on input Handles User s keystrokes SIGIO on alarm Handles Timer s expirations SIGALRM The Signal Handlers main loop Handles redrawing whenever Vertical Retrace Is active Waiting and Drawing Program loop revised again done 0 do oldx xloc oldy yloc remember these draw ball use current location vsync await next retrace hide ball erase previous ball while done xloc yloc and done get
View Full Document