
A project that creates falling asteroids at random positions along the top of the screen for a space ship at the bottom to shoot, using a Nokia N5110 LCD, joystick and pushbuttons
Dependencies: DebounceIn N5110 PowerControl mbed
main.cpp
- Committer:
- wray2303
- Date:
- 2015-05-08
- Revision:
- 0:6eba0e66ce01
- Child:
- 2:8d28a2f491eb
File content as of revision 0:6eba0e66ce01:
/** @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; /// timeout to create the asteroids Timer shootSoundtimer; /** 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; int main() { asteroid.nscore = 0; srand(15000*randomPin); /// seeding random function calibrateJoystick(); /// set's centred values of joystick pollJoystick.attach(&updateJoystick,1/45.0); /// read joystick 45 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(); PauseDisplay(); break; case 3: EndDisplay(); /// end of game display break; } Sleep(); /// sleep function when nothings happening mbed can sleep and save power consumption } } 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.05); /// set ticker to read the position of the bullet } else {} if(AsteroidCreatedFlag==1) { /// check if an asteroid has been created readTheAsteroid.attach(&ReadAsteroid,0.05); /// 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.05); /// 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 } 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 asteroid.nscore=asteroid.nscore-1; /// minus one point for the asteroid that was detroyed in losing state=3; /// go to state 3 (end screen) } else {} lcd.drawLine(0,0,83,0,1); } 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 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,10,5); /// display on screen } lcd.printString("Game Over !",12,1); /// closing message lcd.printString("Press S4 to",11,2); lcd.printString("Play again",12,3); 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(!buttonS) { /// 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 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; }