Documentation


Contents

1. Initializing and Using GameX
2. Advanced GameX Initialization
3. About Game Speed and Frame Rate
4. Loading Images - The ImageX class

5. Drawing Images in GameX

6. Special Effects with Drawing Modes
7. Shading Images and the ColorX class

8. Advanced Graphics Rendering in GameX
9. 3D Graphics & CameraX
10. Painting in and Filtering Images
11. Loading and Playing Sounds - The SoundX class
12. Music and the MusicX class
13. Keyboard Input in GameX
14. Mouse Input in GameX
15. Loading and Saving Files in GameX
16. Reserved Controls
17. Things to Remember! (Problems? Look here first!)
18. GameX Performance

 

1) Initializing and Using GameX

GameX is designed to be extremely easy to use. A GameX game is just like any other C++ program except that all GameX programs follow a very basic main program template. Windows functions (WinProc and WinMain) have been hidden so you don't need to directly deal with the Windows API or DirectX.

The main program template is as follows:

#define GAMEX_MAIN
#pragma comment (lib, "gamex.lib")
#include "gamex.hpp"
// #include <...>

void GameInit (void)
{
     GameX.Initialize ("My Game", VIDEO_16BIT,
                                                             800, 600);
     //… {load images/sounds/music/whatever} …
}

void GameRun (void)
{
     //... {motion, behavior, input } ...
}

void GameDraw (void)
{
     //... {drawing functions}...
}

// Tells GameX that this is your main .cpp file
// Tells your compiler to link with the GameX library
// Includes GameX itself
// (Include whatever else we want to use here)

// Required GameInit( ) function. GameX calls this once at startup.
// The purpose of GameInit( ) is to set everything up to run the game.
// Required GameX Initialization. 2nd parameter is for display mode
// or other options. 800 x 600 is game window size in pixels.
// (Now load or set up whatever else our game needs)


// Required GameRun( ) function. Called repeatedly (speed can be set).
// Purpose of GameRun( ) is to advance the game's state by one instant.
// (Calls to implement motion, behavior, input, and sound for game)
// Make sure not to draw anything here!

// Required GameDraw( ) function.
// Purpose of GameDraw( ) is to draw the game's current state.
// (Draw background then sprites using GameX draw functions)
// Make sure not to change or move anything here!

This is the minimum length of a GameX game (note that this is *much* smaller than the minimal Windows application). The WinProc and WinMain functions which you would normally need for a windows application are handled automatically by GameX, so all you need to define are the GameInit( ), GameRun( ) and GameDraw( ) functions, which are called separately by GameX at different times to accomplish different things:

- The GameInit( ) function is called once as the game is starting up. Thus, you will place all setup code in GameInit( ).
After calling GameX.Initialize( ) here, it's a good idea to load sounds and images and whatever else your game will need.

- The GameRun( ) function is called repeatedly. Thus, place what would go inside of the main loop of your game in GameRun( ).
The code can be as complex as necessary to give your game the motion and behavior you desire. BUT, make sure that it does not call any drawing functions, directly or indirectly.

- The GameDraw( ) function is also called repeatedly, although possibly less often. It should do nothing but draw whatever game state has been set by GameRun( ).
Make sure not to alter the state of the game while you're drawing it; even appearance-related changes should not be made here unless they have no effect on any subsequent frames of animation.
 
Using GameX's built-in functions is very simple. There is a global object called GameX which you can use to call any GameX function. The GameX object provides everything you need to make a game - graphics, sound, and user-input. Its functions can be called from anywhere, including inside class member functions, as long as the gamex.hpp file is included in the class header.

Briefly, some of the most essential GameX functions are:

For starting up:
   - GameX.Initialize (name, mode, width, height, [speed]) -- Initializes GameX and sets general game properties.
For graphics:
   - GameX.DrawImage (&image, xpos, ypos, [angle, scale]) -- Draws an image sprite at xpos, ypos (image is an ImageX)
   - GameX.DrawRect (color, xleft, ytop, xright, ybottom) -- Draws a filled rectangle at the given location.
   - GameX.DrawTiled (&image, xoffset, yoffset) -- Draws an image tiled as a background.
For sound:
   - GameX.PlaySound (&sound, how, [volume, pan, frequency]) -- Plays a sound clip in real-time (sound is a SoundX).
   - GameX.PlayMusic (&song, [times, volume, fade_in_time, tempo, pitch]) -- Starts playing a MIDI music clip (song is a MusicX).
For keyboard input:
   - GameX.IsKeyDown (key) -- Tells you if the given keyboard key is being pressed by the user.
   - GameX.GetKeyPress (key) -- Tells you if the given keyboard key was just pressed at this instant by the user.
   - GameX.GetBufferedKeyPress( ) -- Gets a typed character from the user, or 0 if nothing was typed
For mouse input:
   - GameX.IsMouseDown (button) -- Tells you if the given mouse button is being pressed.
   - GameX.GetMouseClick (button) -- Tells you if the given mouse button was just clicked this instant.
   - GameX.GetMouseX( ) and GameX.GetMouseY( ) -- Gets the position of the mouse cursor
   - GameX.GetMouseDX( ), GetMouseDY( ), GetMouseDZ( ) -- Gets the rate of change of the mouse cursor or wheel.
For general use:
   - GameX.GetGlobalCounter( ) -- Gets a value that increases linearly over time.
   - GameX.GetOscillatingValue (min, max, speed, [phase]) -- Gets a value that oscillates sinusoidally over time.
   - GameX.GetRandomInt (min, max) -- Gets a pseudo-randomly generated integer within the bounds given.
   - GameX.GetRandomFloat (min, max) -- Gets a pseudo-randomly generated floating point value within the bounds given.
   - GameX.DebugOutput (char* message) -- Adds a log to the "debug.txt" output file located in the same directory as your game.

 

2) Advanced GameX Initialization

The only function you are required to call when initializing GameX is GameX.Initialize( ). The code above gives you an example of how to use this function, but let's take a closer look at it:

bool Initialize (char* name, GameXInitFlags options, int xres, int yres, [int speed = 60]); // speed is optional

Initialize returns true if it succeeds and false otherwise, but don't worry about this; your code can assume that it always succeeds, and when it fails, GameX will let you know with an informative popup message that will give you an idea of how to fix the problem.
The important things to note about this function are the parameters it takes and what it does with them:
- name is simply a string enclosed in quotes, such as "My Game" or "Asteroids". It's used only to let Windows know what the game is called so it can give it the right titles.
- xres and yres tell GameX the width and height to make your game screen. They can be almost anything, but standard values include 640x480 or 800x600 (it is best, but not required, to use a 4:3 ratio of width to height).
- speed is optional; if you don't give a speed parameter, GameX will assume a speed of 60 cycles per second (cps), which is a fairly typical game speed. If you do give a speed parameter, that value is the number of times that your GameRun( ) function is called per second. The speed is NOT the frame rate, although it determines the maximum frame rate your game can reach, along with the monitor's refresh rate. This parameter must be between 5 and 600.
- options is just an int value consisting of combinable initialization flags. This required parameter tells GameX what features to set up for your game. For instance, if you want the game to only run in "full screen" mode, that's an option you can specify. The only required part about this parameter is that you must specify a preferred bit depth (monitor color mode) for your game. You should almost always use VIDEO_16BIT because 16 bit color mode is the most widely supported and the fastest mode. There are many other options though, which you can combine with each other using the | operator. Here's the list, it's a long one but keep in mind you will probably only ever use a few of these:

GameX Init Flag:

Description of Effect:

VIDEO_16BIT

Run game in 16-bit color mode -- currently the fastest, most common, and best-supported mode.

VIDEO_32BIT

Run game in 32-bit color mode -- beware: on many computers, this mode is slower and also looks worse than 16-bit mode. This flag is incompatible with VIDEO_16BIT for obvious reasons.

VIDEO_FULLSCREEN

Immediately enter full screen mode when the game begins.

VIDEO_WINDOWED

Begins game in windowed mode. This flag is incompatible with VIDEO_FULLSCREEN for obvious reasons. If you don't specify this flag or the previous flag, then the user is automatically given a choice at game startup.

RUN_USEESCAPEKEY

Allows your game to detect the escape key instead of having ESC automatically quit.

RUN_AUTOSHOWINFO

Tells GameX to automatically display the following debugging information in real-time: game speed, frame rate, idle percent, and mouse position. It will be displayed in the title bar if the game is in windowed mode, or at the bottom-left corner of the game screen if the game is in full screen mode. This flag is for debugging only, so you should remove it when you are done with your game.

RUN_ALWAYSKEEPCURSOR

Prevents GameX from hiding the Windows mouse cursor, even in full screen mode.

RUN_ALWAYSHIDECURSOR

Allows GameX to hide the cursor whenever it is over the game screen. (If you want, your game can draw its own cursor easily.)

RUN_NOCONFIRMQUIT

Disallows GameX from asking whether the user is sure about quitting.

VIDEO_LOWRES

Tells GameX to use low-resolution images to save memory and speed at the expense of some graphical quality.

VIDEO_NORESIZE

Prevents the user from being able to resize or maximize the game window.

VIDEO_ALLOWREFRESHSYNC

Tells GameX to attempt to automatically synchronize game drawing updates with the monitor's refresh rate. This is known as "V-Sync" and it can prevent "tearing" artifacts to improve the visual quality of your game's animation, but its implementation is not perfect (sacrifices some accuracy for speed) so it is not on by default.

VIDEO_SLOWDEBUGDRAWING

Has GameX draw individual frames very s-l-o-w-l-y so you can get a visual representation of what order things are being drawn in. This flag is for temporary debugging purposes only.

VIDEO_SOFTWAREONLY

Forces all drawing operations to take place in software instead of video hardware. Not recommended since it will make any game run a lot worse; only use this for temporary debugging.

AUDIO_DISABLE

Disables audio support, which prevents GameX from playing any sounds or music.

RUN_BACKGROUND

Allow the game to keep running even in the background by preventing GameX from automatically pausing the game -- possible uses are for networked games or cheat prevention, maybe.

RUN_NOMOUSEINPUT

Prevents GameX from keeping track of mouse movement and clicks.

RUN_NOALTENTERTOGGLE

Allows the player to hit alt-enter without toggling between full screen/windowed mode.

So, here's an example of a specialized call to Initialize( ):

GameX.Initialize("My First Person Shooter",
                          (VIDEO_16BIT | VIDEO_FULLSCREEN | RUN_USEESCAPEKEY | RUN_ALWAYSHIDECURSOR),
                          800, 600, 100);

This would initialize a game called "My First Person Shooter" that runs in 16-bit fullscreen mode, that treats ESC like a regular key for the game to use, and that always hides the cursor so you can draw your own cursor (a crosshair for example). It sets the game screen size to a standard 800x600 pixels, and it tells GameX to call GameRun( ) 100 times every second, which is slightly faster than the usual 60.

3) About Game Speed and Frame Rate

GameX now incorporates automatic game speed and frame rate management. Because it is completely automatic, you do not need to worry about it or write any timing code in order to program your own GameX game. However, although it is not necessary to know exactly how it works, a general understanding of it can be educational and will help you better understand the level of performance of your game, and so it is described in detail in this section of the documentation, if you wish to learn more about it.

There are two important terms to know with regard to how GameX does its automatic timing:

CPS -- Cycles Per Second -- The game's speed -- Technically, the number of times that GameRun( ) is called per second.
FPS -- Frames Per Second -- The game's smoothness -- Technically, the number of times that GameDraw( ) is called per second.

If you Initialize GameX with RUN_AUTOSHOWINFO, you will see values (actual / target) for CPS and FPS; now you know what they mean.

The CPS value is what determines how fast your game goes. A target CPS is determined when you Initialize GameX, and you can change this value later by calling GameX.SetGameSpeed( ), or find out what it is at run-time by calling GameX.GetGameSpeed( ). The default value is 60 CPS, which is a standard (pretty fast) game speed. A specific value doesn't necessarily translate to how fast your game seems to play, because it also matters how fast you tell the individual objects in your game to move. Whatever the CPS is, what matters is that it remains constant, because an unpredictably/unintentionally varying CPS is unacceptable.

You may already be familiar with the term "FPS", also known as the game's "frame rate", in which case you would know that a high FPS is good because it makes the game animate smoothly, whereas a low FPS makes the game appear choppy. The FPS your game can obtain is limited by several factors: The frame rate cannot go higher than the refresh rate of your monitor, and the FPS also cannot go higher than the CPS of your game. When you Initialize GameX, it determines a target FPS that is as high as possible without going over these limits. There are other limiting factors (for instance, if your computer is too slow to handle the complexity of your game), but these are not calculable.

The absolute top priority of the GameX timing code is to ensure that the actual CPS of the game remains exactly fixed at the target CPS value. It then makes the best attempt possible to keep the actual FPS at or around the target FPS, but this attempt is a secondary concern. This means that, if necessary, GameX will skip a few frames of drawing here and there, lowering the actual FPS (this is known as intentional lag), in order to keep the game going at the same speed for a consistent playing experience even if it doesn't appear quite as smooth. It will also wait between frames when necessary to prevent the game from running too quickly, which would be just as serious a problem as it going too slowly. Note that change in keyboard input is sometimes ignored during lag, so there is a "lag limit" which defaults to 12 and can be set with GameX.SetLagLimit(value). If the control is still imprecise during lag on slow computers, then you should set the lag limit lower, but don't set it too low. On the other hand, if your game is a network game, you probably want the lag limit to be infinitely high, which you can do by calling GameX.SetLagLimit(0), which GameX interprets to mean no limit at all.

(It is implied in the above that the timing code is able to operate because the "updating" and the "drawing" code of the game can be called independently. Thus, it is important that your GameRun and GameDraw functions really do Run or Draw your game (respectively) as GameX expects them to.)

Ideally, the computer that GameX is running on is capable of handling the game's complexity, in which case the target CPS and FPS will both be obtained. Which leads to the timing code's third-priority concern: conservation of CPU cycles. If the target CPS and FPS are both approximately reached, then GameX will attempt to conserve CPU cycles by gathering what spare milliseconds it can (between frames) and giving them back to the system, which increases the "idle time" of the game. CPU cycles that are not conserved directly translate to energy used and heat produced by your computer, so the higher the idle time is, the cooler your system runs and the less energy it uses. This is especially important for laptop computers which have issues with both energy and cooling. Also, any CPU cycles conserved remain available for background processes to make use of without disturbing the game.

So how exactly does the above information help a programmer who is making a GameX game? Here is some advice that it roughly translates into:

- Make sure that GameDraw( ) only draws your game and doesn't change anything at all, or the timing code will malfunction.
- If you don't quite understand all of this, don't worry about it; the timing code is pretty self-sufficient as long as your code is valid.
- Don't set the speed of your game too low, because it limits the game's frame rate, but don't set it too high, either. 45 to 100 CPS is normal, 60 is the standard value.
- Until you are done with or are presenting your game, use RUN_AUTOSHOWINFO as a flag for GameX.Initialize, because that way you will know the CPS, FPS, and Idle% of your game when you're testing it. But don't leave it in after that, because it can make your game look less professional. If you want an FPS display in your game, query GameX for the frame rate and draw it yourself instead.
- If the CPS of your game is not approximately at the requested game speed, then something serious is wrong.
- If the FPS of your game becomes low, for instance if it says 40/60 or even 10/60, then your game's drawing section is too complex for your computer to handle it. Make sure you are building your program in "Release" mode and not "Debug", since this can make a big difference in speed. If you are running in Release mode, and your computer is decently fast, and the FPS is still low, that probably means you are doing something inefficient. Don't blame low FPS on GameX or its timing code; it is purely the result of your computer and its video card not being powerful enough to handle the computations that your code is asking them to perform.
- If the Idle% of your game is high (such as 30% to 80%), that is a good thing, however, it also means that you have a lot of room for expansion. Idle time translates to unused potential processing power that you could harness by adding code to make your game look better or act smarter, without causing any drop in the frame rate. But don't use up *all* of the idle time if you can avoid it, because as stated above, idle time is good and ultimately makes your game more compatible with different computers. If the idle time is 0, and it used to be higher, consider optimizing your code and/or removing unnecessary features.


