| |
|
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
| |