A Space Invaders Game
source: Katrin Becker, 2000
But hey, how often are you going to get an assignment that starts off with:
Go Play.
I really mean it too.
The best way to get a feel for what your
program is supposed to do and how it's supposed to work
is to actually play the game for a while.
On-line versions are linked below.
CONTENTS of THIS PAGE...
- Introduction & Background (just below) Description of Our Version The OBJECTS GameClass ThingClass RangerClass SpaceShipClass MissileClass Minimal Solution Testing and Marking Bonuses
- The Original Space Invaders (with a java-version you can play as well as a whole buch of other cool stuff)
- A Java-Version you can play
- See the Lab Notes for background information.
- The following files will be available in the course directory:
- /home/235/Graphics
- Invaders.Play (game options)
- easycurses.help (easycurses documentation)
-
- easycurses.h (window stuff)
- easycurses.o (ALREADY COMPILED!!)
- Random.h
-
- Random.o (ALREADY COMPILED)
- Const.h (constants)
- play.cc (a sample main)
- Point.h ( X and Y together in one object )
- Point.o
- Thing.h ( the base class for the guys on the screen )
- Thing.cc
- makefile (mostly filled in )
- play (sample to run )
- Problem Statement:
- Write a program to play a simple version of the old classic game, "Space Invaders".
-
- Background:
- Space Invaders is one of the early arcade games (1978) and one of the first to make into the home PC market (in 1980 by Atari). In this game you (the "ranger-guy") can fly back and forth (left or right) along the bottom of the screen while rows of aliens march across the screen. They can shoot at you and you can shoot at them. Once the aliens have made it all the way across the screen, they "drop down" a level (i.e. get closer to you), change directions, and begin their march again. If any of the aliens manage to land (i.e. get down to your level), you loose. If any of them hit you when they shoot, you loose. Your job is to shoot them all before that can happen. In most versions of the game the aliens start to move faster as they get closer. Sometimes they also get faster as soon as you get rid of an entire row. In most versions there are also a certain number of "shields" between you and the aliens. You can hide behind them but no-one can shoot through them and they can be destroyed just like any other object on the screen.
- (see also: http://spaceinvaders.retrogames.com/html/history.htm) An exerpt from this link:
- Space Invaders was designed and programmed by Toshihiro Nishikado for Taito, Japan in 1978 and remains one of the most popular arcade games ever made. The game was licensed from Taito by Midway for production in the US. In 1980, the game was licensed by Atari for the 2600 game system and was the first arcade game ever adapted for Atari's home system. The Space Invaders franchise has flourished for more than 20 years and according to Taito, the game has generated more than $500 million in revenues over multiple platforms including coin-op, the Atari 2600 and the Nintendo.
It was based on a 8080 CPU, had muffled analog audio, and simulated color by putting a transparent overlay on top of a monochrome display.
Space Invaders was the first arcade game to work it's way out of seedy arcades and into pizza parlors and ice cream shops.
The Space Invaders phenomenon stuned conservative adults who were certain the games soured the minds of their youngsters. Residents of Mesquite, Texas pushed the issue all the way to the Supreme Court in their efforts to ban the illicit machines from their Bible-belt community.
The game was so amazingly popular in Japan that it caused a coin shortage until the country's Yen supply was quadrupled. Entire arcades were opened in Japan specifically for this game.
- 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 MINESWEEPER last term.
-
- - we will create an initial configuration at the start of the game consisting of a number of different spaceships. When we have destroyed them all, we win. If we get destroyed first, we loose.
-
- - just as in MINESWEEPER 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
- - spaceships continue to move
- - 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 "shields", spaceships, shooting range, etc.)
- - or could allow user to specify range, 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
-
- (suggested) user input: (everyone but ranger moves EACH "turn")
- q = Quit
- <blank> = move everyone but ranger
- z = move ranger left
- / = move ranger right
- j = make ranger Jump (like hyperspace i.e. move several squares at once)
- s = Shoot
- o = mOve and shoot
- . = move right and shoot
- x = move left and shoot
- u = jUmp and shoot
-
- The "names" of these commands need not be as specified - can use others (single-character Highly Recommended). Check the keyboard for conveniently located keys.
-
- I would suggest implementing them in the above order (roughly). Do <blank> and 'q' first with just the shields 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 Game Class (known as the "AI" in games-writing circles) and a hierarchy of "things". You must use inheritance in this assignment. The "things" (shields, spaceships, ranger) are all derived from the same base class (Thing or some-such).
- The Game Class
- The Game Class 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 Game Class needs to keeps track of the following things:
- DATA: some kind of list of the objects (shields, aliens, me)
- - this could be: Thing* list[100]; // an array containing pointers to the objects
- Needs a count of things (a count for shields, 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 with the ranger or sheilds (because of their configuration, spaceships will not collide with each other)
- - 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 left
- - make the Ranger move right
- - make the Ranger jump
- - make the Ranger shoot
-
-
- The Objects:The ThingClass
-
- This is the base class for the major objects: Shields, SpaceShips, Ranger, (missiles?)
-
- It contains all the parts common to all:
- 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: NOTE: this is more general than currently required for this game)
- 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
- - can base these on the "nextX" and "nextY" methods in cursWindow
-
- 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 shields since they can't)
-
- - constructor/destructor and access functions are already defined and don't need to be redefined in the derived class (remember we still need to do the constructor/destructor for the derived class)
- - base class constructor and destructor do nothing so you'll probably want to look after things in the derived class.
-
- 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 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 one or two characters (a 'head' and a 'body') drawing it is simpler. Its orientation will not change.
-
- - can move one square at a time
- - can change direction
- - can shoot in direction it's pointing ONLY
- - can move E,W ONLY
-
- Also need:
- Jump (move 5-10 - you pick)
- Move (LEFT or RIGHT)
- The SpaceShip Class (there may actually be several kinds of spaceship)
- origin : random
- status : alive
- orientation: always SOUTH
- 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 initially. As it gets closer to landing it may speed up.
- - once it is close enough, it will shoot at the ranger
- - can change direction. Once a spaceship has moved all the way across the screen, it will change direction and start to move the other way. Some of the spaceships will not be visible on the screen all the time. (Question: how many spaceships will you need to "fill" a row so no gaps are visible?)
- - can shoot in direction it's facing ONLY
- - can move E,W ONLY
- A Missile Class?
- 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. It too could be a thing. Once fired, it can look after this itself: the thing that shot 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.
-
- An alternative is to have the missile be a proper sub-class of thing which is created by a spaceship or ranger and then basically has a life of it's own: it moves, maybe hits something, and dies. Once fired, the shooter no longer cares about it so it needn't keep track of it. This would make it behave more like a proper missile, whereas the other description above is perhaps more like a laser.
- 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 a ranger that moves correctly on the screen and a few shields. This solution is worth a maximum mark of C+
-
- The midrange solution will have the shields and a working ranger who can move and shoot stuff.
- This solution is worth a maximum mark of B+
-
- The best solution will have shields, the ranger, AND sereval kinds of spaceship 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 shields ( get them placed )
- 3. the AI (who will be in charge of all Things)
- 4. the ranger (move, then do shoot last)
- 5. the spaceships (move, do shoot last)
- Testing and Marking:
- Needs external documentation that user can refer to while playing the game.
-
- Sample Mark Guide Here
-
- 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?
Shields
- drawn correctly?
- do they explode when shoot or hit?
Ranger
- initial position correct?
- can the player move him?
- can the player make him shoot?
- does he explode when hit?
- is it possible to win?
SpaceShips
- do they consistently get closer to the ranger
- do they change direction at the right time
- do they shoot when in the proper range
- do they ever win?
- How to submit your assignment:
- This assignment SHOULD be 'demo'ed for your TA. Be sure to arrange a time IN LAB (or when your TA is scheduled in CT) with your TA.
-
- This assignment can be submitted electronically using submit.
- Include:
- - all '.cc' files
- - all '.h' files
- A MAKEFILE!!!!!
- - your external documentation
- BONUSES:
- 1. [2 points] Have some rows of spaceships move in the opposite direction from the rest.
- 2. [2-3 points] Detect "Game Over": when Ranger dead; or when all 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] Spaceships speed up as they get closer to landing
- 6. [2 points] Set up "key bindings" so player can use the arrow keys, etc.
- 7. [4-? points] Make it Interrupt Driven
-
CHALLENGE:
- 1. [4-? points] Add sound.
- 2. [4-? points] Create a full GUI
- 3. [5-? points] Do it in colour
- 4. [5-? points] 3-D