Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: DebounceIn N5110 PowerControl mbed
main.cpp
- Committer:
- wray2303
- Date:
- 2015-05-11
- Revision:
- 3:39c95d65bee5
- Parent:
- 2:8d28a2f491eb
File content as of revision 3:39c95d65bee5:
/**
@file main.cpp
@brief Program implementation
@author Louis Wray
@date 14th April 2015
*/
#include "main.h"
/// timer to regularly read the joystick
Ticker pollJoystick;
/// timer to regularly call the read bullet function
Ticker readShoot;
/// timer to regularly call new asteroids
Ticker readTheAsteroid;
/// timer to create the asteroids
Timer shootSoundtimer;
///timeout used to stop button skip
Timeout EndGame;
/**
create enumerated type (0,1,2,3 etc. for direction)
*/
enum DirectionName {
UP,
DOWN,
LEFT,
RIGHT,
CENTRE,
UNKNOWN
};
/**
struct for Joystick
*/
typedef struct JoyStick Joystick;
struct JoyStick {
float x; /// current x value
float x0; /// 'centred' x value
float y; /// current y value
float y0; /// 'centred' y value
int button; /// button state (assume pull-down used, so 1 = pressed, 0 = unpressed)
DirectionName direction; /// current direction
};
/// create struct variable
Joystick joystick;
int printFlag =0; /**< flag for calling joystick value printing */
int state = 0; /**< integer value for what state the game is in.
for use of the switch statement */
int GenAsteroidFlag = 0; /// asteroid generation flag
int AsteroidCreatedFlag = 0; /// flag to note asteroid is created
int BulletExistsFlag = 0; /// flag to note bullet has been fired and is on screen
int PauseNumber = 0; /// pause flag
int HighScore = 0; /// integer set for highscore
int main()
{
asteroid.nscore = 0;
srand(15000*randomPin); /// seeding random function
calibrateJoystick(); /// set's centred values of joystick
pollJoystick.attach(&updateJoystick,1/50.0); /// read joystick 50 times per second
ship.SetValues(42,39); /// initialise ships starting x,y coordinates
PHY_PowerDown(); /// power down ethernet connection
while(1) {
switch(state) { /// switch statement this enables the game to switch between states giving a start state
/// a game play state and subsequently a game over state giving choice to start again.
case 0:
startUpDisplay(); /// call start up display function
state=1;
break;
case 1:
Game(); /// game play
break;
case 2:
lcd.clear(); /// clears display
PauseDisplay(); /// applies pause screen
break;
case 3:
EndDisplay(); /// end of game display
break;
}
Sleep(); /// sleep function when nothings happening mbed can sleep and save power consumption
}
}
void Read()
{
FILE *fp = fopen("/local/HSCORES.txt","r"); /// open file or create then open if not already made. and read value
fscanf(fp, "%i", &HighScore); /// look in the local file system
fclose(fp); /// close file
}
void Write()
{
FILE *fp = fopen("/local/HSCORES.txt","w"); /// open file or create then open if not already made. make ready for writing to the file
fprintf(fp, "%i\r\n", HighScore); /// print value to the local file
fclose(fp); /// close file
}
void startUpDisplay()
{
lcd.init(); /// initialise the display
lcd.clear();
lcd.printString("Space-Teroid",6,1); /// opening message
lcd.printString("Press S5 to",12,3);
lcd.printString("Play",30,4);
lcd.drawLine(0,0,0,47,1); /// draw outline
lcd.drawLine(83,0,83,47,1);
lcd.drawLine(0,0,83,0,1);
lcd.drawLine(0,47,83,47,1);
lcd.refresh(); /// refesh LCD to create this display
while(!buttonP) { /// while the pause flag or pause button has not been set or used , the mbed will sleep saving power and allowing
/// the user to start when they are ready
sleep();
}
GenAsteroidFlag = 1;
lcd.clear(); /// when flag has been set while loop has been broken and start up display will be escaped
ship.shape(); /// the ships shape is drawn and and the game can begin
}
void Game()
{
lcd.drawLine(0,0,0,47,1); /// draw outline repeatedly when asteroid is falling
lcd.drawLine(83,0,83,47,1);
lcd.drawLine(0,0,83,0,1);
lcd.drawLine(0,47,83,47,1);
if (printFlag) { /// if print flag set, clear flag and use joysticks horizontal position
printFlag = 0;
if (joystick.direction == LEFT && ship.xs>=7) { /// 7 represents the left most boundary
ship.ShipLeft(); /// if joystick moves left, call ship moving left function
}
if (joystick.direction == RIGHT && ship.xs<=76) { /// 76 represents the right most boundary
ship.ShipRight(); /// if joystick moves right, call the ship moving right function
} else {} /// else do nothing
}
if(button) {
AsteroidCreatedFlag = 0;
GenAsteroidFlag = 0;
asteroid.destroyAsteroid();
readTheAsteroid.detach();
PWM1 = 0;
state = 2;
} else {}
if(BulletExistsFlag==0) { /// check if there is already a bullet on the screen, a rule of the game one bullet at a time!
if(buttonS) { /// if shoot button is pressed
shootSoundtimer.start(); /// start timer for shooting sound
PWM1.period(2e-3); /// set the period of the PWM
PWM1 = 0.5; /// set the duty cycle
BulletExistsFlag=1; /// bullet exists flag set
bullet.SetValues(ship.xs,ship.ys-1); /// set the bullets values according to where the ship is
bullet.collision(); /// chec for bullet collision
if(bullet.collision()==true) {
readShoot.detach();
bullet.clearBullet();
BulletExistsFlag=0;
/** if bullet colision happens during sound being made then
*buzzer doesnt stop, thisis because of the interrupt the button makes
*here we reset the buzzer manually */
shootSoundtimer.stop(); /// stop the timer
shootSoundtimer.reset(); /// reset the timer
PWM1 = 0.0; /// turn of the PWM
}
else if(bullet.collision()==false) { /// if bullet co-ordinates are not off the screen
bullet.createBullet(); /// create the bullet
readShoot.attach(&ReadBullet,0.045); /// set ticker to read the position of the bullet
} else {}
if(AsteroidCreatedFlag==1) { /// check if an asteroid has been created
readTheAsteroid.attach(&ReadAsteroid,0.045); /// set ticker for asteroid movement
} else {}
} else {}
}
if(GenAsteroidFlag == 1) { /// check if an asteroid is to be generated
int A = rand() % 75 + 6; /// returns random value between 6 and 7
asteroid.SetAsteroidValue(A,0); /// set asteroid position according to randomly generated value
asteroid.createAsteroid(); /// create asteroid
AsteroidCreatedFlag = 1; /// set flag to state an asteroid has been created and is on screen
GenAsteroidFlag=0; /// reset Generate asteroid flag so no more asteroid are created
if(AsteroidCreatedFlag==1) { /// if asteroid has been created
readTheAsteroid.attach(&ReadAsteroid,0.045); /// set ticker to read and move asteroid
} else {}
} else {}
}
void ReadAsteroid()
{
bullet.collision(); /// check if the bullet has made a collision this must mean an asteroid has been shot
if(bullet.collision()==false) { /// if no collision and the asteroid y position is less than the end of the screen move the asteroid
asteroid.ya=asteroid.ya+1; /// move asteroids y position down the screen
asteroid.erasePrevAsteroid(); /// erase the previous asteroid
asteroid.createAsteroid(); /// create the asteroid in its new position
} else {}
////////// using a double check seems to make the game run smoother //////////////
bullet.collision(); /// check if the bullet has made a collision this must mean an asteroid has been shot
if(bullet.collision()==true) { /// if a collision is made
BulletExistsFlag=0; /// reset the bullet exists flag
readShoot.detach();
readTheAsteroid.detach(); /// detach the read asteroid function from the ticker
bullet.clearBullet(); /// clear the bullet from the screen
AsteroidCreatedFlag=0; /// reset Asteroid created Flag to state there is no longer an asteroid on screen
GenAsteroidFlag=1; /// set the Generate asteroid flag
asteroid.destroyAsteroid(); /// destroy on screen asteroid
/** if bullet colision happens during sound being made then
buzzer doesnt stop, thisis because of the interrupt the button makes
here we reset the buzzer manually*/
shootSoundtimer.stop(); /// stop the timer
shootSoundtimer.reset(); /// reset the timer
PWM1 = 0.0; /// turn of the PWM
} else {}
asteroid.armageddon(); /// check if asteroid has reached the bottom of the screen
if(asteroid.armageddon() == true) { /// if asteroid has it the bottom of the screen ... RUN!!!
/// armageddon takes place and the game is over
bullet.clearBullet(); /// clear the existing bullet
readTheAsteroid.detach(); /// detach the read asteroid function
asteroid.destroyAsteroid(); /// destroy asteroid in place
EndGame.attach(&endState,0.3);
} else {}
lcd.drawLine(0,0,83,0,1); /// keep re-drawing top line as this is damaged while asteroid moves accross it
}
void ReadBullet()
{
if(shootSoundtimer.read() > 0.1) { /// check when the sound timer reaches 0.1 sec
shootSoundtimer.stop(); /// stop the timer
shootSoundtimer.reset(); /// reset the timer
PWM1 = 0.0; /// turn of the PWM
} else {}
if(button) {
AsteroidCreatedFlag = 0;
GenAsteroidFlag = 0;
asteroid.destroyAsteroid();
readTheAsteroid.detach();
PWM1 = 0;
state = 2;
} else {}
bullet.collision(); /// check if the bullet has collided with anything
bullet.offScreen(); /// check if the bullet is off screen
if (bullet.collision() == true||bullet.offScreen()==true) { /// if a collision is made or the bullet goes off the screen
BulletExistsFlag=0;
bullet.clearBullet(); /// clear the bullet
readShoot.detach(); /// detach the ticker
/** if bullet colision happens during sound being made then
buzzer doesnt stop, thisis because of the interrupt the button makes
here we reset the buzzer manually*/
shootSoundtimer.stop(); /// stop the timer
shootSoundtimer.reset(); /// reset the timer
PWM1 = 0.0; /// turn of the PWM
} else {}
bullet.y=bullet.y-1; /// move the bullet up i.e. move its y coordinate
bullet.createBullet(); /// draw new bullet
bullet.erasePrevBullet(); /// erase previous position
////////// double check this seems to help rid some bugs ////////////
bullet.offScreen(); /// check if the bullet is off screen
bullet.collision(); /// check if the bullet has collided with anything
if (bullet.collision() == true||bullet.offScreen()==true) { /// if a collision is made or the bullet goes off the screen
BulletExistsFlag=0;
bullet.clearBullet(); /// clear the bullet
readShoot.detach(); /// detach the ticker
} else {}
if (printFlag) { /// here we are checking the position of the joystick, so the user can move while the bullet is shooting else where
printFlag = 0;
if (joystick.direction == LEFT && ship.xs>=7) {
ship.ShipLeft();
}
if (joystick.direction == RIGHT && ship.xs<=76) {
ship.ShipRight();
} else {}
}
}
void EndDisplay()
{
lcd.clear(); /// clear entire display to make way for end screen
asteroid.nscore = asteroid.nscore-PauseNumber; /// takes points off for the asteroid destroyed when pausing game and destroy asteroid command sent
asteroid.nscore = asteroid.nscore-1;
char buffer[14]; /// set buffer to 14, screen 84 pixels long , 6 pixel per char , 84/6 = 14
int score = sprintf(buffer,"Score: %d",asteroid.nscore); /// print formatted data to buffer
if (score <= 14) { /// if string will fit on display
lcd.printString(buffer,20,5); /// display on screen
}
Read(); /// read file to compare values
if(asteroid.nscore>HighScore) { /// compare current score against highscore
HighScore = asteroid.nscore; /// if current score is larger than highscore = current score
Write(); /// write this to file
}
Read(); /// read the file to then print to lcd
char buffer1[14]; /// set buffer to 14, screen 84 pixels long , 6 pixel per char , 84/6 = 14
int Hscore = sprintf(buffer1,"HighScore:%d",HighScore); /// print formatted data to buffer
if (Hscore <= 14) { /// if string will fit on display
lcd.printString(buffer1,7,4); /// display on screen
}
lcd.printString("game over !",12,0); /// closing message
lcd.printString("Press S5 to",10,1);
lcd.printString("Play again",12,2);
lcd.drawLine(0,0,0,47,1); /// draw outline
lcd.drawLine(83,0,83,47,1);
lcd.drawLine(0,0,83,0,1);
lcd.drawLine(0,47,83,47,1);
lcd.refresh(); /// refesh LCD to create this display
while(!buttonP) { /// while button b has not been pressed sleep (save power)
Sleep();
}
/// when button s pressed
state = 0; /// set the state to 0 (intital game display
asteroid.nscore=0; /// reset the score
}
void PauseDisplay()
{
lcd.printString("PAUSE",28,1); /// print pause display message
lcd.printString("press S5 to",11,3);
lcd.printString("resume",24,4);
lcd.drawLine(0,0,0,47,1); /// draw outline
lcd.drawLine(83,0,83,47,1);
lcd.drawLine(0,0,83,0,1);
lcd.drawLine(0,47,83,47,1);
lcd.refresh();
while(!buttonP) { /// while button P is not pressed Sleep() to save power
Sleep();
if(buttonP) { /// if button P is pressed
lcd.clear(); /// clear LCD
ship.shape(); /// draw the ship back on in position it was left
GenAsteroidFlag = 1; /// reset the Generate asteroid flag
PauseNumber = PauseNumber+1; /// increment pause amount counter
state=1; /// state = 1 means back to the game in the switch statement
}
}
}
void endState()
{
state = 3;
}
void calibrateJoystick()
{
button.mode(PullDown);
/// must not move during calibration
joystick.x0 = xPot; /// initial positions in the range 0.0 to 1.0 (0.5 if centred exactly)
joystick.y0 = yPot;
}
void updateJoystick()
{
/// reading the joystick position 0.0 is centered returns a value in the range -0.5 and 0.5
joystick.x = xPot - joystick.x0;
joystick.y = yPot - joystick.y0;
/// read button state
joystick.button = button;
/// calculate direction depending on x,y values
/// tolerance allows a little lee-way in case joystick not exactly in the stated direction
if ( fabs(joystick.y) < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
joystick.direction = CENTRE;
} else if ( joystick.y > DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
joystick.direction = UP;
} else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
joystick.direction = DOWN;
} else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
joystick.direction = RIGHT;
} else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
joystick.direction = LEFT;
} else {
joystick.direction = UNKNOWN;
}
/// set flag for use of the joystick position
printFlag = 1;
}