Note that GameX allows you to change the game's speed while it is running, which can be an enormous help when testing or debugging.
Here is a useful block of code you can paste at the end of your GameRun( ) function that makes the + and - keys speed up and slow down time, respectively:

#ifdef _DEBUG
            if(GameX.IsKeyDown(KEY_MINUS)) GameX.SetGameSpeed(GameX.GetGameSpeed( ) - 1);
            if(GameX.IsKeyDown(KEY_PLUS))  GameX.SetGameSpeed(GameX.GetGameSpeed( ) + 1);
#endif

One last thing about GameX timing: It is possible to completely disable GameX's timing and frame rate management by making GAMEX_RUN_UNMANAGED a preprocessor definition in your game's project settings. This is to allow custom timing code to be implemented, but be warned that writing good, flexible timing code is a surprisingly subtle and difficult task. In any case, when GAMEX_RUN_UNMANAGED is defined, GameX repeatedly calls a single function GameMain instead of GameRun and GameDraw.

 

4) Loading Images - The ImageX class

The graphics of any game are the most important way that the game is presented to the person playing it. To achieve an acceptable level of graphical quality, most games draw many pre-made images in various combinations of ways to represent the game. To allow you to do this, GameX provides an ImageX class which maintains sprites and textures (images) which you can use to piece together your game's graphics.

The ImageX class provides features to easily load and manage your images. You will usually want to pre-load your images in the GameInit( ) part of the program before anything is drawn (although this is not essential). Here is an example:

ImageX background, target, ship;
 
void GameInit (void)
{
    background.Load ("back.jpg");
    target.Load ("target.tif", true);
    ship.Load ("ship.gif", "ship_alpha.gif");
}

// Allocate a ship, a target, and a background sprite
 
// Required void GameInit (void) function

// Load back.jpg file into the background image
// Load target.tif file with transparency into target image
// Load ship.gif file with transparency from ship_alpha.gif

The Load function loads the specified image file into an ImageX object, which you can (later) tell GameX to draw. The first parameter of Load( ) is the image file's path, and the second (optional) parameter tells GameX how/whether to load the image with a transparency layer.

For those who are not familiar with the conventions of filename paths required to identify Windows files in C++ code:

The first parameter is a C-string that is the path to the file to load. A path consists of the names of the folders that the file is inside (each followed by a slash), then the file's name with its extension. In this case, the first image we load has a path of "back.jpg", which means that the file is not inside any folders (it's just sitting in our game's directory), its filename is "back.jpg", and ".jpg" is the extension, which means that the file is a JPEG file. The extension tells GameX what type of file it is; GameX can currently load JPEG, GIF, BMP, and TIFF files.

To load an image that isn't directly in the game's directory, it must be in a sub-directory of a known name, such as "Images", then you can call something like:
    background.Load("Images\\back.jpg");

NOTE:
The double slash is required, because \\ means \ to your compiler when inside a string.
These paths are NOT case-sensitive, so "BaCk.JpG" means the same thing as "back.jpg".

IMPORTANT:
If you are using Windows XP, filenames may appear to have no extension at all (i.e. "back.jpg" shows up as "back"), but that is only because the operating system is hiding the extensions from you. To fix this, go to Start -> Control Panel -> Folder Options-> View, and scroll down until you see a checkbox next to "Hide extensions for known file types", which you should uncheck and then click OK.

In any case, once GameX finds the image where you tell it to look, it will load the image, with or without transparency as mentioned briefly above. Basically, if you pass in "true" as the second parameter, GameX will attempt to load the alpha channel in the image as well as its color channels, and if it does not find an alpha channel, it will instead use an on/off "mask" where pure black becomes fully transparent. Or, you can pass in a second filename (instead of a boolean) for the second parameter to indicate that the alpha channel comes from a different image file, like so:

            ship.Load ("ship_color.gif", "ship_alpha.gif"); // (from the sample code above)

This allows you to use a separate grayscale image as the alpha/transparency layer instead of needing the color and alpha merged into the same file. In this case, the alpha actually comes from the second image's non-alpha color data, which is converted to grayscale and then to alpha.

You must have called GameX.Initialize( ) before you can load any images. Your images can be almost any size you want, but computers like squares and powers of two, so the most efficient image sizes to use are exactly 64x64, 128x128, 256x256, and 512x512. Anything larger will still work, but should be avoided. Try to conserve memory and speed by using small images (you can scale them up to make them look as big as you want in the game) and re-using loaded images whenever possible.

Images can be saved in many different formats. GameX can currently load 4 of these formats, each of which is best when used in some situations and not in others. Here is a list of the image types GameX can handle with its Load function, along with the optimal use of each image format:

Image File Type:

File Name Extension:

Specific Loading Capabilities:

Best Used For:

Bitmap File

.bmp or .BMP or .dib or .DIB

8-bit (Indexed), 16-bit (X1R5G5B5),
24-bit (R8G8B8), or 32-bit (R8G8B8A8)

General use, small images that don't need to be compressed much. 16-bit and sometimes 8-bit BMP files are better.

Tag Image File

.tif or .TIF or .tiff or .TIFF

24-bit (R8G8B8) or 32-bit (R8G8B8A8)

Must be saved with NO compression using IBM byte order.

Small images that don't need to be compressed at all (or are not in their final form) and would benefit from having alpha saved directly in them.

JPEG File

.jpg or .JPG or .jpeg or .JPEG

All qualities and compression methods supported.

Background images, artwork, screenshots, and most other large images.

Graphic Image File

.gif or .GIF

Non-animated, without LZW compression or interlacing. Transparent color, if anything, must be pure black, if not using a separate file.

All images that use or look acceptable with 256 colors or (preferably) less.

There are a few things to note about these image formats and the issue of transparency:
 - TIFF and 32-bit BMP are capable of storing a detailed alpha channel directly inside of them.
 - JPEG images must be saved as two separate files (one for color, one for alpha/transparency) in order to represent an image with transparency.
 - The other image formats can use pure-black to represent fully-transparent (a mask), OR they can be saved as two separate files (one for color, one for alpha).

To conserve file memory, you should save each different image in the format that best suits it according to the uses suggested in the above "Best Used For" column. Conserving file memory is important, because when it comes time to distribute your game or even just transfer it between computers, it will go a lot faster if the files take up less memory. When saving each image, a good method to use is this: First, can it be saved and look good as a GIF? If not, try JPEG. If neither of those are acceptable, then consider 16-bit BMP and finally TIFF.


Besides Load, ImageX has several other methods you may find useful. Excluding the image painting and filtering methods (which are described below in section 17, "Painting in Images"), here are the functions that ImageX provides:

image.Load (char * filename, [bool alpha]); // alpha is optional, defaults to false
    Loads an image from file into this ImageX. See above in this section for details and example code.

image.Load (char * filename, char * alphafilename);
    Loads an image from file, with alpha from another file, into this ImageX

image.LoadIntoAlpha (char * filename);
    Loads a grayscale image and uses it to replace this image's alpha channel

image.Create (int xSize, int ySize, [bool alpha=false]); // alpha is optional, defaults to false
    Creates a blank image of the given size.

image.Destroy (void);
    Completely unloads this image from memory.

image.Save (char * filename);
    Saves the image to file. The filename must have a .bmp or .tif extension.

image.CopyTo (ImageX * dest);
    Copies this image into a destination image.

image.CopyToAlpha (ImageX * dest);
    Copies the grayscale conversion of this image's color into the alpha of a destination image.

image.CopyToClipboard (void);
    Copies the image to the clipboard, from where it can be pasted into other programs.

image.GetWidth (void); // returns the width of this image, in pixels
image.GetHeight (void); // returns the height of this image, in pixels

image.Resize (int new_xres, int new_yres);
    Resizes this image, preserving and scaling current contents to the extents of the new size.


5) Drawing Images in GameX

The heart of the GameX engine consists of functions for drawing sprites and images which you have loaded, and other graphical objects.
All drawing must take place (directly or indirectly) inside the GameDraw( ) function. It is a good idea to not do any other processing in this section of the program, or at least as little processing as necessary. Preferably, the drawing section should be used just to call the appropriate GameX drawing functions (which may be called via member functions of another class). This drawing happens every single frame, which is often as many as 60 times per second, to make the game appear continuously animated.

Drawing an image:

To draw an image in 2D, use the DrawImage( ) function. Here's a sample call to DrawImage:

GameX.DrawImage(&ship1, 200, 300);

This simple line of code takes a ship image (which must have already been loaded) and draws it at the position (200,300) pixels from the top-left corner of the game screen. If the ship image was loaded with transparency, GameX will automatically take that into account when it draws it here. And if you want to draw the ship rotated by 180 degrees and scaled to be 5 times as big, you would simply replace the above line of code with:

GameX.DrawImage(&ship1, 200, 300, 180.0, 5.0); // 180 is the angle, 5 is the scale

That's how easy it is to do scaling and rotation. You could replace 180.0 with any arbitrary angle and 5.0 with any arbitrary scale and that's how GameX would draw it; there's no need to create a buffer image beforehand. Also, note that all clipping is fully automatic.

The general DrawImage function prototype is:
void DrawImage(ImageX* img, int x, int y, [float angle, float scale]) // angle and scale are optional

Note that the angle and scale provided in this function are for convenience, it's really just shorthand for calling GameX.SetDrawAngle(angle) and GameX.SetDrawScale(scale) before you draw the image with GameX.DrawImage(img, x, y). The other drawing functions do not have this shorthand version, so you will have to use SetDrawScale and SetDrawAngle to change the angle and scale with them.

Keep in mind that DrawImage takes a pointer to the image you're drawing. So, if your image variable is called "image", then you would call DrawImage(&image, x, y) instead of DrawImage(image, x, y) (which would give a compiler error). If you have an image pointer variable already (ImageX* imagePointer), then you can call DrawImage(imagePointer, x, y).

A final note about DrawImage: Normally, the x,y coordinates you give are used to determine where the top-left corner of the image goes. However, you will often want to draw an image that is centered at a particular point, and you don't care where its top-left corner is. There is now an easy way to center images: Before you make the call to DrawImage, call GameX.SetDrawMode (DRAWOP_CENTERED), and GameX will automatically center the image at the x,y coordinates you give. SetDrawMode is described in further detail later (section 13 of this documentation).

Drawing a background:

There is actually one thing you should do before drawing any images: draw a background. If you draw the background after drawing the images, then the background will cover up the images, which is probably not intended. If you don't draw a background at all, then previous frames of animation will show through to the current one, which can look neat but is not usually desirable.

There are several ways of drawing a background:

GameX.ClearScreen( )
            Sets the entire screen to black, to create a black background without requiring any background art graphics.

GameX.FillScreen (ColorX color )
            Sets the entire screen to the given color, which can be a gradient color (see below for info on ColorX objects)
.           Example: to fill the screen bright green, you would call GameX.FillScreen (ColorX (0, 255, 0)).

GameX.DrawTiled (&backgroundImage, [x, y]) // x and y are optional

Draws an image automatically tiled multiple times to make a background image. Here, the (x, y) is an offset value which you can change over time to make the background scroll smoothly. You should make sure backgroundImage is NOT loaded with transparency, unless you are drawing the background in multiple layers. Also, to make the background spin and/or zoom, you can call SetDrawAngle and/or SetDrawScale beforehand. If spinning it, you can give two extra coordinates which are rotational offset values if you want to make the background spin about a specific point: GameX.DrawTiled (&backgroundImage, x, y, rot_x, rot_y). Finally, note that DrawTiled (and FillScreen also) are not necessarily limited to being used to draw the background; you might also use them to overlay the screen with a transparent and/or tiled layer, for example, to achieve a fog or mist effect. Transparency of this nature is discussed in further detail below in section 14 of this documentation, "Shading Images and the ColorX Class".

Of course, you could also draw your background by piecing it together out of images using DrawImage, but the above functions are generally more convenient.

Note about Clipping and Split-Screen Modes:

When you draw an image that is partway out of the game window, it is "clipped" so that only the part of it inside your game window is drawn.

Clipping against the edges of the game view is automatic, and when you draw the background, it normally fills this entire view. However, sometimes you may want to only use a smaller portion of the window. For instance, if your game has a split-screen mode, you want the two halves of the screen to be independent and never overlap each other, which you can have GameX enforce for you by clipping to each half of the screen when you draw to it. To change the clipping region, use this function:

GameX.SetView (int xLeft, int yTop, int xRight, int yBottom);

When you want to reset the clipping to the way it was before, call GameX.ResetView( ).

Note about Drawing Order:

In the drawing section, the drawing of sprites and other things normally proceeds from back to front. If you draw in front-to-back order instead, then everything will be drawn in the wrong order and covered up by the background. If you draw two things in the same place, the second one will always end up on top of (obscuring) the first one. There is one important exception: You can tell GameX to sort the scene for you so that it does not matter what order you draw in, but this is an advanced option (described later) used primarily to simplify 3D drawing.


6) Special Effects with Drawing Modes

GameX allows you to change the "drawing mode" before drawing an image (or other graphic) in order to achieve a wide variety of special effects.

An example of a common effect is "additive drawing", which is where the image's color values are added to the color values of whatever it is drawn on top of, as opposed to replacing them completely like normal. Additive drawing is the perfect way to achieve special effects such as fire, lightning, photons, spotlights, explosions, laser beams, etc.

To draw an image additively, simply make the following call before drawing the image: GameX.SetDrawMode (DRAW_ADD).

There are two types of constants for use with SetDrawMode: "Drawing Mode" constants (such as DRAW_ADD), and "Draw Option" constants (such as DRAWOP_CENTERED). When you call SetDrawMode, you can specify one Drawing Mode constant, and you can also optionally specify any number of Draw Option constants. This is done by combining constants via the | operator, for example, GameX.SetDrawMode (DRAW_ADD | DRAWOP_CENTERED).

There are many other constants besides DRAW_ADD and DRAW_CENTERED, which are as follows:

Image Drawing Mode:

Resulting effect:

Sample:

Drawing Formula:

DRAW_NORMAL

Image is drawn normally (by replacing the background with the image). If the image has transparency, it is automatically drawn with the transparency taken into account. This mode is assumed by default unless you specify otherwise.

SOURCE

DRAW_ADD

Image is drawn additively by adding color brightness together, in the same way that light works. This useful mode is great for special effects such as fire, lightning, photons, spotlights, explosions, laser beams, etc. If the image has alpha (transparency), it is taken into account, HOWEVER the image should NOT have any alpha layer, because the effect generates its own transparency using the image's colors. Darkness in the image automatically becomes transparency, so there is no need for an alpha layer. For this and the following modes, you should use images with black backgrounds that are not loaded with alpha.

DEST + SOURCE

DRAW_SUBTRACT

Image is drawn subtractively, which is good for shadows, shadowy effects, or black text. The brighter the image, the more it darkens what you draw it over. Also, the darker what you are drawing over, the more quickly it goes to black. The image should NOT have any alpha layer (in fact, this and the following Draw Modes completely ignore any alpha layer that the image may have).

DEST - SOURCE

DRAW_GHOST

Image is drawn using color-valued transparency, creating an interesting effect that is good for raindrops, some particle effects, and (of course) ghosts. You can think of this effect as a sort of combination of DRAW_SUBTRACT and DRAW_ADD (only very loosely), because it can both darken and lighten what it is drawn over.

DEST*(1-SOURCE) + SOURCE*SOURCE

DRAW_INVERT

Image is drawn by inverting the destination proportionally to the image colors. Good for either inverting things (creating a "nuclear-winter" type effect if what you draw is white) or for drawing images that must be visible against both light and dark backgrounds.

DEST + SOURCE - 2*SOURCE*DEST

DRAW_BURN

Image is drawn by inverting the destination proportionally to the grayness of the image colors. Very interesting, but of limited use (perhaps useful for things like smoke, oil, and etchings). You can think of this effect as a sort of combination of DRAW_INVERT and DRAW_SUBTRACT, or as a inverted version of DRAW_GHOST.

