GameX

Copyright (C) 2002 Rama C. Hoetzlein

Programming Documentation

(July 10th, 2002) The GameX engine is currently being used as a teaching tool for a computer game class - CS490 Introduction to Game Design - being taught at Cornell University (Ithaca NY) by myself and Prof. David Schwartz.


0. The GameX GNU Public Liscense
1. Overview
2. Benefits of GameX
3. Limitations of GameX
4. How to Get Started
5. Creating a GameX Project
6. Creating a GameX Main Program
7. Using GameX Functions
8. GameX Images - The ImageX and ImageExt classes
9. Drawing Images and Sprites
10. Rotating & Scaling Images
11. Using GameX for User Input
12. GameX Performance



O. The GameX GNU GPLPublic Liscense

The GameX GNU GPL
Open Source License

Copyright (C) 2002 Rama C. Hoetzlein

Open Source Licenses allow freely modifiable software, with source code, to be widely available by (1) maintaining the copyright of the developer(s) and (2) offering a "license to the public which gives anyone legal permission to copy, distribute and/or modify the software". Open Source Licenses are based on the idea of relaxing the conditions of a standard copywright to permit modification, while allowing the original developer to maintain copywright over works created. One important feature of the GNU GPL is that all derivative works based on GNU open-source software also fall under the terms of the GNU GPL license, thus creating a network of freely modifiable open-source software which includes a history of all those who worked on the software. For complete terms of the GNU GPL, see the following web site or document:

http://www.gnu.org/copyleft/gpl.html

Summary of GameX GNU GPL Terms:

- Anyone can freely download the software and use or modify the source code, so long as the copyright of previous developers is maintained.

- If derivative software is to be re-released, the full source code, including any original source code, must also be re-released under the GNU GPL along with the original copyrights.

- The license does not prevent you from charging for distribution of your software (that is, selling it), but only requires that you include your source code and the names of the original copyrights. (Note: As classwork, Cornell Univ. may prevent you from selling your software, as all student classwork is technically the copyright of Cornell Univ.)

- Downloading and/or modifying the source code constitutes acceptance of the terms of the license.

The GameX graphics engine is distributed under the GNU GPL, with precisely the terms given in the GNU GPL license itself.

More specifically, the GameX engine is released under the following terms:

- You can use GameX to do homework assignments and learn game programming.

- You can modify the GameX core library and also re-release it, but you must re-release it under the GNU GPL, with all source code, and you must include the original copyrights in what you release. (According to the terms of the GPL)

- You can distribute games that you make with GameX so long as you include all the source code for your game, include the source code for the GameX graphics engine, and also include the original copyrights. (According to the terms of the GNU GPL)

- The Game Design class (Prof. Schwartz and myself) will be maintaining an "official" release version which students may contribute to over the years. There will be additional terms and specifications for having student software incorporated into this release. These are not legally binding terms, but simply requirement that we will make so that the official "classroom" GameX engine can continue to grow and be useful to students.

Disclaimer

The GameX software and code is released as is, under the terms of the GPL. This includes the disclaimer, which states that by downloading or modifying the GameX code you agree to the terms of the liscense and therefore accept the software as is an agree not to hold myself or other developers liable for the code. The GameX engine is not intended to be used as a professional game development library.

Warranty

No warranty is provided for the GameX engine, either written or implied. The code is provided as is. However, if you would like to send comments, bug reports, or suggestions, please direct them to myself at..

Rama C. Hoetzlein
rch8@cornell.edu

Copyright (C) 2002 Rama C. Hoetzlein

I. Overview

GameX is computer game, interface and graphics engine for the development of 2D

and 3D games. It is designed with the goal of being extremely easy to use, and provides an interface layer which hides many system and platform specific details. This makes it ideal for higher education, and for those wishing to learn how to make games without having to worry about some of the more established, or system-specific, technical details.

II. Benefits of GameX

GameX gives you the ability to develop computer games much more easily than if you tried to make them from scratch. The benefits of the GameX engine include:

- Makes it very easy to write complete games. (Often in just one or two pages of C++ code!)
- Provides access to keyboard and mouse input as well as graphics output
- Does not require knowledge of Windows API functions
- Does not require knowledge of DirectX or OpenGL
- Functions are provided to automatically load images (.TIF) for your game.
- Graphics output currently supports 2D Sprites with transparency, masking
and tiled backgrounds.
- Does not limit you from make very complex games (using the C++ language)

III. Limitations of GameX

As GameX is in its very early stages of development, it does not yet operate under all systems, platforms, and graphics hardware configurations.

