Technical Writing
TECHNICAL WRITING SAMPLE
Strategic War Game Design by C.Stewart 2002
Game pieces are implemented as class objects. You can have, for example, a Player class where an instance
represents one of the players in the game. This object would keep track of such things as player name, player status
(eliminated, etc.), a list of pointers to region objects owned by the player, and so on. Other classes may include a
region class representing a different space on the 'map board' (land, sea, etc.). The different 'playing pieces' can also
be indicated with class objects. These objects can be of a derived nature. For example, an infantry unit can be
derived from a land unit class object which in turn is derived from a unit object. This base Unit class contains the
attributes common to all unit types ( land, air, sea, etc.) such as movement points, attack and defense values, etc.
The act of moving a playing piece to us humans can seem a relatively simple operation. You just pick it up and place
it in the new location as long as you fall within the guidelines of the game rules. To a computer, however, this 'simple'
operation can become a complex series of tasks. For example, in the 'old days' of procedural programming a typical
combat move might look as follows:
1. Is the playing piece mine?
2. Is there an enemy to attack within range?
3. Are there enough move points to make the move?
4. Will a move go off screen and cause a scroll or restrict movement?
5. Is the unit a land unit attempting to enter a sea zone, in which case a transport unit must be present in that region?
6. Is the unit crossing a canal or other region feature that requires special handling?
7. And so on, and so on,...
In fact, the checks necessary to make a so-called 'simple move' can become quite numerous depending on unit and
region types. Adjustments made to the necessary class objects to indicate a move can be equally abundant. A
common move like the one above could usually be implemented with a combination of if and switch statements.
However, if one of these statements is left out or otherwise overlooked the code becomes prone to error.
A better, more effective way to manage all these checks would be to take a more object-oriented design approach.
Unit classes can be defined with a hierarchical structure. Checks common to all unit types can be indicated 'higher up'
in the hierarchy, and more unit-specific checks (land, air, sea, etc.) are represented with virtual functions further down
the class 'pyramid.'
Another important aspect of strategy game design is to keep the user interface logic 'invisible' from the actual game
design. Once programmed, a good graphics interface should be a manifestation of the configurations of the class
objects. Manipulate the objects (changing certain data members) and the graphics will reflect these changes visually.
It is only when a good graphics interface is developed that the game programmer can concentrate on the real task at
hand; and that is the design of the game logic and not on how to display it.
There is a recognizable cycle to any computer game (or any interactive software for that matter). This cycle consists of
three stages: read the mouse direction (locator), read the mouse button or keyboard (choice), and update (render) the
screen based on possible changes made to the class objects during the previous two stages. Of course, there are many
of these cycles in just one second of time.
If we follow this 'locator/choice/render' approach to software development we see that at any given time we are con-
cerned mainly with the immediate on screen portion of the game. We say mainly because we are also interested in the
immediate off screen pixels for scrolling purposes. All other 'drawing' outside this area is unnecessary. The same logic
used to determine a pixel index in the screen memory also determines a 'handler' code index value in the equivalent
position in a logic table. All program code is then restricted to interpreting the current conditions of screen memory
and the pixel rows and columns surrounding it.
When moving from one region to another, we don't need to check for its region type. Instead, a special function called
a handler is activated already knowing this information and responding to it. As mentioned before, for every pixel on
the screen there is an equivalent position in a logic table that represents an index value used in accessing an array (or
vector) of pointers to handler functions. Just by knowing what screen position the cursor is at, we already have the
logic we need to perform our operation.
These handlers can be grouped into 'sets' and updated to reflect different phases of a game. For instance, you can
have one set of handlers for the combat movement phase and another set for actually resolving combat. If an alert
has been activated, the set of handlers can be replaced with another set that handles input during an alert.
To check for off screen pixels and possible scrolls we no longer need an if or switch statement testing for the outer
bounds of the screen. Instead we can have a special version of a regular handler called an 'edge handler' that already
knows this information. For example, if the cursor is located on the far left pixel of the screen and an attempt is made
to move left, the handler already knows how to process this input.
One type of basic game design might consist of a backdrop on which playing pieces (represented by icons) are moved
around. In some applications this backdrop is referred to as a game board made up of 'spaces.' When these spaces
represent territorial regions, sea zones, and such; this game board is often referred to as a world map. The purpose
of the world map is to visually display the relationships between the various class objects that make up the game
(Region class objects, Unit class objects, etc.) as well as guiding a player with input.
It is important to note that very rarely is the whole world map displayed at once; maybe to show the overall status of
the players in the game, or something like that. Indeed, when the entire map is displayed it is 'zoomed-out' to such a
maximum that icon size shrinks and becomes difficult to work with. In most situations it is instead likely that only a
portion of the world map is viewed at any given time. An example might include zooming-in on a particular battle front
between regions where every icon can clearly be seen and interpreted. The ability to zoom in and out on a world map
to view different numbers of regions and icons implies that the world map must be a very dynamic (scalable) data
abstraction.
A simple solution to designing a world map is to just use a large bitmap in memory defining the pixel settings that
determine the world map. Unfortunately, even with the highest resolution and the most detailed graphics; only the most
rudimentary scaling can be accomplished when extreme close-ups (like many unit icons on a small island, for example)
are involved. In most cases, region boundaries represented by smooth-looking curves become too geometric and tend
to look more like connecting line segments.
A better and more effective method of creating a playing background that would allow for smoother scaling between
levels of detail is to define it mathematically using laws from vector calculus and differential geometry. Using this
method, region boundaries are no longer defined by predefined pixel settings, but rather they are now represented by
a mathematical curve defined as a function of arc length and curvature. This is a very mathematically intensive area of
programming; in particular using functions of more than one variable, the details of which will be explained later. For
now, it is just important to know a few of the basic ideas behind generating a good world map using advanced mathe-
matical techniques.
In both systems of world map design, bitmap or vector, an array of pixel (screen) memory is written to. The difference
between the two approaches is in how these pixels are determined. The bitmap method is relatively simple but pro-
duces a less than desired effect when scaling is involved.
With vector techniques, however, the curves representing the various borders are stored as vector functions based on
arc length and curvature. Scaling is possible because no matter the scale of arc length, its relation to curvature remains
invariant. In other words, a pixel's value is not determined from a table but computed mathematically at the time it is
generated. Since at most times only a portion of the whole map is displayed, we only perform the mathematics neces-
sary to write to the screen pixels (and those immediately around them).
Now that we have a design for a background playfield, how do we know when the cursor is over a region or over a
unit (or other) icon? Again, this is an issue of interface design versus application design. Once the mechanics of the
interface are worked out and coded, the interface no longer gets major attention and plays no part in programming the
actual abstract rules of the game.
Icons, in the simplest sense, are represented using the Icon class. Specific icons are then derived from this class, i.e.,
unitIcon objects, numberIcon objects, etc. One thing all icons have is a certain range of pixels they occupy on the
screen. These ranges can be specified as class members in the Icon class at the top of the class hierarchy. By sorting
a list of icons by this range data member we can easily determine what pixel represents an icon, if any, by simply
traversing the list.
To determine which region a specific pixel belongs to we create a compressed storage buffer holding the current ranges
of pixel values (position and occurance count) for each region. Given any pixel location it is then simply a matter of
scanning this buffer to determine the region containing the pixel. These compressed codes are updated and changed
routinely at the time a pixel is written to the screen buffer.
Once all the graphics intricacies are resolved, it is now time to go on to the actual design and implementation of the
custom game rules that make a particular game unique.