Planetoid Game - Main Class Design
The entire Planetoid game was designed and built around an object-oriented environment. Every object in the game
is an instance of a class, and they each interact with other objects on the screen.
Sprite Class
The Sprite class is the basis of all other classes in this game. A sprite is any object on the screen that has 3D
cooridinates and that can possibly move.
The main definition code for the Sprite class is as follows:
/* Sprite - this represents any moveable object on the screen */
class Sprite {
protected:
float x, y, z; // position of enemy
float vx, vy, vz; // speed of enemy
bool alive; // state of enemy
float timer; // time since last movement
float radius; // radius of bounding circle
virtual void updateAllTiming(float t) {};
public:
Sprite *next;
Sprite();
Sprite(float, float, float, float, float, float);
virtual void move();
virtual void draw() {};
bool shouldDie();
void setRadius(float r) { radius = r; };
bool collides(Sprite *other);
bool collides(Sprite *other, float r);
void setAlive(bool a) { alive = a; };
bool isAlive() { return alive; };
float getX() { return x; };
float getY() { return y; };
float getZ() { return z; };
float distance(Sprite *other);
virtual void remove() {};
void updateTiming(float t) { timer += t; updateAllTiming(t); };
};
Those functions labeled "virtual" are ones that can be overridden by sub-classes. The most important
one to override is the draw() function, which will define how the object will appear on the screen. As you
can see from this code the Sprite class alone will not display anything on the screen.
Powerup Class
The Powerup class represents any of the five different powerups on the screen. I chose to include all the powerups
in this class rather than forcing sub-classing in order to keep the programming simpler. Since each powerup is so
similar there was no need to further expand on this class.
The code for the Powerup class is as follows:
/* Powerup - this represents powerups that the player can shoot at */
class Powerup: public Sprite {
private:
int type;
public:
Powerup();
Powerup(int, float, float, float, float, float, float);
void draw();
int getType() { return type; };
};
The type attribute specifies which kind of powerup the class is. These are predefined as follows:
// powerup definitions
#define POWERUP_HP 0 // healing powerup
#define POWERUP_DMG 1 // weapon damage upgrade
#define POWERUP_UPGRADE 2 // weapon upgrade
#define POWERUP_ABOMB 3 // additional abomb
#define POWERUP_PASS 4 // weapon pass-through upgrade
Enemy Class
The Enemy class is the basis for all enemies on the screen. The base Enemy class is used
directly for all normal enemies.
The code is as follows:
/* Enemy - this class represents any type of enemy (whether intelligent or not) that will be
trying to kill the player */
class Enemy : public Sprite {
protected:
int hitPoints; // hitpoints of enemy
int r, g, b; // color of enemy
int type; // type of enemy
public:
Enemy();
Enemy(float, float, float, float, float, float);
void draw();
void setHitPoints(int h) { hitPoints = h; };
void hit(Projectile *p);
int getHitPoints() { return hitPoints; };
void setColor(int rc, int gc, int bc) { r = rc; g = gc; b = bc; };
void setType(int t) { type = t; };
void die();
};
The hitPoints determine both how many hits it will take to kill the enemy and how much damage it will
do to the player when it collides with the spaceship.
FiringEnemy Class
The FiringEnemy class represents the enemies that move back and forth and fire at the player. Their projectiles
are actually small Enemy class instances.
Their code is as follows:
/* FiringEnemy - this represents an enemy that moves back and forth and fires at the player */
class FiringEnemy : public Enemy {
protected:
float lastFired; // last time the enemy fired
float fireRate; // rate at which enemy can fire
int dmg; // damage that this enemy inflicts
virtual void updateAllTiming(float t) { lastFired += t; };
public:
FiringEnemy();
FiringEnemy(float, float, float, float, float, float);
void move();
virtual void remove() { global.numFiringEnemies--; };
void setFireRate(float f) { fireRate = f; };
void setDamage(int d) { dmg = d; };
};
You can see that the FiringEnemy overrides the remove function. This ensures that whenever a FiringEnemy
is removed the global counter is updated.
Boss Class
The Boss class represents the various bosses that are found throughout the game. They are mainly
FiringEnemy enemies that are much larger and stronger.
Their code is as follows:
/* Boss - this represents a sub-boss */
class Boss : public FiringEnemy {
public:
Boss(float, float, float, float, float, float);
virtual void remove() { global.numBosses--; forceSound("boss_die.wav", 5); };
};
Projectile Class
The Projectile class represents any projectiles on the screen. The base class is used for the cannon shots
that the player fires.
The code is as follows:
/* Projectile - this represents any projectile (e.g. bullets, rockets, debri) that is
moving through space */
class Projectile : public Sprite {
protected:
int damage; // damage this projectile does
int pass; // how many enemies it will pass through
int blast; // blast radius
int r, g, b; // color of projectile
public:
Projectile();
Projectile(float, float, float, float, float, float);
virtual void draw();
void setDamage(int d) { damage = d; };
int getDamage() { return damage; };
virtual void hit(Enemy *e);
void setPass(int p) { pass = p; };
void setBlast(int b) { blast = b; };
virtual void checkTarget() {};
};
ABomb Class
Since a-bombs are treated differently than regular projectiles a special class was required. The ABomb class
takes care of these special weapons.
The code is as follows:
/* ABomb - this represents an abomb fired by the player */
class ABomb : public Projectile {
protected:
float dieTime;
virtual void updateAllTiming(float t) { dieTime += t; };
public:
ABomb();
virtual void move();
virtual void draw();
virtual void hit(Enemy *e) {};
};
The most important part is that the function hit is overridden, thus removing any consequences of the projectile
hitting enemies while it floats away from the player.
Missile Class
The Missile class represents the weapon utility that fires out of the side(s) of the player's spaceship. They
have special "heat-seeking" capabilities that required a separate class to be built.
The code is as follows:
/* Missle - this is a type of projectile that will look for the nearest target and go
after it */
class Missile : public Projectile {
private:
int radar; // radius of radar
float lookTime; // tracks last time an attempt was made to find a target
bool hasTarget; // target was found
Sprite *target; // target being tracked
virtual void updateAllTiming(float t) { lookTime += t; };
public:
Missile();
Missile(int, float, float, float, float, float, float);
void findTarget();
void move();
void checkTarget();
};
SpaceShip Class
The SpaceShip class represents the player's spaceship that resides in the middle of the screen.
The code is as follows:
/* SpaceShip - this class represents a ship that can be displayed on the screen. It
contains all information such as hitpoints, weapons, movement speeds, etc. */
class SpaceShip : public Sprite {
private:
int hitPoints; // current hitPoints (i.e. how much more damage the ship can take)
float facing; // direction ship is facing (in degrees)
int dmg; // weapon damage
int wPass; // number of enemies the weapon will pass through
int blast; // blast radius
int missiles; // number of missiles to be fired out
float lastMissile; // last missile time
int aBombs; // number of abombs left
float lastABomb; // last time an abomb was launched
virtual void updateAllTiming(float t) { lastMissile += t; lastABomb += t; };
public:
SpaceShip();
void draw();
void setFacing(float f) { facing = f; };
void hit(Enemy *e);
int getHitPoints() { return hitPoints; };
int getWeaponDmg() { return dmg; };
int getWeaponPass() { return wPass; };
int getBlast() { return blast; };
void getPowerup(Powerup* p);
int getMissiles() { return missiles; };
bool fireMissile();
void fireABomb();
int getABombs() { return aBombs; };
};
By examining the various functions you can see what the SpaceShip is able to do. It is able to getPowerups,
fireMissiles, and fireABombs to name a few.
Animation Class
The Animation class was made to allow for explosion animations. I also created an Explosion
class even though it was the only type of animation. I did this to make the game expandable to include animated enemies,
animated projectiles, and maybe even an animated spaceship for the player.
The code is as follows:
/* Animation - this class represents an animation that is taking place on the screen. */
class Animation : public Sprite {
protected:
int frame; // current frame
int numFrames; // number of frames in this animation
float frameRate; // rate at which the frames change
float frameTimer; // used to regulate time for animation
virtual void updateAllTiming(float t) { frameTimer += t; };
public:
Animation();
void updateFrame();
};
The class is basic and does not even have a draw() function. The updateFrame() function
will need to be called by any child's draw() function to ensure that the proper frame is rendered.
Explosion Class
As described above, the Explosion class implements the Animation class to show any size
explosion on the screen.
The code is as follows:
/* Explosion - this is a child of the Animation class and represents an explosion on the screen */
class Explosion : public Animation {
int radius;
public:
Explosion();
Explosion(float, float, float, float, float, float, float);
void draw();
};
Again the class is basic. The special animation is found in the draw() function:
/* draw the explosion to the screen */
void Explosion::draw() {
// frames 1 - 8 are explosion growing, 9 and 10 are for explosion going away
if (!global.paused) updateFrame();
if (!alive) return;
// store old matrix
glPushMatrix();
// load the identity and translate it
glLoadIdentity();
glTranslatef(x, y, z);
if (frame <= 0.8 * numFrames) {
float r = radius * frame / 5.0;
glColor3ub(255, 255 - (140 * (frame - 1) / (numFrames * 0.8)), 0);
glutSolidSphere(r, r, r);
} else {
float r = radius * (frame - numFrames * 0.8);
glColor3ub(150, 150, 150);
glutSolidSphere(r, r, r);
}
// restore previous matrix
glPopMatrix();
};
Copyright © 2006 Matthew Glanfield
http://www.planetoidgame.com
|