home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / GAMEKIT.ZIP / GAMES.TXT < prev    next >
Encoding:
Text File  |  1992-10-18  |  7.3 KB  |  199 lines

  1. x1
  2. How to use GAMES.TPU -- overview -- by Lou DuChez, Pascal-kind-of-guy
  3.  
  4. GAMES.TPU is a Turbo Pascal unit designed to rework the keyboard and timer
  5. interrupts to better function in game writing.  The keyboard is the biggest
  6. problem in a lot of games: the keyboard buffer reads keys sequentially, but you
  7. want simultaneous reads for action games.  Now scan codes for key presses and
  8. releases are transmitted through port 60h, so it seems like it should be
  9. possible just to keep an eye on that memory location.  Unfortunately, interrupt
  10. 09h (the keyboard interrupt) ends up resetting the port to 0 before you can
  11. rwad the contents.  So I wrote a new interrupt handler that does these steps:
  12.  
  13. 1)  reads port 60h and records presses / releases;
  14. 2)  calls the regular keyboard interrupt;
  15. 3)  clears the keyboard buffer.
  16.  
  17. All key presses are stored in an array of 128 boolean values.  I've found that
  18. you can keep track of about six keys simultaneously -- more than enough for
  19. most games.
  20.  
  21. I've also found it useful to nullify the "Ctrl-Break" interrupt.  Basically,
  22. you don't want to "Ctrl-Break" out of a Pascal program before resetting the
  23. keyboard interrupt, so I made a "Ctrl-Break" interrupt that does absolutely
  24. nothing.
  25.  
  26. Finally, when you write an action game, you want it to run at the same speed on
  27. all computers, be they original PC's or 486's.  The best way to do that is to
  28. monitor the computer's timer; I wrote an interrupt that will pause until a
  29. fixed number of "ticks" (18.2 per second) go by.
  30.  
  31.                       GAMES.TPU -- the Keyboard interrupt
  32.  
  33. You install the new keyboard interrupt by invoking procedure INITNEWKEYINT (and
  34. reset to the old one by invoking SETOLDKEYINT).  As mentioned before, the
  35. status of the keys is recorded in a boolean array (from 0 to 127) called
  36. KEYDOWN.  A "True" indicates the key is down; a "False" indicates it is not. 
  37. So your program just has to check this array periodically to see what keys are
  38. down.
  39.  
  40. Now as for figuring out which array elements correspond to which keys: I
  41. provide two ways.  First of all, there is a function "SCANOF": it takes a
  42. character argument, and returns (as a byte) what scan code corresponds to the
  43. character (more accurately, the key that makes the character).  If, for
  44. example, you need to know the scan code of the "1" key, you'd want the value
  45. returned by SCANOF('1') (or SCANOF('!'), since you're trying to see if the
  46. "1"/"!" key is down, and the "Shift" keys aren't an issue).  In particular,
  47. you'd know that the "1" key is down if KEYDOWN[SCANOF('1')] was "True".
  48.  
  49. The SCANOF function works for all the alphanumeric and punctuation keys; it
  50. doesn't work for the arrows, "NumLock", function keys, etc. because there's no
  51. particular characters to associate with them.  So here are some constants that
  52. you can use instead:
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68. CONSTANT  VAL  DESCRIPTION              CONSTANT  VAL  DESCRIPTION
  69.  
  70. escscan   $01  "Esc"                    entscan   $1c  "Enter"
  71. backscan  $0e  Backspace                rshscan   $36  Right Shift
  72. ctrlscan  $1d  "Ctrl"                   prtscan   $37  "PrntScrn"
  73. lshscan   $2a  Left Shift               altscan   $38  "Alt"
  74. capscan   $3a  "CapLock"                homescan  $47  "Home"
  75. f1scan    $3b  F1                       upscan    $48  Up Arrow
  76. f2scan    $3c  F2                       pgupscan  $49  "Pg Up"
  77. f3scan    $3d  F3                       minscan   $4a  "-" on keypad
  78. f4scan    $3e  F4                       leftscan  $4b  Left Arrow
  79. f5scan    $3f  F5                       midscan   $4c  "5" on keypad
  80. f6scan    $40  F6                       rightscan $4d  Right Arrow
  81. f7scan    $41  F7                       plusscan  $4e  "+" on keypad
  82. f8scan    $42  F8                       endscan   $4f  "End"
  83. f9scan    $43  F9                       downscan  $50  Down Arrow
  84. f10scan   $44  F10                      pgdnscan  $51  "Pg Down"
  85. f11scan   $d9  F11                      insscan   $52  "Ins"
  86. f12scan   $da  F12                      delscan   $53  "Del"
  87. scrlscan  $46  "ScrollLock"             numscan   $45  "Num Lock"
  88. tabscan   $0f  Tab
  89.  
  90. Is the left arrow down?  It is, if KEYDOWN[LEFTSCAN] is "True".
  91.  
  92. There is a second array of booleans (0 to 127), called WASDOWN: it records
  93. whether or not a key has been depressed in a period of time.  This is more
  94. useful for keys that get tapped instead of continuously held down: for example,
  95. a movement key is held, but a fire button is tapped.  Has the Space Bar been
  96. pressed?  Only if WASDOWN[SCANOF(' ')] is "True".  A procedure to use with the
  97. WASDOWN array is CLEARWASDOWNARRAY:  resets all the elements of WASDOWN to
  98. "False".  ("FOR COUNTER := 0 TO 127 DO WASDOWN[COUNTER] := FALSE")  So you
  99. reset the array with CLEARWASDOWNARRAY, and WASDOWN will record all the keys
  100. that have been pressed until you call CLEARWASDOWNARRAY again.
  101.  
  102.                      GAMES.TPU -- the "Ctrl-Brk" interrupt
  103.  
  104. This one takes little to no explanation.  Call INITNEWBRKINT to call the new
  105. interrupt (essentially, to disable it); call SETOLDBRKINT to reset it.
  106.  
  107.                        GAMES.TPU -- the Timer interrupt
  108.  
  109. 18.2 times per second, the computer generates a "tick", calls hardware
  110. interrupt 08h, updates its clock/calendar, does various house-cleaning
  111. functions, and then calls interrupt 1Bh.  1Bh is an interrupt for programmers
  112. to hook their programs onto for timing purposes; that's exactly what GAMES.TPU
  113. does.  Invoke the new timer handler with INITNEWTIMINT (and disable it with
  114. SETOLDTIMINT); it first calls whatever TSR's might be using that interrupt
  115. already, then it increments a counter.  You indirectly access that counter by
  116. the procedure TICKWAIT: the computer waits until the counter gets to the number
  117. of ticks specified before doing anything else (byte values only).  Once that
  118. number has been reached, the counter resets to 0.
  119.  
  120. I think an example is in order: let's say you have an action game where each
  121. round should take one-half second on any machine.  So at the beginning of the
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134. first round, call TICKWAIT(0) (to set the tick counter to 0).  At the end of
  135. each round, call TICKWAIT(9) (to wait out the half second).  Now between those
  136. steps, while the computer has been drawing things on the screen, updating enemy
  137. positions, etc., the tick counter has been automatically incrementing every
  138. .055 seconds.  On a 4.77Mhz XT, the counter may have gotten to 6 by the time
  139. the program gets to the TICKWAIT(9) statement, which waits three more ticks
  140. before proceeding to the next step.  On a 486, the tick counter might get only
  141. to 1 before encountering the TICKWAIT(9); in which case, the computer will wait
  142. eight ticks before proceeding.  So you can make programs that run at the same
  143. speed on any computer via the timer interrupt and TICKWAIT.
  144.  
  145. Some sample pseudocode:
  146.  
  147. program gamething;
  148. uses games;
  149.  
  150. procedure movefoes;
  151.      begin
  152.        .
  153.        .
  154.      end;
  155.  
  156. procedure firephasers;
  157.      begin
  158.        .
  159.        .
  160.      end;
  161.  
  162. procedure updatescore;
  163.      begin
  164.        .
  165.        .
  166.      end; 
  167.  
  168. procedure playgame;
  169.      begin
  170.      repeat begin
  171.           movefoes;
  172.           firephasers;
  173.           updatescore;
  174.           tickwait(2);
  175.           end until igotblownup;
  176.      end;
  177.  
  178. begin {main program}
  179. initnewtimint;
  180. tickwait(0);
  181. playgame;
  182. setoldtimint;
  183. end.
  184.  
  185. Included are GAMES.PAS (compile it yourself -- I wrote it via Turbo Pascal 6.0,
  186. but it ought to work on 4 and 5 too), and RAIDERS.EXE, a game I wrote using all
  187. those interrupts.  Enjoy!
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.