- Presently, Windows is the only supported operating system
- GameX was developed for the Visual C++ 6.0 environment. It has also been tested with Visual C++ 4.0, but opening a new GameX Project in VC 4.0 may involve different steps than those described below.
- GameX uses DirectX for underlying graphics output, and therefore requires that you have DirectX installed. If you will be modifying the GameX source code, you will also need the DirectX SDK. The GameX engine has been tested with DirectX 3.1 and 8.1
- The ONLY supported pixel format at the moment is High Color (16-bit). You must set your monitor or display adapter to this pixel mode.
- As the GameX engine is still in development, the graphics output routines have not been optimized for assembly language, although they still give reasonable performance in most cases. (See the performance statistics below.)
- GameX has not been tested with every variety of graphics card.

IV. How To Get Started

To start using and making games with GameX, you will need the following:

The GameX Engine (GPL release including source code)
Visual C++ 6.0 Developer Studio (VC++ 4.0 is also possible)
DirectX 3.1 or 8.1 (the DirectX SDK is recommended, but not necessary)

Make sure that you have this software installed. The GameX engine is released as a ZIP file, which can be extracted to a blank folder on your hard drive.

V. Creating a GameX Project

Creating a Visual C++ project which uses GameX is relatively simple, but requires a few essential steps to get started. These steps are as follows:

- Create a new Visual C++ workspace or project.
- Be sure that the project you create is a Win32 Application. (not a console application)
- You must link in DirectX by adding ddraw.lib to the link path as follows:

1) Goto Project Menu -> Settings
2) Select the Project folder (highest level folder)
3) Click on the Link tab
4) In the box for Object/library modules..
5) Add ddraw.lib at the end of the list of library files. (remember to leave a space)

- Add all the gamex-.cpp files to the Source Files for your project. (This is done by right clicking on the Source Files folder in the FileView and selecting Add Files to Folder...)
- Add all the gamex-.hpp files to the Header Files for your project.
- You will also need a GameX main program, which is described in more detail below. (Note: If you want to try out the demo, just include all the xdemo-.cpp and xdemo-.hpp files in the project)

A complete GameX Project includes the source code and header files for GameX as well as the source code and header files for your specific game. In the future, GameX will be provided as a library so this will not be necessary.

If you were to build the GameX Demo, for example, the finished Project would look like this:

GameDemo (project name)

Source Files

gamex-debug.cpp -- GameX Source (Debug class)
gamex-buffer.cpp -- GameX Source (Buffer class)
gamex-file.cpp -- GameX Source (File class)
gamex-image.cpp -- GameX Source (Image class)
gamex-win-dx8.cpp -- GameX Source (WindowsDX class)
xdemo-main.cpp -- Ship Demo - Main Program Loop
xdemo-ship.cpp -- Ship Demo - Ship Class
xdemo-photons.cpp Ship Demo - Photons Class

Header Files

gamex-debug.hpp -- GameX Source (Debug class)
gamex-buffer.hpp -- GameX Source (Buffer class)
gamex-file.hpp -- GameX Source (File class)
gamex-image.hpp -- GameX Source (Image class)
gamex-win-dx8.hpp -- GameX Source (WindowsDX class)
xdemo-ship.hpp -- Ship Demo - Ship Class
xdemo-photons.hpp -- Ship Demo - Photons Class

 

VI. Creating a GameX -- Main Program

GameX is designed to be extremely easy to use. A GameX game is just like any other C++ program except that all GameX programs will follow a very standard main program template. The main program template is as follows:

#include <...> // Whatever includes you need in main

#define GAMEX_MAIN // Tells GameX this is the Main Program
#define GAMEX_WINDOWS // Tells GameX to use Windows (required)
#define GAMEX_XSIZE 800 // Requests a specific display size from
#define GAMEX_YSIZE 600 // (these are optional)

#include "gamex.hpp" // Include for GameX itself
int time; // Useful to keep track of (but not required)

void initialize (void) // Required initiailization function
{
time = 0; // Useful to keep track of (but not required)
}
void main (void) // Required main loop function
{
GameX.DrawOpen(); // Opens GameX for drawing output
.. {drawing functions}.. // Put all GameX drawing functions here
GameX.DrawClose(); // Closes GameX output
GameX.ViewUpdate(); // Updates the view with the new drawing
time++; // Useful to keep track of (but not required)
}

The initialize() and main() functions replace the WinProc and WinMain functions which you would normally need for a windows application. These Windows functions are taken care of by GameX, and you are provided two functions - initalize() and main() - which are a simple as a console-type program but provide all the graphics and real-time features of GameX.

The initialize() function is called once, while the main() function will be called repeatedly as quickly as the operating system is capable. Thus, you will place all setup code in initialize() and the main loop of your game in main().

VII. Using GameX Functions

Using GameX's built-in functions is very easy. As the main program template above demonstrates, there is a global object called GameX which you can use to call any GameX function. For example:

