You can be the Captain Some of the more astute gamers among you may have noticed a familiarity in the description of this project last month. The rumors are true - this game will be an OS/2 version of Fasa's Battletech and Mechwarrior. Fasa is a company based in Chicago that specializes in role-playing games. A simple agreement between us allows me to use Fasa's trademarks, provided I share the copyright with them and include all the appropriate dis claimers and trademark notices in everything I publish. The most important thing to remember is that this game is not an official product from Fasa. When I spoke with the president, I only asked for permission to use their trademarks. Beyond that, they have no connection with it, so any correspondence should be directed to me. Before I describe this month's source code, there are a few terms which need to be defined. These terms will be used throughout the entire project. Anyone who is interested in following or contributing to the development should obtain the rule books. A good start would be Fasa's "The Rules of Warfare" Battletech manual, available at your local gaming store. Battlemech - a trademark of Fasa, this is the name given to the humanoid tanks described in last month's article. It is usually abbreviated as 'Mech. hex - a regular hexagon, where all six sides and all six interior angles are the same size. Figure 1 is an example. hex map - a map of a playing field divided into hexagons. This setup allows a player to move in six directions, while a normal quadrile grid only allows four. trajectory - a straight line between the center-points of any two hexagons which indicates the path a projectile can take if it were launched from one hex and aimed at the other. shortest path - a connecting series of hexes that trace the shortest route from one hex to another. A walking 'Mech would most likely take the shortest path. If he were to fire a rocket, its path would be a trajectory. The complete source code will not be published in this magazine because of its length, but it will be available electronically and (eventually) on disk. Listed at the end are some BBS's which will get the files directly from me. Feel free to distribute them to all your friends and loved ones. The code is intended to be compiled under OS/2 2.0 only, and at this writing the only compiler that qualifies is a pre-release of IBM's C Set/2. This compiler (or its full-release version) will be used until Borland C++ for OS/2 is released, hopefully in the fourth quarter of this year. At that point we will also make the code somewhat object-oriented. The following list describes the files that accompany this month's installment: GAME.C Main executable HEXES.C Map/targetting routines HEXES.H Header/Prototype file for HEXES.C GAME.EXE Ready-to-run executable GAME.ICO Icon file GAME.RC Resource source file (for the icon) HEX.PCX PCX bitmap description of a hexagon GAME.PRJ WorkFrame/2 project file The game is divided into three sections: initialization and shutdown (function main() in GAMES.C), the window procedure (function WinProc() in GAMES.C), and the hex map routines (file HEXES.C). This first version of the program demonstrates the targetting mechanism of combat mode. Upon startup, it draws a dark grey hex map on a black background. Use the mouse to select an origin hex, and drag the targetting line to a destination. While you are dragging, a background thread highlights the origin hex. Figure 1 is a diagram of a hexagon marked with various constants which explain their definitions. HEX_SIDE is the only constant that needs to be specified, since the length of a side is all that is needed to determine the size of a regular hexagon. How ever, to insure that our visual representation is accurate, HEX_HEIGHT is given a value that creates a symmetrical hexagon on a VGA monitor. Future versions will overcome this limitation. File HEXES.H includes a hex map that shows how the indices are chosen. This particular numbering scheme makes certain calcula tions easier, such as the screen pixel algorithms in function HexCoord(). Next month, we will look at algorithms for the dis tance and the shortest path that also benefit from this method. The size of the window is given by WINDOW_WIDTH and WINDOW_HEIGHT, two constants defined in HEXES.H. This is actu ally the size of the client window. Unfortunately, we can only specify the size of the frame window, which has a title bar for a top border. The height of the title bar can only be determined after it has been drawn, so we need to draw the window, find the title bar's handle, obtain its size, and re-size the frame again with the added height. The window procedure handles only five messages: create, repaint, button down, button up, and button moved. The code for WM_CREATE calculates the maximum number of colors that the display can handle. This is used by HexHighlight() to choose the highlight ing method, either color-cycling if there are more than sixteen colors, or blinking if the selection is not as wide. I had to create both methods since the color-cycling routine did not work as expected on a 16-color screen. It seems that lines are not ditehered, so all you see are two alternating shades of red. Since I do not have access to a 256-color display, this portion of the code has not been fully tested. The drawing of the actual map is handled by WM_PAINT. Targetting is cancelled in the rare event that the window is repainted while we are aiming our rockets. Remember that WM_PAINT must be able to redraw all the graphics in the window at any time. Before long, it will become the largest section of the window procedure. The remaining three messages regulate the targetting mechanism. WM_BUTTON1DOWN activates it, WM_BUTTON1UP terminates it, and WM_MOUSEMOVE moves the line. When button one is pressed, the index of the hex under the mouse pointer is determined. If it is found, then 'target' is initialized with data on the origin hex. Two presentation space handles are obtained - one for the line and another for hex highlighting. The parameters for line draw ing are set, and then HexHighlight() is started. When the button is released, 'fActive' is set to false, causing the while-loop in HexHighlight() to terminate. The targetting line is erased, and its presentation space is released. If the mouse is moved while targetting is active, then WM_MOUSEMOVE determines whether the new location warrants redrawing the line. If so, it erases the existing line (if any), stores the new destination-hex information, and draws the new line. The code in HEXES.C should be rather straightforward and easy to understand. The only possible exception is the array of POINTL's in function HexDraw(). The value returned by HexCoord() is the X,Y coordinate of the lower-left vertex. A hexagon is created by drawing the six sides in a counter-clockwise fashion. The array is a list of all the vertices, in counter-clockwise order, rela tive to the lower-left corner. Add the proper offset to each point, call GpiPolyLine to draw them all at once, and you have a hexagon. That wraps up this month's installment. Please feel free to mail any comments, suggestions, or complaints to me, because I am very interested in knowing your thoughts. Next month's installment will continue the development of the targetting machanism and introduce the code for terrains. It would be very nice if some one volunteered a few bitmaps to represent the different surfaces (hint, hint).