SOURCE - SOURCE*SOURCE - DEST*SOURCE

DRAW_INTENSIFY

Image is drawn additively but also proportionally to the brightness of the destination. Thus, the destination must already contain brightness for anything drawn with this mode to add more. Tends to preserve hues while increasing brightness. This mode is often useless for drawing a scene, but can be used to intensify parts of what has already been drawn.

DEST + 2*SOURCE*DEST

DRAW_ADDSOFT

Image is drawn additively but also proportionally to the darkness of the destination. In other words, it's a lot like DRAW_ADD but tapers off as it approaches full brightness, preventing the burnout effect that is common to normal additive drawing, for a softer and more uniform resulting effect.

DEST + SOURCE - SOURCE*DEST

DRAW_ADDSHARP

Image is drawn additively but with increased contrast, often resulting in its colors becoming more prominent.

DEST + 4*SOURCE*SOURCE

DRAW_MULTIPLY

Image is drawn by multiplying image colors by destination colors. This mode can make the destination darker but not brighter, since it treats white as 1 and black as 0. May be useful for color filter overlays or certain other effects.

DEST * SOURCE

 

Image Draw Option:

Resulting effect: (can be combined)

DRAWOP_BRIGHT

Draw image with 2X brightness, causing the brighter parts of the image to drawn with a level of "overexposure" which can make for a nice effect. Combine this flag with SetDrawColor if you want a higher degree of control over image shading and brightness, such that 127 is normal and 255 is extra-bright. You can also combine this flag with draw modes like DRAW_ADD, DRAW_SUBTRACT, etc. to apply the special effect to a greater extent.

DRAWOP_INVERTED

Temporarily invert the image when drawing it. White becomes black, black becomes white, blue becomes yellow, gray stays gray, etc. Do not confuse this with DRAW_INVERT which inverts the background based on the image; this just inverts the image and lets you apply it to the background however you want.

DRAWOP_NOFILTER

Render the image without doing bilinear filtering, i.e. turn off automatic smoothing of image scaling. This is good if for some reason you want your images to look blocky. This flag usually does NOT speed up image drawing.

DRAWOP_NODITHER

Normally, GameX dithers what you draw to give the impression that the image is showing more colors than the monitor can really display. However, certain effects may suffer from the predictable pattern that dithering follows, in which case you can specify this flag to avoid the problem. Usually, it does not make a difference one way or the other, and it does not affect drawing speed at all.

DRAWOP_CENTERED

Makes point coordinates specify center instead of top-left of the image. Very useful for many objects (space ships, for instance) whose positions are defined in relation to their center, so you don't have to calculate an offset radius to center them. Only has an effect on DrawImage, DrawImage3D, DrawPoint, and DrawPoint3D.

DRAWOP_HMIRROR

Mirror or flip the image horizontally (sideways) when drawing.

DRAWOP_VMIRROR

Mirror or flip the image vertically when drawing.

DRAWOP_NOCULL

If a polygon is facing away from the camera in 3D, or if an image/rectangle has a negative x and/or y scale in 2D, GameX normally skips drawing it, but this flag prevents GameX from skipping (culling) it. Using this on too many polygons will result in decreased performance, however.

DRAWOP_NOBLENDALPHA

For advanced use only. Tells GameX to treat the alpha/transparency layer like a normal color layer to be transferred instead of using it to blend colors. If drawing to the screen or into an image with no alpha, this means the alpha layer gets ignored.

DRAWOP_ALPHAINTERSECT

For advanced use only. If you are drawing an image in auto-sorted 3D, AND if the image has alpha/transparency, AND if you want it to be able to intersect in 3D with other images or polygons, then you should specify this flag. Otherwise, do not specify this flag because it slows things down. When the flag is on, parts of the image that are 97% opaque or greater will be Z-buffered and show up properly over/under partially intersecting images and polygons.

DRAWOP_KEEPSTATES

For advanced use only. Preserves image state settings past the call to the next drawing function. Most drawing states are reset to default after the next thing you draw if you don't specify this flag before you draw it.

Keep in mind that the above drawing modes and drawing options do NOT modify the source image, only the way it is drawn during one drawing operation. Also, remember that you cannot combine two Draw Modes, such as DRAW_ADD and DRAW_SUBTRACT at the same time; you can only combine one DRAW_ constant with any number of DRAWOP_ constants.

7) Shading Images and the ColorX class

Another useful function you can call before drawing an image is GameX.SetDrawShading (ColorX color). This allows you to shade a particular drawing of an image without changing the actual image, so you can even use a color that changes dynamically with time, and the shading operation is very fast. As a simple example, to draw an image shaded bright red, you would call GameX.SetDrawShading (ColorX(255, 0, 0)). Shading is capable of doing much more interesting things, but first it is necessary to know what a ColorX really is:

An object of class ColorX is intended to hold a color. Specifically, it holds red, green, and blue values which add to produce a wide range of possible colors, in fact, every color that a computer monitor is capable of displaying. If you're not familiar with additive color, then you'll just have to get used to the fact that Red+Green=Yellow, Red+Blue=Magenta, Green+Blue=Cyan, and Red+Green+Blue=White. The ColorX class uses the convention that 0 means no color amount, and 255 means full brightness of that color amount. So, when (red, green, blue) = (255, 255, 0), that corresponds with the color yellow. So, to create a yellow ColorX, you would call the constructor ColorX(255, 255, 0). For some other examples: pure black is (0, 0, 0), 50% gray is (128,128,128), pure white is (255, 255, 255), a pinkish color is (255,128,128), a deep violet color is (48, 0, 112). Components that are out-of-bounds of the 0-255 range are clipped, so for instance (400,300,200) becomes (255,255,200) (pale yellow) when used.

We now extend the definition of "color" to include an additional concept: transparency. Transparency is defined via an "alpha" value, where 0 means fully transparent, and 255 means fully opaque. Like color values, it can be anywhere in-between, for instance, alpha of 128 means it is exactly halfway transparent. So each color is really defined as (red, green, blue, alpha), also known as RGBA. To create a ColorX that is red and with 50% transparency, you would call the constructor ColorX(255, 0, 0, 128). Drawing this color on white would result in pink, on yellow would result in orange, on black would result in dark-red. When you call SetDrawShading with a transparent color, the image is drawn with the given degree of transparency, even if the image itself does not have transparency in it, and even if you are using one of the special effect drawing modes.

Finally, a ColorX can encompass one more concept related to color: The gradient. A color gradient basically means that, instead of one single color, you can actually have something that fades between multiple colors (including alpha). In other words, a ColorX can actually hold multiple ColorX's inside of it, which are automatically used by GameX to create smooth color gradient shading effects. A ColorX can hold 4 colors which are given in this order: top-left, top-right, bottom-left, bottom-right. So, to make a ColorX with a gradient, you can call the constructor ColorX (top_left_color, top_right_color, bottom_left_color, bottom_right_color). Or, you can give all of the RGBA values at once and call ColorX (r1,g1,b1,a1, r2,g2,b2,a2, r3,g3,b3,a3, r4,g4,b4,a4).

The ColorX class also contains several operator overloads for convenience, for instance, you can multiply a ColorX by a number to change its brightness, or you can add two ColorX objects together and use the result to shade something.

NOTE: When you use a ColorX in a function that draws a color, for instance with GameX.FillScreen(ColorX color), the color that the ColorX represents is exactly what will be drawn to the screen. However, in the case of shading an image with SetDrawShading, you should know that the shading color is actually multiplied by the image, so "pure white" when shading an image means that the image does not get shaded at all, "50% gray" means that the image is drawn at 50% brightness, and "bright red" means that the image is drawn with all of its green and blue components removed. But, a neat trick is to use the drawing option DRAWOP_BRIGHT, which makes 50% gray mean no shading, pink means intensified red, and white means doubled brightness, in other words DRAWOP_BRIGHT doubles the range of possible colors you can shade your image by letting you make it brighter as well as darker.

Here is an example that draws a ship image that is shaded transparent at the top-left, bright green at the top right, bright blue at the bottom-left, and totally black at the bottom-right:

GameX.SetDrawShading (ColorX( ColorX(0,0,0,0), ColorX(0,255,0), ColorX(0,0,255), ColorX(0,0,0) ));
GameX.DrawImage (&ship_img, x, y)

To save space, you could also change the above SetDrawShading call to the equivalent:
            GameX.SetDrawShading (ColorX( 0,0,0,0,  0,255,0,255,  0,0,255,255,  0,0,0,255 ));

(Note that you can store a ColorX object as a global or member variable if you don't want to keep creating it each frame.
Also, take advantage of the fact that you can perform arithmetic with ColorX's.)

Some uses of ColorX and image shading include the following:
- Drawing shapes of a certain color (see the next section of this documentation)
- Making a sprite fade out (draw it using a slowly decreasing alpha shading).
- Dynamic special effect colors (for instance, keep one white "fire" effect and shade it red for red flame, or blue for blue flame, etc.)
- Drawing a gradient background (call GameX.FillScreen with a gradient color, at the beginning of GameDraw)
- Dimming the screen (call GameX.FillScreen with a black but partially transparent color, at the end of GameDraw).
- Light source shading a sprite (make a gradient color with white-to-black shading generated sinusoidally toward a light source)
- 3D gouraud-shaded texture lighting effects (add lighting components to gradient color using polygon normals and vertex positions)

As you can see, you can implement some quite advanced and interesting features by taking advantage of the flexibility of the ColorX class, but even simple games with simple graphics can benefit from a little creative use of image shading.

8) Advanced Graphics Rendering in GameX

The previous four sections of this documentation tell you how to load, draw, shade, and create special effects with images, which is everything you need to know to create graphics for a standard 2D game. However, some games need to be able to do more than this, even many regular 2D games. What if you want to draw lines, rectangles, points or polygons with just colors or with image textures? What about drawing only selected parts of an image, creating "blur" effects, drawing text, or drawing in 3D? The answer is that GameX makes all of these things simple to do: just call the appropriate drawing functions (which are described here).

Drawing Shapes (In 2D):

Sometimes you will want to draw simple things that are not based on an image, such as a line or a rectangle. You can use GameX to draw points, lines, rectangles, and polygons, with the following functions:
(These are all compatible with GameX.SetDrawMode, so you can do special effects with them.)

GameX.DrawPoint (ColorX clr, float x, float y);
    Draws a simple dot of the given color at the given x,y coordinates.
    To set the dot's size, call GameX.SetDrawScale(float size_in_pixels) beforehand.
    To center the dot if it's larger than 1 pixel, use the DRAWOP_CENTERED draw option flag.

    Example: GameX.DrawPoint (ColorX(255,0,0), 10,20); // draws a red dot at (10,20) pixels from top-left of screen

GameX.DrawLine (ColorX clr, float x1,float y1,  float x2,float y2);
    Draws a line segment of the given color between the two given x,y coordinates.
    To set the line's width, call GameX.SetDrawScale(float width_in_pixels) beforehand.
    If clr is a gradient color, the top-left and top-right are applied to the (x2, y2) side of the line, the others to the (x1, y1) side.

GameX.DrawRect (ColorX clr, float xLeft, float yTop, float xRight, float yBottom);
    Draws a rectangle filled with the given color, bounded by the given x and y values.
    You can use SetDrawScale and SetDrawAngle in conjunction with this function.

GameX.DrawPolygon (ColorX clr, float x1,float y1,  float x2,float y2,  float x3,float y3,  float x4,float y4);
    Draws a quadrilateral polygon filled with the given color, with vertices at the given x,y coordinates.
    The coordinates must be given in a roughly "Z" shape.
    So, an example of drawing a green diamond-shaped polygon: GameX.DrawPolygon (ColorX(0,255,0), 0,0,  20,10,  10,20,  30,30)
    To draw a triangular polygon, repeat x3,y3 for x4,y4, like so: GameX.DrawPolygon (ColorX(0,255,0),  0,0,  20,10,  10,20,  10,20);


Mapping Images to Shapes (In 2D):

Often, a color is not enough, and you want to be able to texture-map an image across one of the above shapes.
(The following are all compatible with GameX.SetDrawMode and GameX.SetDrawShading)

To map an image to a point (a point-sprite):
GameX.DrawImage (ImageX* img, float x, float y)
    This has already been described several sections above this in "Drawing Images in GameX".

To map an image across a line (a line-sprite):
GameX.DrawLineImage (ImageX* img, float x1,float y1,  float x2,float y2,  [bool pixelUnitScale=false])
    Draws the image with its bottom at x1,y1, and its top at x2,y2.
    pixelUnitScale defaults to false. If false, the line's width is chosen to preserve the image's proportions, otherwise the width equals the scale amount in pixels.
    To alter the line's width, call GameX.SetDrawScale( ) beforehand.
    This function is useful for things like pendulums, lightning, borders, oriented sprites, or compound line-based special effects.

To map an image to a rectangle:
GameX.DrawTexturedRect (ImageX* img, float xLeft, float yTop, float xRight, float yBottom);
    You can use SetDrawScale and SetDrawAngle in conjunction with this function.
    If you use the DRAWOP_NOCULL flag, you can specify a flipped rectangle to flip the image.

To map an image to a polygon:
GameX.DrawTexturedPolygon (ImageX* img, float x1,float y1, float x2,float y2,  float x3,float y3,  float x4,float y4);
    Works the same as GameX.DrawPolygon, see above for details.

Drawing Text:

Text is very useful for games to be able to draw, even if all you need to draw is the score and the title. Currently, the best and fastest way to draw text is to draw it graphically using an alphabet image (see the GameX downloadable demos for example graphics and code you can use for this). However, GameX also provides simple text drawing functions (which are limited to size 12 Windows API font) for when you're just getting started and want to put some letters or numbers on the screen.

    GameX.DrawText (int x, int y, char* msg, [int r, int g, int b]); // (r,g,b) is optional and defaults to (255,255,255) white

Or, to make the text more legible if there's anything in the background, you can instead use:

    GameX.DrawOutlinedText (int x, int y, char* msg, [int r, int g, int b], [int ro, int go, int bo]); // (r,g,b) defaults to white, (ro,go,bo) defaults to black

Either way, the result is that you output a message string starting at the given (x,y) coordinates onscreen.

Unfortunately, drawing text in this way is extremely slow. And if you alternate between drawing text and drawing any other type of graphics, you will cause even more slowdown problems. This is why it is better to draw text made out of images, because it doesn't have this speed limitation, plus it will allow you to use different text sizes and rotation and drawing modes, etc.

In any case, here is an example of drawing a textual score (number of points) at the top-left corner of the screen:

char scoreString [64]; // allocate memory for a string that can be at most 64 digits
sprintf (scoreString, "%d", points); // fill the string with the number of points to draw
GameX.DrawOutlinedText(10, 10, scoreString); // draw the score at top-left of screen

 

Causing a Blur Effect:

Blurring can actually mean several things (motion-blur, radial-blur, position-blur, etc.), all of which are rather advanced effects for a game to perform in real-time.

To perform a position-blur effect on the screen (to make everything that was drawn earlier in this frame look unfocused), you can use the following functions:

GameX.BlurScreen (float amount)
    Blurs the entire screen by the given amount, amount being a float value between 0.0 and 1.0, where 1.0 blurs it all the way and 0.0 blurs it not at all.
    Only changes what has already been drawn. So, you could draw the graphics you want to blur, then use this function, then draw the graphics that you don't want to blur.

GameX.BlurRect (float amount, int xLeft, int yTop, int xRight, int yBottom)
    Same as BlurScreen, but only affects the given rectangular portion of the screen.

This effect is very slow. Some computers aren't even fast enough to perform this operation at a reasonable speed, in which case the blur is automatically skipped to avoid slowing the game to a crawl. Since this means there is a chance that the blur will be skipped when the game is played on certain computers, you should not rely on position blur frequently or to obscure information, but rather to create an aesthetically pleasing (but not strictly necessary) effect at certain parts of the game.