ImageX back_img;

void main (void)
{
GameX.DrawOpen();
GameX.DrawBackground (20, 30, &back_img);
GameX.DrawClose();
GameX.ViewUpdate();
time++;
}

This would continuously draw a scrolling background image on the display.
Note that the ImageX class is provided to maintain sprites for your game.
See more regarding the GameX Images and the ImageX and ImagExt classes below.

GameX does not limit you from developing whatever class and code structure you would like for your game.

You can access the GameX object and functions from your source code or header file so long as you include the gamex.hpp header in it. An arbitrary header file would look like this:

#define GAMEX_WINDOWS // Required whenever including gamex.hpp
#include "gamex.hpp" // Access to GameX objects and functions

class MyGameObject {
// Some game class or object
..
}

 

VIII. GameX Images - The ImageX and ImageExt classes

GameX provides an ImageX class which maintains renderable sprites in GameX.

The ImageX and ImageExt classes provide features to easily load and manage your sprites. Images are usually preloaded in the initialize() part of the program, although this is not essential. Here is an example:

ImageX ship1;
ImageX ship2;
ImageExt imgext;

void initialize (void)
{
imgext.Load ("ship1.tif", &ship1);
ship1.ConvertFormat (IMG_HICOLOR);
ship1.ConvertAlphaToMask ();

imgext.Load ("ship2.tif", &ship2);
ship2.ConvertFormat (IMG_HICOLOR);
ship2.ConvertAlphaToBlend ();
}

The ImageExt class is an Image extension which does the actually loading of the image. This is kept seperate from the ImageX objects so that the storage of images and sprites can be very efficient (that is, the ImageX class does not maintain the extra data required to load images). The imgext.Load function loads the specified tif image, including any alpha channels, into the given ImageX object (in this case, ship1 or ship2).

Once the TIF images are loaded, the ConvertFormat function modified the loaded image to make sure the pixel format of the image matches the supported output.. As the only supported mode is 16-bit (IMG_HICOLOR), this line is required in order to prepare the image for output.

The last step, either ConvertAlphaToMask or ConvertAlphaToBlend, is only required if your sprite will be used as a masked sprite or as a alpha-blended sprite. The ConvertAlphaToMask function prepares the images so that it can be passed to the the DrawMasked function, while the ConvertAlphaToBlend prepares the images so that it can be passed to the DrawAlpha or DrawAdded function.. If you intend to use either of these two drawing functions for your sprite, you must remember to do ConvertAlphaToMask or ConvertAlphaToBlend in the initialization() of your images.

IX. Drawing Images and Sprites

The heart of the GameX engine are the functions for drawing sprites and images which you have loaded. All drawing of images must take place between the GameX.DrawOpen and GameX.DrawClose functions in the main() loop. It is a good idea not to do any other processing in this section of the program, as Windows relinquishes all system resources while the display is open. For the same reason, the drawing section should be kept as fast as possible, preferably used just to call the appropriate GameX drawing functions.

The drawing functions are as follows. Clipping with the display area is fully automatic.

GameX.DrawBackground (int x, int y, ImageX &img)

Draws a tiled, scrolling background in the display. The coordinates x,y (in pixels) determine the offset of the background.If the x,y coordinates are kept static, the background will not move. Adjusting the x,y coordinates in real-time can be used to facilitate scrolling.

GameX.DrawImage (int x, int y, ImageX &img)

Draws an image at the specified coordinates.No mask or alpha blending is used, and all pixels in the image img a drawn. This essential overwrites whatever was behind the image and replaces it with what is contained in the image.

GameX.DrawMasked (int x, int y, ImageX &img)

Draws a masked image at the specified coordinates. A masked image is an image in which the pixels may or may not be displayed based a "mask". The mask is a binary (on or off) image which tells which pixels should be drawn. When using TIF images, the alpha channel is used as the mask.

GameX.DrawAlpha (int x, int y, ImageX &img)

Draws an alpha-blended image at the specified coordinates. An alpha-blended image is an image which uses an "alpha" channel to create transparency effects. Black (0) in the alpha channel will render to the background, while white (255) in the alpha channel will render to the image. Values in-between will give transparency effects. When using TIF images, the alpha channel of the TIF file is used for transparency. NOTE: This function is slower than the DrawMasked function.

GameX.DrawAdded (int x, int y, ImageX &img)

Draws an overlay-added image at the specified coordinates. An overlay-added image is an image which combines the background with the foreground based on addition. The addition effect does not require an alpha channel, since the image is simply added to the background. The result is that the image will essential "brighten" the background, thus providing a useful lighting effects (like those need for ship photons, etc.) NOTE: This function is even slower than DrawAlpha, and should only be used with very small sprites.

