home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mnth0108.zip / Timur / vol1n8.txt < prev    next >
Text File  |  1994-03-25  |  10KB  |  233 lines

  1. The Body Electric
  2.  
  3. Those pink checkerboards just had to go.  Representing 
  4. different building types by colored patterns is not my idea 
  5. of an intuitive user interface, so this month I introduce 
  6. bitmaps to enhance the combat map.
  7.  
  8. To facilitate bitmap programming, a new BITMAP module has 
  9. been added.  All bitmaps are loaded from the executable's 
  10. resources and stored in a memory presentation space.  From 
  11. there, they are displayed with a GpiBitBlt() call.
  12.  
  13. The game now allows you to move a 'Mech across the playing 
  14. field.  The 'Mech starts out at location (0,0) and can be 
  15. moved one hex at a time.  Simply click on a nearby hexagon, 
  16. and the 'Mech will either turn to face it or move onto it.  
  17. In BattleTech, each sixty-degree turn is one movement point, 
  18. and a 'Mech can only move forward or backward.  The current 
  19. version of this game does not keep track of movement points 
  20. or turns, however.
  21.  
  22. During targetting, the source hexagon is always taken to be 
  23. the 'Mech, so once you click with the left mouse button, the 
  24. targetting line is automatically drawn to the mouse pointer.
  25.  
  26. BITMAP
  27. ------
  28.  
  29. This new module provides generic bitmap support for the 
  30. entire game.  All bitmaps are stored in the same memory 
  31. presentation space.
  32.  
  33. BitmapLoad() loads a bitmap and returns a bitmap handle if it 
  34. succeeds.  It also initializes the module when first called.  
  35. Note all the WinMessageBox() calls to indicate an error.  A 
  36. more advanced error handler will be included in a future 
  37. version.
  38.  
  39. BitmapDraw() draws a bitmap on the client window.  Most 
  40. bitmaps in this game are irregular in shape.  The bitmap 
  41. itself is always rectangular, but the image it holds usually 
  42. is not.  For instance, a bitmap of a terrain is hexagonal.  
  43. The four corners are part of the bitmap, but not part of the 
  44. image.
  45.  
  46. Thus there is a problem.  Some bitmap pixels must be drawn 
  47. over the screen, and others should not overwrite anything.  
  48. In other words, only a portion of the rectangular bitmap 
  49. should be drawn.  The rest should be ignored.
  50.  
  51. By using a bitmap mask, this effect can be achieved.  The 
  52. mask is the same size and shape as the original bitmap and is 
  53. drawn at the same location, but it contains only two colors: 
  54. white and black.  The black portions are where the true image 
  55. exists in original bitmap.  The white areas are where the 
  56. background image should show through.  It is important to 
  57. remember that wherever the mask is white, the original bitmap 
  58. should be black.
  59.  
  60. The mask is logically-AND'ed with the screen.  The black 
  61. portions of the mask erase the screen, and the white portions 
  62. leave the screen unaltered.  Then the original bitmap is 
  63. logically-OR'ed onto the screen over the mask.
  64.  
  65. If the mask bitmap handle is NULLHANDLE, then no masking 
  66. operation is performed.  This is handy for times when the 
  67. background is already known to be black.
  68.  
  69. GAME
  70. ----
  71.  
  72. Most of the window-related variables have been moved to a new 
  73. module, WINDOW.  However, all of the code is tentatively 
  74. still here.  See the discussion of WINDOW for details. 
  75.  
  76. The window procedure has been updated only to reflect changes 
  77. in the other modules.  For instance, WM_CREATE now calls 
  78. MechInit() to initialize the MECH module.
  79.  
  80. HEXES
  81. -----         
  82.  
  83. The biggest change in this module is the technique used to 
  84. draw the combat map.  The addition of bitmap support 
  85. necessitated an update of the drawing functions.  Also, the 
  86. routines which support the different terrains have been moved 
  87. to a separate module, TERRAIN.
  88.  
  89. The following two methods were previously used to draw the 
  90. combat map:
  91.  
  92. 1. The client window is painted black.  For each hexagon, the 
  93. current color and pattern is set, and an area bracket is 
  94. started. A hexagon is drawn, the bracket is closed, and OS/2 
  95. fills in the rest.
  96.  
  97. 2. Similar to the first method, except that the client window 
  98. is painted with the color and pattern of the default terrain 
  99. (in this case, clear ground).  A black hexagonal grid is 
  100. overlaid.  Only the hexagons which differ from the default 
  101. are then painted.
  102.  
  103. Beginning this month, a third technique comes into play:
  104.  
  105. 3.  The client window is once again painted black, the color 
  106. of the hexagonal grid.  The inside of each hexagon is painted 
  107. without redrawing the hexagon itself.
  108.  
  109. The window procedure should take no longer than 1/10th of a 
  110. second to process any message, otherwise it blocks the 
  111. message queue for too long.  Unfortunately, drawing the 
  112. entire combat map can take several seconds.
  113.  
  114. One solution is to move HexDrawMap() into a separate thread. 
  115. This may solve the queue problem, but the combat map still 
  116. takes too long to draw.  Method #2 works well as long as the 
  117. combat field is mostly of clear ground, which is not always 
  118. the case.
  119.  
  120. The proper technique would be to use WinQueryWindowRect() to 
  121. determine the hexagons which need to be redrawn.  This 
  122. function returns a rectangle that outlines the region of the 
  123. client window which has been invalidated.  A function similar 
  124. to HexLocate() could be used to find the four hexagons that 
  125. lie on the corners of that rectangle.  Then HexDrawMap() 
  126. would read:
  127.  
  128.    for (hi.c=iStartC; hi.c<=iEndC; hi.c++)
  129.      for (hi.r=iStartR; hi.r<=iEndR; hi.r++)
  130.        HexFillDraw(hi);
  131.  
  132. The individual hexagons, however, still take a long time to 
  133. draw. There are a few potential solutions to this problem.  
  134. Look for these and other speed enhancements in future 
  135. articles:
  136.  
  137. 1. Draw all hexagons of a given terrain at once, thereby 
  138. avoiding multiple calls to GpiSetColor() and GpiSetPattern().
  139.  
  140. 2. Use a different technique for drawing filled polygons.  I 
  141. have not explored all the possibilities yet, so there may be 
  142. other Gpi functions which work better.
  143.  
  144. 3. Use bitmaps for all the terrains.  The GpiBitBlt() 
  145. function might be faster than area-bracket fills.
  146.  
  147. Two new defines, XLAG and YLAG, represent the horizontal and 
  148. vertical spacing between the hexagons on the hex map.  The 
  149. default value of two produces a spacing of one pixel.  These 
  150. defines only affect HexCoord(), HexMidpoint(), and 
  151. HexLocate(), since these are the only functions which 
  152. maintain a link between screen coordinates and hex indices.  
  153. WINDOW_WIDTH and WINDOW_HEIGHT also use XLAG and YLAG to 
  154. determine the size of the client window needed to display the 
  155. entire hex map.
  156.  
  157. MECH
  158. ---- 
  159.  
  160. This month introduces a user-controlled 'Mech, supported by 
  161. the MECH module.  This module initializes the 'Mech's 
  162. position and orientation in MechInit() and changes them in 
  163. MechMove(). MechInit() also loads the bitmaps representing 
  164. the 'Mech in all six orientations.
  165.  
  166. MechMove() has to determine whether the 'Mech needs to be 
  167. rotated or moved.  First, it rejects any target hexagon which 
  168. is not adjacent to the 'Mech.  Then, it calculates the 
  169. direction to that hexagon.  If this value is different from 
  170. the current orientation, the 'Mech is rotated and redrawn.  
  171. Otherwise, it is moved to the new position.
  172.  
  173. If you wish to move the 'Mech to a hexagon on its left or 
  174. right side, click on the target hex once to rotate the 'Mech 
  175. and again to move him.  However, do not click the mouse twice 
  176. too quickly.  This action is registered as a double-click, 
  177. which means that OS/2 does not send two WM_BUTTON1DOWN 
  178. messages.  Rather, it sends one WM_BUTTON1DOWN followed by a 
  179. WM_BUTTON1DBLCLK.
  180.  
  181. MENU
  182. ----
  183.  
  184. Changes in the header file for this module eliminate the need 
  185. for MenuInit(), since this function did nothing but 
  186. initialize global variables.  A separate if-statment in 
  187. MainCommand() allows this function to handle any number of 
  188. terrains without a code change. The only other change to this 
  189. module is the inclusion of my address in the "About..." 
  190. dialog box.
  191.  
  192. TERRAIN
  193. -------
  194.  
  195. This module encapsulates all the terrain-related code and 
  196. data which was once in HEXES.  There are eleven terrain 
  197. types, and each one has a set of attributes listed in 
  198. structure TERRAIN. Function TerrainInit() initializes the 
  199. array of terrain data, ater[], with pre-defined constants.  A 
  200. configuration file will eventually be created to store 
  201. information on all the terrains.
  202.  
  203. Function TerrainIdFromMenu() returns the terrain ID (a number 
  204. from 0 to 10) which maps to a given IDM_TER_xxx value.  In 
  205. previous versions of this game, the terrain ID was the same 
  206. as the menu ID listed in file RESOURCE.H.
  207.  
  208. WINDOW
  209. ------
  210.  
  211. This module does not contain any code yet, but its purpose is 
  212. to localize most of the presentation-manager specific 
  213. features of this game.  In the distant future, there might be 
  214. interest in porting this game to other platforms.  Separating 
  215. the operating system specific code early on will make 
  216. cross-platform development much easier.
  217.  
  218. Next Month
  219. ----------
  220.  
  221. There are a few quirks and minor bugs in this code which have 
  222. yet to be fixed.  The mouse is never captured during 
  223. targetting.  Clicking on the client window will not bring it 
  224. into focus.  The info box is not hidden when the main window 
  225. is minimized.  These and other problems will be addressed in 
  226. the next installment.
  227.  
  228. I would also like to make a formal request for volunteer 
  229. translators.  As you know, multilingual support is one of the 
  230. goals of this project.  I expect to have a few dozen 
  231. single-line strings (most of them error messages) which need 
  232. to be translated into as many foriegn languages as possible.  
  233. Anyone out there interested in lending a hand?