The GMMachine Object
Here are the basic properties and methods of the GMMachine. They are presented here in a list for quick reference, but you should start with the basics, beginning right after these links. In all function definitions, parameters listed between brackets [ ] are optional.
Special Notes about GraphicsMagician.h and Filenames
cin and cout | Filenames and directory paths | Path
Basic Functions, Text Input and Output
Start
| GetKeypress
/ getch / get | getline
| << ,
>> , and modifiers
TextPosition
| Home | SetTextHome
| ChangeFont
| TextColor
ClearScreen
Drawing Functions
Using RGB
Colors | Pre-defined Color
Values
SetPixel | GetPixel
| Rectangle
| Line
| Circle
| Arc | PieSlice
| Ellipse | TriFill
Screen-Related Functions
GetScreenWidth
/ GetScreenHeight | GetTargetWidth/GetTargetHeight
DrawOn/DrawToFrontBuffer/DrawToBackBuffer
| DrawBatch/Show
GetTarget/GetFrontBuffer/GetBackBuffer
| SaveScreen
Windows Loop, Input Devices
Active | Mouse
| Mouse Buttons
CheckKeys
| KeyDelay | Keys array
Delay | Milliseconds
Sound Functions
PlayWave / StopWave |
CloseWave | WavePlaying
PlayMIDI
| PauseMIDI / ResumeMIDI
| ReplayMIDI
Animation Functions
Flip / FlipTimed | SetFrameRate | PlayWhileDelay
Debugging
Sample Programs
Hello |
Text commands |
Drawing commands |
Background Bitmap
(needs winter.zip)
Loop with key and mouse input |
Drawing with the mouse |
Animation with screen flipping
Standard C++?
cout and cin do not exist in Windows applications. But GMMachine has been written to emulate these objects, so you CAN do things like:
Machine << "What is your name?"; Machine >> variable;
To make it appear like standard C++, the GraphicsMagician.h file defines the words cin and cout to be Machine. This lets you type:
cout << "What is your name?"; cin >> variable;
just as if you were using standard C++.
Filenames
All functions that receive filenames in GMMachine and its related objects assume that the file is in the same directory as your executable code. When working in Visual C++, that will be the Debug or Release directory inside your project directory. You may create subdirectories inside the executable directory and put your bitmaps and sounds there also. You may also override the default directory by giving a filename with a full drive and directory path, but that is generally a poor idea because it reduces portability. All image files will also work as resources.
This is a pointer to a character string containing the drive and directory of your program executable file. The last character in this string is always a backslash. You can use this string for reading and writing data files in the application directory, wherever it may be.
Basic functions
Before getting bogged down with any details of the Start function, see the sample Hello program
Here is the full prototype of the Start function:
void Machine.Start(
[int flags=gmWINDOWED, unsigned int width=800, unsigned int height=600,
char* title=0, int keyout=VK_ESCAPE]);
All of the listed parameters are optional (in gray, shown between brackets []) .
The possible values for the first parameter are gmFULLSCREEN, gmMOUSE, gmSINGLEPRECISION, and gmDOUBLEBUFFER. These choices can be combined by adding with the plus operator (+) or using the pipe operator (|) in a bitwise or operation. For example, you could use gmMOUSE+gmSINGLEPRECISION or gmMOUSE|gmSINGLEPRECISION.
Use gmFULLSCREEN if you want to use DirectX fullscreen mode, where your application takes over the entire screen. The default starts your application in a window.
If you use the default windowed mode and you want to use the mouse for input, set the first parameter to gmMOUSE. Because DirectInput takes full control of the mouse, it defaults to "off" when running your application in a window. If you activate the mouse with gmMOUSE, it will only be useful within your application window). In fullscreen mode the mouse is always set to "on" since there are no other visible applications that would need it.
An advanced option for the flags parameter is gmDOUBLEBUFFER. This will speed up animation if you use Flip instead of FlipTimed, but the results may vary with different computers.
Another advanced option is gmSINGLEPRECISION. By default Graphics Magician maintains the standard precisions of the data types float and double. However DirectX has a setting that causes ALL floating point operations to be performed as float, for speed. If you want to speed up your application and if you can live with 7-digit precision for both float and double, use the gmSINGLEPRECISION flag value.
width and height let you specify the screen or window width and height in pixels. The defaults are 800 by 600, but in fullscreen mode other common screen resolutions usually work, such as 640 by 480, 1024 by 768, and 1280 by 1024. In windowed mode you can create any size window that fits on the screen.
title is a string that will appear in the title bar of a windowed application. If you omit this parameter the default is "Graphics Magician".
keyout lets you specify a different key to exit the program. The default is the ESCAPE key. This uses Microsoft's Virtual Key codes (which are different than ASCII and DirectKey codes). Using a 0 (zero) here causes the GMMachine to have no exit key. If you do this, it is your responsibility to provide a way to get to the end of your program to exit.
Some properties of interest to advanced programmers are hWindow, hInstance, bActive, and KeyOut, which are the handle to your application window, the handle to your app's instance, the boolean state that tells whether your app is currently the active window, and the key value that is used for exiting the application..
Basic Text Input and Output
The following functions are all those that you need to be able to start writing standard C++ programs with the Graphics Magician. There's much more you can do, of course, but you should first be acquainted with the basics.
Machine.GetKeypress()
or Machine.get(char &c)
or cin.get(&c)
or getch()
This function pauses for a keypress. When a keypress is received, the ASCII value is returned as an integer. If it is not an ASCII key (such as the function keys or arrows), a unique integer value is returned for each. These values are the same ones that DOS applications used for these keypresses. A series of key constants are defined for your use. Here is the complete list:
gmF1, gmF2, gmF3, gmF4, gmF5, gmF6, gmF7, gmF8, gmF9, gmF10 gmUPARROW, gmDOWNARROW, gmLEFTARROW, gmRIGHTARROW gmHOME, gmEND, gmPAGEUP, gmPAGEDOWN, gmINSERT gmDELETE, gmENTER, gmBACKSPACE, gmTAB, gmESC
You can also use Machine.GetKeypress() to simply pause the machine for any keypress before you go on with other operations.
Machine.getline(char* string, unsigned int length)
or cin.getline(char* string, unsigned int length)
and getline(Machine, string& s)
or getline(cin, string &s)
This works like the input stream getline function in the standard C++ library for reading strings from the keyboard, except it always uses the ENTER key to terminate the string. It will also return if length-1 characters have been entered. You can use getline with the name of your GMMachine instance, or with the more familiar keyword cin.
cin.getline(cstring,20); Machine.getline(cstring,20);
The non-member variation of the function getline works with the string data type.
The stream insertion operator (<<) may be used with a GMMachine object. This prints to the current Target screen. It will work with c-strings (char*), string objects, characters, integers, and floating point numbers.
cout << "Hello!"; Machine << "Hello!";
Machine.setf(), Machine.precision(), Machine.width(), Machine.fill(), Machine.unsetf()
cout.setf(), cout.precision(), cout.width(), cout.fill(), cout.unsetf()
These output modifier functions work as in standard C++.
Machine >>
or cin >>
The stream extraction operator (>>) can be used with a GMMachine object for input or the familiar keyword cin. It will read integers, floating point numbers, characters, and strings.
Note: The >> operator intentionally works different than the standard when used with c-strings (char *) and string objects.
>> is dangerous when used with C-strings, just as in standard C++. It is easy to overrun the character array and trash anything beyond the array in memory. getline is always better suited for strings in any programming environment.
Unlike standard C++, with GMMachine the >> operator sets a limit of 20 characters when used with any kind of string. If you use a c-string (char *) make sure your character array size is at least 21. To input longer strings from the keyboard GMMachine requires use of getline.
Unlike the standard behavior, >> does not stop at whitespace characters when used to input strings with the GMMachine object.
Machine.TextPosition(int x, int y)
Sets the following text output to position (x,y) on the screen. This is a pixel location, with (0,0) at the top-left corner of the screen. 800 by 600 mode (the default), the lower-right corner is (799,599).
The position given by this command is where the top-left corner of the next character will be drawn.
Returns the text output to the home position, usually (0,0) on the screen.
Machine.SetTextHome(int x, int y)
Sets the home position for text to location (x,y). The x position is used when each new line is advanced.
Machine.ChangeFont(const char* FontName, int Height)
This changes the font for printing (using the << operator). FontName is a string containing a Windows font name, such as "Times New Roman" or "Courier New". Make sure the font you use is a standard Windows font. If it is not, substitutions will be made on other computers, and the results may not be desirable. Set the Height parameter to the desired point size.
Machine.TextColor(unsigned int RGBColor)
or Machine.TextColor(int Red, int Green, int Blue)
Sets the text color until the next TextColor command. For example, TextColor(RGB(255,255,255)) gives white text. TextColor(RGB(0,255,0)) gives green text. The three parameters give the intensity of red, green, and blue, respectively. Alternately, you can simply give the three RGB values in the TextColor function's parameter list (second usage above). The accepted range for each color intensity is 0 to 255.
Machine.ClearScreen(
[unsigned int RGBColor])
or Machine.ClearScreen(
[int Red, int Green, int Blue])
This clears the Target screen to the designated color. If no color is given, the screen is cleared to black.
Sample: Text Commands
Drawing Functions
Your "text" screen is also a graphics screen. The following functions let you draw and display images along with your text. Some of the functions relate to animation features found later. You'll find references to the "Target screen". Unless you change it (we'll show you how), the "Target" is the screen you see on the monitor.
Most of the drawing functions described here are duplicated and can also be used directly with any GMBitmap object. See the GMBitmap documentation for details.
All of the Graphics Machine functions use RGB colors. Colors are created by mixing the three primary colors in "additive coloration": red, green, and blue. Use the RGB function to create a color as follows:
RGB(255,255,0)
Each value can be from 0 to 255. The first number represents how much red, the second number represents the intensity of green, and the third number is the amount of blue. The above example gives yellow!
There are nine pre-defined colors that are automatically set for you when GMMachine is initialized:
Machine.White, Machine.Black, Machine.Red, Machine.Green, Machine.Blue, Machine.Gray, Machine.Yellow, Machine.Orange, and Machine.Violet
Machine.SetPixel(int x, int y, unsigned int RGBColor)
This sets the pixel at x,y to the specified color. (0,0) is at the top left corner of the screen. In default mode the bottom right corner is (799,599).
unsigned int Machine.GetPixel(int x, int y)
Returns the RGB color of the pixel at x,y.
Machine.Rectangle(int x1, int y1, int x2, int y2, unsigned int RGBColor [, int fill])
Draws a rectangle with corners at (x1,y1) and (x2,y2) with the specified color. The sides are horizontal and vertical. The rectangle is outlined unless you set the optional fill parameter to 1.
Machine.Line(int x1, int y1, int x2, int y2, unsigned int RGBColor)
Draws a line from (x1,y1) to (x2,y2) in the given color.
Machine.Circle(int xc, int yc, int radius, unsigned int RGBColor [,int fill])
Draws a circle with center at (xc,yc), with radius and the specified color. The circle is outlined unless you set the optional fill parameter to 1.
Machine.Arc(int xc, int yc, int radius, int startangle, int endangle, unsigned int RGBColor)
Draws an arc with center at (xc,yc), with the radius and color as given, starting at startangle and ending at endangle. Both angles are given in degrees, with 0 degrees to the right, 90 degrees at the top, 180 degrees to the left, and 270 degrees at the bottom.
startangle should be less than endangle. For example, if you want the right half of a circle, set startangle to 90 and endangle to 270. If you want the left half of a circle, set startangle to -90 and endangle to 90 (or set startangle to 270 and endangle to 450).
Machine.PieSlice(int xc, int yc, int radius, int startangle, int endangle, unsigned int RGBColor[, int fill])
Draws a pie slice (an arc with endpoints connected to the circle's center) with center at (xc,yc), with the radius and color as given, starting at startangle and ending at endangle. Both angles are given in the same manner as in the Arc function.
The pie slice is outlined unless you set the optional fill parameter to 1.
Machine.Ellipse(int xf1, int yf1, int xf2, int yf2, int radius, unsigned int RGBColor [,int fill])
Draws a filled ellipse with focal points (xf1,yf1) and (xf2,yf2), with radius and color as given.
NOTE: the fill parameter does nothing for now. This function only draws filled ellipses. The fill parameter is there as a placeholder when an "outlined" option becomes available in the future. Use the fill parameter and set it to 1 to ensure compatibility with future versions.
Machine.TriFill(int x1, int y1, int x2, int y2, int x3, int y3, unsigned int RGBColor)
A fast filled triangle with (x1,y1), (x2,y2), and (x3,y3) as the vertices. The triangle is filled with the color given. Written for speed, this function does not work when drawing to the FrontBuffer. It only works with offscreen drawing.
Sample: Drawing Commands
Screen-Related Functions
DWORD Machine.GetScreenWidth()
DWORD Machine.GetScreenHeight()
These return the output screen's size. If your application is running in a window, these functions give the interior size of the window.
DWORD Machine.GetTargetWidth()
DWORD Machine.GetTargetHeight()
Drawing can be done on any GMBitmap object. The FrontBuffer and BackBuffer are treated as GMBitmaps. You can use the function DrawOn to draw to the GMBitmap of your choice. GetTargetWidth and GetTargetHeight get the size attributes of any bitmap to which you are drawing.
Machine.DrawToFrontBuffer()
Machine.DrawToBackBuffer()
Machine.DrawOn(GMBitmap* target)
Machine.DrawOn(GMBitmap& target)
The Graphics Machine object has two "screens". One is the FrontBuffer, which is the one currently displayed on the monitor. The other is a "hidden" screen called the BackBuffer, which is not displayed until you issue one of the Flip commands. For flicker-free animation, you compose your scene on the BackBuffer, and when you are done you Flip it to the FrontBuffer. By repeating this process you create an animation. Drawing to the BackBuffer is MUCH faster than drawing to the FrontBuffer, but you don't see the results until you issue a Flip command.
When you create your GMMachine object, the default is that all output (or drawing) will be done on the FrontBuffer. This is called the Target screen. The DrawToFrontBuffer and DrawToBackBuffer functions let you change the Target as needed.
If you want to draw on a bitmap other than the two screen bitmaps, use the DrawOn function to set the target to any GMBitmap. All drawing, text, and bitmap transfer operations will use this as a target until you specify otherwise.
Machine.DrawBatch()
Machine.Show()
Drawing to the FrontBuffer is inherently extremely slow. In reality, with the recent versions of DirectX, you CAN'T draw to the FrontBuffer. So we fake it by creating an offscreen bitmap that we pretend is the FrontBuffer. Every time you draw anything "to the FrontBuffer", we really draw it to that offscreen bitmap and then transfer the whole thing to the real FrontBuffer. Slow, slow, slow!!
Learn to use the BackBuffer as soon as possible, and use it whenever you don't need "instant feedback" to see what was drawn. But if you want to use the FrontBuffer for a while, or if you have to use the FrontBuffer because your application requires immediate visual feedback, we provided two functions that speed things up somewhat.
When you are drawing to the FrontBuffer you can speed up a series of drawing commands by using Machine.DrawBatch() first, then using your drawing commands, then Machine.Show(). This prevents each and every draw command in between from transferring all the fake FrontBuffer pixels to the real FrontBuffer. That's done only once, when you say Machine.Show().
GMBitmap* Machine.GetTarget()
Returns a pointer to the current target bitmap.
GMBitmap* Machine.GetFrontBuffer()
Returns a pointer to the frontbuffer GMBitmap. WARNING: If you are drawing to the BackBuffer, do
not use this function because it will only return NULL.
GMBitmap* Machine.GetBackBuffer()
Returns a pointer to the backbuffer GMBitmap.
BOOL Machine.SaveScreen(const char* filename)
This saves the current visible screen as a Windows BMP file. It saves the full screen exactly as you see it. The function returns TRUE if successful, and FALSE if there was a problem trying to save. The most common problem is an invalid filename. As with all Graphics Machine functions, if you omit a drive/directory on the filename, the BMP file is saved in the directory where your executable program resides.
Sample: Loading a Background Bitmap (needs winter.zip)
Windows Loop
For programs that rely on a main loop which simply keeps polling the input devices and responding accordingly, this function tests whether your application is still active under Windows. If it is, your DirectInput status variables are all updated. If your app is not the active window, this function will not return until it becomes active. This function always returns a TRUE value, unless your application is instructed to exit. If you receive a FALSE response from this function, you should exit your main loop and end your program.
This function provides the most typical structure for Windows-type applications, and is very speedy for animation. Here is a sample of a program's main loop if you use the Active function:
while(Machine.Active())
{
// do something interesting here... this is the main program loop!
}
Input Devices
The returned point value gives the relative position of the mouse since the previous update (using the Active function). Each point has an x and y property. These will be negative for left or upward movement, positive for right or downward movement. Access these values with commands like:
x = x + Machine.Mouse.x;
See the Start function to make sure the mouse is activated if you are using windowed mode.
BOOL Machine.MouseLeftButton
BOOL Machine.MouseRightButton
These are boolean values that tell you TRUE or FALSE about the current button states.
After a call to the Active function, CheckKeys will see if any keys were pressed, and if so, will translate the value to ASCII. (If it's a non-ASCII key, such as the function or arrow keys, see the list of constants defined at the end of the required file GM0.H.) CheckKeys returns 0 if no keys are pressed.
CheckKeys and GetKeypress both use repeat intervals to allow a user to hold down a key and have it repeat. These intervals can be set with the KeyDelay function.
void Machine.KeyDelay(unsigned int milliseconds , [int directkey])
This function sets the delay value in milliseconds between "key repeats". If a user presses a key and holds it, by default it will generate a repeat press of the key every 500 milliseconds (1/2 second). You can change this delay between repeats by using the KeyDelay function. Send the length of the delay you desire. If you use this function with just one parameter, that number sets the delay for ALL keys. You can also set the delay for individual keys by including the second parameter with the DirectKey constant for the key you want. For example, you might want the alphabetic characters to have a slow delay and the arrow keys to have a fast delay so they repeat more quickly. You can call the KeyDelay function with a shorter time (200 milliseconds?) for each of the arrow keys while leaving the default 500 milliseconds for all the other keys on the keyboard.
(ADVANCED) This is the DirectInput key status array. You can check the status of any physical key on the keyboard by using this array as documented in the DirectInput documentation.
void Machine.Delay(unsigned long d)
This function simply pauses for d milliseconds. If d=1000, the pause is one second.
unsigned long Machine.Milliseconds()
This function uses a Windows timing function to return a number of milliseconds. You can measure the time elapsed between events by comparing the results of the Milliseconds function before and after the event. This is similar to the standard C clock() function.
Samples:
Loop with key and mouse input
Drawing with the mouse
Sound Functions
void Machine.PlayWave(char *filename [, int mode, int pan, int volume])
This plays the WAV file given with filename. If you set the mode parameter to 1, the sound will keep repeating until you use StopWave or CloseWave. If you set mode to 2, the WAV plays once, but the function does not return until the WAV is completed. The default is 0, which plays the sound just once and the function returns immediately so your program can do other things while the sound is playing.
The pan parameter directs the sound anywhere from the left to right speaker. 0 is the center, -10000 is all the way to the left, and 10000 is all the way to the right. Centered is the default. The volume parameter can be between 10000 (full volume) and 0. Full volume is the default.
void Machine.StopWave()
This stops the current WAV file, if one is playing. The WAV file stays in memory until you use PlayWave with a different WAV file, or until you use CloseWave.
This stops the current WAV file, if one is playing, and removes it from memory. Using this function would be good practice if you are playing a large WAV file just once. You can use the WavePlaying function to determine when the WAV has finished, and then use CloseWave to free the memory.
This returns True (non-zero) if the WAV file from PlayWave is still playing, and False (0) if the WAV has completed playing. This can be used to determine when to CloseWave to free memory, if you didn't use mode 2 for playing the wave.
int Machine.PlayMIDI(char *filename [, BOOL loop = 0])
This plays a MIDI music file (usually with a .MID extension) given with filename. If you set the loop parameter to a non-zero value, the music will keep repeating until you use PauseMIDI. The default is 0, not looped.
This pauses or stops the current MIDI music file. Music can be restarted with either ResumeMIDI or ReplayMIDI.
void Machine.ResumeMIDI()
Resumes playing a MIDI file from the point where it was paused by PauseMIDI.
Restarts from the beginning a MIDI file that's already in memory from PlayMIDI.
Sample: See first sample program in GMBitmapList documentation
Animation Functions
Machine.Flip()
Machine.FlipTimed()
Machine.FlipTimed(int &percent)
These functions are used when you are drawing to the BackBuffer and animating to the FrontBuffer. When you are done composing the scene on the BackBuffer, call either of these Flip functions to move the BackBuffer to the FrontBuffer, which displays on the monitor. You can then draw the next scene on the BackBuffer.
Machine.Flip() will simply flip screen without regard for timing. It is not unusual to exceed 100 frames per second of animation by simply using Flip(). One potential problem is that when you add more sprites, your frame rate will decrease, and everything will appear to slow down. The other problem is that actual speed will vary depending on the speed of the computer you are using!
Machine.FlipTimed() will keep the animation at a constant rate as long as possible. When you start the machine, the frame rate is set to 30 frames per second (the same as used in motion pictures). After you compose your scene on the BackBuffer, call FlipTimed and it will wait until 1/30th of a second has elapsed since the previous call to FlipTimed. It will actually slow your animation to a fixed time rate that is not dependent on the speed of your machine. As you add more sprites, less delay will be needed, but the apparent velocity of your sprites will appear the same.
If you are curious about how much delay is actually needed, you can call FlipTimed(percent), where percent is an integer variable. FlipTimed will store a number in percent that represents the percent of time that was actually used in computing between frames. For example, if percent is 25 after a call to FlipTimed, that means that you spent 25 percent of your time between frames drawing and doing whatever else your program does, and 75 percent of the time was spent by FlipTimed in a delay loop. If you really hate wasting that precious machine time, check the PlayWhileDelay property below.
Machine.SetFrameRate(int rate)
The default frame rate for FlipTimed is 30 frames per second. You can change the frame rate with this function.
void (*PlayWhileDelay)(GMMachine& Machine)
PlayWhileDelay is a property. It is a function pointer. You can create a function that does something repeatedly during the delay cycle of FlipTimed. Your function must be declared to receive a GMMachine pointer and return nothing (void). For example:
void MyDelayFunction(GMMachine& Machine)
This function should perform some short task, then return. It may use the GMMachine or not. During the delay loop of FlipTimed, your function will be called repeatedly until the delay time expires. Your function should not perform any long tasks that will interfere with FlipTimed accurately polling the time between calls to your function, and definitely don't call the Flip or FlipTimed function within this one or you'll get some weird recursion going!
To use PlayWhileDelay, simply assign the name of your function to this property, as in:
Machine.PlayWhileDelay = MyDelayFunction;
Sample: Animation with screen flipping
(even better samples like this are in the GMBitmap documentation section!)
Debugging
void Machine.Message(char *message)
void Machine.Message(char *message1, char *message2)
void Machine.Message(int i)
void Machine.Message(char *message, int i)
Each of the variations interupts the program with a message or a pop-up message box. Use of this function may disrupt the operation of the remainder of your program!
In windowed mode, a pop-up message box is used. Mouse control is passed back to Windows from DirectX. That seems to disrupt DirectInput, which will likely affect the rest of your program after this function is used.
In full screen mode, Message forces some parameters to be changed so the message will display. Therefore your program may continue with some oddities. The parameters affected are: drawing mode is switched to the FrontBuffer which is cleared to black, the font is changed to 18-point Courier, the font color is changed to white, and the text position is moved to the top of the screen.
The optional second message parameter allows you to send a fixed string plus a variable string, such as "Could not open file: c:\windows\somefile.txt".
If used with an integer parameter, the integer is displayed in hexadecimal.
void Machine.Exit()
Exits the program immediately.
![]()