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

  1. A Turn for the Better
  2.  
  3. This issue marks the seventh installment of my column - it's 
  4. the perfect time to get some perspective on how far we've 
  5. come.
  6.  
  7. This column has two purposes.  The first is to teach OS/2 2.x 
  8. PM programming, mainly by example.  The second is to develop 
  9. the ultimate game for OS/2.  All of the OS/2 games I have 
  10. seen so far are rather simple - they barely take advantage of 
  11. any of the features that OS/2 has over DOS.
  12.  
  13. The Ultimate OS/2 Game is a variation of the BattleTech and 
  14. MechWarrior from Fasa.  BattleTech is a board game based upon 
  15. combat among large humanoid tanks called BattleMechs, and 
  16. MechWarrior is its role-playing counterpart.  I have 
  17. permission from Fasa to use their trademarks with two 
  18. provisos: the copyright must be shared between Fasa and 
  19. myself, and the game must be distributed free of charge.
  20.  
  21. Although this game has been in development for over a year, 
  22. it is still in its infancy.  Construction of a functional 
  23. combat system is the first goal.  The combat system is 
  24. composed of four subsystems: terrain editing, movement, 
  25. weapons control, and damage control.  At this point, the 
  26. first three are partially completed.
  27.  
  28. The terrain editor allows the player to create or alter a 
  29. combat field which is organized into a hexagonal grid.  Each 
  30. hexagon represents an area thirty meters in diameter.  The 
  31. current implementation allows the player to select from 
  32. eleven different terrain types.
  33.  
  34. The movement subsytem controls the navigation of all the 
  35. 'Mechs on the playing field, whether they are piloted by the 
  36. player or by the computer.  It keeps track of game time, it 
  37. determines initiative (a role-playing term that describes who 
  38. goes first in a given turn), and it regulates movement 
  39. points.
  40.  
  41. The weapons control subsytem handles all the details of 
  42. firing a weapon.  It decides what targets are visible, which 
  43. weapons are available, and whether the shot was successful.  
  44. It knows all the stats of each weapon and attack type.
  45.  
  46. The damage subsystem determines the effect of any attack, and 
  47. it keeps track of each BattleMech's condition.  It knows what 
  48. is damaged, how long it will take to repair the damage, and 
  49. how much the repair will cost.
  50.  
  51. Once these four are fully implemented, then the first half of 
  52. this project will be completed.  A discussion of the second 
  53. half, the role-playing MechWarrior, will be saved for a later 
  54. date.
  55.  
  56. The text from the first installment of this column (volume 1, 
  57. number 3) is now available electronically, for those of you 
  58. who are interested in getting a better picture of what this 
  59. game is all about.  Look for it wherever "OS/2 Monthly" 
  60. archives are available.
  61.  
  62. The compiler options have been changed to use the 
  63. single-threaded library.  It is possible for a multi-threaded 
  64. program to function correctly with this library.  The trick 
  65. is to ensure that only one thread calls the run-time library 
  66. at any given time.  The function which handles hexagon 
  67. highlighting during targeting, Highlight() in module TARGET, 
  68. does not contain any library calls.  Therefore, the 
  69. multi-threaded library is not necessary.
  70.  
  71. ERRORS
  72. ------
  73.  
  74. As the complexity of a piece of software increases, so will 
  75. its error handling capabilities.  Unfortunately, most 
  76. languages have poor syntactical support for error handling, 
  77. and C is no exception.  I am not going to present a detailed 
  78. analysis of error handling, since that topic deserves far 
  79. more attention than I can give it.
  80.  
  81. There are two errors handled by this program.  API errors, 
  82. such as the failure to create a presentation space via 
  83. GpiCreatePS(), are unrecoverable and force the program to 
  84. terminate immediately, sometimes with a message box 
  85. appearing.  I have never experienced such an error, and I 
  86. doubt that I ever will.  Nevertheless, they are almost 
  87. exclusively caused by invalid parameters and need to be 
  88. checked.
  89.  
  90. The other condition is a user error, such as attempting to 
  91. load a map that does not exists.  For these errors, a message 
  92. box always appears, informing the user of his mistake.  The 
  93. operation is usually cancelled automatically, and the program 
  94. continues without a hitch.
  95.  
  96. Error messages are of type ERROR, an unsigned 32-bit integer 
  97. that uniquely describes the location where the error occured.  
  98. Function ErrorBox() takes an error code and displays a 
  99. message box that shows the module name, the function name, 
  100. and the error message.  The names and messages and stored in 
  101. file ERRORMSG.H in look-up array amsg[].
  102.  
  103. Function ErrorBox() displays an error message box.  Using the 
  104. information in the error code, it knows to which module and 
  105. function the error belongs.
  106.  
  107. For example, take the error code ERR_BITMAP_LOAD_HBM 
  108. (0x01020300).  This error occurs when the bitmap ID passed to 
  109. function BitmapLoad() is invalid.  A bitwise-AND with 
  110. 0xFF000000 results in ERR_BITMAP (0x01000000), and another 
  111. AND with 0xFFFF00000 gives ERR_BITMAP_LOAD (0x01020000).  The 
  112. look-up array translates these values to "BITMAP" and 
  113. "BitmapLoad", respectively.  This is how ErrorBox() knows the 
  114. module and function names.
  115.  
  116. At this point, you might be wondering why the error messages 
  117. are not stored as string resources.  The reason is quite 
  118. simple: the resource compiler that comes with the OS/2 2.0 
  119. toolkit does not accept ERRORS.H because it contains 
  120. arithmetic expressions for some of its definitions.  Until an 
  121. improved resource compiler can be found, the error messages 
  122. stay where they are.
  123.  
  124. BITMAP
  125. ------
  126.  
  127. The first thing you will notice is that BitmapShutdown() will 
  128. only perform a shutdown if needed.  Then it resets all the 
  129. handles (hdcMemory, etc.) so that the module can be 
  130. reinitialized.  This feature is not used, but it is good 
  131. programming practice.  If the shutdown procedure fails, then 
  132. the appropriate error code is returned.
  133.  
  134. All of the bitmaps are stored in a single memory presentation 
  135. space.  When a particular bitmap needs to be drawn, it must 
  136. first be selected, and then copied from that PS to the screen 
  137. PS.  GpiSetBitmap() is used to select the bitmap, and 
  138. GpiBitBlt() then draws it on the screen.
  139.  
  140. For reasons unknown to me, GpiSetBitmap() returns an error if 
  141. the desired bitmap is already selected.  Just to make sure 
  142. that this "error condition" does not cause any problems, the 
  143. variable hbmCurrent has been added to keep track of the 
  144. currently selected bitmap.
  145.  
  146. FILES
  147. -----
  148.  
  149. This module now focuses on the file dialog boxes only.  
  150. Previously, the functions in the module would not only prompt 
  151. the user for a filename, but they would also read or write 
  152. the data.  To keep things modular, the responsibility of file 
  153. I/O (and file I/O errors) has been placed on the function 
  154. which calls this module.  
  155.  
  156. Currently, the only module which performs any file I/O is 
  157. TERRAIN, and the routines for opening and saving maps are 
  158. there.
  159.  
  160. GAME
  161. ----
  162.  
  163. Thanks to the WM_MINMAXFRAME message, the info box is now 
  164. hidden/shown when the main window is minimized/restored.  For 
  165. this message, the 'mp1' parameter is a pointer to a SWP 
  166. structure, which contains quite a bit of information about 
  167. the window's new size and position.
  168.  
  169. The Move and Target modes have been combined.  The left mouse 
  170. button moves the 'Mech as before, but now the right button is 
  171. used to target.  Edit mode works the same as always.
  172.  
  173. HEXES
  174. -----
  175.  
  176. All of the targetting-specific functions have been moved out 
  177. of this module and placed in TARGET, where they belong.  The 
  178. list includes function HexHighlight() and HexFirstSide().
  179.  
  180. In a previous issue, I mentioned that the presentation space 
  181. handles created with WinGetPS() are cached-micro spaces, and 
  182. therefore should only be used for a short-term drawing.  To 
  183. ensure this restriction, all functions in this module that 
  184. perform any drawing now take an HPS parameter.  OS/2 
  185. allocates a limited number of these presentation spaces in a 
  186. cache (hence the name).  If the cache is fully allocated, 
  187. then WinGetPS() will return a NULLHANDLE.
  188.  
  189. The new function HexOutline() is used to highlight a hexagon 
  190. by drawing its outline.  All hexagons have a one-pixel border 
  191. between them.  The thickness of the border is determined by 
  192. the XLAG and YLAG constants defined in HEXES.H.
  193.  
  194. In the next installment, however, the hexagonal grid will be 
  195. removed.  This is easily accomplished by setting XLAG and 
  196. YLAG to one, instead of the current value of two.  It seems 
  197. that the hexagon borders are screwing up the targeting path 
  198. algorithm.  Sometimes the targeting line squeezes between two 
  199. or three hexagons, and the routines which determine the path 
  200. get confused.  
  201.  
  202. Unfortunately, without a grid, the player will not be able to 
  203. distunguish individual hexagons.  As a remedy, the info box 
  204. will be expanded to always show the hex index under the mouse 
  205. pointer, and a ruler will be drawn around the combat map.
  206.  
  207. MECH
  208. ----
  209.  
  210. The only addition is function ShowPosition(), which shows the 
  211. BattleMech's current position.
  212.  
  213. MENU
  214. ----
  215.  
  216. The changes in this module reflect the changes in module 
  217. FILES.  The funtions that actually load and save maps are in 
  218. module TERRAIN.  The "File" menu now has the option to save 
  219. the current map and to quit the program.  The "close" option 
  220. is also present but has not yet been implemented.
  221.  
  222. TARGET
  223. ------
  224.  
  225. This month introduces yet another attempt at the targetting 
  226. path algorithm.  In most situations, the path is correctly 
  227. outlined, but there are still cases where breakdown occurs.  
  228. Strangely enough, the targeting path is not symmetric about a 
  229. column.  For example, the targeting path from (7,7) to 
  230. (13,11) is not the same shape is the path from (7,7) to 
  231. (1,11).  One possible cause for this aberration is that the 
  232. coordinate returned by HexMidpoint() may not be the exact 
  233. center of the hexagon. 
  234.  
  235. The low-level functions for the targeting path have been 
  236. placed in submodule TARGET0.  This module contains the hex 
  237. highlighting routines (formerly in HEXES) and all the 
  238. functions which calculate the targeting path.
  239.  
  240. The problem with the previous algorithm was explained in 
  241. issue seven: it's too accurate.  Hexagons which were only 
  242. touched or briefly entered were being included, even though 
  243. they had no significant impact on the visibility.  These 
  244. hexagons are called insignificant.  Remember, the whole point 
  245. behind the targeting path is to determine the visibility of 
  246. the target.
  247.  
  248. To explain a solution to this problem, three new definitions 
  249. are introduced:
  250.  
  251. True exit side - the exact side through with the targeting 
  252. line exits.
  253.  
  254. Redirection - the act of selecting an alternate hexagon for a 
  255. better targeting path.  The normal procedure would be to use 
  256. the true exit side.  However, in certain cases, a neighboring 
  257. side might produce a better targeting path that more 
  258. accurately represents the true visibility of the target.  If 
  259. a different exit side is chosen, then redirection is said to 
  260. have occured.
  261.  
  262. Vertex redirection - a redirection technique based on whether 
  263. the targeting line exits near a vertex of the hexagon.  If it 
  264. does, then the slope of the targeting line is compared to the 
  265. slopes of the radii of the exit side and its neighbor.  The 
  266. closest match determines which exit side is actually chosen.
  267.  
  268. Figure 1 shows a condition where this technique works.  
  269. Normally, the targeting path would jump from (0,2) to (1,1) 
  270. to (1,3) to (2,2).  With vertex redirection, hexagon (1,1) is 
  271. skipped, and the resultant path is smoother.
  272.  
  273. Figure 2 shows a condition where this technique does not 
  274. work.  The slope is so shallow that the targeting line never 
  275. enters hexagon (1,3).  Once the algorithm jumps to that hex, 
  276. it no longer knows where to go.  So it just gives up and 
  277. terminates, leaving the targeting path incompletely drawn on 
  278. the screen.
  279.  
  280. The only solution would be to backtrack and try a different 
  281. path.  However, I will put the targeting path algorithm to 
  282. rest for now.  Perhaps a more adventurous soul would want to 
  283. pursue this further?
  284.  
  285. I had the opportunity to test the game on an XGA-2 system.  
  286. Drawing the combat map is certainly much quicker than on my 
  287. VGA system.  However, the background highlighting of the 
  288. source hexagon during targeting does not work properly.  
  289. Function Highlight(), which uses a color-cycling technique if 
  290. the screen supports more than sixteen colors, is too CPU 
  291. intensive.  
  292.  
  293. The targeting path could not respond to mouse movements 
  294. quickly enough.  Adding another DosSleep() call in function 
  295. DoHighlight() alleviated the problem.  A better solution 
  296. would be to temporarily disable this thread while the main 
  297. thread is redrawing the targeting path.  This enhancement can 
  298. be accomplished by using semaphores.  Look for it in a future 
  299. issue.
  300.  
  301. TERRAIN
  302. -------
  303.  
  304. This module now handles all combat map functions.  
  305. Previously, module HEXES handled map drawing, and module 
  306. FILES handled the file I/O.
  307.  
  308. All the functions in this module are self-sufficient.  They 
  309. obtain the file name, if necessary.  If an error occurs, they 
  310. display the proper error messages.  After a successful "open" 
  311. or "save as" operation, the window title is automatically 
  312. changed.  There is no need to return any error condition.
  313.  
  314. WINDOW
  315. ------
  316.  
  317. Function WindowSetTitle() sets the title that is displayed in 
  318. the title bar window.  The parameter that is passed is the 
  319. name of the current map.  A null string is used to represent 
  320. an unnamed map.
  321.  
  322. /* FLAME ON */
  323.  
  324. I am reserving the last few inches of my column for an open 
  325. discussion of OS/2 issues.  Here is an opportunity for users 
  326. and developers alike to have their voices heard.
  327.  
  328. This past December, I noticed a bug in OS/2's keyboard 
  329. driver.  IBM has a CompuServe E-mail address for reporting 
  330. bugs.  The procedure is to obtain the bug-report form, fill 
  331. it out completely, and send it to the proper address.  Since 
  332. I don't have a CompuServe account, I sent the form via 
  333. Internet.  So far, so good.
  334.  
  335. The response I got was that IBM no longer supported Internet 
  336. customers, and that I should use other means to report the 
  337. bug.  In effect, I was being forced to pay money to tell IBM 
  338. about a bug in their software.
  339.  
  340. Things are back to normal now.  Apparently, there was enough 
  341. commotion, both inside and outside IBM, to reverse that 
  342. decision and allow Internet users to report bugs.  About four 
  343. weeks after I initially reported the problem, a diskette with 
  344. the new keyboard driver arrived in my mailbox.  My computer 
  345. is much happier now.  And so am I.
  346.  
  347. The moral of this story is: users who are reporting bugs are 
  348. doing you a favor, so make it easy for them.  Do not force 
  349. them to communicate with normal technical support channels, 
  350. since they are not asking for technical support.  
  351. Fortunately, IBM's support department is the best I have ever 
  352. seen, but there are plenty of other companies out there which 
  353. could use some improvement.
  354.  
  355. Next Month
  356. ----------
  357.  
  358. New window design, a cool opening screen, and maybe some 
  359. experimentation with IBM's new C++ compiler.