In the drawing section (between DrawOpen and DrawClose), the drawing of sprites proceeds from back to front. That is, images drawn later will appear in front of images which were drawn earlier. For example, the correct way to create a shadaow "behind" an object is as follows:

GameX.DrawOpen ();
GameX.DrawMasked (x, y, &ship_shadow); // Shadow first (behind)
GameX.DrawMasked (x, y, &ship); // Ship itself (in front)
GameX.DrawClose();

X. Rotating & Scaling Images

The ImageX class is expected to provide many optimized functions for transforming and manipulating images. At the moment, there are only a few functions available. One of these is a function for rotating images to an arbitrary angle (and also scaling them).

In order to rotate images, you must provide an additional ImageX object which will hold the resulting rotated image. The rotate image function thus takes an image, rotates it, and puts the result into a different image object. This is the ideal way to rotate images because it can be done repeatedly from the original object, thus maintain the best quality when rotating an image repeatedly (ie. in real-time).

The rotate image function is:

img.Rotate (ImageX &output_img, float angle, float scale);

Here is an example of how it is used:

ImageX ship;
ImageX rotated_img;
ImageExt imgext;

void initialize (void)
{
imgext.Load ("ship.tif", &ship); // Load ship
// Create blank image for rotation output
rotate_img.Size (70, 70, IMG_HIGHCOLOR | IMG_ALPHA);
}
void main (void)
{
GameX.DrawOpen (); // Start drawing
ship.Rotate (&rotated_img, ang, 1.0); // Rotate ship by 'ang'
GameX.DrawMasked (x, y, rotated_img); // Draw rotated image
GameX.DrawClose ();
}

Note that it is not necessary for the size of the blank rotated image (70 x 70) to correspond to the original image. However, for performance issues, it is important to consider the, possibly scaled, size of the final rotated image so that you do not end up drawing a mostly empty image. If the original image is 70x70, and the blank rotated image is initialized to 70x70, as in the code above, but you set the scale parameter to .25, then the resulting sprite will use only about 20x20 pixels within the 70x70 output image.

XI. Using GameX for User Input

GameX also provides function to easily access user input for your game. There are functions for accessing input from both the keyboard and the mouse. Like all GameX function, these can be used at any point in your program (or within your classes), by accessing the global GameX object.

Mouse Input Functions

int GetMousePress ();

Returns the condition of the mouse buttons. The value returned can be and-ed with the following predefined constants: MK_LBUTTON, MK_MBUTTON, MK_RBUTTON
Here is an example:
if (GetMousePress () & MK_LBUTTON) { ... do stuff for left button}

int GetMouseX ();

Returns the X coordinate of the mouse

int GetMouseY ();

Returns the Y coordinate of the mouse

float GetMouseDX ();

Returns the change (velocity) of the X coordinate of the mouse

float GetMouseDY ();

Returns the change (velocity) of the Y coordinate of the mouse

Keyboard Input Functions

char GetKey (void)

GetKey is used to return buffered keyboard input from the user. Keys are returned by GetKey one at-a-time in the order that they were pressed. This is useful for getting sequentially entered data such as filenames or commands.

bool GetKeyDown (int n)

GetKeyDown tells weather or not a specific key is currently held down. This is more useful for game programming since we just want to know which keys are being pressed, and not necessarily their order. You pass the virtual-key code to the function, and it will return true or false indicating weather the key is down or not.. Multiple keys can be pressed simultaneously, so you can check several different keys at different points in your code as needed.

The virtual-key code passed is either a ascii character like 'A' or 'Z', or a Windows virtual key. The virtual-keys are defined with the predefined constants:
VK_UP Up key
VK_DOWN Down key
VK_LEFT Left key
VK_RIGHT Right key
VK_SPACE Space key
etc.

See the Windows API documentation under Virtual-Key Codes for a complete list of the available key codes. (The easiest way to find this is by doing a Visual C++ Help Search for VK_SPACE)

For example:
if (GameX.GetKeyDown (VK_SPACE)) { .. do stuff for spacebar .. }

 

XII. GameX Performance

As GameX is in early stage of development, its performance is not as good as if you were to use DirectX or OpenGL directly. This is expected to change as GameX is more completely developed to take advantage of these underlying systems.

The speed at which you game runs will depend on several factors. The most important factor will be the display section in the main() loop, and the various drawing functions that you use.

The relative performance of the drawing functions is as follows:

 

 

Pixels Per Millisecond

 

Measured Machine Cycles per Pixel

DrawBackground

11418

 

17

DrawImage

11418

 

17

DrawMasked

14681

 

13

DrawAlpha

2081.25

 

96

DrawAdded

731.25

 

274