Advanced Info: Other types of blurring require a little more creativity to achieve, but they are still possible. To create a pseudo-motion-blur if your game consists mostly of objects against a background, you can just draw the background as mostly transparent (shaded with alpha value 32) and with the DRAWOP_NODITHER flag to avoid accumulated dithering artifacts. To create an actual motion-blur effect, you can create an image that's the same size as the game screen, and at the end of GameDraw, draw that image (with DrawTexturedRect) to the screen shaded with a high alpha value (such as 128, 160, or 192), then draw the screen itself back into the image (see below for details of how to do this). To create a radial blur effect, do the same thing as the motion-blur effect but also use SetDrawScale( ) with a scale somewhat greater than 1 when drawing the image to the screen, and you can optionally add rotation to make the blurring spiral out of the center. Needless to say, these effects can cause a substantial hit to the frame-rate, except for the pseudo-motion-blur which is relatively fast. To see an example of the radial blur effect in action, download ParticleDemoX, run it, and press the 5 key once after it starts going. It requires a substantially better computer than do almost all other GameX effects.


Advanced Draw States:

We have already covered how to set the Mode and Shading draw states with GameX.SetDrawMode( ) and GameX.SetDrawShading( ). We have also briefly mentioned how to use GameX.SetDrawScale( ) and GameX.SetDrawAngle( ). Here is the detailed explanation of these and other draw states:

Drawing State:

Tells GameX To:

Function Prototypes:

Mode

Draw the next thing in a special way. See "Special Effects with Drawing Modes" above for details.

GameX.SetDrawMode(DrawFlags mode)

Portion

Draw only the given rectangular part of the next image, instead of the entire image. This is useful because you can store multiple sprites in one image, and use this function to specify which sprite to draw out of it at a given time.

GameX.SetDrawPart (int x1, int y1, int x2, int y2)

Destination

Draw the next thing into the given destination image instead of to the screen. This is the only case where it is OK to use drawing functions from inside GameRun(). Note: Drawing into images is currently not hardware-accelerated.

GameX.SetDrawDestination (ImageX* dest)

Angle

Rotate the next thing drawn by the given angle, which is in degrees counter-clockwise.

GameX.SetDrawAngle (float angle)

Scale

Scale the next thing drawn by the given scaling factor. 2.0 means it's drawn twice as large as normal, 0.5 means half as large as normal. Negative scaling values result in the image not being drawn at all, unless you also set the DRAWOP_NOCULL draw flag.

GameX.SetDrawScale (float scale)

Same as above, but allows you to scale the width and height by separate scaling factors.

GameX.SetDrawScale (float scaleX, float scaleY)

Shading

Draw the image shaded with the given ColorX. See "Shading Images with the ColorX class" above for details.

GameX.SetDrawShading (ColorX color)

Shading Effect

Apply image shading in a different way. "effect" must be a non-combined image drawing mode, such as DRAW_ADD (which would cause any shading to be added to the image). The default value is DRAW_MULTIPLY, which means that image shading is normally done multiplicatively. This state is totally unrelated to SetDrawMode, although it uses some of the same constants.

GameX.SetDrawShadingEffect (DrawFlags effect)

Warp

Draw with advanced image warping / distortion / pinching. (1,1,1,1) is normal, >1 stretches out, <1 pinches in, at each corner. Only works on sprites/images/textures, and does not change the outline of the shape they are mapped to.

GameX.SetDrawWarp (float w0, float w1, float w2, float w3)

Translation

Draw the next thing offset by the given translation offsets which are in pixels, after any 3D projection. This is really only useful for certain special cases with the 3D drawing functions.

GameX.SetDrawTranslate (float transX, float transY)

Depth

Draw all following 2D graphics at a certain Z-depth until the depth is set again. Intended for drawing 2D objects in 3D scenes, or for automatic sorting of 2D scenes. "depth" of 0.0 means as close as possible, 10.0 means further away, etc.

GameX.SetDrawDepth (float depth)

Camera

Use the given CameraX for all following 3D projections until another camera is set. This mode must be set with a valid camera object before you use any 3D drawing functions. See "3D Graphics and the CameraX class" below for more details.

GameX.SetDrawCamera (CameraX* camera)

Keep in mind that not all of these affect all drawing functions. When you understand what a draw state does, it should be pretty obvious what functions it does or does not apply to. However, to avoid any possible confusion, here is a table that shows exactly which drawing functions are affected by which drawing states, for your reference:
(It's a very wide table, so it has been split into two parts for viewing.)

 

Draw
Point

Draw
Line

Draw
Rect

Draw
Polygon

Fill
Screen

Draw
Image

Draw
Line
Image

Draw
Textured
Rect

Draw
Textured
Polygon

Draw
Tiled

Mode

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Angle

Yes

No

Yes

Yes

No

Yes

Yes

Yes

Yes

Yes

Scale

Yes

Yes

Yes

Yes

No

Yes

Yes

Yes

Yes

Yes

Portion

No

No

No

No

No

Yes

Yes

Yes

Yes

Yes

Destination

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Shading

No?

No?

No?

No?

No?

Yes

Yes

Yes

Yes

Yes

Shading Effect

No

No

No

No

No

Yes

Yes

Yes

Yes

Yes

Warp

No

No

No

No

No

Yes

Yes

Yes

Yes

Yes

Translation

Yes

Yes

Yes

Yes

No

Yes

Yes

Yes

Yes

No

Depth

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Camera

No

No

No

No

No

No

No

No

No

No

 

 

Draw
Point
3D

Draw
Line
3D

Draw
Polygon
3D

Draw
Image
3D

Draw
Line
Image
3D

Draw
Textured
Polygon
3D

Clear
Screen

Blur
Rect, or
Blur
Screen

Draw
Text, or

Draw
Outlined
Text

Mode

Yes

Yes

Yes

Yes

Yes

Yes

No

No

No

Angle

Yes

No

No

Yes

Yes

No

No

No

No

Scale

Yes

Yes

No

Yes

Yes

No

No

No

No

Portion

No

No

No

Yes

Yes

Yes

No

No

No

Destination

Yes

Yes

Yes

Yes

Yes

Yes

Yes

Yes

No

Shading

No?

No?

No?

Yes

Yes

Yes

No

No

No

Shading Effect

No

No

No

Yes

Yes

Yes

No

No

No

Warp

No

No

No

Yes

Yes

Yes

No

No

No

Translation

Yes

Yes

Yes

Yes

Yes

Yes

No

No

No

Depth

No

No

No

No

No

No

Yes

No

No

Camera

Yes

Yes

Yes

Yes

Yes

Yes

No

No

No

Note that "No?" for Shading means that, while SetDrawShading has no effect, such functions take a ColorX object directly which basically means they are always shaded anyway.


9) 3D Graphics and the CameraX class

Beginning with GameX version 5, you can now draw 3-dimensional scenes comprised of polygons, or a combination of polygons and sprites. This is done in a way analogous to drawing 2-dimensional scenes, because GameX is primarily a 2D engine, which means two things:
- Drawing 3D graphics with GameX is easy and does not require any advanced knowledge of the mathematics or established methods of 3D graphics.
- 3D graphics in GameX are not as optimized or as flexible as a real/dedicated 3D engine would allow for.

Despite the limitations, it is easy to make 3D graphics in GameX look quite good as long as you limit them to a reasonable scope. See below on the issue of feasibility for details.

In GameX, 3D scenes are drawn in about the same way as 2D scenes, with the following differences:
- There is an extra, 3rd dimension (obviously). So the 3D drawing functions are just like the 2D ones, but take x, y, AND z.
- There is a camera which you can position in the 3D scene which determines how the scene becomes projected onto your 2D screen.
- To make things much easier, you can tell GameX to automatically buffer and sort the scene for you, so it does not matter what order you draw objects in.

Viewing the 3D Scene:

Before you can draw anything in 3D, you must decide on a viewpoint in 3D space. GameX provides the CameraX class for this purpose. You can think of a CameraX object as a "camera" which has a position in 3D space (where you're looking from) and a target location also in 3D space (where you're looking at or to). For example, to create an overhead view you could set your camera's "from" position to be over your scene, and set its "to" position to be on the ground, so that when you draw objects in the scene, it looks as if the player is up in the air looking down at the objects that are on the ground. Of course, you can move the camera during the game to allow the player to see things from different angles or locations. If the camera stays fixed at one location or angle throughout most of the game, it becomes more of a 2D game but with 3D rendering (which is perfectly okay and a good idea for some types of games; you can use 3D for a 2D game and treat the 3rd dimension as an optional element to give you more freedom should the need arise to use it).
Here is some sample code that creates a CameraX, sets it over the scene looking down, and does all the other set-up required to do 3D drawing:

CameraX cam;
float sky = 100.0;
float ground = 0.0;

void GameInit (void) {
    GameX.Initialize ("CamTest", VIDEO_16BIT, 800, 600);
   
cam.SetWindow(0, 0, 800, 600);
   
GameX.SetDrawCam(&cam);
}

void GameRun (void)
{
    cam.SetFromPosition(Vector3DF(0, 0, sky));
    cam.SetToPosition(Vector3DF(0, 0, ground));
}

void GameDraw (void)
{
    GameX.Begin3DScene( );
     ... {call functions to draw 3D polygons and/or sprites} ...
    GameX.End3DScene( );
}

// Create a CameraX object
// choose a height (z) value of 100 for the sky
// choose a height (z) value of 0 for the ground


// Initialize GameX
// Tells the camera where to let GameX draw (entire screen)
// Tells GameX to use this camera for drawing - important!




// Set the camera to be up in the sky...
// Looking down at the ground.




// Tell GameX we're about to draw a 3D scene
// (Draw some 3D stuff here)
// Tell GameX we're done drawing the 3D scene

You could also use cam.SetFromAngles( ) instead of cam.SetFromPosition( ) to set the "from" position using 2 angles and a distance, which would make it easy to have the camera spins around a scene or character, and zoom in and out. Look in the sample CamDemoX code for an example of this in action. Other useful camera functions include cam.SetFarPlane (float dist) which allows you to increase or decrease the maximum drawing distance, and cam.SetRollAngle (float angle) which lets you easily make the camera "roll" (for instance, turning a camera upside-down) while looking in the same direction.

Notice the call to the GameX.SetDrawCam( ) function, which you must call to tell GameX what camera to use for drawing, otherwise it will just draw the scene from some arbitrary default viewpoint. Make sure not to let the CameraX object you specify get deleted while GameX is using it (i.e. you should make the camera a global variable).

