A web-based copy of this assignment, and all the necessary support files can be found on the web at:
You are in charge of an anti-ballistic missile installation. You have to direct interceptor missiles to destroy incoming warheads. If any warhead slips past your defenses then the game is over.
You have to build this game using C# and XNA using the supplied graphical resources.
IMPORTANT: You MUST use XNA version 4 and the supplied resources
The game displays the message "Press ESC key to start game"
The player presses ESC to start the game.
The game starts with an interceptor missile waiting on the pad and, soon after the game starts, the first warhead appears from an underground silo.
As the player moves the mouse, the mouse position is tracked using the cursor image. This image is shown in white while the missile is on the pad.
The player clicks the left mouse button to mark the target position and launch the missile. The target position should be some distance in advance of the incoming warhead to allow for the missile's flight time. The cursor colour changes from white to red. Clicking the mouse again has no effect until the missile has exploded and a new missile has appeared on the pad.
The missile flies towards the marked target position. Upon reaching this position, it explodes. If a warhead is within range of the explosion then the warhead disappears, otherwise it continues on its trajectory. In the event of the missile being unable to reach the target position, it should continue flying until it reaches the edge of the screen and disappears without exploding.
When the explosion has finished (or the missile has disappeared off the edge of the screen) a new missile appears on the pad and the mouse cursor changes back to white, ready for the next missile launch.
If the incoming warhead is destroyed by the interceptor then a new warhead should appear after a short pause. Destroying a warhead gains 20 points.
If the incoming warhead reaches the ground then there is a nuclear explosion and the game finishes.
When the game is over, then last image of the nuclear explosion should remain on the screen and the message "Game Over" displayed in red. After a few seconds, the program should change back to the "Press ESC key to start game" state.
The mouse cursor continuously tracks the position of the mouse, with the cursor cross-hairs indicating the hot spot position. The cursor is shown in white when there is a missile ready to fire and in red when the missile is in flight or exploding.
There are an infinite number of missiles in the storage silo but only one missile can be used at a time.
The position of the cursor when the mouse is clicked determines the target position of the missile and once its flight has started, subsequent clicks are ignored. Hence it is necessary for the player to accurately judge the missile flight time and the velocity of the incoming warhead before the missile is launched.
The missile velocity should be 7 pixels per update in the direction of the marked target position.
The missile should explode when it is within 4 pixels of the marked target position. When in flight, images 1 and 2 (counting from zero) from the missile sprite sheet should be alternated every 3 updates to give the effect of animating the missile flame.
When the missile explodes, it should be replaced by the explosion sequence. Each explosion image should be displayed for 3-5 updates to give the effect of an explosion which rapidly grows and then dissipates to nothing.
There are an infinite number of incoming warheads, although only one will be shown at a time. Each warhead starts from the top of the screen at a random X position and moves in a straight line towards a random X position on the ground.
The flight speed of the warhead is 0.5 pixels per update. The warhead image should change every 3 updates to give the illusion of rotation.
The warhead is destroyed whenever it is within 60 pixels of the centre of a missile explosion. To make the sequence look more believable, the warhead should glow red for 5 more updates before disappearing from the screen.
When a warhead reaches the ground (which is not necessarily the absolute bottom of the screen), there is a nuclear explosion which terminates the game. The missile and any missile explosion should be removed from the screen. The mouse cursor can be removed or can remain at your discretion.
The current score should be displayed at the top right corner of the screen. Each warhead destroyed is worth 10 points.
With the simple game, the missile leaves the pad pointing directly at the target. With limited slew, the missile leaves the pad pointing upward and then slowly turns towards the target during flight. The maximum amount that the missile can turn in a single update period is 0.03 radians. The missile trajectory angle needs to be recalculated for each update period.
Note that implementing this feature makes likely that the missile will miss when the target position is low to the ground and close to the launch pad. Should this happen, the missile may zig zag in an interesting manner before reaching the edge of the screen. This behaviour is acceptable.
The speed of the first warhead is 0.5 pixels per update. The speed of subsequent warheads is increased by 0.1 pixels per update for each one, so that warheads get faster and more difficult to hit.
You are supplied with a C# project containing the following complete and incomplete classes:
BasicSprite, MovingSprite, VectoredSprite - complete
classes as described in sections 7-8 of your notesCursorSprite, MissileSprite and WarheadSprite classes
in various states of completion.Game1 boilerplate class - for you to complete.To assist you to build your game, the following graphical resources are supplied: Download
graphic resources
(Note: the graphical resources have already been loaded into the supplied project)
A background image is supplied in the form of a JPG file. This should be used as the background for the game. Situated at the bottom left of the image is a missile gantry and launch pad for the interceptor missile.
A mouse cursor is provided in form of a PNG file. This image is 144x144 pixels in size and the centre point is (72,72).
A set of interceptor missile and explosion images in the form of a PNG file.
There are three separate missile images: one for the missile when it is waiting on the pad, and two more for when it is in flight.
The sprite sheet also has six separate explosion images which are to be shown in quick succession
when the missile explodes.
Each image is exactly 100x100 pixels wide and the whole file is 900x100 pixels. The centre point for each image is (50, 50)
A set of images for the incoming warhead and images for the nuclear explosion should it reach the ground, provided in the form of a PNG file.
There are three separate warhead images. The game should cycle through these images whenever the warhead is displayed to produce the illusion of rotation. Note that these images are larger than required and should be scaled to 0.5 when drawn, so that the image of the warhead is reduced in size.
When a warhead strikes the ground, there is a nuclear explosion. The warhead sprite sheet also has a further four images for this explosion. Note that these images are smaller than requited and should be scaled up to 2.00 when drawn, so that the image of the explosion is increased in size.
Each image on the sprite sheet is 100x100 pixels in size, however the centre point for each image is (50, 75) (not 50, 50 as you might expect).
The behaviour of each sprite is described by a separate Finite State Machine which you are required to implement using the techniques described in Section 9 of your lecture notes.
You are also required to develop your code using the supplied Object Oriented sprite classes
(BasicSprite, MovingSprite, VectoredSprite) which
are described in Sections 7 and 8 of your lecture notes. Each sprite class should "extend" one
of these of these classes, and provide (at least) a customised Update() method,
which will be called from the Game1 class Update() method.
Important: The customised Update() method for each sprite must make an explicit
call to base.Update() so that any default animation and sprite movement takes
place!
This class is supplied and needs no modification. The colour of the cursor image depends upon a bool parameter to the Update() method.
The missile is initially stored in an underground and rises onto the launch pad. When the player presses the left mouse button, the position of the mouse is recorded as the target position, and the missile launches and heads for that position. When the missile is within four pixels of the position, it explodes.
C# Class Heading: class MissileSprite : BasicSprit
Design notes:
MissileSprite class should inherit from the VectoredSprite class.public methods named IsWaiting() and IsExploding().
These methods return true if the object is in the Waiting or Exploding state,
as appropriate.Update() method must call base.Update() before
returning.Finite State Diagram:
| State | Transition | Trigger | Actions | Next State |
|---|---|---|---|---|
| Start |
T1.1
|
No Trigger
|
set Show flag to true; set X,Y to start position; |
Preparing
|
| Preparing |
T1.2
|
Missile fully on pad |
set Velocity to 0.0 |
Waiting
|
| Waiting |
T1.3
|
Launch triggered
|
set Velocity to 7.0 |
Flying
|
| Flying |
T1.5
|
Missile has flown off screen | No actions |
Off Screen
|
| Flying |
T1.6
|
Missile within 4 pixels of target point | set Velocity = 0; set X,Y to target point position; set frame number to 3; start animation cycle for explosion; |
Exploding
|
| Flying |
T1.4
|
(else no other trigger) | calculate Angle to point missile at target point |
Flying
|
| Off Screen |
T1.7 |
No trigger
|
set Finished flag to true; set Show flag to false |
End
|
| Exploding |
T1.8
|
Animation Finished
|
set Finished flag to true; set Show flag to false |
End
|
The warhead appears at a random position at the top of the screen and heads towards a random point at ground level. To give the player some breathing space, the starting Y position should be a hundred or so pixels above the top of visible screen. Once the random starting and finishing point have been chosen, the Angle (direction of travel) can be calculated.
C# Class Heading: class WarheadSprite : VectoredSprite
Design Notes:
WarheadSprite class should inherit from the VectoredSprite class.public methods named IsWaiting(), IsExploding() and HasExploded().
These methods return true if the object is in the Waiting, Exploding or Exploded
state, as appropriate._hitByMissile.SendMissileExplodingMessage(BasicSprite
missileSprite). If the position of the supplied missileSprite object
is within 60 pixels of this WarheadSprite then it should set the _hitByMissile flag
to true. This method will be called by the Game1 class during the period
that the missile is exploding.static
double _velocity field. The initial value of this field should be 0.5, and it
should be increased by 0.1 each time a new warhead is created. ResetVelocity() which should set the _velocity field
to its initial velocity of 0.5. This method will be called by the Game1 class
at the start of each new game.Update() method must call base.Update() before
returning.Finite State Diagram:
| State | Transition | Trigger | Actions | Next State |
|---|---|---|---|---|
| Start | T2.1 | No trigger |
set Show to true; set Scale to 0.5; set Tint to White; |
Falling |
| Falling | T2.2 | Hit by exploding missile |
set Tint to Red; set timer to zero |
Glowing |
| Falling | T2.3 | Reached ground level |
set Scale to 2.0; Set Velocity to 0; Set Angle to 0; |
Exploding |
| Glowing | T2.4 | After 5 updates | set Show flag to false | Destroyed |
| Exploding | T2.5 | Animation Finished | set Show flag to false; set Finished flag to true | Exploded |
| Destroyed | T2.6 | No trigger | set Finished flag to true | End |
| Exploded | T2.7 | Time expired | set Finished flag to true; set Show flag to true! | End |
The Update() method in the Game1 class oversees the whole game
process, whilst the Draw() method sequences the drawing order for the background,
sprites and score.
The required processing within the Update() method is represented by a short
piece of pseudocode; you must convert this into standard C# statements. At
the same time you will need to add statements to the Draw() method.
Finite State Diagram:
| State | Transition | Trigger | Actions | Next State |
|---|---|---|---|---|
| Start | T0.1 | No trigger | Insert Coin | |
| Insert Coin | T0.2 | User presses ESC (simulates insert coin) |
Initialise all game variables and objects | Playing Game |
| Playing Game | T0.3 | Nuclear Explosion finished |
Start timer | Game Over |
| Playing | T0.4 | (no trigger) |
Game play continues | Playing |
| Game Over | T0.5 | Timer running for 2 seconds |
(none) | Insert Coin |
Whilst the game is in each state, the Draw() method should display graphics
as follows:
| State | Draw() method displays |
|---|---|
| Insert Coin | "Press ESC key to start game" |
| Playing | Normal game operation including score |
| Game Over | Normal game background, last frame of nuclear explosion, "GAME OVER" and final score |
The game scenario requires the missile to appear to rise from a hidden underground silo beneath the launch pad. This requires special code within the Draw() method. This code should draw the background, then the missile sprite, then redraw a small section of the background below the launch pad. This will have the effect of hiding the missile when its position is below the launch pad.
Assume that the missile is at position missileX, missileY and
it's supposed to be pointing in the direction of some target at targetX, targetY...
The maths behind the calculation requires the use of the arctan() function. However, the actual implementation is a little tricky so here's the code in C#:
double desiredAngle = Math.Atan2((double)(targetX - missileX), (double)(missileY
- targetY));
This code calculates the angle for the missile's trajectory. Be aware that the desiredAngle is measured in radians and not degrees.
Assume that you've calculated the missile's desired angle to get to the target as desiredAngle and
its current angle is missileAngle. The missile's flight path is more interesting
if we limit how far the angle can change for each update. Let's assume that the maximum change
of angle (for each call to Update()) is given by MAX_SLEW_RATE.
The code to limit the change is:
if ((desiredAngle - missileAngle) > MAX_SLEW_RATE)
{
missileAngle += MAX_SLEW_RATE;
}
else if ((desiredAngle - missileAngle) < -MAX_SLEW_RATE)
{
missileAngle -= MAX_SLEW_RATE;
}
else
{
missileAngle = desiredAngle;
}
As before, all angles are measured in radians and not degrees.
This code actually has a subtle feature - under certain circumstances it can make the missile follow a zig zag trajectory to the edge of the screen. This is a limitation of the code and you don't need to try to fix it; however, you should make sure that your game can cope if the missile does go off the edge of the screen.
Using XNA 4, you must complete the supplied project so that the game operates as described above. Your code must conform to these guidelines:
Game1 Update() method.consts for constant numeric values and (in particular)
the names of each state. Avoid usages such as if (Y > 540) preferring
instead: if (Y > GROUND_LEVEL)const to maximise the "playability" of
the game.| Consts: | const int GROUND_LEVEL = 150; |
All capitals |
| Fields: |
|
Leading underscore |
| Properties: | public double Velocity { get... set ...} |
Leading capital |
| Methods: | public void Update() |
Leading capital |
| Variables: | double distanceToTarget; |
Leading lower case letter |
Marks are available for each class you complete and get working. The following table shows the maximum marks available for each class - partial marks will be given if appropriate:
| Class | C# Coding | Comments | Choice of Names | Use of consts |
|---|---|---|---|---|
| MissileSprite | 20 | 8 | 6 | 6 |
| WarheadSprite | 20 | 8 | 6 | 6 |
| Game1.Draw() method | 10 | 4 | 3 | 3 |
For hand-in and other dates, see Formal Assignment Specification
You must hand-in your work as follows: