Overview
|
Makefile
|
Common.hpp
|
Common.cpp
|
Asteroids.hpp
|
Asteroids.cpp
|
Number.hpp
|
Number.cpp
|
Text.hpp
|
Text.cpp
|
AstroRock.hpp
|
AstroRock.cpp
|
AstroShip.hpp
|
AstroShip.cpp
|
AstroShot.hpp
|
AstroShot.cpp
|
Astro_UFO.hpp
|
Astro_UFO.cpp
|
GNU License
|
|
Coding a Linux Game
2012-04-17 12:40 By Jason Birch
Penultimate in a series of how to code articles. Demonstrating coding an Asteroids Clone game with various technologies. This example using C++ and xWindows, implementing as an application on Linux operating systems.
In this article I have converted my Asteroids Clone code into a Linux xWindows application. I am now publishing the source code here under the GNU General Public License License as a series of articles describing how to write code using various technologies.
The code here can be freely distributed, but only on the condition that a credit to Jason Birch is maintained in the source code files and running application.
The source code is broken down into the classes which make the application, in the tabs on the left of this article. The tabs are placed in order from the simplest classes to the more complex classes last. There is a commentary accompanying each source code file explaining how the code operates.
A compiled version of the Linux application, compiled on CentOS 32bit, is available here, it is just 110KB in size.
Keys:
ESC - Exit Application, F1 - New Game, UP - Thrust, DOWN - Hyperspace, LEFT - Rotate Counter Clockwise, RIGHT - Rotate Clockwise, CTRL - Fire
Audio files can be downloaded here:

Screen Shot Of Linux Conversion
Required Environment
To run the application, a Linux operating system is required with xWindows installed. The source code should specifically be compiled for the version of the distribution of Linux it is to run on.
The following packages are required to compile and run the application:
yum install gcc
yum install gcc-c++
yum install libX11-devel
yum install alsa-lib-devel
yum install libsndfile-devel
Writing Code
To develop the application, any text editor can be used, such as gEdit.
Compiling Code
gcc and make are the best tools for compiling the source code.
Distributing Application
The application can be run on an xWindows Linux operating system. Compile the code specifically for the target operating system.
Running Application
The application can be run by double clicking on the application icon.
|
This file allows the make utility to compile and link all of the source files, by simply typing "make" in a command shell. Or type "make clean" to clear all compiled and linked files so make can compile and link the project from a fresh start.
REF: 1.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
EXE = Asteroids
LIBDIRS = -L/usr/X11R6/lib -L/usr/local/lib
INCDIRS = -I/usr/include -I/usr/local/include
CC = g++
CFLAGS = -ggdb -g $(INCDIRS)
LIBS = -lX11 -lsndfile -lasound
$(EXE) : $(EXE).o
$(CC) $(CFLAGS) -c $(LIBDIRS) *.cpp $(LIBS)
$(CC) $(CFLAGS) -o $(EXE) $(LIBDIRS) *.o $(LIBS)
clean:
rm -f *.o
|
|
The Linux specific functions have been placed in the Common.hpp/cpp files.
REF: 2.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef __COMMON_HPP
#define __COMMON_HPP
#define BUFF_SIZE 1024
typedef struct
{
XColor xBlack;
XColor xGreen;
} xColorsType;
typedef struct
{
int* Data;
long DataSize;
} WavData;
void CreateWindow(Display** xDisplay, int* xScreen, Window* xWindow,
GC* xGC, xColorsType* xColors, XRectangle* Desktop,
const char* Title);
void DestroyWindow(Display** xDisplay, Window* xWindow, GC* xGC);
void ReadSoundFile(const char* PathFilename, WavData* SoundData);
void PlaySoundFile(WavData* SoundData);
#endif
|
|
The application uses xWindows and the alsa sound library, so these header files are included here.
REF: 3.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <sndfile.h>
#include <alsa/asoundlib.h>
#include "Common.hpp"
|
Create an xWindows Window for the application to run the game in. Also provide a function to ensure all Window components are removed from memory when the Window is no longer required.
REF: 3.1
|
void CreateWindow(Display** xDisplay, int* xScreen, Window* xWindow, GC* xGC,
xColorsType* xColors, XRectangle* Desktop, const char* Title)
{
int xPos;
int yPos;
int xLen;
int yLen;
int BorderWidth;
long BorderColour;
long BackgroundColour;
int xDepth;
int xConnection;
Window xRootWindow;
Visual xVisual;
unsigned int xWindowClass;
unsigned long xWinAttribMask;
XSetWindowAttributes xWinAttrib;
XSizeHints xSizeHint;
XWMHints xWinManHint;
XGCValues xGCValues;
Colormap xColormap;
Atom wmDelete;
char Black[] = "#000000";
char Green[] = "#55DD55";
xPos = Desktop->x;
yPos = Desktop->y;
xLen = Desktop->width;
yLen = Desktop->height;
BorderWidth = 2;
BorderColour = 0xFF0000;
BackgroundColour = 0x00FF00;
xWindowClass = InputOutput;
*xDisplay = XOpenDisplay(NULL);
*xScreen = DefaultScreen(*xDisplay);
xDepth = DefaultDepth(*xDisplay, *xScreen);
xConnection = ConnectionNumber(*xDisplay);
xRootWindow = RootWindow(*xDisplay, *xScreen);
xColormap = DefaultColormap(*xDisplay, *xScreen);
XParseColor(*xDisplay, xColormap, Black, &xColors->xBlack);
XAllocColor(*xDisplay, xColormap, &xColors->xBlack);
XParseColor(*xDisplay, xColormap, Green, &xColors->xGreen);
XAllocColor(*xDisplay, xColormap, &xColors->xGreen);
xWinAttribMask = CWBackPixel | CWBorderPixel | CWOverrideRedirect;
xWinAttrib.border_pixel = xColors->xGreen.pixel;
xWinAttrib.background_pixel = xColors->xBlack.pixel;
xWinAttrib.override_redirect = False;
*xWindow = XCreateWindow(*xDisplay, xRootWindow, xPos, yPos, xLen, yLen,
BorderWidth, xDepth, xWindowClass, CopyFromParent,
xWinAttribMask, &xWinAttrib);
wmDelete=XInternAtom(*xDisplay, "WM_DELETE_WINDOW", True);
XSetWMProtocols(*xDisplay, *xWindow, &wmDelete, 1);
XStoreName(*xDisplay, *xWindow, Title);
XSetIconName(*xDisplay, *xWindow, Title);
xWinManHint.initial_state = NormalState;
xWinManHint.flags = StateHint;
XSetWMHints(*xDisplay, *xWindow, &xWinManHint);
xSizeHint.flags = PPosition | PSize | PMinSize | PMaxSize;
xSizeHint.x = xPos;
xSizeHint.y = yPos;
xSizeHint.width = xLen;
xSizeHint.height = yLen;
xSizeHint.min_width = xLen;
xSizeHint.min_height = yLen;
xSizeHint.max_width = xLen;
xSizeHint.max_height = yLen;
XSetNormalHints(*xDisplay, *xWindow, &xSizeHint);
XMapWindow(*xDisplay, *xWindow);
XFlush(*xDisplay);
*xGC = XCreateGC(*xDisplay, *xWindow, (unsigned long)0, &xGCValues);
XAutoRepeatOff(*xDisplay);
}
void DestroyWindow(Display** xDisplay, Window* xWindow, GC* xGC)
{
XFreeGC(*xDisplay, *xGC);
XDestroyWindow(*xDisplay, *xWindow);
XCloseDisplay(*xDisplay);
}
|
Read a sound file into a memory buffer so it can be played when required.
REF: 3.2
|
void ReadSoundFile(const char* PathFilename, WavData* SoundData)
{
SNDFILE* SoundFileHandle;
SF_INFO SoundFileInfo;
sf_count_t ReadCount;
char Buffer[BUFF_SIZE+1];
printf("%s\n", PathFilename);
sf_command (NULL, SFC_GET_LIB_VERSION, Buffer, BUFF_SIZE);
printf("%s\n", Buffer);
SoundFileHandle = sf_open(PathFilename, SFM_READ, &SoundFileInfo);
printf("frames: %lu\n", SoundFileInfo.frames);
printf("samplerate: %u\n", SoundFileInfo.samplerate);
printf("channels: %u\n", SoundFileInfo.channels);
printf("format: %u\n", SoundFileInfo.format);
printf("sections: %u\n", SoundFileInfo.sections);
printf("seekable: %u\n", SoundFileInfo.seekable);
SoundData->DataSize = SoundFileInfo.frames * 2;
SoundData->Data = (int*)malloc(SoundData->DataSize * sizeof(int));
ReadCount = sf_readf_int(SoundFileHandle, SoundData->Data, SoundData->DataSize);
printf("Data Size: %lu, Data Read: %lu\n", SoundData->DataSize, ReadCount);
sf_close(SoundFileHandle);
printf("\n");
}
|
Start a sound buffer playing from memory.
REF: 3.3
|
void PlaySoundFile(WavData* SoundData)
{
unsigned int Rate;
int FramesPlayed;
snd_pcm_t *SoundHandle;
snd_pcm_hw_params_t *Hardware = NULL;
snd_pcm_open(&SoundHandle, "plughw:0,0", SND_PCM_STREAM_PLAYBACK, 0);
snd_pcm_hw_params_malloc(&Hardware);
snd_pcm_hw_params_any(SoundHandle, Hardware);
snd_pcm_hw_params_set_access(SoundHandle, Hardware, SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(SoundHandle, Hardware, SND_PCM_FORMAT_S16_LE);
Rate = 11025;
snd_pcm_hw_params_set_rate_near(SoundHandle, Hardware, &Rate, 0);
snd_pcm_hw_params_set_channels(SoundHandle, Hardware, 2);
snd_pcm_hw_params_set_periods(SoundHandle, Hardware, 2, 0);
snd_pcm_hw_params_set_buffer_size(SoundHandle, Hardware, SoundData->DataSize);
snd_pcm_hw_params(SoundHandle, Hardware);
snd_pcm_hw_params_free(Hardware);
snd_pcm_prepare(SoundHandle);
FramesPlayed = snd_pcm_writei(SoundHandle, SoundData->Data, SoundData->DataSize);
printf("Data: %lu, Played: %lu\n", SoundData->DataSize, FramesPlayed);
snd_pcm_close(SoundHandle);
}
|
|
The main header file for the application contains an enumeration of values to configure the visual elements of the application. These will be explained in detail in the source code file Asteroids.cpp.
REF: 4.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef __ASTERIODS_HPP
#define __ASTERIODS_HPP
int main(int argc, char* argv[]);
void Timer(int signum);
void DrawGraphics(Display** xDisplay, int* xScreen, Window* xWindow,
GC* xGC, xColorsType* xColors);
enum
{
START_ROCKS = 5,// Asteroids Clone Screen Saver
MAX_ROCKS = 100,
HISCORE_XOFFSET = 55,
HISCORE_YOFFSET = 20,
GAMEOVER_XOFFSET = 90,
GAMEOVER_YOFFSET = 20,
INSERTCOIN_XOFFSET = 110,
INSERTCOIN_YOFFSET = 20,
HISCORE_SCALE = 3
};
#endif
|
|
The main application code includes a header file for the standard xWindows API. Then all of the application's class header files are included.
REF: 5.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "Common.hpp"
#include "Number.hpp"
#include "Text.hpp"
#include "AstroShot.hpp"
#include "AstroShip.hpp"
#include "Astro_UFO.hpp"
#include "AstroRock.hpp"
#include "Asteroids.hpp"
|
The application uses a main message loop to receive events from the Windows system. These events can be key presses, mouse clicks, requests to redraw the applications Window, ... Because of this some variables in the application require global scope, in order for the message loop to act on events and manipulate objects the application owns.
REF: 5.1
|
/***********************************************************/
/* Allow signal routines access to the application Window. */
/***********************************************************/
Display* xDisplay;
int xScreen;
Window xWindow;
GC xGC;
xColorsType xColors;
XRectangle Desktop;
/*****************/
/* Game objects. */
/*****************/
short FirstRock;
short NextRock;
AstroShip Ship;
AstroUFO UFO;
AstroRock Rock[MAX_ROCKS];
Number HiScore;
Text GameOver;
Text InsertCoin;
/***************/
/* Sound data. */
/***************/
WavData RockWav;
WavData HyperSpaceWav;
WavData ShotWav;
WavData ThrustWav;
WavData UFOWav;
WavData UFOShotWav;
/***************/
/* Game flags. */
/***************/
bool ThrustFlag = false;
bool RotateLeftFlag = false;
bool RotateRightFlag = false;
|
A standard C++ entry point function is used to initialize the application.
REF: 5.2
|
int main(int argc, char* argv[])
{
bool SetFlag;
int Count;
XEvent xEvent;
XKeyboardControl xKeyboard;
struct itimerval NewTimer;
struct timeval tp;
struct timezone tzp;
|
Sound files are read into memory, ready for use as sound effects in the game.
REF: 5.3
|
/********************/
/* Load sound data. */
/********************/
ReadSoundFile("Rock.wav", &RockWav);
ReadSoundFile("HyperSpace.wav", &HyperSpaceWav);
ReadSoundFile("Shot.wav", &ShotWav);
ReadSoundFile("Thrust.wav", &ThrustWav);
ReadSoundFile("UFO.wav", &UFOWav);
ReadSoundFile("UFOShot.wav", &UFOShotWav);
|
Create a standard xWindows Window to display the game in.
REF: 5.4
|
/***************************/
/* Set the play area size. */
/***************************/
Desktop.x = 0;
Desktop.y = 0;
Desktop.width = 640;
Desktop.height = 480;
/****************************************/
/* Create a Window for the application. */
/****************************************/
CreateWindow(&xDisplay, &xScreen, &xWindow, &xGC, &xColors, &Desktop, "Asteroids");
XAutoRepeatOff(xDisplay);
|
Create a timer to animate the game at 50 frames per second.
REF: 5.5
|
/***************************/
/* Generate a frame timer. */
/***************************/
signal(SIGALRM, Timer);
NewTimer.it_interval.tv_usec = 50000;
NewTimer.it_interval.tv_sec = 0;
NewTimer.it_value.tv_usec = 50000;
NewTimer.it_value.tv_sec = 0;
if (setitimer(ITIMER_REAL, &NewTimer, NULL))
printf("Failed to start timer.");
|
Generate a random seed for creating random numbers.
REF: 5.6
|
/********************/
/* Set random seed. */
/********************/
gettimeofday (&tp, &tzp);
srand(tp.tv_usec);
|
Initialize the objects for use in the game.
REF: 5.7
|
/*******************************/
/* Initialise game components. */
/*******************************/
GameOver.SetLocation((Desktop.width - Desktop.x) / 2 - GAMEOVER_XOFFSET,
(Desktop.height - Desktop.y) / 2 - GAMEOVER_YOFFSET,
5, 200, false, "GAME OVER", xColors.xGreen.pixel);
InsertCoin.SetLocation((Desktop.width - Desktop.x) / 2 - INSERTCOIN_XOFFSET,
(Desktop.height - Desktop.y) / 2 - INSERTCOIN_YOFFSET,
5, 15, true, "INSERT COIN", xColors.xGreen.pixel);
HiScore.SetLocation((Desktop.width - Desktop.x) / 2 - HISCORE_XOFFSET,
HISCORE_YOFFSET, HISCORE_SCALE, xColors.xGreen.pixel);
Ship.SetArea(&Desktop, xColors.xGreen.pixel);
UFO.SetArea(&Desktop);
FirstRock = START_ROCKS;
NextRock = FirstRock;
for (Count = 0; Count < FirstRock; ++Count)
Rock[Count].SetArea(&Desktop);
|
Set the type of messages to capture in a message loop. Then perform a message loop to handle keyboard events from the user.
REF: 5.8
|
/*****************************************************/
/* Select the events to capture in the message loop. */
/*****************************************************/
XSelectInput(xDisplay, xWindow, /* ExposureMask | */ KeyPressMask
| KeyReleaseMask | ButtonPressMask
| StructureNotifyMask);
/**************************************************************/
/* Process application messages until the ESC key is pressed. */
/**************************************************************/
do
{
while (!XPending(xDisplay))
{
pause();
};
/**************************************************/
/* Read the next event posted to the application. */
/**************************************************/
XNextEvent(xDisplay, &xEvent);
/***************************************************************************/
/* Update the content of the Window when required by the operating system. */
/***************************************************************************/
if (xEvent.type == Expose)
DrawGraphics(&xDisplay, &xScreen, &xWindow, &xGC, &xColors);
/****************************/
/* Handle key press events. */
/****************************/
else if (xEvent.type == KeyPress || xEvent.type == KeyRelease)
{
if (xEvent.type == KeyPress)
SetFlag = true;
else
SetFlag = false;
/****************************/
/* 'Ctrl' key press, shoot. */
/****************************/
if (xEvent.type == KeyPress && xEvent.xkey.keycode == 37
|| xEvent.xkey.keycode == 105)
Ship.Shoot();
/***************************/
/* 'up' key press, thrust. */
/***************************/
else if (xEvent.xkey.keycode == 111)
ThrustFlag = SetFlag;
/**********************************/
/* 'left' key press, rotate left. */
/**********************************/
else if (xEvent.xkey.keycode == 113)
RotateLeftFlag = SetFlag;
/************************************/
/* 'right' key press, rotate right. */
/************************************/
else if (xEvent.xkey.keycode == 114)
RotateRightFlag = SetFlag;
/*********************************/
/* 'down' key press, hyperspace. */
/*********************************/
else if (xEvent.xkey.keycode == 116)
Ship.Hyperspace();
/*****************************/
/* 'F1' key press, new game. */
/*****************************/
else if (xEvent.xkey.keycode == 67)
{
if (Ship.GetLives() == false)
{
if (Ship.GetScore() > HiScore.GetNumber())
HiScore.SetNumber(Ship.GetScore());
Ship.Reset();
UFO.Destroy();
UFO.GetShot().Destroy();
FirstRock = START_ROCKS;
NextRock = FirstRock;
for (Count = 0; Count < MAX_ROCKS; ++Count)
Rock[Count].Destroy();
for (Count = 0; Count < FirstRock; ++Count)
Rock[Count].SetArea(&Desktop);
}
}
}
} while (xEvent.type != ClientMessage
&& !(xEvent.type == KeyPress
&& XLookupKeysym(&xEvent.xkey, 0) == XK_Escape));
|
When closing the application Window, stop the application timer, close the Window and free all objects from memory.
REF: 5.9
|
/*******************/
/* Stop the timer. */
/*******************/
signal(SIGALRM, SIG_IGN);
/*****************************************************/
/* Release the resources for the application Window. */
/*****************************************************/
XAutoRepeatOn(xDisplay);
DestroyWindow(&xDisplay, &xWindow, &xGC);
/********************/
/* Free sound data. */
/********************/
free(RockWav.Data);
free(HyperSpaceWav.Data);
free(ShotWav.Data);
free(ThrustWav.Data);
free(UFOWav.Data);
free(UFOShotWav.Data);
/*************************************/
/* Exit application with value zero. */
/*************************************/
return 0;
}
|
The timer displays one frame of animation and checks for object collisions.
REF: 5.10
|
void Timer(int signum)
{
int Count;
int ShotCount;
XEvent xEvent;
bool RockFound;
if (ThrustFlag)
Ship.Thrust();
else if (RotateLeftFlag)
{
Ship.IncAngle(false);
Ship.IncAngle(false);
}
else if (RotateRightFlag)
{
Ship.IncAngle(true);
Ship.IncAngle(true);
}
Ship.Move();
UFO.Move();
RockFound = false;
for (Count = 0; Count < MAX_ROCKS; ++Count)
{
if (Rock[Count].GetSize() != AstroRock::INACTIVE)
RockFound = true;
/*****************************/
/* Check for ship collision. */
/*****************************/
if (Ship.GetCrash() == false
&& UFO.Collide(Ship.GetXOffset(), Ship.GetYOffset(),
Ship.GetWidth(), Ship.GetHeight()))
Ship.SetCrash(true);
if (UFO.GetShot().Active() == true
&& Ship.Collide(UFO.GetShot().GetXOffset(),
UFO.GetShot().GetYOffset(), 2, 2))
Ship.SetCrash(true);
if (Ship.GetCrash() == false
&& Rock[Count].Collide(Ship.GetXOffset(), Ship.GetYOffset(),
Ship.GetWidth(), Ship.GetHeight()))
{
Ship.SetCrash(true);
Rock[++NextRock].SetArea(&Desktop, Ship.GetXOffset(),
Ship.GetYOffset(),
Rock[Count].GetSize());
}
/*************************/
/* Check for shot rocks. */
/*************************/
for (ShotCount = 0; ShotCount < Ship.GetShotCount(); ++ShotCount)
{
if (Ship.GetShot(ShotCount).Active() != false)
{
if (UFO.Collide(Ship.GetShot(ShotCount).GetXOffset(),
Ship.GetShot(ShotCount).GetYOffset(), 2, 2))
{
Ship.SetScore(Ship.GetScore() + 100);
Ship.GetShot(ShotCount).Destroy();
}
if (Rock[Count].Collide(Ship.GetShot(ShotCount).GetXOffset(),
Ship.GetShot(ShotCount).GetYOffset(), 2, 2))
{
Ship.SetScore(Ship.GetScore() + 5*Rock[Count].GetSize());
Ship.GetShot(ShotCount).Destroy();
if (NextRock+1 < MAX_ROCKS)
Rock[++NextRock].SetArea(&Desktop, Rock[Count].GetXOffset(),
Rock[Count].GetYOffset(),
Rock[Count].GetSize());
}
}
}
Rock[Count].Move();
}
if (RockFound == false)
{
++FirstRock;
NextRock = FirstRock;
for (Count = 0; Count < FirstRock; ++Count)
Rock[Count].SetArea(&Desktop);
}
GameOver.SetVisible(Ship.GetLives() == false);
InsertCoin.SetVisible(GameOver.GetVisible() == false
&& Ship.GetLives() == false);
DrawGraphics(&xDisplay, &xScreen, &xWindow, &xGC, &xColors);
}
|
Draw all objects onto the application Window.
REF: 5.11
|
void DrawGraphics(Display** xDisplay, int* xScreen, Window* xWindow,
GC* xGC, xColorsType* xColors)
{
int Count;
/*******************************/
/* Draw ship and rock objects. */
/*******************************/
InsertCoin.Draw(xDisplay, xWindow, xGC, xColors);
GameOver.Draw(xDisplay, xWindow, xGC, xColors);
HiScore.Draw(xDisplay, xWindow, xGC, xColors);
Ship.Draw(xDisplay, xWindow, xGC, xColors);
UFO.Draw(xDisplay, xWindow, xGC, xColors);
for (Count = 0; Count < MAX_ROCKS; ++Count)
Rock[Count].Draw(xDisplay, xWindow, xGC, xColors);
XFlushGC(*xDisplay, *xGC);
XFlush(*xDisplay);
}
|
|
The number class draws numbers on the display simulating the way a vector CRT display would do on an 80s' Asteroids arcade machine. The class only requires a few member functions and is the simplest class in this project. There is a Draw function as all of the classes have, which draws the current numeric value onto a Window. SetLocation is a function used to initialize the object with required values. GetNumber gets the current value of the object and SetNumber sets the object with a new value.
REF: 6.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef __NUMBER_HPP
#define __NUMBER_HPP
class Number
{
public:
enum
{
DIGITS = 10,
MAX_POINTS = 10,
};
Number();
~Number();
void Draw(Display** xDisplay, Window* xWindow, GC* xGC, xColorsType* xColors);
void SetLocation(int NewxOffset, int NewyOffset, int NewScale,
long NewTextColour, int NewWidth = 1);
long GetNumber();
void SetNumber(long NewNumber);
private:
int xOffset;
int yOffset;
int Scale;
int Width;
long TextColour;
long NumberValue;
XPoint Decimal[DIGITS][MAX_POINTS+1];
XPoint DisplayFrame[DIGITS][MAX_POINTS+1];
XPoint OldFrame[DIGITS][MAX_POINTS+1];
};
#endif
|
|
The number class draws numbers on the display simulating the way a vector CRT display would do on an 80s' Asteroids arcade machine. The class only requires a few member functions and is the simplest class in this project.
REF: 7.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdlib.h>
#include <X11/Xlib.h>
#include "Common.hpp"
#include "Number.hpp"
Number::Number()
{
NumberValue = 0;
xOffset = 0;
yOffset = 0;
Scale = 0;
Width = 0;
}
Number::~Number()
{
}
|
Each of the game objects has a draw function which draws the current state of the object onto a Window using xWindows calls.
REF: 7.1
|
void Number::Draw(Display** xDisplay, Window* xWindow, GC* xGC, xColorsType* xColors)
{
short Digit;
short Count;
div_t Divide;
long TempNumber;
/*****************************/
/* Plot score current value. */
/*****************************/
TempNumber = NumberValue;
for (Digit = 0; Digit < 10; ++Digit)
{
Divide = div(TempNumber, 10);
TempNumber = Divide.quot;
for (Count = 0; Count < Decimal[Divide.rem][MAX_POINTS].x; ++Count)
{
DisplayFrame[Digit][Count].x = Decimal[Divide.rem][Count].x
+ xOffset + (10 - Digit) * 3*Scale;
DisplayFrame[Digit][Count].y = Decimal[Divide.rem][Count].y
+ yOffset;
}
DisplayFrame[Digit][MAX_POINTS].x = Decimal[Divide.rem][MAX_POINTS].x;
/*************************/
/* Erase previous score. */
/*************************/
XSetForeground(*xDisplay, *xGC, xColors->xBlack.pixel);
XDrawLines(*xDisplay, *xWindow, *xGC, OldFrame[Digit],
OldFrame[Digit][MAX_POINTS].x, CoordModeOrigin);
/***************************/
/* Draw the current score. */
/***************************/
XSetForeground(*xDisplay, *xGC, xColors->xGreen.pixel);
XDrawLines(*xDisplay, *xWindow, *xGC, DisplayFrame[Digit],
DisplayFrame[Digit][MAX_POINTS].x, CoordModeOrigin);
/***************************************/
/* Plot current score, */
/* next time it will be the old score. */
/***************************************/
for (Count = 0; Count < DisplayFrame[Digit][MAX_POINTS].x; ++Count)
{
OldFrame[Digit][Count].x = DisplayFrame[Digit][Count].x;
OldFrame[Digit][Count].y = DisplayFrame[Digit][Count].y;
}
OldFrame[Digit][MAX_POINTS].x = DisplayFrame[Digit][MAX_POINTS].x;
}
}
|
The SetLocation member function re-initializes the object. It sets the objects properties passed in as arguments. When the object draws it's image to a Window, it does so by drawing a series of lines defined by x-y co-ordinates. All of the objects possible visual representations are defined in an array of arrays of x-y co-ordinates. In the case of this class the first array represents the digits zero to nine and the second array the x-y co-ordinates which represent each digit.
REF: 7.2
|
void Number::SetLocation(int NewxOffset, int NewyOffset, int NewScale,
long NewTextColour, int NewWidth)
{
xOffset = NewxOffset;
yOffset = NewyOffset;
Scale = NewScale;
Width = NewWidth;
TextColour = NewTextColour;
Decimal[0][MAX_POINTS].x = 6;
Decimal[0][0].x = 2*Scale;
Decimal[0][0].y = 0*Scale;
Decimal[0][1].x = 0*Scale;
Decimal[0][1].y = 0*Scale;
Decimal[0][2].x = 0*Scale;
Decimal[0][2].y = 4*Scale;
Decimal[0][3].x = 2*Scale;
Decimal[0][3].y = 4*Scale;
Decimal[0][4].x = 2*Scale;
Decimal[0][4].y = 0*Scale;
Decimal[0][5].x = 0*Scale;
Decimal[0][5].y = 4*Scale;
Decimal[1][MAX_POINTS].x = 2;
Decimal[1][0].x = 1*Scale;
Decimal[1][0].y = 0*Scale;
Decimal[1][1].x = 1*Scale;
Decimal[1][1].y = 4*Scale;
Decimal[2][MAX_POINTS].x = 6;
Decimal[2][0].x = 0*Scale;
Decimal[2][0].y = 0*Scale;
Decimal[2][1].x = 2*Scale;
Decimal[2][1].y = 0*Scale;
Decimal[2][2].x = 2*Scale;
Decimal[2][2].y = 2*Scale;
Decimal[2][3].x = 0*Scale;
Decimal[2][3].y = 2*Scale;
Decimal[2][4].x = 0*Scale;
Decimal[2][4].y = 4*Scale;
Decimal[2][5].x = 2*Scale;
Decimal[2][5].y = 4*Scale;
Decimal[3][MAX_POINTS].x = 7;
Decimal[3][0].x = 0*Scale;
Decimal[3][0].y = 0*Scale;
Decimal[3][1].x = 2*Scale;
Decimal[3][1].y = 0*Scale;
Decimal[3][2].x = 2*Scale;
Decimal[3][2].y = 2*Scale;
Decimal[3][3].x = 0*Scale;
Decimal[3][3].y = 2*Scale;
Decimal[3][4].x = 2*Scale;
Decimal[3][4].y = 2*Scale;
Decimal[3][5].x = 2*Scale;
Decimal[3][5].y = 4*Scale;
Decimal[3][6].x = 0*Scale;
Decimal[3][6].y = 4*Scale;
Decimal[4][MAX_POINTS].x = 5;
Decimal[4][0].x = 0*Scale;
Decimal[4][0].y = 0*Scale;
Decimal[4][1].x = 0*Scale;
Decimal[4][1].y = 2*Scale;
Decimal[4][2].x = 2*Scale;
Decimal[4][2].y = 2*Scale;
Decimal[4][3].x = 2*Scale;
Decimal[4][3].y = 0*Scale;
Decimal[4][4].x = 2*Scale;
Decimal[4][4].y = 4*Scale;
Decimal[5][MAX_POINTS].x = 6;
Decimal[5][0].x = 2*Scale;
Decimal[5][0].y = 0*Scale;
Decimal[5][1].x = 0*Scale;
Decimal[5][1].y = 0*Scale;
Decimal[5][2].x = 0*Scale;
Decimal[5][2].y = 2*Scale;
Decimal[5][3].x = 2*Scale;
Decimal[5][3].y = 2*Scale;
Decimal[5][4].x = 2*Scale;
Decimal[5][4].y = 4*Scale;
Decimal[5][5].x = 0*Scale;
Decimal[5][5].y = 4*Scale;
Decimal[6][MAX_POINTS].x = 6;
Decimal[6][0].x = 2*Scale;
Decimal[6][0].y = 0*Scale;
Decimal[6][1].x = 0*Scale;
Decimal[6][1].y = 0*Scale;
Decimal[6][2].x = 0*Scale;
Decimal[6][2].y = 4*Scale;
Decimal[6][3].x = 2*Scale;
Decimal[6][3].y = 4*Scale;
Decimal[6][4].x = 2*Scale;
Decimal[6][4].y = 2*Scale;
Decimal[6][5].x = 0*Scale;
Decimal[6][5].y = 2*Scale;
Decimal[7][MAX_POINTS].x = 3;
Decimal[7][0].x = 0*Scale;
Decimal[7][0].y = 0*Scale;
Decimal[7][1].x = 2*Scale;
Decimal[7][1].y = 0*Scale;
Decimal[7][2].x = 2*Scale;
Decimal[7][2].y = 4*Scale;
Decimal[8][MAX_POINTS].x = 7;
Decimal[8][0].x = 0*Scale;
Decimal[8][0].y = 0*Scale;
Decimal[8][1].x = 2*Scale;
Decimal[8][1].y = 0*Scale;
Decimal[8][2].x = 2*Scale;
Decimal[8][2].y = 4*Scale;
Decimal[8][3].x = 0*Scale;
Decimal[8][3].y = 4*Scale;
Decimal[8][4].x = 0*Scale;
Decimal[8][4].y = 0*Scale;
Decimal[8][5].x = 0*Scale;
Decimal[8][5].y = 2*Scale;
Decimal[8][6].x = 2*Scale;
Decimal[8][6].y = 2*Scale;
Decimal[9][MAX_POINTS].x = 6;
Decimal[9][0].x = 0*Scale;
Decimal[9][0].y = 4*Scale;
Decimal[9][1].x = 2*Scale;
Decimal[9][1].y = 4*Scale;
Decimal[9][2].x = 2*Scale;
Decimal[9][2].y = 0*Scale;
Decimal[9][3].x = 0*Scale;
Decimal[9][3].y = 0*Scale;
Decimal[9][4].x = 0*Scale;
Decimal[9][4].y = 2*Scale;
Decimal[9][5].x = 2*Scale;
Decimal[9][5].y = 2*Scale;
}
|
The last two member functions of this class set or retrieve the numeric value which is to be displayed by the current instance of the class.
REF: 7.3
|
long Number::GetNumber()
{
return NumberValue;
}
void Number::SetNumber(long NewNumber)
{
NumberValue = NewNumber;
}
|
|
The text class draws text strings on the display simulating the way a vector CRT display would do on an 80s' Asteroids arcade machine. The class only requires a few member functions. There is a Draw function as all of the classes have, which draws the text string onto a Window. SetLocation is a function used to initialize the object with required values. GetVisible checks if the current instance of the object is currently being displayed and SetVisible sets the object to be drawn or hidden.
REF: 8.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef __TEXT_HPP
#define __TEXT_HPP
class Text
{
public:
enum
{
MAX_LETTERS = 58,
MAX_POINTS = 12,
MAX_TEXT = 2048,
INFINATE_FRAMES = -1
};
Text();
~Text();
void Draw(Display** xDisplay, Window* xWindow, GC* xGC, xColorsType* xColors);
void SetLocation(int NewxOffset, int NewyOffset, int NewScale, int NewFrames,
bool NewFlash, const char* NewText, long NewTextColour,
int NewWidth = 1);
void SetVisible(short NewVisible);
short GetVisible();
private:
short xOffset;
short yOffset;
short Scale;
short Width;
long TextColour;
bool Visible;
bool LastVisible;
bool FlashVisible;
short Active;
short Frames;
short FrameCount;
bool Flash;
char TextString[MAX_TEXT+1];
XPoint Letter[MAX_LETTERS+1][MAX_POINTS+1];
XPoint DisplayFrame[MAX_TEXT+1][MAX_POINTS+1];
};
#endif
|
|
The text class draws text strings on the display simulating the way a vector CRT display would do on an 80s' Asteroids arcade machine.
REF: 9.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <string.h>
#include <ctype.h>
#include <X11/Xlib.h>
#include "Common.hpp"
#include "Text.hpp"
Text::Text()
{
TextString[0] = '\0';
xOffset = 0;
yOffset = 0;
Scale = 0;
Width = 0;
TextColour = 0;
Visible = false;
LastVisible = false;
FlashVisible = false;
Active = false;
Frames = INFINATE_FRAMES;
FrameCount = 0;
Flash = false;
}
Text::~Text()
{
}
|
Each of the game objects has a draw function which draws the current state of the object onto a Window using xWindows calls.
REF: 9.1
|
void Text::Draw(Display** xDisplay, Window* xWindow, GC* xGC, xColorsType* xColors)
{
short Digit;
if (Active == true)
{
/********************************************/
/* Display only for given number of frames. */
/********************************************/
if (FrameCount != INFINATE_FRAMES)
--FrameCount;
if (FrameCount == false && Flash == true)
{
FrameCount = Frames;
FlashVisible = !FlashVisible;
}
else if (FrameCount == false)
{
Active = false;
}
/****************************/
/* Plot Text current value. */
/****************************/
for (Digit = 0; Digit < MAX_TEXT && TextString[Digit] != '\0'; ++Digit)
{
if (TextString[Digit] >= '!' && TextString[Digit] <= 'Z')
{
/************************/
/* Erase previous Text. */
/************************/
if (Active == false || Visible == false || FlashVisible == false)
{
XSetForeground(*xDisplay, *xGC, xColors->xBlack.pixel);
XDrawLines(*xDisplay, *xWindow, *xGC, DisplayFrame[Digit],
DisplayFrame[Digit][MAX_POINTS].x, CoordModeOrigin);
}
else
/**************************/
/* Draw the current Text. */
/**************************/
{
XSetForeground(*xDisplay, *xGC, TextColour);
XDrawLines(*xDisplay, *xWindow, *xGC, DisplayFrame[Digit],
DisplayFrame[Digit][MAX_POINTS].x, CoordModeOrigin);
}
}
}
}
}
|
The SetLocation member function re-initializes the object. It sets the objects properties passed in as arguments. When the object draws it's image to a Window, it does so by drawing a series of lines defined by x-y co-ordinates. All of the objects possible visual representations are defined in an array of arrays of x-y co-ordinates. In the case of this class the first array represents the ASCII characters ! to Z and the second array the x-y co-ordinates which represent each digit.
REF: 9.2
|
void Text::SetLocation(int NewxOffset, int NewyOffset, int NewScale,
int NewFrames, bool NewFlash, const char* NewText,
long NewTextColour, int NewWidth)
{
short Count;
short Length;
short Digit;
short xOffsetOrig;
xOffsetOrig = NewxOffset;
xOffset = NewxOffset;
yOffset = NewyOffset;
Scale = NewScale;
Width = NewWidth;
TextColour = NewTextColour;
Frames = NewFrames;
Flash = NewFlash;
strncpy(TextString, NewText, MAX_TEXT);
Length = strlen(TextString);
for (Count = 0; Count < Length; ++Count)
TextString[Count] = toupper(TextString[Count]);
// !
Letter[0][MAX_POINTS].x = 2;
Letter[0][0].x = 2*Scale;
Letter[0][0].y = 0*Scale;
Letter[0][1].x = 2*Scale;
Letter[0][1].y = 3*Scale;
// "
Letter[1][MAX_POINTS].x = 4;
Letter[1][0].x = 1*Scale;
Letter[1][0].y = 1*Scale;
Letter[1][1].x = 1*Scale;
Letter[1][1].y = 0*Scale;
Letter[1][2].x = 2*Scale;
Letter[1][2].y = 0*Scale;
Letter[1][3].x = 2*Scale;
Letter[1][3].y = 1*Scale;
// #
Letter[2][MAX_POINTS].x = 11;
Letter[2][0].x = 1*Scale;
Letter[2][0].y = 0*Scale;
Letter[2][1].x = 1*Scale;
Letter[2][1].y = 4*Scale;
Letter[2][2].x = 1*Scale;
Letter[2][2].y = 3*Scale;
Letter[2][3].x = 0*Scale;
Letter[2][3].y = 3*Scale;
Letter[2][4].x = 3*Scale;
Letter[2][4].y = 3*Scale;
Letter[2][5].x = 2*Scale;
Letter[2][5].y = 3*Scale;
Letter[2][6].x = 2*Scale;
Letter[2][6].y = 4*Scale;
Letter[2][7].x = 2*Scale;
Letter[2][7].y = 0*Scale;
Letter[2][8].x = 2*Scale;
Letter[2][8].y = 1*Scale;
Letter[2][9].x = 3*Scale;
Letter[2][9].y = 1*Scale;
Letter[2][10].x = 0*Scale;
Letter[2][10].y = 1*Scale;
// $
Letter[3][MAX_POINTS].x = 9;
Letter[3][0].x = 3*Scale;
Letter[3][0].y = 1*Scale;
Letter[3][1].x = 1*Scale;
Letter[3][1].y = 1*Scale;
Letter[3][2].x = 0*Scale;
Letter[3][2].y = 2*Scale;
Letter[3][3].x = 3*Scale;
Letter[3][3].y = 2*Scale;
Letter[3][4].x = 2*Scale;
Letter[3][4].y = 3*Scale;
Letter[3][5].x = 0*Scale;
Letter[3][5].y = 3*Scale;
Letter[3][6].x = 1*Scale;
Letter[3][6].y = 3*Scale;
Letter[3][7].x = 0*Scale;
Letter[3][7].y = 4*Scale;
Letter[3][8].x = 3*Scale;
Letter[3][8].y = 0*Scale;
// %
Letter[4][MAX_POINTS].x = 11;
Letter[4][0].x = 0*Scale;
Letter[4][0].y = 0*Scale;
Letter[4][1].x = 0*Scale;
Letter[4][1].y = 1*Scale;
Letter[4][2].x = 1*Scale;
Letter[4][2].y = 1*Scale;
Letter[4][3].x = 1*Scale;
Letter[4][3].y = 0*Scale;
Letter[4][4].x = 0*Scale;
Letter[4][4].y = 0*Scale;
Letter[4][5].x = 3*Scale;
Letter[4][5].y = 0*Scale;
Letter[4][6].x = 0*Scale;
Letter[4][6].y = 4*Scale;
Letter[4][7].x = 3*Scale;
Letter[4][7].y = 4*Scale;
Letter[4][8].x = 3*Scale;
Letter[4][8].y = 3*Scale;
Letter[4][9].x = 2*Scale;
Letter[4][9].y = 3*Scale;
Letter[4][10].x = 2*Scale;
Letter[4][10].y = 4*Scale;
// &
Letter[5][MAX_POINTS].x = 7;
Letter[5][0].x = 3*Scale;
Letter[5][0].y = 4*Scale;
Letter[5][1].x = 0*Scale;
Letter[5][1].y = 1*Scale;
Letter[5][2].x = 1*Scale;
Letter[5][2].y = 0*Scale;
Letter[5][3].x = 2*Scale;
Letter[5][3].y = 1*Scale;
Letter[5][4].x = 0*Scale;
Letter[5][4].y = 3*Scale;
Letter[5][5].x = 1*Scale;
Letter[5][5].y = 4*Scale;
Letter[5][6].x = 3*Scale;
Letter[5][6].y = 2*Scale;
// '
Letter[6][MAX_POINTS].x = 2;
Letter[6][0].x = 2*Scale;
Letter[6][0].y = 0*Scale;
Letter[6][1].x = 1*Scale;
Letter[6][1].y = 1*Scale;
// (
Letter[7][MAX_POINTS].x = 6;
Letter[7][0].x = 2*Scale;
Letter[7][0].y = 0*Scale;
Letter[7][1].x = 1*Scale;
Letter[7][1].y = 0*Scale;
Letter[7][2].x = 0*Scale;
Letter[7][2].y = 1*Scale;
Letter[7][3].x = 0*Scale;
Letter[7][3].y = 3*Scale;
Letter[7][4].x = 1*Scale;
Letter[7][4].y = 4*Scale;
Letter[7][5].x = 2*Scale;
Letter[7][5].y = 4*Scale;
// )
Letter[8][MAX_POINTS].x = 6;
Letter[8][0].x = 1*Scale;
Letter[8][0].y = 0*Scale;
Letter[8][1].x = 2*Scale;
Letter[8][1].y = 0*Scale;
Letter[8][2].x = 3*Scale;
Letter[8][2].y = 1*Scale;
Letter[8][3].x = 3*Scale;
Letter[8][3].y = 3*Scale;
Letter[8][4].x = 2*Scale;
Letter[8][4].y = 4*Scale;
Letter[8][5].x = 1*Scale;
Letter[8][5].y = 4*Scale;
// *
Letter[9][MAX_POINTS].x = 11;
Letter[9][0].x = 0*Scale;
Letter[9][0].y = 1*Scale;
Letter[9][1].x = 2*Scale;
Letter[9][1].y = 3*Scale;
Letter[9][2].x = 1*Scale;
Letter[9][2].y = 2*Scale;
Letter[9][3].x = 0*Scale;
Letter[9][3].y = 3*Scale;
Letter[9][4].x = 2*Scale;
Letter[9][4].y = 1*Scale;
Letter[9][5].x = 1*Scale;
Letter[9][5].y = 2*Scale;
Letter[9][6].x = 0*Scale;
Letter[9][6].y = 2*Scale;
Letter[9][7].x = 2*Scale;
Letter[9][7].y = 2*Scale;
Letter[9][8].x = 1*Scale;
Letter[9][8].y = 2*Scale;
Letter[9][9].x = 1*Scale;
Letter[9][9].y = 1*Scale;
Letter[9][10].x = 1*Scale;
Letter[9][10].y = 3*Scale;
// +
Letter[10][MAX_POINTS].x = 5;
Letter[10][0].x = 1*Scale;
Letter[10][0].y = 1*Scale;
Letter[10][1].x = 1*Scale;
Letter[10][1].y = 3*Scale;
Letter[10][2].x = 1*Scale;
Letter[10][2].y = 2*Scale;
Letter[10][3].x = 0*Scale;
Letter[10][3].y = 2*Scale;
Letter[10][4].x = 2*Scale;
Letter[10][4].y = 2*Scale;
// ,
Letter[11][MAX_POINTS].x = 2;
Letter[11][0].x = 2*Scale;
Letter[11][0].y = 3*Scale;
Letter[11][1].x = 1*Scale;
Letter[11][1].y = 4*Scale;
// -
Letter[12][MAX_POINTS].x = 2;
Letter[12][0].x = 0*Scale;
Letter[12][0].y = 2*Scale;
Letter[12][1].x = 2*Scale;
Letter[12][1].y = 2*Scale;
// .
Letter[13][MAX_POINTS].x = 2;
Letter[13][0].x = 2*Scale;
Letter[13][0].y = 4*Scale;
Letter[13][1].x = 2*Scale;
Letter[13][1].y = 4*Scale;
// /
Letter[14][MAX_POINTS].x = 2;
Letter[14][0].x = 0*Scale;
Letter[14][0].y = 4*Scale;
Letter[14][1].x = 3*Scale;
Letter[14][1].y = 0*Scale;
// 0
Letter[15][MAX_POINTS].x = 9;
Letter[15][0].x = 1*Scale;
Letter[15][0].y = 0*Scale;
Letter[15][1].x = 2*Scale;
Letter[15][1].y = 0*Scale;
Letter[15][2].x = 3*Scale;
Letter[15][2].y = 1*Scale;
Letter[15][3].x = 3*Scale;
Letter[15][3].y = 3*Scale;
Letter[15][4].x = 2*Scale;
Letter[15][4].y = 4*Scale;
Letter[15][5].x = 1*Scale;
Letter[15][5].y = 4*Scale;
Letter[15][6].x = 0*Scale;
Letter[15][6].y = 3*Scale;
Letter[15][7].x = 0*Scale;
Letter[15][7].y = 1*Scale;
Letter[15][8].x = 1*Scale;
Letter[15][8].y = 0*Scale;
// 1
Letter[16][MAX_POINTS].x = 2;
Letter[16][0].x = 2*Scale;
Letter[16][0].y = 0*Scale;
Letter[16][1].x = 2*Scale;
Letter[16][1].y = 4*Scale;
// 2
Letter[17][MAX_POINTS].x = 9;
Letter[17][0].x = 0*Scale;
Letter[17][0].y = 1*Scale;
Letter[17][1].x = 1*Scale;
Letter[17][1].y = 0*Scale;
Letter[17][2].x = 2*Scale;
Letter[17][2].y = 0*Scale;
Letter[17][3].x = 3*Scale;
Letter[17][3].y = 1*Scale;
Letter[17][4].x = 2*Scale;
Letter[17][4].y = 2*Scale;
Letter[17][5].x = 1*Scale;
Letter[17][5].y = 2*Scale;
Letter[17][6].x = 0*Scale;
Letter[17][6].y = 3*Scale;
Letter[17][7].x = 0*Scale;
Letter[17][7].y = 4*Scale;
Letter[17][8].x = 3*Scale;
Letter[17][8].y = 4*Scale;
// 3
Letter[18][MAX_POINTS].x = 9;
Letter[18][0].x = 0*Scale;
Letter[18][0].y = 0*Scale;
Letter[18][1].x = 2*Scale;
Letter[18][1].y = 0*Scale;
Letter[18][2].x = 3*Scale;
Letter[18][2].y = 1*Scale;
Letter[18][3].x = 2*Scale;
Letter[18][3].y = 2*Scale;
Letter[18][4].x = 1*Scale;
Letter[18][4].y = 2*Scale;
Letter[18][5].x = 2*Scale;
Letter[18][5].y = 2*Scale;
Letter[18][6].x = 3*Scale;
Letter[18][6].y = 3*Scale;
Letter[18][7].x = 2*Scale;
Letter[18][7].y = 4*Scale;
Letter[18][8].x = 0*Scale;
Letter[18][8].y = 4*Scale;
// 4
Letter[19][MAX_POINTS].x = 4;
Letter[19][0].x = 2*Scale;
Letter[19][0].y = 4*Scale;
Letter[19][1].x = 2*Scale;
Letter[19][1].y = 0*Scale;
Letter[19][2].x = 0*Scale;
Letter[19][2].y = 3*Scale;
Letter[19][3].x = 3*Scale;
Letter[19][3].y = 3*Scale;
// 5
Letter[20][MAX_POINTS].x = 7;
Letter[20][0].x = 3*Scale;
Letter[20][0].y = 0*Scale;
Letter[20][1].x = 0*Scale;
Letter[20][1].y = 0*Scale;
Letter[20][2].x = 0*Scale;
Letter[20][2].y = 2*Scale;
Letter[20][3].x = 2*Scale;
Letter[20][3].y = 2*Scale;
Letter[20][4].x = 3*Scale;
Letter[20][4].y = 3*Scale;
Letter[20][5].x = 2*Scale;
Letter[20][5].y = 4*Scale;
Letter[20][6].x = 0*Scale;
Letter[20][6].y = 4*Scale;
// 6
Letter[21][MAX_POINTS].x = 9;
Letter[21][0].x = 3*Scale;
Letter[21][0].y = 0*Scale;
Letter[21][1].x = 1*Scale;
Letter[21][1].y = 0*Scale;
Letter[21][2].x = 0*Scale;
Letter[21][2].y = 1*Scale;
Letter[21][3].x = 0*Scale;
Letter[21][3].y = 3*Scale;
Letter[21][4].x = 1*Scale;
Letter[21][4].y = 4*Scale;
Letter[21][5].x = 2*Scale;
Letter[21][5].y = 4*Scale;
Letter[21][6].x = 3*Scale;
Letter[21][6].y = 3*Scale;
Letter[21][7].x = 3*Scale;
Letter[21][7].y = 2*Scale;
Letter[21][8].x = 0*Scale;
Letter[21][8].y = 2*Scale;
// 7
Letter[22][MAX_POINTS].x = 3;
Letter[22][0].x = 0*Scale;
Letter[22][0].y = 0*Scale;
Letter[22][1].x = 3*Scale;
Letter[22][1].y = 0*Scale;
Letter[22][2].x = 0*Scale;
Letter[22][2].y = 4*Scale;
// 8
Letter[23][MAX_POINTS].x = 9;
Letter[23][0].x = 0*Scale;
Letter[23][0].y = 1*Scale;
Letter[23][1].x = 1*Scale;
Letter[23][1].y = 0*Scale;
Letter[23][2].x = 2*Scale;
Letter[23][2].y = 0*Scale;
Letter[23][3].x = 3*Scale;
Letter[23][3].y = 1*Scale;
Letter[23][4].x = 0*Scale;
Letter[23][4].y = 3*Scale;
Letter[23][5].x = 1*Scale;
Letter[23][5].y = 4*Scale;
Letter[23][6].x = 2*Scale;
Letter[23][6].y = 4*Scale;
Letter[23][7].x = 3*Scale;
Letter[23][7].y = 3*Scale;
Letter[23][8].x = 0*Scale;
Letter[23][8].y = 1*Scale;
// 9
Letter[24][MAX_POINTS].x = 9;
Letter[24][0].x = 0*Scale;
Letter[24][0].y = 4*Scale;
Letter[24][1].x = 2*Scale;
Letter[24][1].y = 4*Scale;
Letter[24][2].x = 3*Scale;
Letter[24][2].y = 3*Scale;
Letter[24][3].x = 3*Scale;
Letter[24][3].y = 1*Scale;
Letter[24][4].x = 2*Scale;
Letter[24][4].y = 0*Scale;
Letter[24][5].x = 1*Scale;
Letter[24][5].y = 0*Scale;
Letter[24][6].x = 0*Scale;
Letter[24][6].y = 1*Scale;
Letter[24][7].x = 0*Scale;
Letter[24][7].y = 2*Scale;
Letter[24][8].x = 3*Scale;
Letter[24][8].y = 2*Scale;
// :
Letter[25][MAX_POINTS].x = 2;
Letter[25][0].x = 2*Scale;
Letter[25][0].y = 1*Scale;
Letter[25][1].x = 2*Scale;
Letter[25][1].y = 3*Scale;
// ;
Letter[26][MAX_POINTS].x = 3;
Letter[26][0].x = 2*Scale;
Letter[26][0].y = 1*Scale;
Letter[26][1].x = 2*Scale;
Letter[26][1].y = 3*Scale;
Letter[26][2].x = 1*Scale;
Letter[26][2].y = 4*Scale;
// <
Letter[27][MAX_POINTS].x = 3;
Letter[27][0].x = 3*Scale;
Letter[27][0].y = 1*Scale;
Letter[27][1].x = 0*Scale;
Letter[27][1].y = 2*Scale;
Letter[27][2].x = 3*Scale;
Letter[27][2].y = 3*Scale;
// =
Letter[28][MAX_POINTS].x = 4;
Letter[28][0].x = 3*Scale;
Letter[28][0].y = 1*Scale;
Letter[28][1].x = 0*Scale;
Letter[28][1].y = 1*Scale;
Letter[28][2].x = 0*Scale;
Letter[28][2].y = 3*Scale;
Letter[28][3].x = 3*Scale;
Letter[28][3].y = 3*Scale;
// >
Letter[29][MAX_POINTS].x = 3;
Letter[29][0].x = 0*Scale;
Letter[29][0].y = 1*Scale;
Letter[29][1].x = 3*Scale;
Letter[29][1].y = 2*Scale;
Letter[29][2].x = 0*Scale;
Letter[29][2].y = 3*Scale;
// ?
Letter[30][MAX_POINTS].x = 7;
Letter[30][0].x = 0*Scale;
Letter[30][0].y = 1*Scale;
Letter[30][1].x = 1*Scale;
Letter[30][1].y = 0*Scale;
Letter[30][2].x = 2*Scale;
Letter[30][2].y = 0*Scale;
Letter[30][3].x = 3*Scale;
Letter[30][3].y = 1*Scale;
Letter[30][4].x = 3*Scale;
Letter[30][4].y = 2*Scale;
Letter[30][5].x = 2*Scale;
Letter[30][5].y = 3*Scale;
Letter[30][6].x = 2*Scale;
Letter[30][6].y = 4*Scale;
// @
Letter[31][MAX_POINTS].x = 12;
Letter[31][0].x = 3*Scale;
Letter[31][0].y = 4*Scale;
Letter[31][1].x = 1*Scale;
Letter[31][1].y = 4*Scale;
Letter[31][2].x = 0*Scale;
Letter[31][2].y = 3*Scale;
Letter[31][3].x = 0*Scale;
Letter[31][3].y = 1*Scale;
Letter[31][4].x = 1*Scale;
Letter[31][4].y = 0*Scale;
Letter[31][5].x = 2*Scale;
Letter[31][5].y = 0*Scale;
Letter[31][6].x = 3*Scale;
Letter[31][6].y = 1*Scale;
Letter[31][7].x = 3*Scale;
Letter[31][7].y = 2*Scale;
Letter[31][8].x = 2*Scale;
Letter[31][8].y = 3*Scale;
Letter[31][9].x = 1*Scale;
Letter[31][9].y = 2*Scale;
Letter[31][10].x = 2*Scale;
Letter[31][10].y = 1*Scale;
Letter[31][11].x = 3*Scale;
Letter[31][11].y = 1*Scale;
// A
Letter[32][MAX_POINTS].x = 6;
Letter[32][0].x = 0*Scale;
Letter[32][0].y = 4*Scale;
Letter[32][1].x = 0*Scale;
Letter[32][1].y = 0*Scale;
Letter[32][2].x = 3*Scale;
Letter[32][2].y = 0*Scale;
Letter[32][3].x = 3*Scale;
Letter[32][3].y = 4*Scale;
Letter[32][4].x = 3*Scale;
Letter[32][4].y = 2*Scale;
Letter[32][5].x = 0*Scale;
Letter[32][5].y = 2*Scale;
// B
Letter[33][MAX_POINTS].x = 8;
Letter[33][0].x = 0*Scale;
Letter[33][0].y = 0*Scale;
Letter[33][1].x = 0*Scale;
Letter[33][1].y = 4*Scale;
Letter[33][2].x = 3*Scale;
Letter[33][2].y = 4*Scale;
Letter[33][3].x = 3*Scale;
Letter[33][3].y = 3*Scale;
Letter[33][4].x = 0*Scale;
Letter[33][4].y = 2*Scale;
Letter[33][5].x = 3*Scale;
Letter[33][5].y = 1*Scale;
Letter[33][6].x = 3*Scale;
Letter[33][6].y = 0*Scale;
Letter[33][7].x = 0*Scale;
Letter[33][7].y = 0*Scale;
// C
Letter[34][MAX_POINTS].x = 6;
Letter[34][0].x = 3*Scale;
Letter[34][0].y = 0*Scale;
Letter[34][1].x = 1*Scale;
Letter[34][1].y = 0*Scale;
Letter[34][2].x = 0*Scale;
Letter[34][2].y = 1*Scale;
Letter[34][3].x = 0*Scale;
Letter[34][3].y = 3*Scale;
Letter[34][4].x = 1*Scale;
Letter[34][4].y = 4*Scale;
Letter[34][5].x = 3*Scale;
Letter[34][5].y = 4*Scale;
// D
Letter[35][MAX_POINTS].x = 6;
Letter[35][0].x = 0*Scale;
Letter[35][0].y = 0*Scale;
Letter[35][1].x = 0*Scale;
Letter[35][1].y = 4*Scale;
Letter[35][2].x = 1*Scale;
Letter[35][2].y = 4*Scale;
Letter[35][3].x = 3*Scale;
Letter[35][3].y = 2*Scale;
Letter[35][4].x = 1*Scale;
Letter[35][4].y = 0*Scale;
Letter[35][5].x = 0*Scale;
Letter[35][5].y = 0*Scale;
// E
Letter[36][MAX_POINTS].x = 7;
Letter[36][0].x = 3*Scale;
Letter[36][0].y = 0*Scale;
Letter[36][1].x = 0*Scale;
Letter[36][1].y = 0*Scale;
Letter[36][2].x = 0*Scale;
Letter[36][2].y = 2*Scale;
Letter[36][3].x = 2*Scale;
Letter[36][3].y = 2*Scale;
Letter[36][4].x = 0*Scale;
Letter[36][4].y = 2*Scale;
Letter[36][5].x = 0*Scale;
Letter[36][5].y = 4*Scale;
Letter[36][6].x = 3*Scale;
Letter[36][6].y = 4*Scale;
// F
Letter[37][MAX_POINTS].x = 6;
Letter[37][0].x = 3*Scale;
Letter[37][0].y = 0*Scale;
Letter[37][1].x = 0*Scale;
Letter[37][1].y = 0*Scale;
Letter[37][2].x = 0*Scale;
Letter[37][2].y = 2*Scale;
Letter[37][3].x = 2*Scale;
Letter[37][3].y = 2*Scale;
Letter[37][4].x = 0*Scale;
Letter[37][4].y = 2*Scale;
Letter[37][5].x = 0*Scale;
Letter[37][5].y = 4*Scale;
// G
Letter[38][MAX_POINTS].x = 6;
Letter[38][0].x = 3*Scale;
Letter[38][0].y = 0*Scale;
Letter[38][1].x = 0*Scale;
Letter[38][1].y = 0*Scale;
Letter[38][2].x = 0*Scale;
Letter[38][2].y = 4*Scale;
Letter[38][3].x = 3*Scale;
Letter[38][3].y = 4*Scale;
Letter[38][4].x = 3*Scale;
Letter[38][4].y = 2*Scale;
Letter[38][5].x = 1*Scale;
Letter[38][5].y = 2*Scale;
// H
Letter[39][MAX_POINTS].x = 6;
Letter[39][0].x = 0*Scale;
Letter[39][0].y = 0*Scale;
Letter[39][1].x = 0*Scale;
Letter[39][1].y = 4*Scale;
Letter[39][2].x = 0*Scale;
Letter[39][2].y = 2*Scale;
Letter[39][3].x = 3*Scale;
Letter[39][3].y = 2*Scale;
Letter[39][4].x = 3*Scale;
Letter[39][4].y = 0*Scale;
Letter[39][5].x = 3*Scale;
Letter[39][5].y = 4*Scale;
// I
Letter[40][MAX_POINTS].x = 6;
Letter[40][0].x = 1*Scale;
Letter[40][0].y = 0*Scale;
Letter[40][1].x = 3*Scale;
Letter[40][1].y = 0*Scale;
Letter[40][2].x = 2*Scale;
Letter[40][2].y = 0*Scale;
Letter[40][3].x = 2*Scale;
Letter[40][3].y = 4*Scale;
Letter[40][4].x = 1*Scale;
Letter[40][4].y = 4*Scale;
Letter[40][5].x = 3*Scale;
Letter[40][5].y = 4*Scale;
// J
Letter[41][MAX_POINTS].x = 6;
Letter[41][0].x = 1*Scale;
Letter[41][0].y = 0*Scale;
Letter[41][1].x = 3*Scale;
Letter[41][1].y = 0*Scale;
Letter[41][2].x = 2*Scale;
Letter[41][2].y = 0*Scale;
Letter[41][3].x = 2*Scale;
Letter[41][3].y = 4*Scale;
Letter[41][4].x = 0*Scale;
Letter[41][4].y = 4*Scale;
Letter[41][5].x = 0*Scale;
Letter[41][5].y = 3*Scale;
// K
Letter[42][MAX_POINTS].x = 6;
Letter[42][0].x = 0*Scale;
Letter[42][0].y = 0*Scale;
Letter[42][1].x = 0*Scale;
Letter[42][1].y = 4*Scale;
Letter[42][2].x = 0*Scale;
Letter[42][2].y = 2*Scale;
Letter[42][3].x = 3*Scale;
Letter[42][3].y = 0*Scale;
Letter[42][4].x = 0*Scale;
Letter[42][4].y = 2*Scale;
Letter[42][5].x = 3*Scale;
Letter[42][5].y = 4*Scale;
// L
Letter[43][MAX_POINTS].x = 3;
Letter[43][0].x = 0*Scale;
Letter[43][0].y = 0*Scale;
Letter[43][1].x = 0*Scale;
Letter[43][1].y = 4*Scale;
Letter[43][2].x = 3*Scale;
Letter[43][2].y = 4*Scale;
// M
Letter[44][MAX_POINTS].x = 6;
Letter[44][0].x = 0*Scale;
Letter[44][0].y = 4*Scale;
Letter[44][1].x = 0*Scale;
Letter[44][1].y = 0*Scale;
Letter[44][2].x = 1*Scale;
Letter[44][2].y = 2*Scale;
Letter[44][3].x = 2*Scale;
Letter[44][3].y = 2*Scale;
Letter[44][4].x = 3*Scale;
Letter[44][4].y = 0*Scale;
Letter[44][5].x = 3*Scale;
Letter[44][5].y = 4*Scale;
// N
Letter[45][MAX_POINTS].x = 4;
Letter[45][0].x = 0*Scale;
Letter[45][0].y = 4*Scale;
Letter[45][1].x = 0*Scale;
Letter[45][1].y = 0*Scale;
Letter[45][2].x = 3*Scale;
Letter[45][2].y = 4*Scale;
Letter[45][3].x = 3*Scale;
Letter[45][3].y = 0*Scale;
// O
Letter[46][MAX_POINTS].x = 9;
Letter[46][0].x = 0*Scale;
Letter[46][0].y = 1*Scale;
Letter[46][1].x = 0*Scale;
Letter[46][1].y = 3*Scale;
Letter[46][2].x = 1*Scale;
Letter[46][2].y = 4*Scale;
Letter[46][3].x = 2*Scale;
Letter[46][3].y = 4*Scale;
Letter[46][4].x = 3*Scale;
Letter[46][4].y = 3*Scale;
Letter[46][5].x = 3*Scale;
Letter[46][5].y = 1*Scale;
Letter[46][6].x = 2*Scale;
Letter[46][6].y = 0*Scale;
Letter[46][7].x = 1*Scale;
Letter[46][7].y = 0*Scale;
Letter[46][8].x = 0*Scale;
Letter[46][8].y = 1*Scale;
// P
Letter[47][MAX_POINTS].x = 5;
Letter[47][0].x = 0*Scale;
Letter[47][0].y = 4*Scale;
Letter[47][1].x = 0*Scale;
Letter[47][1].y = 0*Scale;
Letter[47][2].x = 3*Scale;
Letter[47][2].y = 0*Scale;
Letter[47][3].x = 3*Scale;
Letter[47][3].y = 2*Scale;
Letter[47][4].x = 0*Scale;
Letter[47][4].y = 2*Scale;
// Q
Letter[48][MAX_POINTS].x = 6;
Letter[48][0].x = 2*Scale;
Letter[48][0].y = 3*Scale;
Letter[48][1].x = 3*Scale;
Letter[48][1].y = 4*Scale;
Letter[48][2].x = 0*Scale;
Letter[48][2].y = 4*Scale;
Letter[48][3].x = 0*Scale;
Letter[48][3].y = 0*Scale;
Letter[48][4].x = 3*Scale;
Letter[48][4].y = 0*Scale;
Letter[48][5].x = 3*Scale;
Letter[48][5].y = 4*Scale;
// R
Letter[49][MAX_POINTS].x = 6;
Letter[49][0].x = 0*Scale;
Letter[49][0].y = 4*Scale;
Letter[49][1].x = 0*Scale;
Letter[49][1].y = 0*Scale;
Letter[49][2].x = 3*Scale;
Letter[49][2].y = 0*Scale;
Letter[49][3].x = 3*Scale;
Letter[49][3].y = 2*Scale;
Letter[49][4].x = 0*Scale;
Letter[49][4].y = 2*Scale;
Letter[49][5].x = 3*Scale;
Letter[49][5].y = 4*Scale;
// S
Letter[50][MAX_POINTS].x = 8;
Letter[50][0].x = 3*Scale;
Letter[50][0].y = 0*Scale;
Letter[50][1].x = 1*Scale;
Letter[50][1].y = 0*Scale;
Letter[50][2].x = 0*Scale;
Letter[50][2].y = 1*Scale;
Letter[50][3].x = 1*Scale;
Letter[50][3].y = 2*Scale;
Letter[50][4].x = 2*Scale;
Letter[50][4].y = 2*Scale;
Letter[50][5].x = 3*Scale;
Letter[50][5].y = 3*Scale;
Letter[50][6].x = 2*Scale;
Letter[50][6].y = 4*Scale;
Letter[50][7].x = 0*Scale;
Letter[50][7].y = 4*Scale;
// T
Letter[51][MAX_POINTS].x = 4;
Letter[51][0].x = 1*Scale;
Letter[51][0].y = 0*Scale;
Letter[51][1].x = 3*Scale;
Letter[51][1].y = 0*Scale;
Letter[51][2].x = 2*Scale;
Letter[51][2].y = 0*Scale;
Letter[51][3].x = 2*Scale;
Letter[51][3].y = 4*Scale;
// U
Letter[52][MAX_POINTS].x = 6;
Letter[52][0].x = 0*Scale;
Letter[52][0].y = 0*Scale;
Letter[52][1].x = 0*Scale;
Letter[52][1].y = 3*Scale;
Letter[52][2].x = 1*Scale;
Letter[52][2].y = 4*Scale;
Letter[52][3].x = 2*Scale;
Letter[52][3].y = 4*Scale;
Letter[52][4].x = 3*Scale;
Letter[52][4].y = 3*Scale;
Letter[52][5].x = 3*Scale;
Letter[52][5].y = 0*Scale;
// V
Letter[53][MAX_POINTS].x = 4;
Letter[53][0].x = 0*Scale;
Letter[53][0].y = 0*Scale;
Letter[53][1].x = 1*Scale;
Letter[53][1].y = 4*Scale;
Letter[53][2].x = 2*Scale;
Letter[53][2].y = 4*Scale;
Letter[53][3].x = 3*Scale;
Letter[53][3].y = 0*Scale;
// W
Letter[54][MAX_POINTS].x = 6;
Letter[54][0].x = 0*Scale;
Letter[54][0].y = 0*Scale;
Letter[54][1].x = 0*Scale;
Letter[54][1].y = 4*Scale;
Letter[54][2].x = 1*Scale;
Letter[54][2].y = 3*Scale;
Letter[54][3].x = 2*Scale;
Letter[54][3].y = 3*Scale;
Letter[54][4].x = 3*Scale;
Letter[54][4].y = 4*Scale;
Letter[54][5].x = 3*Scale;
Letter[54][5].y = 0*Scale;
// X
Letter[55][MAX_POINTS].x = 7;
Letter[55][0].x = 1*Scale;
Letter[55][0].y = 0*Scale;
Letter[55][1].x = 2*Scale;
Letter[55][1].y = 2*Scale;
Letter[55][2].x = 3*Scale;
Letter[55][2].y = 0*Scale;
Letter[55][3].x = 2*Scale;
Letter[55][3].y = 2*Scale;
Letter[55][4].x = 1*Scale;
Letter[55][4].y = 4*Scale;
Letter[55][5].x = 2*Scale;
Letter[55][5].y = 2*Scale;
Letter[55][6].x = 3*Scale;
Letter[55][6].y = 4*Scale;
// Y
Letter[56][MAX_POINTS].x = 5;
Letter[56][0].x = 1*Scale;
Letter[56][0].y = 0*Scale;
Letter[56][1].x = 2*Scale;
Letter[56][1].y = 2*Scale;
Letter[56][2].x = 3*Scale;
Letter[56][2].y = 0*Scale;
Letter[56][3].x = 2*Scale;
Letter[56][3].y = 2*Scale;
Letter[56][4].x = 2*Scale;
Letter[56][4].y = 4*Scale;
// Z
Letter[57][MAX_POINTS].x = 4;
Letter[57][0].x = 0*Scale;
Letter[57][0].y = 0*Scale;
Letter[57][1].x = 3*Scale;
Letter[57][1].y = 0*Scale;
Letter[57][2].x = 0*Scale;
Letter[57][2].y = 4*Scale;
Letter[57][3].x = 3*Scale;
Letter[57][3].y = 4*Scale;
for (Digit = 0; Digit < MAX_TEXT && TextString[Digit] != '\0'; ++Digit)
{
if (TextString[Digit] == '\n')
{
xOffset = xOffsetOrig;
yOffset += 5*Scale + 2;
}
else if (TextString[Digit] >= '!' && TextString[Digit] <= 'Z')
{
for (Count = 0; Count < Letter[TextString[Digit]-'!'][MAX_POINTS].x; ++Count)
{
DisplayFrame[Digit][Count].x = Letter[TextString[Digit]-'!'][Count].x
+ xOffset;
DisplayFrame[Digit][Count].y = Letter[TextString[Digit]-'!'][Count].y
+ yOffset;
}
DisplayFrame[Digit][MAX_POINTS].x = Letter[TextString[Digit]-'!'][MAX_POINTS].x;
xOffset += 4*Scale;
}
else
xOffset += 4*Scale;
}
}
|
The text string in an instance of this class can be made visible or hidden at any time by calling one of the function SetVisible. And the current visible state of the instance of this class can be checked by calling the member function GetVisible.
REF: 9.3
|
void Text::SetVisible(short NewVisible)
{
if (NewVisible != LastVisible)
{
Visible = NewVisible;
LastVisible = Visible;
FlashVisible = Visible;
Active = true;
FrameCount = Frames;
}
}
short Text::GetVisible()
{
return Active;
}
|
|
Many instances of the AstroRock class are active at the same time, however this class is not particually complex. The rock object just does what other objects tell it to do.
REF: 10.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef __ASTROROCK_HPP
#define __ASTROROCK_HPP
class AstroRock
{
public:
enum
{
FRAMES = 3,
FRAME_POINTS = 9,
ROCK_WIDTH = 36,
ROCK_HEIGHT = 36,
ERASE = 3,
INACTIVE = 4,
NEW_POSITION = -1,
HYPERSPACE = -500,
};
AstroRock();
~AstroRock();
void Draw(Display** xDisplay, Window* xWindow, GC* xGC, xColorsType* xColors);
void Move();
void SetArea(XRectangle* ClientRect, int NewxOffset = NEW_POSITION,
int NewyOffset = NEW_POSITION, int NewSize = NEW_POSITION);
short Collide(int xPos, int yPos, int Width, int Height);
short GetSize();
void Destroy();
short GetXOffset();
short GetYOffset();
private:
short xMax;
short yMax;
short Size;
short xOffset;
short yOffset;
short xVelocity;
short yVelocity;
XPoint Frame[FRAMES][FRAME_POINTS];
XPoint DisplayFrame[FRAME_POINTS];
XPoint OldFrame[FRAME_POINTS];
};
#endif
|
|
Many instances of the AstroRock class are active at the same time, however this class is not particually complex. The rock object just does what other objects tell it to do. The drawing data, arrays of x-y co-ordinates are defined in the class constructor. The drawing data consists of an array of three sizes of rock. Each instance of the class is set to inactive by default.
REF: 11.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdlib.h>
#include <X11/Xlib.h>
#include "Common.hpp"
#include "AstroRock.hpp"
AstroRock::AstroRock()
{
xMax = 0;
yMax = 0;
xOffset = HYPERSPACE;
yOffset = HYPERSPACE;
xVelocity = 0;
yVelocity = 0;
for (Size = 0; Size < FRAMES; ++Size)
{
Frame[Size][0].x = -30 / (Size*Size+1);
Frame[Size][0].y = -22 / (Size*Size+1);
Frame[Size][1].x = -5 / (Size*Size+1);
Frame[Size][1].y = -32 / (Size*Size+1);
Frame[Size][2].x = +35 / (Size*Size+1);
Frame[Size][2].y = -17 / (Size*Size+1);
Frame[Size][3].x = +25 / (Size*Size+1);
Frame[Size][3].y = +28 / (Size*Size+1);
Frame[Size][4].x = +12 / (Size*Size+1);
Frame[Size][4].y = -2 / (Size*Size+1);
Frame[Size][5].x = +10 / (Size*Size+1);
Frame[Size][5].y = +28 / (Size*Size+1);
Frame[Size][6].x = -20 / (Size*Size+1);
Frame[Size][6].y = +33 / (Size*Size+1);
Frame[Size][7].x = -37 / (Size*Size+1);
Frame[Size][7].y = +5 / (Size*Size+1);
Frame[Size][8].x = -30 / (Size*Size+1);
Frame[Size][8].y = -22 / (Size*Size+1);
}
Size = INACTIVE;
}
AstroRock::~AstroRock()
{
}
|
Each of the game objects has a draw function which draws the current state of the object onto a Window using xWindows calls. The object is only drawn if the instance of the object is flagged as active.
REF: 11.1
|
void AstroRock::Draw(Display** xDisplay, Window* xWindow,
GC* xGC, xColorsType* xColors)
{
short Count;
if (Size < INACTIVE)
{
XSetForeground(*xDisplay, *xGC, xColors->xBlack.pixel);
XDrawLines(*xDisplay, *xWindow, *xGC, OldFrame,
FRAME_POINTS, CoordModeOrigin);
if (Size == ERASE)
Size = INACTIVE;
if (Size < INACTIVE)
{
for (Count = 0; Count < FRAME_POINTS; ++Count)
{
DisplayFrame[Count].x = Frame[Size][Count].x + xOffset;
DisplayFrame[Count].y = Frame[Size][Count].y + yOffset;
}
XSetForeground(*xDisplay, *xGC, xColors->xGreen.pixel);
XDrawLines(*xDisplay, *xWindow, *xGC, DisplayFrame,
FRAME_POINTS, CoordModeOrigin);
for (Count = 0; Count < FRAME_POINTS; ++Count)
{
OldFrame[Count].x = DisplayFrame[Count].x;
OldFrame[Count].y = DisplayFrame[Count].y;
}
}
}
}
|
If the instance of the object is active, move the object by it's current velocity. When the object moves off one side of the display, move it back on to the opposite side of the display.
REF: 11.2
|
void AstroRock::Move()
{
if (Size < INACTIVE)
{
if (xOffset < 0 - ROCK_WIDTH)
xOffset = xMax + ROCK_WIDTH;
else if (xOffset > xMax + ROCK_WIDTH)
xOffset = 0 - ROCK_WIDTH;
if (yOffset < 0 - ROCK_HEIGHT)
yOffset = yMax + ROCK_HEIGHT;
else if (yOffset > yMax + ROCK_HEIGHT)
yOffset = 0 - ROCK_HEIGHT;
xOffset += xVelocity;
yOffset += yVelocity;
}
}
|
Re-initialise the object. Move the object to a specified position, or move the object to a random starting position. Set the velocity of the object to a random velocity, the smaller the object size, the faster the object can move.
REF: 11.3
|
void AstroRock::SetArea(XRectangle* ClientRect,
int NewxOffset, int NewyOffset, int NewSize)
{
xMax = (short)(ClientRect->width - ClientRect->x);
yMax = (short)(ClientRect->height - ClientRect->y);
if (NewxOffset == NEW_POSITION)
{
Size = 0;
if ((short)((float)rand()/RAND_MAX * 2) == false)
{
xOffset = (short)((float)rand()/RAND_MAX * xMax);
yOffset = yMax * (short)((float)rand()/RAND_MAX * 2);
}
else
{
yOffset = (short)((float)rand()/RAND_MAX * yMax);
xOffset = xMax * (short)((float)rand()/RAND_MAX * 2);
}
}
else
{
Size = NewSize;
xOffset = NewxOffset;
yOffset = NewyOffset;
}
do
{
xVelocity = (short)((float)rand()/RAND_MAX*6*(Size+1) - 3*(Size+1));
yVelocity = (short)((float)rand()/RAND_MAX*6*(Size+1) - 3*(Size+1));
} while(xVelocity == 0 || yVelocity == 0);
}
|
If the object is active, check if the object has collided with a specific location. If a collision has occurred, make the object smaller and calculate it's new velocity. Return a flag if a collision occurred.
REF: 11.4
|
short AstroRock::Collide(int xPos, int yPos, int Width, int Height)
{
short Collision = false;
if (Size < INACTIVE)
{
if ((Collision = xPos + Width/2 > xOffset - ROCK_WIDTH / (Size*Size+1)
&& xPos - Width/2 < xOffset + ROCK_WIDTH / (Size*Size+1)
&& yPos + Height/2 > yOffset - ROCK_HEIGHT / (Size*Size+1)
&& yPos - Height/2 < yOffset + ROCK_HEIGHT / (Size*Size+1)) == true)
{
++Size;
do
{
xVelocity = (short)((float)rand()/RAND_MAX*6*(Size+1) - 3*(Size+1));
yVelocity = (short)((float)rand()/RAND_MAX*6*(Size+1) - 3*(Size+1));
} while(xVelocity == 0 || yVelocity == 0);
}
}
return Collision;
}
|
If the object is to be destroyed, move the object off of the display.
REF: 11.5
|
void AstroRock::Destroy()
{
Size = ERASE;
xOffset = HYPERSPACE;
yOffset = HYPERSPACE;
}
|
Return various information about the object if requested.
REF: 11.6
|
short AstroRock::GetSize()
{
return Size;
}
short AstroRock::GetXOffset()
{
return xOffset;
}
short AstroRock::GetYOffset()
{
return yOffset;
}
|
|
This is the most complex object in the application. As it is controlled by the player it requires a lot of manipulation. It also owns other game objects such as AstroShot, which represents the number of shots which the player can fire at any one time. And a number object for keeping track of the players score.
REF: 12.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef __ASTROSHIP_HPP
#define __ASTROSHIP_HPP
class AstroShip
{
public:
enum
{
FRAMES = 63,
ERASE_FRAME = FRAMES+1,
FRAME_POINTS = 5,
THRUST_POINTS = 8,
SHIP_WIDTH = 25,
SHIP_HEIGHT = 25,
SHIP_START_ANGLE = 31,
MAX_EXPLODE_FRAME = 40,
LIFE_XGAP = 30,
LIFE_XOFFSET = 150,
LIFE_YOFFSET = 35,
LIVES_HEIGHT = 34,
LIVES_WIDTH = 100,
MAX_LIVES = 3,
SCORE_XOFFSET = 20,
SCORE_YOFFSET = 20,
SCORE_SCALE = 5,
MAX_SHOTS = 10,
HYPERSPACE = -500,
HYPER_FRAMES = 20,
};
AstroShip();
~AstroShip();
void Draw(Display** xDisplay, Window* xWindow, GC* xGC, xColorsType* xColors);
void IncAngle(short Direction);
void Thrust();
void Shoot();
void Move();
void Reset();
void Hyperspace();
void SetArea(XRectangle* ClientRect, long NewTextColour);
short Collide(int xPos, int yPos, int Width, int Height);
void SetCrash(short NewCrash);
short GetCrash();
short GetXOffset();
short GetYOffset();
short GetWidth();
short GetHeight();
long GetScore();
void SetScore(long NewScore);
short GetLives();
AstroShot& GetShot(short ShotCount);
short GetShotCount();
private:
double OneDegree;
double FrameStep;
short Lives;
short Crash;
short ThrustFlag;
short Fade;
short xMax;
short yMax;
short Angle;
short xOffset;
short yOffset;
short ShotIndex;
float xVelocity;
float yVelocity;
short ExplodeFrame;
short HyperCount;
Number PlayerScore;
AstroShot Shots[MAX_SHOTS];
XPoint LifeFrame[FRAME_POINTS];
XPoint LifeDisplayFrame[FRAME_POINTS];
XPoint Frame[FRAMES][FRAME_POINTS];
XPoint DisplayFrame[FRAME_POINTS*2];
XPoint OldFrame[FRAME_POINTS*2];
XPoint ExplodeDirection[FRAME_POINTS*2];
XPoint ThrustTrail[THRUST_POINTS];
};
#endif
|
|
This is the most complex object in the application. As it is controlled by the player it requires a lot of manipulation. It also owns other game objects such as AstroShot, which represents the number of shots which the player can fire at any one time. And a number object for keeping track of the players score. The drawing data, arrays of x-y co-ordinates are defined in the class constructor. The drawing data consists of an array of sixty three angles of rotation for the ship. The ship's rotation is performed by moving from one index of the array to the next.
REF: 13.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <X11/Xlib.h>
#include "Common.hpp"
#include "Number.hpp"
#include "AstroShot.hpp"
#include "AstroShip.hpp"
AstroShip::AstroShip()
{
OneDegree = (double)6.3 / (double)360;
FrameStep = (double)0.1;
xMax = 0;
yMax = 0;
xOffset = HYPERSPACE;
yOffset = HYPERSPACE;
xVelocity = (short)0;
yVelocity = (short)0;
Crash = false;
ThrustFlag = false;
Fade = 0;
Lives = MAX_LIVES;
ExplodeFrame = 0;
ShotIndex = 0;
HyperCount = false;
Angle = SHIP_START_ANGLE;
LifeFrame[0].x = (long)(19 * sin(FrameStep*Angle + OneDegree*0));
LifeFrame[0].y = (long)(19 * cos(FrameStep*Angle + OneDegree*0));
LifeFrame[1].x = (long)(16 * sin(FrameStep*Angle + OneDegree*140));
LifeFrame[1].y = (long)(16 * cos(FrameStep*Angle + OneDegree*140));
LifeFrame[2].x = (long)(8 * sin(FrameStep*Angle + OneDegree*180));
LifeFrame[2].y = (long)(8 * cos(FrameStep*Angle + OneDegree*180));
LifeFrame[3].x = (long)(16 * sin(FrameStep*Angle + OneDegree*220));
LifeFrame[3].y = (long)(16 * cos(FrameStep*Angle + OneDegree*220));
LifeFrame[4].x = (long)(19 * sin(FrameStep*Angle + OneDegree*0));
LifeFrame[4].y = (long)(19 * cos(FrameStep*Angle + OneDegree*0));
for (Angle = 0; Angle < FRAMES; ++Angle)
{
Frame[Angle][0].x = (long)(16 * sin(FrameStep*Angle + OneDegree*0));
Frame[Angle][0].y = (long)(16 * cos(FrameStep*Angle + OneDegree*0));
Frame[Angle][1].x = (long)(13 * sin(FrameStep*Angle + OneDegree*140));
Frame[Angle][1].y = (long)(13 * cos(FrameStep*Angle + OneDegree*140));
Frame[Angle][2].x = (long)(5 * sin(FrameStep*Angle + OneDegree*180));
Frame[Angle][2].y = (long)(5 * cos(FrameStep*Angle + OneDegree*180));
Frame[Angle][3].x = (long)(13 * sin(FrameStep*Angle + OneDegree*220));
Frame[Angle][3].y = (long)(13 * cos(FrameStep*Angle + OneDegree*220));
Frame[Angle][4].x = (long)(16 * sin(FrameStep*Angle + OneDegree*0));
Frame[Angle][4].y = (long)(16 * cos(FrameStep*Angle + OneDegree*0));
}
Angle = SHIP_START_ANGLE;
}
AstroShip::~AstroShip()
{
}
|
The draw function for the ship is quite complex. It must draw the ship under usual circumstances. It must also draw a thrust trail when the thrust is active. If a life is lost the draw function splits the ship into pieces and fades the pieces of ship out. In addition the function draws the number of ships remaining and the player score.
REF: 13.1
|
void AstroShip::Draw(Display** xDisplay, Window* xWindow, GC* xGC, xColorsType* xColors)
{
short Count;
short LifeCount;
char FadeColor[BUFF_SIZE+1];
int xScreen;
Colormap xColormap;
for (Count = 0; Count < MAX_SHOTS; ++Count)
Shots[Count].Draw(xDisplay, xWindow, xGC, xColors);
if (Lives != false || ExplodeFrame != MAX_EXPLODE_FRAME)
{
/*********************/
/* Draw intact ship. */
/*********************/
if (Crash == false)
{
/********************************/
/* Plot ships current position. */
/********************************/
for (Count = 0; Count < FRAME_POINTS; ++Count)
{
DisplayFrame[Count].x = Frame[Angle][Count].x + xOffset;
DisplayFrame[Count].y = Frame[Angle][Count].y + yOffset;
}
XSetForeground(*xDisplay, *xGC, xColors->xBlack.pixel);
if (ExplodeFrame >= ERASE_FRAME)
{
ExplodeFrame = false;
/************************************/
/* Erase previous position of ship. */
/************************************/
for (Count = 0; Count < FRAME_POINTS*2; Count += 2)
XDrawLine(*xDisplay, *xWindow, *xGC, OldFrame[Count].x,
OldFrame[Count].y, OldFrame[Count+1].x, OldFrame[Count+1].y);
}
/************************************/
/* Erase previous position of ship. */
/************************************/
XDrawLines(*xDisplay, *xWindow, *xGC, OldFrame,
FRAME_POINTS, CoordModeOrigin);
/******************************************/
/* Draw the ship in the current position. */
/******************************************/
XSetForeground(*xDisplay, *xGC, xColors->xGreen.pixel);
XDrawLines(*xDisplay, *xWindow, *xGC, DisplayFrame,
FRAME_POINTS, CoordModeOrigin);
/******************/
/* Remove thrust. */
/******************/
XSetForeground(*xDisplay, *xGC, xColors->xBlack.pixel);
for (Count = 0; Count < THRUST_POINTS; ++Count)
XDrawLine(*xDisplay, *xWindow, *xGC, ThrustTrail[Count].x,
ThrustTrail[Count].y, ThrustTrail[Count].x + 1,
ThrustTrail[Count].y + 1);
/*****************************************/
/* Add thrust point if currently active. */
/*****************************************/
if (ThrustFlag == true)
{
XSetForeground(*xDisplay, *xGC, xColors->xGreen.pixel);
for (Count = 0; Count < THRUST_POINTS; ++Count)
{
ThrustTrail[Count].x = xOffset + (short)((float)rand()/RAND_MAX * 7)-3
+ (long)(15 * sin(FrameStep*Angle + OneDegree*180));
ThrustTrail[Count].y = yOffset + (short)((float)rand()/RAND_MAX * 7)-3
+ (long)(15 * cos(FrameStep*Angle + OneDegree*180));
XDrawLine(*xDisplay, *xWindow, *xGC, ThrustTrail[Count].x,
ThrustTrail[Count].y, ThrustTrail[Count].x + 1,
ThrustTrail[Count].y + 1);
}
ThrustFlag = false;
}
/******************************************/
/* Plot ships current position, */
/* next time it will be the old position. */
/******************************************/
for (Count = 0; Count < FRAME_POINTS; ++Count)
{
OldFrame[Count].x = DisplayFrame[Count].x;
OldFrame[Count].y = DisplayFrame[Count].y;
}
}
else
{
if (ExplodeFrame == false)
{
--Lives;
/************************************/
/* Erase previous position of ship. */
/************************************/
XSetForeground(*xDisplay, *xGC, xColors->xBlack.pixel);
XDrawLines(*xDisplay, *xWindow, *xGC, OldFrame,
FRAME_POINTS, CoordModeOrigin);
/******************/
/* Remove thrust. */
/******************/
for (Count = 0; Count < THRUST_POINTS; ++Count)
{
XDrawLine(*xDisplay, *xWindow, *xGC, ThrustTrail[Count].x,
ThrustTrail[Count].y, ThrustTrail[Count].x + 1,
ThrustTrail[Count].y + 1);
}
/**************************************************/
/* Set direction of individual lines of the ship. */
/**************************************************/
for (Count = 0; Count < FRAME_POINTS*2; Count += 2)
{
do
{
ExplodeDirection[Count].x = (short)((float)rand()/RAND_MAX * 10)-5;
} while (ExplodeDirection[Count].x == 0);
do
{
ExplodeDirection[Count].y = (short)((float)rand()/RAND_MAX * 10)-5;
} while (ExplodeDirection[Count].y == 0);
ExplodeDirection[Count+1].x = ExplodeDirection[Count].x;
ExplodeDirection[Count+1].y = ExplodeDirection[Count].y;
}
/********************************************/
/* Split polygon shape into seperate lines. */
/********************************************/
DisplayFrame[0].x = Frame[Angle][FRAME_POINTS-1].x + xOffset;
DisplayFrame[0].y = Frame[Angle][FRAME_POINTS-1].y + yOffset;
OldFrame[0].x = Frame[Angle][FRAME_POINTS-1].x + xOffset;
OldFrame[0].y = Frame[Angle][FRAME_POINTS-1].y + yOffset;
DisplayFrame[FRAME_POINTS*2-1].x = Frame[Angle][FRAME_POINTS-1].x + xOffset;
DisplayFrame[FRAME_POINTS*2-1].y = Frame[Angle][FRAME_POINTS-1].y + yOffset;
OldFrame[FRAME_POINTS*2-1].x = Frame[Angle][FRAME_POINTS-1].x + xOffset;
OldFrame[FRAME_POINTS*2-1].y = Frame[Angle][FRAME_POINTS-1].y + yOffset;
for (Count = 0; Count < FRAME_POINTS-1; ++Count)
{
DisplayFrame[Count*2+1].x = Frame[Angle][Count].x + xOffset;
DisplayFrame[Count*2+1].y = Frame[Angle][Count].y + yOffset;
DisplayFrame[Count*2+2].x = Frame[Angle][Count].x + xOffset;
DisplayFrame[Count*2+2].y = Frame[Angle][Count].y + yOffset;
OldFrame[Count*2+1].x = Frame[Angle][Count].x + xOffset;
OldFrame[Count*2+1].y = Frame[Angle][Count].y + yOffset;
OldFrame[Count*2+2].x = Frame[Angle][Count].x + xOffset;
OldFrame[Count*2+2].y = Frame[Angle][Count].y + yOffset;
}
}
/************************************/
/* Erase previous position of ship. */
/************************************/
XSetForeground(*xDisplay, *xGC, xColors->xBlack.pixel);
for (Count = 0; Count < FRAME_POINTS*2; Count += 2)
XDrawLine(*xDisplay, *xWindow, *xGC, OldFrame[Count].x,
OldFrame[Count].y, OldFrame[Count+1].x, OldFrame[Count+1].y);
/******************************************/
/* Draw the ship in the current position. */
/******************************************/
if (ExplodeFrame < MAX_EXPLODE_FRAME -1)
{
XSetForeground(*xDisplay, *xGC, xColors->xGreen.pixel);
for (Count = 0; Count < FRAME_POINTS*2; Count += 2)
{
DisplayFrame[Count].x += ExplodeDirection[Count].x;
DisplayFrame[Count].y += ExplodeDirection[Count].y;
DisplayFrame[Count+1].x += ExplodeDirection[Count+1].x;
DisplayFrame[Count+1].y += ExplodeDirection[Count+1].y;
XDrawLine(*xDisplay, *xWindow, *xGC, DisplayFrame[Count].x,
DisplayFrame[Count].y, DisplayFrame[Count+1].x,
DisplayFrame[Count+1].y);
}
/******************************************/
/* Plot ships current position, */
/* next time it will be the old position. */
/******************************************/
for (Count = 0; Count < FRAME_POINTS*2; ++Count)
{
OldFrame[Count].x = DisplayFrame[Count].x;
OldFrame[Count].y = DisplayFrame[Count].y;
}
}
/************************/
/* Reset for next life. */
/************************/
++ExplodeFrame;
if (Lives != false && ExplodeFrame == MAX_EXPLODE_FRAME)
{
ExplodeFrame = false;
Crash = false;
ThrustFlag = false;
Angle = SHIP_START_ANGLE;
xOffset = xMax/2;
yOffset = yMax/2;
xVelocity = (short)0;
yVelocity = (short)0;
}
}
/****************************/
/* Display remaining lives. */
/****************************/
for (LifeCount = 0; LifeCount < MAX_LIVES; ++LifeCount)
{
/********************************/
/* Plot ships current position. */
/********************************/
for (Count = 0; Count < FRAME_POINTS; ++Count)
{
LifeDisplayFrame[Count].x = LifeFrame[Count].x
+ (xMax - LIFE_XOFFSET) + (LifeCount+1)*LIFE_XGAP;
LifeDisplayFrame[Count].y = LifeFrame[Count].y + LIFE_YOFFSET;
}
/************************************/
/* Erase previous position of ship. */
/************************************/
XSetForeground(*xDisplay, *xGC, xColors->xBlack.pixel);
XDrawLines(*xDisplay, *xWindow, *xGC, LifeDisplayFrame,
FRAME_POINTS, CoordModeOrigin);
/******************************************/
/* Draw the ship in the current position. */
/******************************************/
if (Lives > LifeCount)
{
XSetForeground(*xDisplay, *xGC, xColors->xGreen.pixel);
XDrawLines(*xDisplay, *xWindow, *xGC, LifeDisplayFrame,
FRAME_POINTS, CoordModeOrigin);
}
}
}
/******************/
/* Redraw scores. */
/******************/
PlayerScore.Draw(xDisplay, xWindow, xGC, xColors);
}
|
The IncAngle member function allows the ship to be rotated clockwise or anti-clockwise.
REF: 13.2
|
void AstroShip::IncAngle(short Direction)
{
if (Crash == false)
{
if (Direction == false)
{
++Angle;
if (Angle >= FRAMES)
Angle = 0;
}
else
{
--Angle;
if (Angle < 0)
Angle = FRAMES-1;
}
}
}
|
The thrust member function increases the velocity of this ship in the direction it is pointing. To slow the ship down the player has to turn the ship in the opposite direction and thrust.
REF: 13.3
|
void AstroShip::Thrust()
{
ThrustFlag = true;
xVelocity += (float)sin(FrameStep*Angle + OneDegree*0);
yVelocity += (float)cos(FrameStep*Angle + OneDegree*0);
// PlaySound("Thrust.WAV", NULL, SND_ASYNC);
}
|
The Shoot member function allows a player to fire a shot from the ship. There are an array of instances of the shot object which can be fired simultaneously.
REF: 13.4
|
void AstroShip::Shoot()
{
if (Crash == false)
{
// PlaySound("Shoot.WAV", NULL, SND_ASYNC);
Shots[ShotIndex].SetArea(xMax, yMax, xOffset, yOffset,
xVelocity + 10*(float)sin(FrameStep*Angle + OneDegree*0),
yVelocity + 10*(float)cos(FrameStep*Angle + OneDegree*0));
if (++ShotIndex == MAX_SHOTS)
ShotIndex = 0;
}
}
|
The ship moves like other objects. However the ship must also take care of moving its shots and handle when the player moves the ship into hyperspace. When hyperspace is activated, the ship disappears for a few seconds and then reappears at a random location.
REF: 13.5
|
void AstroShip::Move()
{
short Count;
if (HyperCount != false)
{
--HyperCount;
if (HyperCount == false)
{
xOffset = (short)((float)rand()/RAND_MAX * (xMax - 2*SHIP_WIDTH));
yOffset = (short)((float)rand()/RAND_MAX * (yMax - 2*SHIP_HEIGHT));
}
}
for (Count = 0; Count < MAX_SHOTS; ++Count)
Shots[Count].Move();
if (Crash == false)
{
if (xOffset < 0 - SHIP_WIDTH)
xOffset = xMax + SHIP_WIDTH;
else if (xOffset > xMax + SHIP_WIDTH)
xOffset = 0 - SHIP_WIDTH;
if (yOffset < 0 - SHIP_HEIGHT)
yOffset = yMax + SHIP_HEIGHT;
else if (yOffset > yMax + SHIP_HEIGHT)
yOffset = 0 - SHIP_HEIGHT;
xOffset += (short)xVelocity;
yOffset += (short)yVelocity;
}
}
|
The Reset member function takes care of re-initialising the ship at the start of a new game.
REF: 13.6
|
void AstroShip::Reset()
{
if (Lives == false)
{
ExplodeFrame = ERASE_FRAME;
Crash = false;
ThrustFlag = false;
Fade = 0;
Angle = SHIP_START_ANGLE;
xOffset = xMax/2;
yOffset = yMax/2;
xVelocity = (short)0;
yVelocity = (short)0;
Lives = MAX_LIVES;
PlayerScore.SetNumber(0);
}
}
|
The SetArea member function allows an instance of this class to be initialized when the application starts up.
REF: 13.7
|
void AstroShip::SetArea(XRectangle* ClientRect, long NewTextColour)
{
xMax = (short)(ClientRect->width - ClientRect->x);
yMax = (short)(ClientRect->height - ClientRect->y);
xOffset = xMax/2;
yOffset = yMax/2;
PlayerScore.SetLocation(SCORE_XOFFSET, SCORE_YOFFSET, SCORE_SCALE, NewTextColour);
}
|
The Hyperspace member function is used to initiate a player activating the ship's hyperspace mode.
REF: 13.8
|
void AstroShip::Hyperspace()
{
if (Crash == false && HyperCount == false)
{
HyperCount = HYPER_FRAMES;
xOffset = HYPERSPACE;
yOffset = HYPERSPACE;
xVelocity = (float)0;
yVelocity = (float)0;
}
}
|
The Collide member function checks to see if the ship has collided with a specific area.
REF: 13.9
|
short AstroShip::Collide(int xPos, int yPos, int Width, int Height)
{
short Collision = false;
if (Crash == false)
if ((Collision = xPos + Width/2 > xOffset - SHIP_WIDTH && xPos
- Width/2 < xOffset + SHIP_WIDTH && yPos + Height/2
> yOffset - SHIP_HEIGHT && yPos
- Height/2 < yOffset + SHIP_HEIGHT) == true)
Crash = true;
return Collision;
}
|
The remaining member functions allow properties of an instance of the ship object to be set and read.
REF: 13.10
|
void AstroShip::SetCrash(short NewCrash)
{
// if (Crash == FALSE && NewCrash == TRUE)
// PlaySound("ShipBlow.WAV", NULL, SND_ASYNC);
Crash = NewCrash;
}
short AstroShip::GetCrash()
{
return Crash;
}
short AstroShip::GetXOffset()
{
return xOffset;
}
short AstroShip::GetYOffset()
{
return yOffset;
}
short AstroShip::GetWidth()
{
return SHIP_WIDTH;
}
short AstroShip::GetHeight()
{
return SHIP_HEIGHT;
}
long AstroShip::GetScore()
{
return PlayerScore.GetNumber();
}
void AstroShip::SetScore(long NewScore)
{
PlayerScore.SetNumber(NewScore);
}
short AstroShip::GetLives()
{
return Lives;
}
AstroShot& AstroShip::GetShot(short ShotCount)
{
return Shots[ShotCount];
}
short AstroShip::GetShotCount()
{
return MAX_SHOTS;
}
|
|
The AstroShot ojbect is used by two other object, the Ship object to allow the player to shoot and the UFO object to allow the UFO to shoot at the player's ship.
REF: 14.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef __ASTROSHOT_HPP
#define __ASTROSHOT_HPP
class AstroShot
{
public:
enum
{
SMALL_SHOT = 0,
LARGE_SHOT = 1,
SMALL_SHOT_FRAMES = 40,
LARGE_SHOT_FRAMES = 20,
ERASE_FRAME = 1,
HYPERSPACE = -500,
};
AstroShot();
~AstroShot();
void Draw(Display** xDisplay, Window* xWindow, GC* xGC, xColorsType* xColors);
void Move();
void SetArea(int NewxMax, int NewyMax, int NewxOffset, int NewyOffset,
float NewxVelocity, float NewyVelocity, int Size = SMALL_SHOT);
short GetXOffset();
short GetYOffset();
void Destroy();
short Active();
private:
int xMax;
int yMax;
int xOffset;
int yOffset;
int OldxOffset;
int OldyOffset;
float xVelocity;
float yVelocity;
int Size;
short FrameCount;
};
#endif
|
|
The AstroShot ojbect is used by two other object, the Ship object to allow the player to shoot and the UFO object to allow the UFO to shoot at the player's ship.
REF: 15.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <X11/Xlib.h>
#include "Common.hpp"
#include "AstroShot.hpp"
AstroShot::AstroShot()
{
xMax = 0;
yMax = 0;
xOffset = HYPERSPACE;
yOffset = HYPERSPACE;
OldxOffset = HYPERSPACE;
OldyOffset = HYPERSPACE;
xVelocity = (float)0;
yVelocity = (float)0;
Size = SMALL_SHOT;
FrameCount = 0;
}
AstroShot::~AstroShot()
{
}
|
The object can be drawn as a small shot for the players ship and a larger shot for the UFO shot.
REF: 15.1
|
void AstroShot::Draw(Display** xDisplay, Window* xWindow,
GC* xGC, xColorsType* xColors)
{
if (FrameCount != false)
{
if (FrameCount == ERASE_FRAME)
FrameCount = false;
if (Size == SMALL_SHOT)
{
XSetForeground(*xDisplay, *xGC, xColors->xBlack.pixel);
XFillRectangle(*xDisplay, *xWindow, *xGC,
OldxOffset, OldyOffset, 2, 2);
if (FrameCount != false)
{
XSetForeground(*xDisplay, *xGC, xColors->xGreen.pixel);
XFillRectangle(*xDisplay, *xWindow, *xGC,
xOffset, yOffset, 2, 2);
OldxOffset = xOffset;
OldyOffset = yOffset;
}
}
else
{
XSetForeground(*xDisplay, *xGC, xColors->xBlack.pixel);
XFillRectangle(*xDisplay, *xWindow, *xGC,
OldxOffset, OldyOffset, 4, 4);
if (FrameCount != false)
{
XSetForeground(*xDisplay, *xGC, xColors->xGreen.pixel);
XFillRectangle(*xDisplay, *xWindow, *xGC,
xOffset, yOffset, 4, 4);
OldxOffset = xOffset;
OldyOffset = yOffset;
}
}
}
}
|
The shot moves in a simple fashion and when it moves off of one side of the display, it moves back on to the opposite side of the display.
REF: 15.2
|
void AstroShot::Move()
{
if (FrameCount > ERASE_FRAME)
{
if (xOffset < 0)
xOffset = xMax;
else if (xOffset > xMax)
xOffset = 0;
if (yOffset < 0)
yOffset = yMax;
else if (yOffset > yMax)
yOffset = 0;
xOffset += (short)xVelocity;
yOffset += (short)yVelocity;
--FrameCount;
}
}
|
The SetArea member function is used to initiate an instance of a shot.
REF: 15.3
|
void AstroShot::SetArea(int NewxMax, int NewyMax, int NewxOffset,
int NewyOffset, float NewxVelocity,
float NewyVelocity, int NewSize)
{
xMax = NewxMax;
yMax = NewyMax;
xOffset = NewxOffset;
yOffset = NewyOffset;
xVelocity = NewxVelocity;
yVelocity = NewyVelocity;
Size = NewSize;
if (Size == LARGE_SHOT)
FrameCount = LARGE_SHOT_FRAMES;
else
FrameCount = SMALL_SHOT_FRAMES;
}
|
Some properties of the object can be read with member functions.
REF: 15.4
|
short AstroShot::GetXOffset()
{
return xOffset;
}
short AstroShot::GetYOffset()
{
return yOffset;
}
short AstroShot::Active()
{
return (FrameCount != false);
}
|
When a shot is destroyed it is removed from the display area.
REF: 15.5
|
void AstroShot::Destroy()
{
FrameCount = ERASE_FRAME;
xOffset = HYPERSPACE;
yOffset = HYPERSPACE;
}
|
|
A UFO can appear at any random time during a game and can be a small or large version. The UFO will continually shoot a single shot in random directions, making the play area a very hazardous place.
REF: 16.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef __ASTRO_UFO_HPP
#define __ASTRO_UFO_HPP
class AstroUFO
{
public:
enum
{
FRAMES = 2,
FRAME_POINTS = 12,
UFO_WIDTH = 16,
UFO_HEIGHT = 6,
INACTIVE = 3,
ERASE = 4,
HYPERSPACE = -500,
};
AstroUFO();
~AstroUFO();
void Draw(Display** xDisplay, Window* xWindow, GC* xGC, xColorsType* xColors);
void Move();
void SetArea(XRectangle* ClientRect);
short Collide(int xPos, int yPos, int Width, int Height);
short GetSize();
void Destroy();
short GetXOffset();
short GetYOffset();
AstroShot& GetShot();
private:
int xMax;
int yMax;
int Size;
int xOffset;
int yOffset;
int xVelocity;
int yVelocity;
AstroShot Shot;
XPoint Frame[FRAMES][FRAME_POINTS];
XPoint DisplayFrame[FRAME_POINTS];
XPoint OldFrame[FRAME_POINTS];
};
#endif
|
|
A UFO can appear at any random time during a game and can be a small or large version. The UFO will continually shoot a single shot in random directions, making the play area a very hazardous place.
REF: 17.0
|
// Linux Asteroids Clone
// Copyright (C) 1997 Jason Birch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdlib.h>
#include <X11/Xlib.h>
#include "Common.hpp"
#include "AstroShot.hpp"
#include "Astro_UFO.hpp"
AstroUFO::AstroUFO()
{
xMax = 0;
yMax = 0;
xOffset = HYPERSPACE;
yOffset = HYPERSPACE;
xVelocity = 0;
yVelocity = 0;
for (Size = 0; Size < FRAMES; ++Size)
{
Frame[Size][0].x = -(8 + (Size+1)*3);
Frame[Size][0].y = -(0 + (Size+1));
Frame[Size][1].x = -(0 + (Size+1));
Frame[Size][1].y = -(3 + (Size+1)*3);
Frame[Size][2].x = +(0 + (Size+1));
Frame[Size][2].y = -(3 + (Size+1)*3);
Frame[Size][3].x = +(8 + (Size+1)*3);
Frame[Size][3].y = -(0 + (Size+1));
Frame[Size][4].x = -(8 + (Size+1)*3);
Frame[Size][4].y = -(0 + (Size+1));
Frame[Size][5].x = -(8 + (Size+1)*3);
Frame[Size][5].y = +(0 + (Size+1));
Frame[Size][6].x = +(8 + (Size+1)*3);
Frame[Size][6].y = +(0 + (Size+1));
Frame[Size][7].x = +(8 + (Size+1)*3);
Frame[Size][7].y = -(0 + (Size+1));
Frame[Size][8].x = +(8 + (Size+1)*3);
Frame[Size][8].y = +(0 + (Size+1));
Frame[Size][9].x = +(0 + (Size+1));
Frame[Size][9].y = +(3 + (Size+1)*3);
Frame[Size][10].x = -(0 + (Size+1));
Frame[Size][10].y = +(3 + (Size+1)*3);
Frame[Size][11].x = -(8 + (Size+1)*3);
Frame[Size][11].y = +(0 + (Size+1));
}
Size = INACTIVE;
}
AstroUFO::~AstroUFO()
{
}
|
Drawing an instance of a UFO is a simple process.
REF: 17.1
|
void AstroUFO::Draw(Display** xDisplay, Window* xWindow, GC* xGC, xColorsType* xColors)
{
short Count;
Shot.Draw(xDisplay, xWindow, xGC, xColors);
if (Size != INACTIVE)
{
XSetForeground(*xDisplay, *xGC, xColors->xBlack.pixel);
XDrawLines(*xDisplay, *xWindow, *xGC, OldFrame,
FRAME_POINTS, CoordModeOrigin);
if (Size == ERASE)
Size = INACTIVE;
if (Size < INACTIVE)
{
for (Count = 0; Count < FRAME_POINTS; ++Count)
{
DisplayFrame[Count].x = Frame[Size][Count].x + xOffset;
DisplayFrame[Count].y = Frame[Size][Count].y + yOffset;
}
XSetForeground(*xDisplay, *xGC, xColors->xGreen.pixel);
XDrawLines(*xDisplay, *xWindow, *xGC, DisplayFrame,
FRAME_POINTS, CoordModeOrigin);
for (Count = 0; Count < FRAME_POINTS; ++Count)
{
OldFrame[Count].x = DisplayFrame[Count].x;
OldFrame[Count].y = DisplayFrame[Count].y;
}
}
}
}
|
As an instance of a UFO moves, it randomly changes direction to a new random direction making it unpredictable. A UFO can appear at any time on the left or right of the display and then move to the opposite side of the display before disappearing.
REF: 17.2
|
void AstroUFO::Move()
{
short ShotDirection;
if (Shot.Active() == true)
Shot.Move();
if (Size != INACTIVE)
{
if (Shot.Active() == false)
{
ShotDirection = (short)((float)rand()/RAND_MAX * 4);
switch (ShotDirection)
{
case 0:
{
Shot.SetArea(xMax, yMax, xOffset, yOffset,
(float)-8, (float)-8, AstroShot::LARGE_SHOT);
break;
}
case 1:
{
Shot.SetArea(xMax, yMax, xOffset, yOffset,
(float)-8, (float)+8, AstroShot::LARGE_SHOT);
break;
}
case 2:
{
Shot.SetArea(xMax, yMax, xOffset, yOffset,
(float)+8, (float)-8, AstroShot::LARGE_SHOT);
break;
}
case 3:
{
Shot.SetArea(xMax, yMax, xOffset, yOffset,
(float)+8, (float)+8, AstroShot::LARGE_SHOT);
break;
}
}
}
if ((short)((float)rand()/RAND_MAX * 10) == false)
yVelocity = (short)((float)rand()/RAND_MAX * ((Size+2)*10)) - ((Size+2)*5);
if (xOffset < 0 - UFO_WIDTH)
Size = INACTIVE;
else if (xOffset > xMax + UFO_WIDTH)
Size = INACTIVE;
if (yOffset < 0)
yOffset = 0;
else if (yOffset > yMax)
yOffset = yMax;
xOffset += xVelocity;
yOffset += yVelocity;
}
else if ((short)((float)rand()/RAND_MAX * 1000) == false)
{
Size = (short)((float)rand()/RAND_MAX * FRAMES);
yOffset = (short)((float)rand()/RAND_MAX * yMax);
if ((short)((float)rand()/RAND_MAX * 2) == false)
{
xOffset = 0 - UFO_WIDTH;
xVelocity = 3 * (2 - Size+1);
}
else
{
xOffset = xMax + UFO_WIDTH;
xVelocity = -3 * (2 - Size+1);
}
yVelocity = (short)((float)rand()/RAND_MAX * 5) - 3;
}
}
|
Initialize an instance of a UFO at the start-up of the application.
REF: 17.3
|
void AstroUFO::SetArea(XRectangle* ClientRect)
{
xMax = (short)(ClientRect->width - ClientRect->x);
yMax = (short)(ClientRect->height - ClientRect->y);
}
|
A check can be made to see if an instance of a UFO has collided with a specific area.
REF: 17.4
|
short AstroUFO::Collide(int xPos, int yPos, int Width, int Height)
{
short Collision = false;
if (Size < INACTIVE)
if ((Collision = xPos + Width/2 > xOffset - UFO_WIDTH / (Size*Size+1)
&& xPos - Width/2 < xOffset + UFO_WIDTH / (Size*Size+1)
&& yPos + Height/2 > yOffset - UFO_HEIGHT / (Size*Size+1)
&& yPos - Height/2 < yOffset + UFO_HEIGHT / (Size*Size+1)) == true)
Destroy();
return Collision;
}
|
When a UFO is destroyed, remove it from the display.
REF: 17.5
|
void AstroUFO::Destroy()
{
Size = ERASE;
xOffset = HYPERSPACE;
yOffset = HYPERSPACE;
}
|
Various properties of a UFO can be read.
REF: 17.6
|
short AstroUFO::GetSize()
{
return Size;
}
short AstroUFO::GetXOffset()
{
return xOffset;
}
short AstroUFO::GetYOffset()
{
return yOffset;
}
AstroShot& AstroUFO::GetShot()
{
return Shot;
}
|
|
|