Note also the Begin3DScene and End3DScene functions in the above code. It is not necessary to use these functions, but they makes things much easier for you because they allow GameX to sort whatever you draw into the proper order, which is difficult (and sometimes impossible) to do properly on your own due to the nature of 3D polygon intersections. If you already know how to sort a scene (if it's simple and/or mostly uses DRAW_ADD), then don't tell call Begin3DScene/End3DScene because it takes time for GameX to sort things. In any case, remember that if you do begin a 3D scene, you must also remember to end the 3D scene later during that frame or GameX may never actually draw it. You can also begin and end multiple scenes in a frame, for instance you could keep 2 separate cameras and draw the scene twice (once for each camera) into separate halves of the screen (using cam.SetWindow( ) and GameX.SetView( )), to create a split-screen mode effect in a 3D game.

Drawing the 3D Scene:

Currently, GameX cannot load 3D models from file or automatically draw higher-level objects than primitives. You could write/use a custom loader to load in 3D polygon vertices and then loop through drawing those. However, as mentioned above, GameX is not well-suited for doing this. Unless your game has complicated 3D needs, you should instead just choose where to draw various things with some simple math in way similar to how 2D drawing often works.

Keep in mind that 3D drawing is not limited to polygons; in addition to 3D polygons (which may be texture-mapped and/or gouraud-shaded), you can draw sprites at 3D locations, or you can draw 3D lines (which may also be texture-mapped). You can even draw all of these types of things in 3D into the same scene, for instance, you could make a game with polygonal terrain, regular sprites standing on top of that terrain, and 3D lines used for special effects.

Instead of having separate x, y, and z variables, you should keep track of 3D positions using the Vector3DF class that GameX provides. You can create a 3D vector "on-the-fly" by just calling Vector3DF(x,y,z) with any float values x,y, and z, or you can create a vector, put it in a Vector3DF variable, and perform vector calculations (see below) on it until you're satisfied with the position it represents.

Remember that, since 3D drawing is an extension of 2D drawing in GameX, all of the previous information about 2D drawing applies to 3D drawing. For instance, you can still use SetDrawMode( ) for special effects, etc. Refer to the table in the previous section to see exactly which state setting functions apply.

Drawing Shapes (In 3D):

GameX.DrawPoint3D (ColorX clr, Vector3DF v);
    Draws a simple dot of the given color at the given vertex v (which contains x,y,z coordinates).
    To set the dot's size, call GameX.SetDrawScale(float size_in_world_units) beforehand.
    To center the dot if it's larger than 1 pixel, use the DRAWOP_CENTERED draw option flag.

    Example: GameX.DrawPoint3D (ColorX(255,0,0), Vector3DF(10,20,30)); // draws a red dot at (10,20,30) units from the origin

GameX.DrawLine3D (ColorX clr, Vector3DF v1, Vector3DF v2);
    Draws a line segment of the given color between the two given 3D vertices.
    To set the line's width, call GameX.SetDrawScale(float width_in_world_units) beforehand.
    If clr is a gradient color, the top-left and top-right are applied to the v2 side of the line, the other two to the v1 side.

GameX.DrawPolygon3D (ColorX clr, Vector3DF v1, Vector3DF v2, Vector3DF v3, Vector3DF v4);
    Draws a quadrilateral polygon filled with the given color, with vertices as given.
    The coordinates must be given in a roughly "Z" shape.
    The polygon is 1-sided, so if viewed form the wrong side to form a "backwards-Z", the polygon is culled and not drawn at all.
    To disable culling for this polygon to make it two-sided, you can use the DRAWOP_NOCULL flag.
    The coordinates should technically all lie in a plane, but it will still usually draw fine even if they don't.
    So, an example of drawing a green diamond-shaped polygon: GameX.DrawPolygon (ColorX(0,255,0), Vector3DF(0,0,0), Vector3DF(20,10,15),  Vector3DF(10,20,15),  Vector3DF(30,30,30))
    To draw a triangular polygon, repeat v3 for v4, like so: GameX.DrawPolygon (ColorX(0,255,0), Vector3DF(0,0,0), Vector3DF(20,10,15),  Vector3DF(10,20,15),  Vector3DF(10,20,15))


Mapping Images (Textures) to Shapes (In 3D):

To map an image to a point (a point-sprite):
GameX.DrawImage3D (ImageX* img, Vector3DF v, [bool worldUnitScale=true])
    Draws the given sprite image with bill-boarding positioned in the 3D scene at the given vertex v.
    worldUnitScale defaults to true. If true, the image is automatically made smaller as it gets further away; if false, the image is drawn at the size of the 2D sprite.
    To alter the size the image is drawn at, call GameX.SetDrawScale( ) beforehand. You may need to use a large value to make the sprite big enough to see.
    Use this function to draw 2D characters into 3D scenes, and to draw most 3D particle effects.

To map an image across a line (a line-sprite):
GameX.DrawLineImage3D (ImageX* img, Vector3DF v1, Vector3DF v2,  [bool worldUnitScale=false])
    Draws the image with its bottom at v1, and its top at v2, in 3D.
    worldUnitScale defaults to false. If false, the line's width is chosen to preserve the image's proportions, otherwise the width equals the scale amount in world units.
    To alter the line's width, call GameX.SetDrawScale( ) beforehand.
    This function is useful for things like pendulums, lightning, oriented sprites, or compound line-based 3D special effects.
    For instance, you could draw a circle textured to a line from the origin to each particle in a particle system, using DRAW_ADD and shading, for an impressive effect.

To map an image (texture) to a polygon:
GameX.DrawTexturedPolygon3D (ImageX* img, Vector3DF v1, Vector3DF v2, Vector3DF v3, Vector3DF v4);
    Works about the same as GameX.DrawPolygon3D, see above for details.
    Draws a texture-mapped polygon, good for piecing together landscapes or structures (or anything).
    You can use GameX.SetDrawShading to apply 3D lighting blended across the polygon's vertices.
    If you duplicate v4 to make a triangular texture-mapped polygon, a diagonal half of the texture will be ignored because textures are rectangular.
    The order that you give the vectors in determines the orientation of the texture. The top-left of the "Z" is where the top-left of the image goes.


More about CameraX:

You can do more with CameraX objects than simply tell GameX to use them for 3D projections. Here is the complete list of functions that CameraX gives that may be useful:

camera.SetToPosition (Vector3DF to);
    Sets the camera to look at the given position vector. This changes the camera's direction, but does not change its position.
    For this and the following functions, note that you can either set the position/other properties each frame, or you can set them just once if you don't want your camera to move.

camera.SetFromPosition (Vector3DF from);
    Sets the camera to be positioned at the given position vector.

camera.SetFromAngles (Vector3DF angs);
    Sets the camera to be positioned at a given x angle (rotation), y angle (pitch), and z distance (zoom) away from its current "To" position.
    To be used as an alternative to SetFromPosition, after calling SetToPosition. Great for making the camera follow or circle around something (or both).
    angs.x is the x rotation angle you want (in degrees), angs.y is the y rotation angle (in degrees), and angs.z is the distance from the target (in world units).
    The y rotation angle you give MUST be between -89.9 and +89.9 degrees, or you will get strange results.
    The x rotation angle, however, wraps around as you would expect and so it can be any degree value.
  
camera.SetRollAngle (float angle);
    Sets the camera to "roll" or "twist", i.e. rotate along the axis that it is facing.
    This function should be called before SetFromAngles or SetFromPosition is called.

camera.SetUpVector (Vector3DF up);
    Sets which way is "up". The default is positive Z, but if you want to make the coordinate system more like 2D,
    you can make negative Y "up" instead by calling camera.SetUpVector(Vector3DF(0,-1,0)).

camera.SetWindow (int x1, int y1, int x2, int y2);
    Sets the rectangular region for this camera to project to, and also sets where 3D graphics will be clipped to.

camera.GetWindow (int&x1, int&y1, int&x2, int&y2);
    Fills the variables you give with the window that this camera is currently set to.

camera.Project (Vector3DF v, float &x, float &y, float &z);
    This is called automatically by the 3D drawing functions, but you can call it to manually project a 3D point.
    Given the 3D vector v, this function fills x and y with the 2D screen position that projects to, and z with the relative z-depth.

camera.GetDirVector( )
    Returns a Vector3DF of length 1 that points in the same direction that the camera is facing (pointing "into" the screen).
    This is different depending on which direction the camera is facing.

camera.GetSideVector( )
    Returns a Vector3DF of length 1 that points "right" from the point of view of the camera (points exactly toward the right side of the screen).
    This is different depending on which direction the camera is facing.
    If the camera is rolling, however, the roll is not taken into account.

camera.GetPixelsPerUnit( );
    Returns a float value that tells you the number of pixels that one world unit is currently equivalent to.

camera.From( );
    Returns a Vector3DF that is the current location of the camera.

camera.To( )
    Returns a Vector3DF that is where the camera is currently looking at.


More about Vector3DF:

    It is possible to just use the Vector3DF as a holder of x, y, and z coordinates for use with the 3D drawing functions, but the Vector3DF class also allows you to perform some very useful mathematical operations easily and efficiently.

vector.Cross (const Vector3DF v);
    Returns a Vector3DF that is the cross product between this vector and the vector v.
    This function also changes this vector to be equal to the resulting cross product, although it does not change the other vector v.
    This function is very useful, essential for things such as 3D lighting, and so is highly optimized (this applies to the following functions also).

vector.Dot (const Vector3DF v);
    Returns a float value that is the dot product of this vector with the vector v.
    This function does not change either vector, unlike Cross( ).

vector.Normalize( );
    Normalizes this vector to have a length of 1.0 while still facing in the same direction.

vector.Length( );
    Returns a float value that is the Pythagorean length of this vector.

vector.Dist (const Vector3DF v);
    Returns a float value that is the Pythagorean distance between this vector and the vector v.

vector.LengthSq( );
    Returns a float value that is the square of the Pythagorean length of this vector.
    This function takes less time to compute than Length because it doesn't have to take a square root.

vector.DistSq (const Vector3DF v);
    Returns a float value that is the square of the Pythagorean distance between this vector and the vector v.
    This function takes less time to compute than Dist because it doesn't have to take a square root.


Also, Vector3DF overloads many operators, so you can add and subtract Vector3DF objects simply by using the + and - operators, or you can scale a Vector3DF by multiplying or dividing it by a floating point value using the * or / operators, or you can assign the values of one Vector3DF to another by simply using the = assignment operator. Other operators that work are +=, -=, *=, and /=. If you use * or *= to multiply two Vector3DFs together, it is assumed to mean Dot Product multiplication, so you must call the Cross function if you want to do a cross product instead.

As a quick example, here is a good use of the += operator:
    position += velocity;     // position and velocity are each Vector3DF objects
This will advance the position vector by a velocity vector, a nice shortcut for doing: position.x += velocity.x; position.y += velocity.y; position.z += velocity.z;
Usually, you would actually make a class that has objects with position and velocity, and once in GameRun for each object, do something like:
    myChar.pos += myChar.vel;
Also, to add a drag to the character's speed so it gradually slows down, you could also then call:
    myChar.vel *= drag;     // drag is a float, usually between 0.8 and 0.99

Finally, there are other types of vectors besides 3DF ones. All of the vector types currently supported are: Vector2DI, Vector2DF, Vector3DI, Vector3DF, and Vector4DF. The number means the number of dimensions the vector has, and the letter at the end means the type (Int or Float) used to represent each coordinate. (A 2D vector only has x and y, a 3D vector has x, y, and z, and a 4D vector has x, y, z, and w coordinates.) All of these vector types support all of the above functions, so for instance you may find Vector2DF very useful in 2D games for making your code simpler by calculating things like lengths, distances, normalizations, additions, multiplications, etc. for you.


The Issue of Visibility:

When you draw something in 2D, it's pretty clear whether it will end up on the screen or not, but in 3D, it all depends on the camera position and angle. If you try drawing something in 3D (such as a 3D polygon) and you don't see anything draw, it could be due to one (or more) of the following reasons:

- You forgot to set the camera with GameX.SetDrawCam.
- The camera is looking at the wrong side of the polygon. If you want to change which side of a polygon is visible, you have to change the order that you give the vectors in the draw function.

- The camera is looking away from where the polygon is, i.e. the polygon is behind you.

- The polygon is too far to the side or above or below the camera.
- The camera is too far away (in which case try increasing the far plane distance of the camera).
- If drawing a point or sprite, the scale of your scene may be so large that you need to scale up your points/sprites by a factor of 10 or 100 just to see them.

- If only half of a polygon draws, then you forgot to specify the vectors in a "Z" shape, in which case switch around vectors 3 and 4 to fix it.

 

For the above reasons, it is often easier to begin with something that works and displays visible results, such as CamDemoX, and modify or build off of that code for your 3D drawing.

 

There is currently no easy or efficient way to test beforehand if the image will be visible before drawing it, so you should just draw all the images/polygons in your scene and let GameX handle skipping drawing the ones that are not visible at the time. This applies to 2D as well, although in both 2D and 3D, don't draw anything that you know for a fact can't be visible at the moment, since it still takes some processing time for GameX to figure out that it isn't visible to avoid drawing it. (Manually testing for 3D visibility is practical if you use it to eliminate a bunch of drawing calls based on a test of a single point's visibility, which you can do by calling camera.Project and comparing the resulting x and y with the game screen's boundary coordinates, offset by a certain amount because of the approximation of using a point.)

 

The Issue of Feasibility:


You may be tempted to make a fully three-dimensional game using GameX's 3D drawing functions. Not only does it take a lot more creative talent to make a 3D game than you might realize, but GameX's current support of 3D graphics is not advanced or optimized enough for a 3D game that is not relatively simple to be feasible. This is not to discourage you from making a 3D game, but to advise you to keep the graphics simple. Do not attempt to draw vast landscapes populated by characters composed of thousands of polygons each. In fact, if you intend your game to run smoothly on current-generation computers, a practical limit is between 200 and 2000 total polygons/sprites/lines drawn per frame. (This is obviously an area of GameX that is of top priority for future improvement.)

 

Thus, at the moment, here are the 3 situations in which GameX's 3D support can be put to practical use:

- 2D games: Believe it or not, a pinch of 3D graphics are easy to add into a 2D game to make it look a lot better.

- Semi-3D games: For instance, a game with some 3D terrain and 2D sprite characters standing on it.
- Simple 3D games: Fully-3D games that can maintain a very low polygon count.

 

Particle Effects:

 

If for nothing else, you are advised to use the 3D support to draw particle effects, because particle effects in particular can be made to look extremely impressive with minimal effort. Just make one "particle" image, such as a blurry white circle on a black background, then draw it lots of times at slightly varying positions using a special drawing mode such as DRAW_ADD, and you have the basic groundwork for good particle effects. This works in 2D also, but is easier to make look good in 3D because you have an extra dimension to move the particles in. See the ParticleDemoX demo for a nice example of particle effects in 3D.


10) Painting in and Filtering Images


Painting or drawing in ImageX objects is useful if you wish to modify an ImageX object while a game or program is running, or if you wish to generate an image programmatically. For instance, you could load in a character image from file, copy that image into another ImageX, then use a built-in image filter to switch its colors around so you can use each image for drawing characters with different colors. Or, you could dynamically generate a wide variety of possible images from scratch for use in your game, which could not be done simply by loading in images. In addition to modifying the image, you can use the image-painting related functions to read the color values from the image, which lets you do things like loading level data stored inside pictures. You can also combine reading and writing in a way of your choice to apply complex custom filters to your images before you draw them, and you can even save edited GameX images as image files, meaning it's actually possible to write a GameX "game" which is really a complete image painting and processing application program (which, no doubt, would be used to draw and save images for use in another game). Admittedly, most games don't really need to save images, but regardless, being able to edit, read, and filter images is extremely useful for a wide variety of features that many games would (and frequently do) implement, such as color swapping, active motion blur, and level map loading. (Storing your levels as pictures is not appropriate for many types of games, however; see (22) "Loading and Saving Files in GameX" below.)

There are three ways of drawing into images:

1: Using ImageX's built-in functions or filters to change the image
2: Using GameX's pixel getting and setting functions to change the image with pixel-level control
3: Using GameX's image and shape rendering functions to draw into the image

These are listed in slowest-to-fastest order, but all three of these ways of drawing into images are pretty slow because none of them are accelerated by hardware. Because of this, if you draw into images, you should try to only do it once or occasionally, not every frame. (Yes, motion and radial blur normally rely on drawing into an image every frame, but that is precisely why these effects are so slow.)

Creating Images

Before you draw into an image, you have to either load it from file (which has already been covered, see "Loading Images" of section 11 above), or you can create a blank image instead without needing to load in an image file. You can create a blank image (all pixel values start at 0) with the following method:

image.Create(int xs, int ys, [bool alpha=false]) // alpha is optional

image (the calling object) is an ImageX that you have already defined but have not yet loaded anything into.
xs
and ys tell GameX how big to make the image, i.e. the width and height of the image in pixels. This is necessary only when creating an image, because when you load an image, GameX gets the image size automatically from the file it loads.
alpha is for setting whether the image is to be created with an alpha (transparency) layer. Pass in "true" to create the image with alpha. See the "Loading Images" section above for more about what this means.

Once you have an image, either loaded from file or created from scratch, you can begin drawing into it:

Modifying the ImageX at the Pixel Level:

Here are the basic ImageX functions you can use for getting or setting pixels:

image.SetPixel (int x, int y, int r, int g, int b, [int a]) // r, g, b, a are from 0 to 255
            Sets one pixel of the image to the given RGB color values. If the image has an alpha channel, you can specify an alpha value as well (if you don't, the alpha is assumed to be 255).

image.GetPixel (int x, int y, int &r, int &g, int &b, [int &a]) // gives you r, g, b, a from 0 to 255
            Reads in the RGB color value from a pixel of the image, and copies these values into the variables you pass in. If the image has an alpha channel, you can also give a variable that takes the alpha value if you want to know what it is.

image.GetWidth( )
image.GetHeight( )
            Returns the width or height of the image in pixels (as an integer). If you want to use SetPixel and GetPixel to modify an entire image, you need to iterate through the entire width and height of the image to change the pixel at each location.

It should be noted that SetPixel and GetPixel and fairly slow, and that there is another way to manipulate the pixels of an image which is somewhat faster, but less friendly:

Basically, just call GameX.AccessPixels(&image) immediately before you start modifying pixels, replace image.SetPixel(…) with GameX.DrawPixel(…), replace image.GetPixel(…) with GameX.ReadPixel(…), and call GameX.EndPixelAccess( ) as soon as you are done modifying the pixels of "image". You can only access the pixels of one image at a time in this way, though, and you must not use any other image or drawing functions or do anything else while the image's pixels are being accessed.

You can also pass in the VIEWPORT constant instead of &image when you call AccessPixels if you want to draw directly to (or read from) the screen in this way, but frankly it is almost without exception a bad idea to draw individual pixels directly to the screen, because whatever you draw only stays there for one frame and it takes such a long time to draw it.

Warning: Unlike SetPixel and GetPixel and the rest of GameX’s functions, DrawPixel and ReadPixel are not automatically clipped. Thus, your game will probably crash if you accidentally draw outside of the image boundaries with these functions. SetPixel( ) and GetPixel( ) are much safer to use if you think there's any chance you'll try to draw anything out of the image's boundaries.

Applying Basic Filters to an ImageX:

The ImageX class has a few methods that you can use to apply standard modifications to the entire image, such as making it darker or changing its colors around. Note that you can easily make your own custom image filters like these by using the basic pixel getting and setting methods above, although these filters make use of the AccessPixels trick described above for extra speed. (In the following, "image" is an ImageX object, of course.)

image.SetFilterRect (int xLeft, int yTop, int xRight, int yBottom)
            Tells the following filters to only filter this part of the image instead of the entire image. Use image.ResetFilterRect( ) to go back to filtering the whole image.

image.Fill (int x, int y, int r, int g, int b, [int a]) // r, g, b, a are from 0 to 255
            Fills the image with the given RGB color (one pixel at a time). If the image has an alpha channel, you can specify an alpha value to set each pixel to as well, otherwise the alpha is assumed to be 255. This function always overwrites the entire (filter rect of the) image, including alpha/transparency.

image.Invert( )
            Inverts the RGB color values of the image, so black becomes white, blue becomes yellow, gray becomes gray, etc. If the image has an alpha channel, the alpha at each pixel stays the same as it was before.

image.ChangeBrightness (int brightness, float contrast) // brightness from -255 to 255 (0 is normal), contrast is a factor (1.0 is normal)
            Changes the brightness and contrast of the image. Can be used to intensify the image, or make it faded, etc. For instance, image.ChangeBrightness(0,2.0f) will double the image's contrast, while image.ChangeBrightness(-64,0.5f) will make the image darker and reduce its contrast. Note that negative contrast results in image color inversion. This filter will not change the image's alpha channel.

image.ChangeBrightnesses (int brightness_r, int brightness_g, int brightness_b, int brightness_a, // from -255 to 255, 0 is normal
                                          float contrast_r, float contrast_g, float contrast_b, float contrast_a) // factors, 1.0 is normal (no change)
            Changes the brightness and contrast of the image like the previous function, but gives individual control over each color channel, including the alpha channel, and so can do more things such as increase only the red contrast, subtract green from the image, sharpen the alpha channel of the image, invert an individual color channel, etc. If the image has no alpha channel, you must still supply values for brightness_a and contrast_a although these values will be ignored.

image.ConvertToGrayscale( )
            Converts the image to grayscale (red=green=blue) while maintaining perceived luminosity. This filter will never change the image's alpha channel.

image.ChangeSaturation (float saturation) // saturation is a factor, 1.0 means no change
            Changes the saturation of the image's colors. Saturation basically means "lack of grayness". For instance, calling image.ChangeSaturation(2.0f) makes the image's colors stand out more, whereas image.ChangeSaturation(0.5f) makes the image go halfway to grayscale, and image.ChangeSaturation(0.0f) does exactly the same thing as calling image.ConvertToGrayscale( ).This filter will never change the image's alpha channel.

image.ChangeSaturations (float saturation_r, float saturation_g, float saturation_b) // factors, 1.0 means no change
            Changes the saturation of the image's colors as above, except it merges or divides the color channels using a separate factor for each channel. You can use this to do things like intensify the red hues of an image or get rid of the blue from an image while keeping the image at approximately the same overall brightness. This filter will never change the image's alpha channel.

image.SetChannel (int channel, int value) // value is out of 255, channel is 0 for red, 1 for green, 2 for blue, 3 for alpha
            Sets all of one channel (red, green, blue, or alpha) of the image to one value. For instance, image.SetChannel(0,255) sets all of the image's red channel to full brightness, and image.SetChannel(3,128) sets the entire alpha channel to 50% transparency if the image has an alpha channel.

image.AddNoise (int noise) // noise is a value from 0 to 255, 0 means no change
            Adds random noise to the image's pixels. Useful if you want to make an image's colors appear less uniform (rougher/grainier). This filter will never change the image's alpha channel. If you specify a negative noise value, that means to only let the noise make the image darker (always negative), otherwise the noise can be positive or negative.

image.AddNoise (int noise_r, int noise_g, int noise_b, [int noise_a]) // values from 0 to 255, 0 means no change
            Adds noise to the image's pixels, with separate noise intensities for each color channel. This filter will change the image's alpha channel if a nonzero fourth argument (noise_a) is given.

image.GaussianBlur (float radius) // radius is blur radius in pixels, 0.0 means no blur, 1.5 means some blur, etc.
            Blurs the image smoothly via a Gaussian blur of all of the image's channels, including alpha if it has an alpha channel. The operation takes longer as the blur radius increases and as the image size increases. If the operation would take too long, the blur radius is reduced to prevent the filter from ever taking more than a second or two to process, which is more likely to happen on larger images.

image.GaussianBlur (float red_radius, float green_radius, float blue_radius, [float alpha_radius]) // alpha_radius is optional
            Blurs the image via a Gaussian blur of each of the image's channels, with a possibly separate blur radius for each channel. If alpha_radius is not specified, then the alpha channel of the image is not modified. The time taken by this operation increases with the maximum of the blur radii given, and also with the image size, but is limited as with the above function.

image.SwapColors (ColorSwapType type)
            Rotates or swaps the color values of the image. This can be used for a basic "color swapping" effect on images, which is used by many games to reduce required artwork. This filter will not change the image's alpha channel. The results of the filter depend on what colors are initially in the image; color-swapping a grayscale image will do nothing.
            type is a variable of type ColorSwapType, which is really just an int intended to hold one of the GameX constants specific to this function, which are:

Type Constant:

Effect:

COLOR_SWAP_SAME

Reds->Reds, Greens->Greens, Blues->Blues

COLOR_SWAP_ROTATE120

Reds->Greens, Greens->Blues, Blues->Reds

COLOR_SWAP_ROTATE240

Reds->Blues, Greens->Reds, Blues->Greens

COLOR_SWAP_REDGREEN

Reds <-> Greens

COLOR_SWAP_REDBLUE

Blues <-> Reds

COLOR_SWAP_GREENBLUE

Greens <-> Blues

COLOR_SWAP_BA

ROYGBIV -> RVIBGYO

COLOR_SWAP_NBA

ROYGBIV -> GBIVROY

COLOR_SWAP_BNA

ROYGBIV -> VROYGBI

COLOR_SWAP_NBNA

ROYGBIV -> BGYORVI

COLOR_SWAP_ANB

ROYGBIV -> VIBGYOR

COLOR_SWAP_NAB

ROYGBIV -> GYORVIB

COLOR_SWAP_NANB

ROYGBIV -> BIVROYG

COLOR_SWAP_BB

ROYGBIV -> RRRRVIB

COLOR_SWAP_NBB

ROYGBIV -> GGGGYIV

COLOR_SWAP_BNB

ROYGBIV -> VVVVIYG

COLOR_SWAP_NBNB

ROYGBIV -> BBBBVIR

COLOR_SWAP_AA

ROYGBIV -> RVIBIVR

COLOR_SWAP_NAA

ROYGBIV -> GYIVIYG

COLOR_SWAP_ANA

ROYGBIV -> VIYGYIV

COLOR_SWAP_NANA

ROYGBIV -> BIVRVIB

Of course, ROYGBIV means Red, Orange, Yellow, Green, Blue, Indigo, Violet, in that order. As used in the table above, each of these letters refers to a general range of colors that are similar to the given color. The words "Red", "Green", and "Blue", on the other hand, refer specifically to a color channel of the image.

            That's all you need to know to use SwapColors, just make a call like: shipImage.SwapColors (COLOR_SWAP_REDBLUE) and the colors will be changed, ready to be drawn as an image which has the same shape and brightness as the original, but different coloring. This is different than shading a drawing of an image with SetDrawShading, because this actually changes what color the image is, whereas SetDrawShading simply tints the image and does not change its pixels.

image.ChangeColors(ColorSetType a_settype, ColorSetType b_settype, [float a_set_mult, float b_set_mult, float a_app_alpha, float b_app_alpha, ColorSetCondition a_acond, ColorSetCondition a_bcond, ColorSetCondition b_acond, ColorSetCondition b_bcond]) // parameters in brackets are optional

Lets you change the colors of an image in just about any way imaginable. However, SwapColors is simpler to use, so it is recommended you use that instead if you are a beginner programmer. If all of the parameters scare you, keep in mind that you are not required to give most of them, just the first two. Anyway: a_settype is what to set the red/green range to, b_settype is what to set the blue/yellow range to. a_app_alpha and b_app_alpha are values between 0.0 and 1.0 for how much to set the given color ranges; it does not affect the image's alpha, just how strongly the color change operation is applied. a_acond and a_bcond are the conditions that must apply to the source a and b in order for the application to the a range to proceed, and b_acond and b_bcond are the conditions that must apply to the source a and b in order for the application to the b range to proceed. See the GameX header file "gamex-defines.hpp" for the list of ColorSetTypes and ColorSetConditions. This function can do things such as target a specific range of colors, like a character's hair or a character's shirt, and changing the color from blonde to green, or green to blue, blue to gold, etc.

Remember that the above image filters permanently change the image that's in memory. However, none of these image filters (or anything else GameX normally does) can actually change the image files on your hard drive.

Rendering into Images

Another useful way to modify images is to treat the image like the game screen and draw shapes, other images, or whatever else you want right into the image, using the regular GameX drawing functions. This method can achieve some effects easily that would be difficult or time-consuming to do by drawing one pixel at a time.

To render into the image, you simply precede any regular drawing function with the call:
GameX.SetDrawDestination(&image);
Where "image" is the image that you want to draw into. When you next call a function like DrawImage or DrawRect, GameX will draw into "image" instead of the screen. After drawing something, GameX resets to drawing to the screen, so you have to call SetDrawDestination once for each graphic you render into an image.

Note that rendering into images is significantly slower than rendering normally to the screen, although often faster than setting the image's pixels individually.

One very useful thing to be able to do when rendering images is to render the game screen itself into an image. To do this, you first call SetDrawDestination to target the image, then you can call GameX.DrawImage (VIEWPORT,0,0) to copy the viewport into the image. This is assuming the image is the same size as the viewport; if not, you can use GameX.DrawTexturedRect to specify a specific rectangle of the image to copy into, and/or you can use GameX.SetDrawPart to specify a specific rectangle of the game screen to copy out of. Effects made possible by rendering from the screen to an image include: Motion blur, radial blur, rotational fadeout transitions, and feedback mirror effects. It can also be used for caching of the image screen for use as a background or other element in another part of the game (for instance, copying the game screen as a static background for the menu screen to improve efficiency).

Painting into Images Example:

Here is a example which manipulates generated images using all three of the above general ways of modifying images. This example paints a circle into a new image A by drawing individual pixels, then uses the DrawImage function to copy image A into another image B (although ImageX::CopyTo could also be used for this step), and finally changes the colors of image B by applying a filter to it. (After doing this in GameInit, it simply draws the two images next to each other each frame.)

#define GAMEX_MAIN
#pragma comment (lib, "gamex.lib")
#include "gamex.hpp"

ImageX img_a, img_b;

void GameInit (void) {
    GameX.Initialize ("ImgPaintTest", VIDEO_16BIT, 800, 600);

   
img_a.Create (100, 100);
    img_b.Create (100, 100); 

   
for (float ang = 0 ; ang < 360 ; ang ++) {
         int x = 50+(cos(ang*DEGtoRAD)*40.0);
         int y = 50+(sin(ang*DEGtoRAD)*40.0);
         img_a.SetPixel(x, y, 255, 0, 0);
    }

    GameX.SetDrawDestination(&img_b);
    GameX.DrawImage(&img_a, 0,0);
    img_b.ChangeColors(COLOR_SWAP_ROTATE120);
}

void GameRun (void) {}

void GameDraw (void)
{
     GameX.ClearScreen( );
     GameX.DrawImage (&img_a, 0, 0);
     GameX.DrawImage (&img_b, 150, 0);
}

// Required defines, etc.



// Make images A and B


// Initialize GameX


// Construct a blank 100x100 image
// Construct another blank 100x100 image

// Draw a circle outline into image A:
// For each degree out of 360, draw a pixel
// 50 is the center value, 40.0 is the circle radius
// Circle color is (255, 0, 0) - bright red.



// Now copy image A into image B
// And switch around image B's colors


// Do nothing here; it's just a test demo that draws two images



// Clear display (draw black background)
// Draw image A at top left of window (should be a red circle)
// Draw image B next to it (should be a green circle).

This example is a complete GameX program that really compiles and works, so feel free to try it out.


11) Loading and Playing Sounds - The SoundX class

GameX provides sound capability as well as graphics, via a SoundX class which stores playable WAV sound clips for your games. Sounds are not anywhere near as necessary as graphics are for most games, but if you don't add sound and/or music to your game, it will seem unfinished no matter what else your game does.

Like images, sounds are usually preloaded in the GameInit( ) function, although they are played in GameRun( ) instead of GameDraw( ) because you can't draw sounds. Here is an example.

SoundX kick, punch;
int status = 0;

void GameInit (void)
{
    GameX.Initialize ("SoundTest", VIDEO_16BIT, 800, 600);
    kick.Load ("kick.wav");
    punch.Load ("punch.wav");
}

void GameRun (void)
{
     ... {check input here and set status accordingly} ...

    if (status==1) GameX.PlaySound (&kick, PLAY_REWIND)
    if (status==2) GameX.PlaySound (&punch, PLAY_REWIND)
}

void GameDraw (void)
{
     ... {draw graphics here} ...
}

// Create a sound object for 'kick' and another for 'punch'
// Status of the 'player' or some other character

// Required void GameInit (void) function

// Initialize GameX
// Load the 'kick' sound into memory.
// Load the 'punch' sound into memory.


// Required GameRun function

// At appropriate time, play the 'kick' sound.
// At appropriate time, play the 'punch' sound.



// Required GameDraw function

// Graphics drawing section. (Do not try to
// start sounds inside the graphics section.)

Unlike images, which should be drawn each frame for continuous animation, you will usually begin playing sound effects at certain times, such as when your character gets hit, and GameX will take care of finishing playing the sound over multiple frames without you needing to keep track of the sound's progress. Sounds are played asynchronously, meaning your game can keep going while any number of sounds are playing; the game will never pause and wait for a sound to finish unless you tell it to.

As illustrated by the above code, to load a sound from a WAV file you just make a call like so: sound.Load ("mysound.wav"). The sound file you load can be a .wav file of any standard PCM format. Please use 8-bit or 16-bit WAVs. 4-bit WAVs are not a valid PCM format, and 24- or 32-bit WAVs are a waste of memory.

Once you have loaded a sound, it is ready to play at any time. GameX provides several functions which let you control the playing of sounds. These are as follows:

GameX.PlaySound (SoundX* snd, SoundPlayMode mode)

Starts playing the sound object 'snd'. The second parameter 'mode' determines how the sound will be played. The options for 'mode' are:

Sound Playing Mode:

Resulting effect:

PLAY_CONTINUE

If it's already playing, let the sound continue playing from where it is.

PLAY_REWIND

Start the sound over if it's already playing.

PLAY_LOOP

Set the sound to automatically rewind when it finishes.

PLAY_NOTIFLESSVOL

If the sound is currently playing, don't start over unless it's as loud or louder now.

(The most common value to use for 'mode' is PLAY_REWIND.)

Using the above PlaySound function to play sounds, the sound always plays at maximum volume, normal panning, and normal frequency. If you want to change these too, you can call the function like this:

GameX.PlaySound (SoundX* snd, SoundPlayMode mode, float volume, float pan, float frequency)

This is the same as the simpler version above, however, it also provides volume, pan, and frequency control for the sound.
volume is in the range of 0 .0 to 1.0, with 1 being maximum volume and 0 being total silence.
pan is in the range of -1.0 to 1.0 where -1 plays the sound entirely out of the left speaker, 1 plays the sound entirely out of the right speaker, and 0 plays the sound the same from both speakers. If outside of this -1 to 1 range, then the volume starts getting scaled down also.
frequency is a factor in the range of 0.5 to 2.0, with 0.5 as half pitch and double length, and 2.0 as double pitch and half length, and 1.0 meaning normal frequency. This basically acts as a multiple of the frequency the sound was recorded at.

Using these parameters, you can create complex effects even with very simple sound clips. For instance, you can play a sound in pseudo-3D by making the volume lower if a sound source is further away, adjusting the pan depending on which side of the player or the screen the sound source is on, and even adjusting the pitch depending on the relative velocity of the sound source (for a Doppler effect). You don't have to do anything that complicated, of course; you can also use these parameters if you just want to make a certain sound effect a little quieter or a little lower pitched. In any case, there are a few more functions besides PlaySound that you may find useful as well:

GameX.StopSound (SoundX* snd)

Immediately stops playing of the sound 'snd'. If the sound has already stopped, then this function does nothing.

GameX.RewindSound (SoundX* snd)

Instructs GameX to immediately rewind the sound 'snd' back to the beginning of the clip. This can be useful if you wish a sound to normally play continuously, while occasionally rewinding the sound clip based on some variable or change in the program or game. It basically has the same effect as playing the sound again with the PLAY_REWIND flag.

GameX.IsSoundPlaying (SoundX* snd)

Returns true if 'snd' is still playing or looping, false otherwise.

Using the above functions, multiple sounds can be started simultaneously, and will be automatically mixed in real-time by GameX. Although GameX will take care of the details, it is a good idea to keep in mind the fact that starting and stopping sounds of different lengths will cause mixing of sounds to occur even if they are not started simultaneously. For example, if you have a very long 'rain' sound 10 seconds long, and a brief 'thunder' sound 1/2 second long, it is possible to start the rain sound, wait 3 seconds, then start playing thunder. When the thunder sound starts, both rain and thunder will be present for 1/2 second, then the rain sound will continue until the full 10 second length of the clip is finished.

NOTE: If you want a sound to play over itself (if you want two instances of the same sound playing at once), then you need to load the sound twice, into two separate SoundX objects, for the sounds to play independently.


12) Music and the MusicX class

GameX also has a MusicX class which you can use to hold MP3, WMA, or Standard MIDI music files in the same way that SoundX objects hold WAV sound files.

