An Asteroids Game
source: Katrin Becker, 1999
- WARNING: Start early!!!!!!!!!!! If you run into serious problems (conceptual or program design) during the last week you may not get help. Design problems must be dealt with in the first 1 1/2 weeks. If you have not got most of your program working by March 31 the TA's Tutors, Instructors, and Lab Coordinator may not have time to help you. (In other words if you leave it till the last minute, you may be out of luck)
-
- CONTENTS of THIS PAGE...
- Introduction & Background (just below)
- Description of Our Version, The OBJECTS, GameClass, ThingClass,
AsteroidClass, RangerClass, AlienClass, Minimal Solution, Testing and Marking, Bonuses
-
-
- The Original Asteroids
- A Java-Version you can play
- See the Lab Notes for background information.
-
- The following files will be available in the course directory:
- /home/233/Graphics
- Asteroids.Play (game options)
- easycurses.h (window stuff)
- easycurses.o (ALREADY COMPILED!!)
- Random.o (ALREADY COMPILED)
- AsConst.h (constants and declaration of Random)
- play.cc (a sample main)
- PointClass.h ( X and Y together in one object )
- PointClass.o
- ThingClass.h ( the base class for the guys on the screen )
- ThingClass.cc
- makefile (mostly filled in )
- play (sample to run )
-
- Problem Statement: Write a program to play a simple version of the old classic game, "Asteroids".
-
- Background:
- Asteroids is an early arcade game that hit the market around 1979 and made a big splash. The original game consisted of one spaceship that can be controlled by the player. It can move forward, turn, and shoot. Randomly placed around the screen are asteroids that move at various speeds. If one hits your spaceship you loose. You can fire on the asteroids but shooting a large one turns it into several smaller ones that move faster. Every now and then an alien craft appears that attempts to shoot you.
- Description of Our Version:
- - no sound
- - ASCII graphics
- our game will consist of a WINDOW defined using "easycurses" and marks displayed in the window will be standard ASCII characters (suggested size: 40W X 35H)
- - graphics done using easycurses
- - our "universe" is two dimensional
-
- Since we do not yet have the experience to create a full-blown event-driven system our game will run as "snapshots in time". This is similar to the approach used in the Game of Life last term.
-
- - rather than having to deal with asteroids and aliens that appear at random time intervals, we will create an initial configuration at the start of the game consisting of a number of asteroids and spaceships. When we have destroyed them all, we win. If we get destroyed first, we loose.
- - asteroids, when shot will explode and disappear rather than turning into smaller ones.
-
- - just as in the Game of Life each object will respond to the conditions as they were at the end of the previous time interval.
-
- At each time interval:
- - each object will make a move based on the screen as it was last
- - asteroids continue to move
- - spaceships try to get within firing range so they can shoot us
- - we retrieve input from the user to tell us what the "Ranger" (that's the player) should do (which could be null meaning don't move the Ranger)
-
- Running the Game:
- - ( optional ) can have command line arguments for game "parameters":
- - level of difficulty (affects # of asteroids, spaceships, shooting range, etc.)
- - or could allow user to specify range, # rocks, etc.
- - with no arguments, it would be run like:
- ./play
- - can have a restart option or can simply require the user to quit and start again
-
- user input: (everyone but ranger moves EACH "turn")
- q = Quit
- <blank> = move everyone but ranger
- m = Move ranger in direction currently headed
- l = turn ranger Left
- r = turn ranger Right
- j = make ranger Jump (like hyperspace i.e. move several squares at once)
- s = Shoot
- o = mOve and shoot
- i = turn rIght and shoot
- e = turn lEft and shoot
- u = jUmp and shoot
-
- The "names" of these commands need not be as specified - can use others (single-character Highly Recommended).
-
- I would suggest implementing them in the above order (roughly). Do <blank> and 'q' first with just the asteroids to make sure they move as they are supposed to. Do this before your ranger even exists.
- The Objects:
- The core of the program consists of a GameClass (known as the "AI" in games-writing circles) and a hierarchy of "things". You must use inheritance in this assignment. The "things" (asteroids, spaceships, ranger) are all derived from the same base class (ThingClass or some-such).
-
- The GameClass
- The GameClass will keep track of who is on the "board". It is"the AI". It is the part of the program that enforces the rules, keeps score, and acts as the go-between. The main program is a simple go-till-quit loop, and any time something needs to happen in the game, it's the "AI" that gets called to do it. There are many ways to implement this and the following description outlines only one. Different approaches will require different data and methods.
-
- The GameClass needs to keeps track of the following things:
- DATA: some kind of list of the objects (asteroids, aliens, me)
- - this could be: ThingClass* list[20]; // an array containing pointers to the objects
- Needs a count of things (a count for asteroids, aliens, and maybe a total)
- - may want to keep a pointer to the Ranger
- - may want to keep a pointer to the "current shooter"
- It needs to be able to do the following:
- - calculate the distance between two points
- - determine if two objects have collided
- - check for collisions in all objects
- - move all objects to their next spot
- - given a point should be able to say "who's there" (a pointer to the object would do it; if there's no-one there it can return NULL)
- Possible access functions:
- return a pointer to the Ranger
- return a pointer to the Shooter
- Possible forwarding functions:
- - make the Ranger move one step
- - make the Ranger turn left
- - make the Ranger turn right
- - make the Ranger jump
- - make the Ranger shoot
-
- The Objects:The ThingClass
-
- This is the base class for the major objects: Asteroids, SpaceShips, Ranger
-
- It contains all the parts common to all 3:
- DATA: Point origin (the centre or head of the object)
- int status (whether it's alive, or dead, or what)
- -in the guide status may have one of these values: ALIVE, EXPLODING, DYING, DEAD
- - the usual "image" is printed when the thing is ALIVE
- - when a thing is ALIVE and someone hits it - it is directed to explode
- - when exploding there is a different "image" that gets drawn and the thing's status is changed to EXPLODING
- - if it's status is EXPLODING then it gets changed to DYING
- - if it's status is DYING it will be erased from the screen and its status changed to DEAD
- - The effect seen on the screen as a result of this is that objets appear to explode and then will stay that way until the next "turn" when they disappear
- int orientation (what direction is it headed? - one of: N, S, E, W, NW, SW, NE, SE)
- int size (how many 'squares' across is it?)
- int radius (an object of size 3 would probably have a radius 2)
- int range (how far can it shoot?)
-
- There are 4 Utility Routines:
- nextX, nextY, prevX, prevY
- - these give the next value (row or column) but takes into account the current edges of the screen as well as the size of the object so we don't "draw outside the window"
- - they also do wrap-around so if you are at the right edge and say nextX you get a point on the far left
-
- Public Routines:
- - these are mostly virtual (meaning the derived class's version will be used instead of the base class version)
- - they are not pure virtual so they can be allowed to default to the base class version if you choose not to define one in the derived class (like maybe shoot for asteroids since they can't)
-
- - constructor/destructor and access functions are already defined and don't need to be redefined in the derived class
- - base class constructor and destructor do nothing so you'll probably want to redefine them.
-
- Others:
- Move() - move in current direction
- - usually the thing will first be erased, then re-drawn depending on it's current status
- Draw() - draw a picture of me on the screen
- Erase() - get rid of the picture of me on the screen
- Explode() - draw a picture of me exploding on the screen
- Shoot() - BANG, BANG!
- - not all objects have the ability to shoot
- - if the base class method is defined as empty, then we have the option of leaving it or overriding it.
-
- The AsteroidClass
- origin : chosen at random
- status : alive
- orientation: one of N, S, E, W
- size: 3?
- radius : 2?
- range : 0
- - can move one square at a time
- - cannot change direction
- Possible "image":
-
- The RangerClass
- origin : middle of screen at bottom
- status : alive
- orientation: facing north
- size: 2?
- radius : 1?
- range : 10-20 you pick
-
- Note: if you have your image made of only two characters (a 'head' and a 'body') drawing it is simpler. Remember the 'image' will have to change whenever the direction changes.
-
- - can move one square at a time
- - can change direction
- - can shoot in direction it's headed ONLY
- - can move N,S,E,W,NW,NE,SW,SE
-
- Also need:
- Jump (move 5-10 - you pick)
- Turn (LEFT or RIGHT)
- The SpaceShipClass
- origin : random
- status : alive
- orientation: one of N,S,E,W,NW,NE,SW,SE chosen at random
- size: 2?
- radius : 1?
- range : 5-10 you pick (the game will definitely last longer if the aliens have a shorter range than the ranger)
-
- - can move one square at a time
- - each time it will look for the ranger and try to get closer (it will change its own orientation and move in such a way that the distance between it and the ranger decreases)
- - once it is close enough, it will shoot at the ranger
- - can change direction
- - can shoot in direction it's headed ONLY
- - can move N,S,E,W,NW,NE,SW,SE
- A MissileClass?
- Some of the "things" can shoot. There are many ways to handle this. Most include "plotting" some sort of missile path and then checking to see if there is anyone at any of the locations along the missile path (only the closest thing will get blown up unless your missile/laser is reeely strong). The missile path can easily be stored as an array of Points. It gets created when as thing shoots: the path is "plotted" and drawn, and then on the next 'turn' it can be erased. The thing can look after this itself: it keeps a pointer to a missile; if not NULL there is an active missile.
- A new missile would need to 'know':
- - its range (set in constructor)
- - its origin(set in constructor)
- - its orientation (which direction it's going)(set in constructor)
- - the endpath (the actual length of the path as opposed to the range - the actual path 'ends' when it hits something) - this value is calculated
- - a flag that remembers if it hit something
- - a pointer to the thing it hit
- It needs to be able to:
- plot the missile path
- erase the missile path
- say whether or not it hit something (access function)
- say who it hit (access function)
- If we implement a missile path, then those things that can shoot will each need a Missile that can be created new when we shoot and destroyed (deactivated) later. Both the Ranger and the Aliens can use the same class.
- Minimal Solution:
- Get some graph paper so you can draw your window and objects. Calculating x,y coordinates is easier if you have a picture of what your are doing.
- The minimal passable solution will have only asteroids that move and explode correctly on the screen. This solution is worth a maximum mark of C+
-
- The midrange solution will have the asteroids and a working ranger who can move and shoot stuff.
- This solution is worth a maximum mark of B+
-
- The best solution will have asteroids, the ranger, AND spaceships all working correctly. It is worth up to an A
-
- HINT: (!!!!) Get the game working in this order: (TEST AFTER EACH STEP!!!!!)
- 1. the main program that sets up the window
- (start by drawing a specific 'picture' in a specific location)
- and runs the main game (switch on user input)
- 2. the asteroids ( get them moving, then get collisions working)
- 3. the AI (who will be in charge of all Things)
- 4. the ranger (move and turn, then do shoot last)
- 5. the spaceships (move and turn, do shoot last)
- Testing and Marking:
- Needs external documentation that user can refer to while playing the game.
-
- Notes on Marking:
- We will be looking for the usual good, clean design; documentation, etc. as always.
- In order to pass it must work. (Some marks will be given to all *reasonable* attempts, working or not)
- Specifics we will be looking for when marking:
- Initial Configuration
- is everyone inside the lines?
Asteroids
- drawn correctly?
- move correctly?
- do they explode on collision?
Ranger
- initial position correct?
- can the player move him?
- can the player make him shoot?
- can the player make him turn?
- does he explode when hit?
- is it possible to win?
SpaceShips
- do they start off in random locations/orientations
- do they consistently get closer to the ranger
- do they follow the ranger when he moves
- do they shoot when in the proper range
- do they ever win?
-
How to submit your assignment:
- This assignment MUST be submitted electronically using submit.
- Include:
- - all '.cc' files
- - all '.h' files
- - your external documentation
- BONUSES:
- 1. [2 points] Allow asteroids and spaceships to appear at random once the game has begun.
- 2. [2-3 points] Detect "Game Over": when Ranger dead; or when all asteroids and aliens gone.
- 3. [2 points] Keep score. (one point per thing or allow a certain number of points for certain kinds of things).
- 4. [2-5 points] Allow different levels of difficulty (different #'s of things, different ranges, etc.)
- 5. [2-4 points] Asteroids break into two when hit - both of which are smaller and go off in different directions.
- 6. [2 points] Set up "key bindings" so player can use the arrow keys, etc.
- 7. [4-? points] Add sound.
- 8. [5-? points] 3-D