MIDI music is useful for many games because MIDI files are extremely small, thus you can have lots of background music that can be as long as you want and it will barely take up any memory at all. The drawback to MIDI is that it restricts music to using a certain set of instruments, so MIDI music can't contain custom instruments, sound effects, or vocals. So, you may choose to use MP3 or WMA music in your game, formats similar to each other which are capable of holding compressed digital audio without such limitations, at the expense of taking longer to load and using a lot more memory than MIDI.

Here is some sample code that loads a MIDI file and immediately begins playing it:

MusicX music;
 
void GameInit (void)
{
    GameX.Initialize ("MusicTest", VIDEO_16BIT, 800, 600);
    music.Load ("musicfile.mid");
    GameX.PlayMusic (&music);
}

void GameRun (void) { ... }
void GameDraw (void) { ... }

// Create a MusicX object

// Required void GameInit (void) function

// Initialize GameX
// Load a music file into memory.
// Start playing it immediately


// Required GameRun function (not shown)
// Required GameDraw function (not shown)

(Loading an MP3 is exactly the same; just change music.Load ("musicfile.mid") to music.Load ("musicfile.mp3"), assuming you actually have an MP3 file named "musicfile.mp3" in the main directory of your game. The same goes for loading WMA files, just use the ".wma" filename extension.)

The above sample code will cause the music to load and begin playing as soon as GameX is done initializing, and the music will continue looping forever while the game is going unless you later tell the music to stop, or begin playing a different song. You can play sound effects while the music is going, but you cannot mix two different music files together; GameX can only play one music file at a time. (In most cases you would not want to play multiple music files at the same time anyway, so this is not too much of a limitation.)

The PlayMusic function can take more parameters than is shown in the above example, if you want greater control over how your music files are played. Here is the full function:

GameX.PlayMusic (MusicX* music, [int times, float volume, float fade_in_seconds, float tempo, float pitch]);

      This function starts playing some music, after stopping any other music that was playing. The parameters are:
music is a pointer to the MusicX object you want to play (must be already loaded).
      (The following parameters are optional):
times is the number of times to play the music before stopping; 0 means to never stop looping it, which is the default.
volume is what volume to play the song at, 0.0 for silent, 1.0 for full volume (default), 1.27 for maximally amplified volume.
      (The following parameters are optional and have no effect on MP3 or WMA music, they only work with MIDI):
fade_in_seconds is how long to "fade in" the music from zero volume so the song doesn't start up too abruptly.
tempo determines the spacing between notes. 0.5 makes the song play at half speed, 2.0 for double speed, etc.
pitch determines the pitch modulation of each note. 0.5 makes the song play at half pitch, 2.0 for double pitch.

Once you start playing some music, there are several more functions you can use to monitor and control its playback:

GameX.IsMusicPlaying(MusicX * music);
    Returns true if the music is currently playing or looping.

GameX.StopMusic (MusicX * music, [float seconds]); // seconds is optional
    Stops the music from playing, after smoothly fading out the volume for a certain number of seconds if given. (Stop is abrupt unless song is MIDI.)

GameX.PauseMusic (void);
    Pauses the music and remembers its location.

GameX.ResumeMusic (void);
    Resumes a paused song, if nothing else music-related was done after it was paused.
GameX.VolumeFadeMusic(MusicX * music, float volume_factor, [float seconds]); // seconds is optional
    Fades the music volume smoothly up or down to the given volume factor, over a certain number of seconds if given. (Transition is abrupt unless song is MIDI.)

GameX.PitchBendMusic(MusicX * music, float pitch_factor, [float seconds]); // seconds is optional
    Bends the pitch of the music smoothly to a given pitch factor, over a certain number of seconds if given. (Only works with MIDI.)

GameX.SetMusicTempo(float tempo_factor);
    Changes the music's tempo of play. (Only works with MIDI.)



13) Keyboard Input in GameX

A vital part of any game is the input, without which the game cannot be interactive.
Naturally, GameX provides functions to easily access user input for your game. Like all GameX function, these can be used at any point in your program (or within your classes), by accessing the global GameX object. Input can be checked for just about anywhere within your game loop, but the best place to do it is at the beginning of GameRun( ). (It is usually not a good idea to check for input inside of GameDraw( ).) Keep in mind that all of the input functions are extremely fast, so you will almost certainly never reduce your game's performance by checking for input.

The Keyboard Input functions are:

Checking Whether a Key is Down:

bool IsKeyDown (KeyID k)

IsKeyDown tells you whether or not a specific key is currently being held down. You pass a KeyID constant to this function which represents a key on the keyboard, and this function will return true if the given key is down, or false if the given key is not down. Multiple keys can be pressed at the same time, so you can check several different keys at different points in your code as needed. A KeyID is a GameX-defined constant that represents a physical key on the keyboard, such as KEY_SPACE or KEY_LEFT or KEY_A or KEY_ESCAPE or KEY_ENTER. These (and many more) key constants are defined in gamex-defines.hpp (there are too many keys on the keyboard to list them all here), but usually you won't need to look them up since they all have common-sense names starting with "KEY_" and ending with the name of the keyboard key.
KeyIDs are not combinable; to check if the user is holding A and B at the same time you would have to do:
    if(GameX.IsKeyDown(KEY_A) || GameX.IsKeyDown(KEY_B))
     { /* insert code here to react to keys A and B being pressed or held simultaneously */ }

Here is a short example of using IsKeyDown to detect multiple keypresses.

ImageX player_img;
int x = 50, y = 50;

void GameInit (void) {... }

void GameRun (void)
{
     if (GameX.IsKeyDown(KEY_UP)) y -= 10;
     if (GameX.IsKeyDown(KEY_DOWN)) y += 10;
     if (GameX.IsKeyDown(KEY_LEFT)) x -= 10;
     if (GameX.IsKeyDown(KEY_RIGHT)) x += 10;
}

void GameDraw (void)
{
        GameX.ClearScreen( );
        GameX.DrawImage (&player_img, x, y);
}

// An image for the 'player'
// Initial position of the character

// Required initialization function (not shown)

// Required main loop.

// If key up is pressed, move up.
// If key down is pressed, move down.
// If key left is pressed, move left.
// If key right is pressed, move right.




// Draw black background
// Draw 'player' at the current position

Since each key down check is independent, it is possible for the user to hold 'up' and 'left' simultaneously, causing the character to move diagonally to the upper left because both x and y will change in the same time step.


bool IsShiftDown (void)
bool IsAltDown (void)
bool IsCtrlDown (void)
bool IsWinDown (void)

These functions tell you whether a certain modifier key is being held down. These are useful because, for instance, most keyboards have two Shift keys, and you probably don't care which shift key is down, in which case calling IsShiftDown( ) will return true if either or both Shift keys are down, and false otherwise. Note that your game can make use of the Windows key just like any other key, although it is not common practice to do so.


bool IsCapsLockOn (void)
bool IsNumLockOn (void)
bool IsScrollLockOn (void)

These functions tell you the state of the "-Lock" keys like Caps Lock. This is useful because, if you just do IsKeyDown(KEY_CAPSLOCK), it will only return true if the user is physically holding the caps lock key down (which is almost never the intent), whereas if you do IsCapsLockOn( ) it will return true only if Caps Lock is actually activated and the little Caps Lock light is lit on the keyboard (which is what you normally want to do). The states of the Num Lock and Scroll Lock can be checked in the same way with the corresponding IsNumLockOn( ) and IsScrollLockOn( ) functions.

Checking Whether a Key was Just Pressed:

bool GetKeyPress (KeyID k)

This function is similar to IsKeyDown( ), except it only returns true if the given key was just pressed. This is very useful when you want to know if the user pressed a key but you only want to respond to that key once. For example, suppose the user is in a menu in your game, and they hit whatever key you decide is the Cancel key. If you checked for this with IsKeyDown, you're likely to respond to their keypress many times in a row which will cause the game to rapidly cancel out of many layers of the menu, which they did not intend to do with a single press of the cancel key. You could keep track of what buttons used to be down so as to only respond once, but GameX already does this for you, so in a case like this, you should check with the GetKeyPress key. By doing so, your game will respond to their keypress exactly one time, and it will not respond to it again until they let go of the key and press it again. Even if the user accidentally holds down the key for longer than they meant to, it will register only once with this method. You can combine the use of this function with IsKeyDown or other Is…Down functions to check if the user pressed one key while another key was down, for example:
    if (GameX.IsCtrlDown( ) && GameX.GetKeyPress (KEY_Q))
        GameX.Quit( );
This would cause the game to quit when the user holds Control and presses Q, in other words, when the user hits Ctrl-Q. If the user instead holds Q and then presses Ctrl, in this case it would not do anything because the Ctrl key would not be down at the instant that Q was pressed. You could replace IsCtrlDown( ) with IsKeyDown(…) to check for the user holding a different key when they pressed Q, and of course you could replace KEY_Q with any other key constant.
Keep in mind that calling GetKeyPress does not prevent you from calling it or other key input functions on the same or other keys, even at the same game instant.
 
bool AnyKeyPress (void);

This function exists to save you the trouble of calling GetKeyPress on every single key on the keyboard if you just want to see if the user pressed a key. The only time you would want to do this is if your game ever asks the user to "Press any key" to continue. Note that sometimes the "Press any key" instruction is implicit, for instance you might automatically pause the game at the end of a mission and wait for the user to press any key to continue, without needing to actually tell them to press anything. Here, "any key" is defined as any normal non-modifier key on the main keyboard or number pad.

Getting Buffered Keyboard Input:

char GetBufferedKeyPress (void)

GetBufferedKeyPress is used to return buffered keyboard input from the user. Keys are returned by GetBufferedKeyPress one at-a-time in the order that they were pressed. This is useful only for getting sequentially entered data such as high score names, filenames, chat messages or typed commands.
The 'char' returned is the ASCII character code for the key that was pressed. For instance, if the user pressed the A key, then GetBufferedKeyPress would return the character 'a'. This method automatically takes modifier keys into account, too, so it would actually return either 'a' or 'A' depending on whether the shift key is down or caps lock is on. This means that most characters that GetBufferedKeyPress return are exactly what the user meant to type, so you can usually immediately add it to a string of what the user has typed so far.
The exception is with certain special keys, for instance, when the user hits the Backspace key, they mean to delete a character of what they last typed. Backspace and certain other keys have their own constant defined by GameX so you don't have to guess what their ASCII code is:

Besides individual characters typed like 'a' for lowercase A, '1' for the number 1, ' ' for the spacebar, etc., GetBufferedKeyPress( ) may return the following constants:
            BUFFERED_KEY_NOTHING           // means no key was pressed
            BUFFERED_KEY_BACKSPACE     // the Backspace key
            BUFFERED_KEY_ENTER                // the Enter key
            BUFFERED_KEY_TAB                     // the Tab key
            BUFFERED_KEY_ESCAPE              // the Esc key

Here is some example code that takes all of this into account to let the user type a message:

char typedString [64];
int typedNum = 0;
 
void GameInit (void)
{
GameX.Initialize("BufferedKeyDemo",VIDEO_16BIT,640,480);
}

void GameRun (void)
{
    char key = GameX.GetBufferedKeyPress( );
    if (key != BUFFERED_KEY_NOTHING) {
        if (key == BUFFERED_KEY_BACKSPACE) {
            if (typedNum > 0) typedNum--;
            typedString [typedNum] = (char) 0;
        } else {
            typedString [typedNum] = key;
            if (typedNum < 64) typedNum++;
        }
    }
}

void GameDraw (void)
{
        GameX.ClearScreen( );
        GameX.DrawText (10, 10, typedString);
}

// A string of at most 64 typed characters
// How many characters are typed so far

// Required initialization function




// Required main loop.

// Get a pressed key, if there is one
// If something was pressed,
// If it was the backspace key,
// Delete a character
// (Sets to the Null character)
// Otherwise, if it wasn't the backspace key,
// Add what was typed to the string
// And increase the number of chars so far




// Required draw function

// Draw black background
// Draw what the user has typed so far

Normally you would also check for and respond to the Enter and Escape keys, for instance Escape might clear out the whole string by setting typedNum = 0, and Enter might cause everything in the string to register as permanently entered.


void ClearKeyBuffer (void)

ClearKeyBuffer is used to simply empty out the key buffer that GetBufferedKeyPress uses. Call this right before asking the user to type something, otherwise, all the buttons they pressed before that you haven't responded to from the buffer will all show up in the key buffer, for example if the player is moving around with the WASD keys and then you ask them to type a password, if you don't call ClearKeyBuffer when you ask for the password, the password box will fill up with garbage like WAAWDSWDWSAWWW before they even try to type anything into it. The above example code doesn't use this function only because it starts checking for buffered input as soon as it starts up, and it constantly processes new input as it is entered, but if your game switches from not processing buffered input to processing it, then you should clear the key buffer once each time the switch happens.

 

14) Mouse Input in GameX

Mouse input, like all other aspects of GameX, is also provided via the GameX object. Mouse input functions give information about the mouse position, its rate of change, and the status of the mouse buttons. The Mouse functions are as follows:

Checking the Mouse Buttons:

bool IsMouseDown (MouseButtonID b);

Returns the condition of the given mouse button (true if down, false if up).
The MouseButtonIDs you can use are MOUSE_LEFT, MOUSE_RIGHT or MOUSE_MIDDLE.
For example:     if (GameX.IsMouseDown (MOUSE_LEFT)) { ... fire lasers}
Keep in mind that not all mice have a middle button to press, and some (uncommon) don’t even have a right button either.

bool GetMouseClick (MouseButtonID b);

Same as IsMouseDown, but only returns true ONCE for a given check of a mouse button during one click.
This function is analogous to GetKeyPress (see above) but for the mouse.
 For example:     if (GameX. GetMouseClick (MOUSE_RIGHT)) { ... switch weapons}

bool GetMouseDoubleClick (MouseButtonID b);

Returns true if the given mouse button was just double-clicked on.

Checking for Mouse Movement or Position:

float GetMouseDX( );

Returns the rate of change (velocity) of the X coordinate of the mouse. Right is positive.

float GetMouseDY( );

Returns the rate of change (velocity) of the Y coordinate of the mouse. Down is positive.

float GetMouseDZ( );

Returns the rate of change of the mouse's scroll wheel. In (up) is positive. Note that not all mice have scroll wheels.

int GetMouseX( );

Returns the X coordinate of the mouse's current onscreen position. (In pixels right from the top left of the game window)

int GetMouseY( );

Returns the Y coordinate of the mouse's current onscreen position. (In pixels down from the top left of the game window)

Mouse coordinates are in pixels measured from the top left of the game window. Thus the maximum values returned by GetMouseX( ) and GetMouseY( ) are the maximum display coordinates specified in the GameX.Initialize (…) function when the game starts. For example: GameX.Initialize ("test", VIDEO_16BIT, 800, 400) will create a game window with 800 x 400 pixels, and the range of values returned by GetMouseX( ) and GetMouseY will be 0 to 800-1 and 0 to 400-1 respectively. If the game is not running in full-screen mode, however, the user may move the mouse outside of the game window, in which case GetMouseX and GetMouseY may return values outside of this range.

void SetMousePosition(int x, int y);

This one is more like "mouse output" than mouse input. It moves the onscreen (Windows) mouse cursor to a new location. This can be useful for restricting the cursor's range or allowing custom cursor behaviour (for instance, keyboard-activated cursor movement).

15) Loading and Saving Files in GameX

Most games (once they reach a certain stage in their production) require that some form of custom data be loaded. The most obvious example of this is level data. Suppose you're making a platform-based sidescroller game. Unless you want the entire game to take place in the same empty room, you will want to have different levels with different obstacles, platforms, powerups, enemies, etc. to make the gameplay more interesting. Technically, there is no need to load this data from file; you could initialize a giant array with values that represent parts of the level data, and just use the array. However, if you do this, you'll have to recompile every time you change the level data, and if you start to add lots of levels, that's a lot of values all being stored in your game's code, and all taking up space in your program's global memory even when it's not being used.

The solution is to save your levels as separate files, and load them into your game as they're needed. Such files can be as simple as a text file with a block of numbers that represent the color of that part of the level, or as complicated as you want or need them to be. They don't even need to be level files; you could store a list of magic spells to file, for instance, or a list of physical constants, or a sequence of commands, or anything at all. And when it starts becoming too complicated to type all the data into the file by hand, you can easily add code to your game to let you change the files intuitively from inside the game, so you get instant visual feedback and don't even have to look at the files to make or change the levels. The earlier you anticipate the eventual need you will have for a level editor in your game, the better such a feature is likely to turn out. Just remember to make it activated by a keypress code or disable it when you're done, so the end-user doesn't accidentally start editing your levels while trying to play the game.

However, this is not really a GameX issue; almost all programs must load some kind of data from file, whatever they do and whatever they run on. Since you are using C++, you should use the built-in features of standard C or C++ file reading functions (fopen( ), fread( ), fscanf( ), etc.) to read and write files from your game. Or: GameX also has a File class which it uses internally for loading data, and which you may choose to use for loading and saving your own data (refer to gamex-file.hpp for the list of functions it provides you). Remember that GameX provides automatic support for loading standard formats of images, sounds, and music, and also support for saving image files, so you do not need to worry about doing these yourself beyond simply calling the Load functions of the appropriate class (ImageX, SoundX, or MusicX) and telling GameX where to find the file.

 

16) Reserved Controls

GameX reserves certain keys and key combinations. When programming a game's input, it may be useful to know what these are. Also, for general use when playing any GameX game or debugging your own, it is nice to know what these reserved keypresses actually do.

Exiting the game:

Alt-F4  (hold either Alt key, then while holding it, press the F4 function key)
- Exits the game. (Also can be used to exit any other Windows program, if you didn't know already.)
- Cannot be disabled; this combination always exits the game.

Ctrl-Q  (hold either Ctrl key, then while holding it, press the Q key)
- Exits the game.
- Cannot be disabled.

Esc  (press the Escape key)
- Exits the game.
- Can be disabled by initializing the game with the RUN_USEESCAPEKEY flag, in which case this key is no longer reserved by GameX itself and may serve another purpose within the game as decided is appropriate by the game's creators.

(When exiting via any of the above three methods, GameX will ask whether you really want to quit, and continue the game if you choose "No". "Yes" is selected by default, so you can choose it by pressing the space bar, but you can also disable the prompt altogether with the RUN_NOCONFIRMQUIT flag.)

Switching the screen mode:

Alt-Enter  (hold either Alt key, then while holding it, press the Enter key)
- Toggles the screen mode between the "full-screen" and "windowed" modes.
- May take a short while to switch modes; be patient when using this.
- Can be disabled by initializing the game with the RUN_NOALTENTERTOGGLE flag (not generally recommended).

Taking a screenshot:

Prnt Scrn  (press the Print Screen button on your keyboard)
- Copies the game's viewport directly to the clipboard, where it can be pasted as an image into other programs.
- As an added convenience, also saves the viewport to an image file called "screenshot.bmp" in the game's main directory.
- Screen mode does not affect the resulting screenshot.
- Cannot be disabled.

Pausing the game:

Alt-Tab  (hold either Alt key, then while holding it, press the Tab key)
- Pauses and switches out of the game without exiting it.
- Cannot be disabled.

Minimize  (click on the Minimize button of the game's window)
- Pauses and minimizes the game without exiting it.
- Does not work when the game is in full-screen mode.
- Cannot be disabled.

Moving/Resizing the game:

You can move, resize, and maximize the window of the game like you can with the window of any normal application.
- Does not work when the game is in full-screen mode.
- The game is paused while its window is in the process of being moved or resized.
- Resizing and maximizing can be disabled by initializing the game with the VIDEO_NORESIZE flag (not generally recommended).

 

17) Things to Remember! (Problems? Look here first!)

If you have any trouble programming with GameX, here are several important things to remember:


If you have problems getting a GameX project to compile, link, or start up:

- You must have GameInit( ) and GameRun( ) and GameDraw( ) functions all in your main code file which #defines GAMEX_MAIN in order for your game code to compile with GameX.
- GameX.Initialize( ) must be the first thing called inside GameInit( ). Otherwise, GameX will generate an error.
- Make sure GameX is linked properly, and that your main .cpp file begins with:    #pragma comment (lib, "gamex.lib")    or, alternatively, you can add gamex.lib in the Project -> Settings -> Link for your game project.
- If you get strange linker errors, you may need to install the DirectX SDK and/or tell your compiler where it is.
- If your compiler says it can't find something, and you know you have that file, that means you have to tell your compiler where it is by going to Tools -> Options -> Directories and adding its location under the appropriate section there. Just because you can see the file in a window doesn't necessarily mean your compiler is smart enough to find it on its own. On the other hand, if you don't know if you have the file, do a file search on your computer for it, and if it really is missing, then download the missing component.
- If your game compiles in Debug mode but not Release, or vice versa, you probably set something in the Settings window and accidentally applied it only to the Debug or only to the Release target, when you should have applied it to All Configurations, in which case you will have to reapply the changes you made as necessary.
- If your compiler gives lots of warnings, you may want to turn the warning level down in the Settings window.

If you have problems loading images or sounds:

- TIFF images must be saved in RGB color format, without LZW compression, and with IBM byte order (using Photoshop, preferably)
- BMP images must NOT be saved in R5G6B5 format (use the standard X1R5G5B5 instead).
- WAV files must be saved without any compression (this is the default for most programs), and they cannot be 4-bit (use 8-bit or 16-bit instead).
- MIDI files (.mid or .midi) must be saved using the standard midi format. It must be precisely Standard MIDI or GameX won't play it.

If your GameX game takes a long time to start up whenever you run it:

- Full-screen mode takes longer to enter than windowed mode, so if you plan on starting and exiting your game many times when testing it, start it up in windowed mode each time.
- If your game Initializes GameX with VIDEO_16BIT, keep your monitor in 16-bit mode while working on the game, that way the monitor won't have to keep switching each time you start or exit your game. Likewise, if your game uses VIDEO_32BIT instead (which NOT recommended, by the way), then keep your monitor in 32-bit mode.
- If you load or process a lot of things in GameInit( ), it is normal that doing so will cause your game to take longer to start up. Make sure you aren't loading/processing things that are unnecessary, however.

If nothing happens when you tell GameX to draw:

- Make absolutely sure that the drawing code is being called (directly or indirectly) inside GameDraw( ).
- Make sure to Load your ImageX objects before drawing them.
- For images you Create, remember to copy/load/draw something into them before trying to draw them to the screen, otherwise you'll just draw a blank image.
- If you're drawing in 3D, make sure the CameraX passed to GameX.SetDrawCam( ) is positioned properly
- If 3D sprites aren't showing up, you may be drawing them too small for your world size -- try using SetDrawScale( ) with a large scale like 500.
- If 3D polygons aren't showing up, remember that all polygons are one-sided which means they are invisible if you look at them from the wrong side, and also remember that polygon vertices should always be listed in a Z shape. The way the Z is flipped determines which side is visible and which isn't. To force GameX to draw a polygon as two-sided, use GameX.SetDrawMode(DRAWOP_NOCULL), but don't use this for all polygons or performance may suffer.

If the game runs strangely or poorly:

- Make sure to only update your game's state in GameRun( ) and only draw that state in GameDraw( ), or else GameX's automatic timing code will not function properly.
- If the game run poorly on your computer, either your drawing code is too complicated and draws too many things for your computer to keep up, or your computer and/or video card are outdated. Make sure your computer meets the requirements and recommendations listed above.
- Or, there is a chance that you have loaded too much into memory or are leaking memory, in which case your computer has to shift lots of RAM around, which takes time and causes performance to suffer while it's happening. You should be memory-efficient in the way you use images; if a level has 200 identical enemies, don't load a separate image for each one! And if you allocate anything with the "new" operator, you must de-allocate it later with the "delete" operator or it becomes a memory leak, which also affects performance.

If the game crashes or freezes:

- If problems arise ONLY in Release mode and not in Debug mode, see the topic below which is specifically about this problem.
- If the game freezes, then you almost certainly have an infinite loop somewhere in your code. If your game freezes when it is in full-screen mode and you have trouble getting out of it, try hitting Alt-Tab, then (if you're running it from VC++ or .NET) hit Shift-F5 (several times if necessary) to stop execution. Or better yet, don't run your game in full-screen mode until your game is mostly bug-free.
- If GameX seems to crash, it is probably due to an oversight in your code which may or may not interact with GameX. Look out for out-of-bounds or buffer overwrite errors in particular. Also, if you pass GameX an uninitialized pointer to an ImageX, it will cause a crash.
- If you get an unexplained memory write error when drawing pixels, it may be because you are accidentally drawing out of bounds with the DrawPixel function. For speed reasons, this function (and only this function) does not do boundary error checking, you have to make sure it's in-bounds yourself.
- Whenever GameX encounters an error, it makes a log of it in the "debug.txt" file located in the same directory as the game executable. Should GameX crash, look in the debug.txt file (scroll to the bottom) and it may tell you what went wrong.

If you switch your game build to "Release" mode, and suddenly things go wrong that worked fine in "Debug" mode:

- Resist the temptation to just keep using Debug mode because it works, because it also performs a lot worse.
- A quick fix that is usually acceptable is to disable individual compiler optimizations until you find the one or two that cause the problem, and leave them disabled because they likely weren't helping your game run better anyway; the optimizations are not the primary reason that Release mode runs better, so it's OK to disable some if they are "causing" a problem.
- If that doesn't work (or maybe even if it does), it means you are depending on the default values of some variables, or you are writing to out-of-bound memory, somewhere in your code. Usually the culprit is an array that you define but don't explicitly loop through and set its values to something, or a variable belonging to a class that you forget to initialize in the class's constructor, or an uninitialized variable in a struct. The reason these errors may appear when you switch to Release mode is that variables start out with different values in Debug mode than they do in Release mode, and you may have accidentally relied on some of these values (which is especially easy to do with the "bool" data type). Also, Debug mode pads the memory a bit which can make reading/writing to nonsense memory locations sometimes not cause an error until the padding is removed at the switch to Release mode.


18) GameX Performance

This is a continuation and brief summary of the earlier section, "About Game Speed and Frame Rate", with more of a focus toward the performance of any given GameX game.

As of version 5, the performance of a GameX game is more comparable to the performance of a game programmed directly in DirectX or OpenGL. This does not apply to full-3D games past a certain complexity, because GameX is not specialized to be a 3D engine and is instead focused on being flexible and easy to use for both 2D and 3D graphics.

GameX contains automatic time management code which manages the game speed and frame rate of the games it runs. Basically, it skips a few frames if the game is going too slowly, and it delays in tiny amounts between each frame if the game is going too quickly, so that the game runs at the same speed regardless of how complicated it is. You can set this speed yourself when you call GameX.Initialize, and you can change it later with GameX.SetGameSpeed.

The frame rate is managed automatically to be the maximum it can possibly be at the moment without altering the game's actual speed. When one refers to the "performance" of a game, they usually mean the game's frame rate, i.e. the number of times per second that the screen is visually updated. This number is the FPS (frames per second) of the game, and the higher it is, the better. If this number is much below 30, the game will appear to play "choppily." If this number is 60, the game appears to play quite smoothly. Once the FPS reaches 60, though, the benefit of going higher than 60 is extremely minimal, because the human eye can barely tell the difference past that point.

In most cases, GameX games will run at exactly 60 FPS, or higher if the monitor supports it. However, this rate can become lower due to several factors.
- The most important factor in determining the frame rate of a game is the complexity of the game's GameDraw( ) function, specifically, the number and size of the images and other graphics that the game draws. Your game's performance will suffer if you try to draw too many sprites and polygons every frame. One way to look at it is this: 60 FPS means GameX only has at most one 60th of a second (that's 16.67 milliseconds) to draw everything in GameDraw each time it is called. Thus, if your game tries to draw so many things at once that GameDraw takes longer than 16.67 milliseconds to finish, then it becomes impossible to maintain the maximum frame rate.
- Another extremely important factor is the speed of the computer you are running the game on and its graphics card, because these affect the speed of each individual thing you draw. GameX's drawing features rely on DirectX and your computer's support for the features of Direct3D, so if your computer is too outdated to play DirectX games at a decent frame rate, it will also be too outdated to play GameX games at a decent frame rate, except for very simple games. On the other hand, if your computer is top-of-the-line, it will be able to play just about any GameX game at a perfect frame rate. Performance depends heavily on your processor speed and quality of your graphics card, in addition to the game's graphical complexity.
- If you set your game speed to lower than the current monitor's refresh rate, whatever speed value you choose becomes the maximum FPS your game can run at on that monitor. This is because updating the screen faster than you update your game would be pointless.

It's important to note that, because of the time management code that GameX uses, a GameX game is not specialized to any specific computer, but rather it adapts to best use the available resources of whatever computer the game is run on. A GameX game is able to run on all computers that meet the minimum requirements of GameX, but the more complicated a game is, the worse it will perform on slower computers, so keep this in mind if you want people with slower computers than yours to be able to run your game well.

Although the drawing functions you use determine (in large part) the performance of a game, it is meaningless to discuss the amount of time that individual drawing functions take because it varies so widely between computers with different capabilities. However, there are some general guidelines to give you an idea of how long a function will take, and the less time your GameDraw function spends on drawing functions, the better the performance of your game in general.

- If you are running the Debug instead of Release build of your game, or if you have any debugging or profiling options enabled in your compiler project settings, then all drawing functions will draw a lot slower, and in fact everything else your game does will also be more time-inefficient. Thus it is very important to test your game in both Debug and Release mode (to make sure they both work) and to use the Release build for presentations/finished products, and Debug only when you are actually working on the game.
- When drawing images or other graphics, the more pixels you are changing at once, the more time it takes. Even more important, though, is the number of things that you draw. It is much faster to draw one medium-sized image than it is to draw twenty smaller images that make up the same thing. This is because every call to a drawing function takes some extra time for GameX to set up (this extra time is often called the "overhead" of calling the function), and this overhead is incurred no matter how big or small the thing is that you are drawing. But you should also avoid drawing extremely huge images (> 512x512), for the different reason that some video cards have trouble handling that many pixels at once.
- Drawing the background is often a major bottleneck, because if you tile an image that is too small, that means drawing the image lots of times, especially if the background is rotated. Remember that the number of times an image is drawn is more important than the number of total pixels you end up drawing, so make sure that you draw background images that are not too small or scaled down too much.
- Blurring the screen (with BlurScreen or BlurRect) is a very slow operation, and so is drawing text with DrawText or DrawOutlinedText, so try not to use these too often. (If you must use these functions, keep in mind that they are faster if you "batch" them together instead of alternating them with other drawing functions)
- The advanced features of GameX are mostly the same as far as performance is concerned. Except on very old computers, drawing an image with an alpha layer is only a little slower than drawing an image without an alpha layer, and (likewise) drawing an image additively or with another special mode is only a bit slower than drawing it normally. Applying shading and transparency, even blended across separate corners, does little to decrease performance, and things like dithering, filtering, inverting, rotating, and mirroring take no time at all.
- Drawing in 3D is slightly slower than drawing in 2D, because there are more calculations involved when in 3D, especially if you tell GameX to Z-Buffer/sort your 3D scene. The speed hit is acceptable considering how much easier the auto-sorting makes it for you to draw in 3D, unless you know for a fact or can easily calculate how to draw your scene in back-to-front order. Either way, any given 3D game will still perform about as well as a 2D game of comparable complexity, but don't get too ambitious and start making vast or detailed landscapes or 3D models with high polygon counts, since GameX can't handle that sort of complexity yet.
- When drawing in 3D, keep in mind that textures loaded with alpha/transparency draw a little bit slower than other textures, and anything you draw with transparent shading or a special Draw Mode (like DRAW_ADD) will also draw a little slower. Don't let this limit what you do with your graphics, but keep it in mind when loading textures, setting up 3D scenes, etc.
- It is possible for something unrelated to drawing to slow down the game, but much less likely. Drawing operations are (by nature) far more costly than most ordinary calculations.