Flappy Bird game on mbed with a micro LCD screen, class D amp, speaker, SD card reader/writer, 5-button navigation switch, and potentiometer speed control
Dependencies: 4DGL-uLCD-SE PinDetect SDFileSystem mbed-rtos mbed
main.cpp@0:cd1d2540aaf4, 2016-03-15 (annotated)
- Committer:
- Mpmart08
- Date:
- Tue Mar 15 01:11:07 2016 +0000
- Revision:
- 0:cd1d2540aaf4
added comments
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Mpmart08 | 0:cd1d2540aaf4 | 1 | #include "mbed.h" |
Mpmart08 | 0:cd1d2540aaf4 | 2 | #include "rtos.h" |
Mpmart08 | 0:cd1d2540aaf4 | 3 | #include "PinDetect.h" |
Mpmart08 | 0:cd1d2540aaf4 | 4 | #include "uLCD_4DGL.h" |
Mpmart08 | 0:cd1d2540aaf4 | 5 | #include "Speaker.h" |
Mpmart08 | 0:cd1d2540aaf4 | 6 | #include "SDFileSystem.h" |
Mpmart08 | 0:cd1d2540aaf4 | 7 | #include "pipe.h" |
Mpmart08 | 0:cd1d2540aaf4 | 8 | #include "bird.h" |
Mpmart08 | 0:cd1d2540aaf4 | 9 | #include "soundBuilder.h" |
Mpmart08 | 0:cd1d2540aaf4 | 10 | #include <stdlib.h> |
Mpmart08 | 0:cd1d2540aaf4 | 11 | |
Mpmart08 | 0:cd1d2540aaf4 | 12 | // image sectors on ulcd sd card |
Mpmart08 | 0:cd1d2540aaf4 | 13 | #define BACKGROUND 0x0000, 0x0000 // background |
Mpmart08 | 0:cd1d2540aaf4 | 14 | #define FLAPPY 0x0000, 0x0041 // bird |
Mpmart08 | 0:cd1d2540aaf4 | 15 | #define PIPEUP 0x0000, 0x0043 // pipe pointing up |
Mpmart08 | 0:cd1d2540aaf4 | 16 | #define PIPEDOWN16 0x0000, 0x0054 // pipe pointing down with a height of 16 |
Mpmart08 | 0:cd1d2540aaf4 | 17 | #define PIPEDOWN32 0x0000, 0x0057 // pipe pointing down with a height of 32 |
Mpmart08 | 0:cd1d2540aaf4 | 18 | #define PIPEDOWN48 0x0000, 0x005C // pipe pointing down with a height of 48 |
Mpmart08 | 0:cd1d2540aaf4 | 19 | #define PIPEDOWN64 0x0000, 0x0063 // pipe pointing down with a height of 64 |
Mpmart08 | 0:cd1d2540aaf4 | 20 | #define PIPEDOWN80 0x0000, 0x006C // pipe pointing down with a height of 80 |
Mpmart08 | 0:cd1d2540aaf4 | 21 | #define PIPEDOWN96 0x0000, 0x0077 // pipe pointing down with a height of 96 |
Mpmart08 | 0:cd1d2540aaf4 | 22 | |
Mpmart08 | 0:cd1d2540aaf4 | 23 | // Nav Switch |
Mpmart08 | 0:cd1d2540aaf4 | 24 | PinDetect nsUp(p16); // up button |
Mpmart08 | 0:cd1d2540aaf4 | 25 | PinDetect nsCenter(p15); // center button |
Mpmart08 | 0:cd1d2540aaf4 | 26 | PinDetect nsDown(p13); // down button |
Mpmart08 | 0:cd1d2540aaf4 | 27 | |
Mpmart08 | 0:cd1d2540aaf4 | 28 | // uLCD |
Mpmart08 | 0:cd1d2540aaf4 | 29 | uLCD_4DGL uLCD(p28, p27, p30); |
Mpmart08 | 0:cd1d2540aaf4 | 30 | |
Mpmart08 | 0:cd1d2540aaf4 | 31 | // Speaker |
Mpmart08 | 0:cd1d2540aaf4 | 32 | Speaker mySpeaker(p25); |
Mpmart08 | 0:cd1d2540aaf4 | 33 | |
Mpmart08 | 0:cd1d2540aaf4 | 34 | // SD File System |
Mpmart08 | 0:cd1d2540aaf4 | 35 | SDFileSystem sd(p5, p6, p7, p8, "sd"); |
Mpmart08 | 0:cd1d2540aaf4 | 36 | |
Mpmart08 | 0:cd1d2540aaf4 | 37 | // Potentiometer |
Mpmart08 | 0:cd1d2540aaf4 | 38 | AnalogIn pot(p20); |
Mpmart08 | 0:cd1d2540aaf4 | 39 | |
Mpmart08 | 0:cd1d2540aaf4 | 40 | // Bird |
Mpmart08 | 0:cd1d2540aaf4 | 41 | Bird flappyBird; |
Mpmart08 | 0:cd1d2540aaf4 | 42 | |
Mpmart08 | 0:cd1d2540aaf4 | 43 | // Pipe |
Mpmart08 | 0:cd1d2540aaf4 | 44 | Pipe pipe; |
Mpmart08 | 0:cd1d2540aaf4 | 45 | |
Mpmart08 | 0:cd1d2540aaf4 | 46 | int score = 0; |
Mpmart08 | 0:cd1d2540aaf4 | 47 | int oldScore = 0; |
Mpmart08 | 0:cd1d2540aaf4 | 48 | int gameSpeed = 0; |
Mpmart08 | 0:cd1d2540aaf4 | 49 | |
Mpmart08 | 0:cd1d2540aaf4 | 50 | // State machine definitions |
Mpmart08 | 0:cd1d2540aaf4 | 51 | enum gameStateType {START, WAIT, GAME_SETUP, GAME, LOSE}; |
Mpmart08 | 0:cd1d2540aaf4 | 52 | /* State Definitions: |
Mpmart08 | 0:cd1d2540aaf4 | 53 | * START -- Creates the start screen |
Mpmart08 | 0:cd1d2540aaf4 | 54 | * WAIT -- After the start screen, goes into wait where mbed waits for player to start the game |
Mpmart08 | 0:cd1d2540aaf4 | 55 | * GAME_SETUP -- Initializes game objects such as the bird and pipe |
Mpmart08 | 0:cd1d2540aaf4 | 56 | * GAME -- When the user actually gets to play |
Mpmart08 | 0:cd1d2540aaf4 | 57 | * LOSE -- clears the screen, prints you lose and if you get a high score, stores it, then goes back to start |
Mpmart08 | 0:cd1d2540aaf4 | 58 | */ |
Mpmart08 | 0:cd1d2540aaf4 | 59 | |
Mpmart08 | 0:cd1d2540aaf4 | 60 | // Global state machine variable |
Mpmart08 | 0:cd1d2540aaf4 | 61 | gameStateType gameState = START; |
Mpmart08 | 0:cd1d2540aaf4 | 62 | |
Mpmart08 | 0:cd1d2540aaf4 | 63 | // function that draws each frame of the game on the lcd |
Mpmart08 | 0:cd1d2540aaf4 | 64 | void drawScreen() { |
Mpmart08 | 0:cd1d2540aaf4 | 65 | |
Mpmart08 | 0:cd1d2540aaf4 | 66 | // clears the pipe from its previous location |
Mpmart08 | 0:cd1d2540aaf4 | 67 | uLCD.filled_rectangle( // draws a rectangle the size of the pipe |
Mpmart08 | 0:cd1d2540aaf4 | 68 | pipe.getOldX(), // the pipe's old x position |
Mpmart08 | 0:cd1d2540aaf4 | 69 | 0, // the top of the screen |
Mpmart08 | 0:cd1d2540aaf4 | 70 | pipe.getOldX() + pipe.getWidth(), // the pipe's old x position + the pipe's width |
Mpmart08 | 0:cd1d2540aaf4 | 71 | 127, // the bottom of the screen |
Mpmart08 | 0:cd1d2540aaf4 | 72 | 0x4EC0CA // the color of the background |
Mpmart08 | 0:cd1d2540aaf4 | 73 | ); |
Mpmart08 | 0:cd1d2540aaf4 | 74 | |
Mpmart08 | 0:cd1d2540aaf4 | 75 | // draws the lower pipe at its current location |
Mpmart08 | 0:cd1d2540aaf4 | 76 | uLCD.set_sector_address(PIPEUP); |
Mpmart08 | 0:cd1d2540aaf4 | 77 | int x = pipe.getX(); |
Mpmart08 | 0:cd1d2540aaf4 | 78 | int y = pipe.getY() + 32; |
Mpmart08 | 0:cd1d2540aaf4 | 79 | uLCD.display_image(x,y); |
Mpmart08 | 0:cd1d2540aaf4 | 80 | |
Mpmart08 | 0:cd1d2540aaf4 | 81 | // draws the upper pipe at its current location |
Mpmart08 | 0:cd1d2540aaf4 | 82 | switch (pipe.getType()) { |
Mpmart08 | 0:cd1d2540aaf4 | 83 | case PIPE16: |
Mpmart08 | 0:cd1d2540aaf4 | 84 | uLCD.set_sector_address(PIPEDOWN16); |
Mpmart08 | 0:cd1d2540aaf4 | 85 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 86 | case PIPE32: |
Mpmart08 | 0:cd1d2540aaf4 | 87 | uLCD.set_sector_address(PIPEDOWN32); |
Mpmart08 | 0:cd1d2540aaf4 | 88 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 89 | case PIPE48: |
Mpmart08 | 0:cd1d2540aaf4 | 90 | uLCD.set_sector_address(PIPEDOWN48); |
Mpmart08 | 0:cd1d2540aaf4 | 91 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 92 | case PIPE64: |
Mpmart08 | 0:cd1d2540aaf4 | 93 | uLCD.set_sector_address(PIPEDOWN64); |
Mpmart08 | 0:cd1d2540aaf4 | 94 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 95 | case PIPE80: |
Mpmart08 | 0:cd1d2540aaf4 | 96 | uLCD.set_sector_address(PIPEDOWN80); |
Mpmart08 | 0:cd1d2540aaf4 | 97 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 98 | case PIPE96: |
Mpmart08 | 0:cd1d2540aaf4 | 99 | uLCD.set_sector_address(PIPEDOWN96); |
Mpmart08 | 0:cd1d2540aaf4 | 100 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 101 | } |
Mpmart08 | 0:cd1d2540aaf4 | 102 | x = pipe.getX(); |
Mpmart08 | 0:cd1d2540aaf4 | 103 | y = 0; |
Mpmart08 | 0:cd1d2540aaf4 | 104 | uLCD.display_image(x,y); |
Mpmart08 | 0:cd1d2540aaf4 | 105 | |
Mpmart08 | 0:cd1d2540aaf4 | 106 | // clears the bird from its previous location |
Mpmart08 | 0:cd1d2540aaf4 | 107 | uLCD.filled_rectangle( // draws a rectangle the size of the bird |
Mpmart08 | 0:cd1d2540aaf4 | 108 | flappyBird.getX(), // the bird's current x position |
Mpmart08 | 0:cd1d2540aaf4 | 109 | flappyBird.getOldY(), // the bird's old y position |
Mpmart08 | 0:cd1d2540aaf4 | 110 | flappyBird.getX() + flappyBird.getWidth(), // the bird's x position + the bird's width |
Mpmart08 | 0:cd1d2540aaf4 | 111 | flappyBird.getOldY() + flappyBird.getHeight(), // the bird's old y position + the bird's height |
Mpmart08 | 0:cd1d2540aaf4 | 112 | 0x4EC0CA // the color of the background |
Mpmart08 | 0:cd1d2540aaf4 | 113 | ); |
Mpmart08 | 0:cd1d2540aaf4 | 114 | |
Mpmart08 | 0:cd1d2540aaf4 | 115 | // draws the bird at its current location |
Mpmart08 | 0:cd1d2540aaf4 | 116 | uLCD.set_sector_address(FLAPPY); |
Mpmart08 | 0:cd1d2540aaf4 | 117 | x = flappyBird.getX(); |
Mpmart08 | 0:cd1d2540aaf4 | 118 | y = flappyBird.getY(); |
Mpmart08 | 0:cd1d2540aaf4 | 119 | uLCD.display_image(x,y); |
Mpmart08 | 0:cd1d2540aaf4 | 120 | |
Mpmart08 | 0:cd1d2540aaf4 | 121 | // prints the player's current score |
Mpmart08 | 0:cd1d2540aaf4 | 122 | uLCD.locate(1,1); |
Mpmart08 | 0:cd1d2540aaf4 | 123 | uLCD.printf("%d", score); |
Mpmart08 | 0:cd1d2540aaf4 | 124 | } |
Mpmart08 | 0:cd1d2540aaf4 | 125 | |
Mpmart08 | 0:cd1d2540aaf4 | 126 | // function that determines if the bird has collided with a pipe |
Mpmart08 | 0:cd1d2540aaf4 | 127 | bool checkCollision() { |
Mpmart08 | 0:cd1d2540aaf4 | 128 | |
Mpmart08 | 0:cd1d2540aaf4 | 129 | if (pipe.getX() <= flappyBird.getX() + flappyBird.getWidth() |
Mpmart08 | 0:cd1d2540aaf4 | 130 | && flappyBird.getX() <= pipe.getX() + pipe.getWidth()) { |
Mpmart08 | 0:cd1d2540aaf4 | 131 | return (flappyBird.getY() < pipe.getY() || flappyBird.getY() >= (pipe.getY() + 32)); |
Mpmart08 | 0:cd1d2540aaf4 | 132 | } else { |
Mpmart08 | 0:cd1d2540aaf4 | 133 | return false; |
Mpmart08 | 0:cd1d2540aaf4 | 134 | } |
Mpmart08 | 0:cd1d2540aaf4 | 135 | } |
Mpmart08 | 0:cd1d2540aaf4 | 136 | |
Mpmart08 | 0:cd1d2540aaf4 | 137 | // Nav switch callbacks |
Mpmart08 | 0:cd1d2540aaf4 | 138 | |
Mpmart08 | 0:cd1d2540aaf4 | 139 | void nsUp_hit_callback() // the up button is pressed |
Mpmart08 | 0:cd1d2540aaf4 | 140 | { |
Mpmart08 | 0:cd1d2540aaf4 | 141 | switch (gameState) |
Mpmart08 | 0:cd1d2540aaf4 | 142 | { |
Mpmart08 | 0:cd1d2540aaf4 | 143 | case GAME: // if game is running, then move the bird upwards |
Mpmart08 | 0:cd1d2540aaf4 | 144 | flappyBird.move(DIRECTION_UP); |
Mpmart08 | 0:cd1d2540aaf4 | 145 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 146 | } |
Mpmart08 | 0:cd1d2540aaf4 | 147 | } |
Mpmart08 | 0:cd1d2540aaf4 | 148 | |
Mpmart08 | 0:cd1d2540aaf4 | 149 | void nsDown_hit_callback() // the down button is pressed |
Mpmart08 | 0:cd1d2540aaf4 | 150 | { |
Mpmart08 | 0:cd1d2540aaf4 | 151 | switch (gameState) |
Mpmart08 | 0:cd1d2540aaf4 | 152 | { |
Mpmart08 | 0:cd1d2540aaf4 | 153 | case GAME: // if game is running, then move the bird downwards |
Mpmart08 | 0:cd1d2540aaf4 | 154 | flappyBird.move(DIRECTION_DOWN); |
Mpmart08 | 0:cd1d2540aaf4 | 155 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 156 | } |
Mpmart08 | 0:cd1d2540aaf4 | 157 | } |
Mpmart08 | 0:cd1d2540aaf4 | 158 | |
Mpmart08 | 0:cd1d2540aaf4 | 159 | void nsCenter_hit_callback() // the center button is pressed |
Mpmart08 | 0:cd1d2540aaf4 | 160 | { |
Mpmart08 | 0:cd1d2540aaf4 | 161 | switch (gameState) |
Mpmart08 | 0:cd1d2540aaf4 | 162 | { |
Mpmart08 | 0:cd1d2540aaf4 | 163 | case WAIT: // if game is waiting to start, set up the game |
Mpmart08 | 0:cd1d2540aaf4 | 164 | gameState = GAME_SETUP; |
Mpmart08 | 0:cd1d2540aaf4 | 165 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 166 | } |
Mpmart08 | 0:cd1d2540aaf4 | 167 | } |
Mpmart08 | 0:cd1d2540aaf4 | 168 | |
Mpmart08 | 0:cd1d2540aaf4 | 169 | // thread that plays game sounds through the speaker |
Mpmart08 | 0:cd1d2540aaf4 | 170 | void speaker_thread(void const *argument) { |
Mpmart08 | 0:cd1d2540aaf4 | 171 | |
Mpmart08 | 0:cd1d2540aaf4 | 172 | Speaker *player = &mySpeaker; |
Mpmart08 | 0:cd1d2540aaf4 | 173 | |
Mpmart08 | 0:cd1d2540aaf4 | 174 | // Start Song |
Mpmart08 | 0:cd1d2540aaf4 | 175 | float sFreq[] = {550,750,550,750}; |
Mpmart08 | 0:cd1d2540aaf4 | 176 | float sDur[] = {.3,.3,.3,.3}; |
Mpmart08 | 0:cd1d2540aaf4 | 177 | float sVol[] = {.5,.5,.5,.5}; |
Mpmart08 | 0:cd1d2540aaf4 | 178 | SoundBuilder startSong(sFreq, sDur, sVol, sizeof(sFreq)/sizeof(*sFreq), player); |
Mpmart08 | 0:cd1d2540aaf4 | 179 | |
Mpmart08 | 0:cd1d2540aaf4 | 180 | // End Song |
Mpmart08 | 0:cd1d2540aaf4 | 181 | float eFreq[] = {300,200,250,225,200,150,150,100}; |
Mpmart08 | 0:cd1d2540aaf4 | 182 | float eDur[] = {.3,.3,.3,.3,.3,.3,.3,.3}; |
Mpmart08 | 0:cd1d2540aaf4 | 183 | float eVol[] = {.5,.5,.5,.5,.5,.5,.5,.5}; |
Mpmart08 | 0:cd1d2540aaf4 | 184 | SoundBuilder endSong(eFreq, eDur, eVol, sizeof(eFreq)/sizeof(*eFreq), player); |
Mpmart08 | 0:cd1d2540aaf4 | 185 | |
Mpmart08 | 0:cd1d2540aaf4 | 186 | while (true) { |
Mpmart08 | 0:cd1d2540aaf4 | 187 | switch (gameState) { |
Mpmart08 | 0:cd1d2540aaf4 | 188 | case GAME: // if game is running and user dodges a pipe, play a note |
Mpmart08 | 0:cd1d2540aaf4 | 189 | if (oldScore < score) { |
Mpmart08 | 0:cd1d2540aaf4 | 190 | mySpeaker.PlayNote(440, 0.1, 0.5); |
Mpmart08 | 0:cd1d2540aaf4 | 191 | oldScore = score; |
Mpmart08 | 0:cd1d2540aaf4 | 192 | } |
Mpmart08 | 0:cd1d2540aaf4 | 193 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 194 | case START: // play a song at the start of the game |
Mpmart08 | 0:cd1d2540aaf4 | 195 | startSong.playSong(); |
Mpmart08 | 0:cd1d2540aaf4 | 196 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 197 | case LOSE: // play a song when the player loses the game |
Mpmart08 | 0:cd1d2540aaf4 | 198 | endSong.playSong(); |
Mpmart08 | 0:cd1d2540aaf4 | 199 | wait(5); |
Mpmart08 | 0:cd1d2540aaf4 | 200 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 201 | } |
Mpmart08 | 0:cd1d2540aaf4 | 202 | } |
Mpmart08 | 0:cd1d2540aaf4 | 203 | } |
Mpmart08 | 0:cd1d2540aaf4 | 204 | |
Mpmart08 | 0:cd1d2540aaf4 | 205 | int main() { |
Mpmart08 | 0:cd1d2540aaf4 | 206 | |
Mpmart08 | 0:cd1d2540aaf4 | 207 | // Setup internal pullup resistors for nav switch input pins |
Mpmart08 | 0:cd1d2540aaf4 | 208 | nsUp.mode(PullUp); |
Mpmart08 | 0:cd1d2540aaf4 | 209 | nsDown.mode(PullUp); |
Mpmart08 | 0:cd1d2540aaf4 | 210 | nsCenter.mode(PullUp); |
Mpmart08 | 0:cd1d2540aaf4 | 211 | // Wait for pullup to take effect |
Mpmart08 | 0:cd1d2540aaf4 | 212 | wait(0.1); |
Mpmart08 | 0:cd1d2540aaf4 | 213 | // Attaches nav switch inputs to the callback functions |
Mpmart08 | 0:cd1d2540aaf4 | 214 | nsUp.attach_deasserted(&nsUp_hit_callback); |
Mpmart08 | 0:cd1d2540aaf4 | 215 | nsDown.attach_deasserted(&nsDown_hit_callback); |
Mpmart08 | 0:cd1d2540aaf4 | 216 | nsCenter.attach_deasserted(&nsCenter_hit_callback); |
Mpmart08 | 0:cd1d2540aaf4 | 217 | // Set sample frequency for nav switch interrupts |
Mpmart08 | 0:cd1d2540aaf4 | 218 | nsUp.setSampleFrequency(); |
Mpmart08 | 0:cd1d2540aaf4 | 219 | nsDown.setSampleFrequency(); |
Mpmart08 | 0:cd1d2540aaf4 | 220 | nsCenter.setSampleFrequency(); |
Mpmart08 | 0:cd1d2540aaf4 | 221 | |
Mpmart08 | 0:cd1d2540aaf4 | 222 | // initialize the lcd |
Mpmart08 | 0:cd1d2540aaf4 | 223 | uLCD.media_init(); |
Mpmart08 | 0:cd1d2540aaf4 | 224 | uLCD.cls(); |
Mpmart08 | 0:cd1d2540aaf4 | 225 | uLCD.background_color(0x4EC0CA); |
Mpmart08 | 0:cd1d2540aaf4 | 226 | uLCD.textbackground_color(0x4EC0CA); |
Mpmart08 | 0:cd1d2540aaf4 | 227 | uLCD.color(WHITE); |
Mpmart08 | 0:cd1d2540aaf4 | 228 | |
Mpmart08 | 0:cd1d2540aaf4 | 229 | int highscore = 0; // variable to store high score |
Mpmart08 | 0:cd1d2540aaf4 | 230 | int i = 0; // variable for seeding random pipe generation |
Mpmart08 | 0:cd1d2540aaf4 | 231 | |
Mpmart08 | 0:cd1d2540aaf4 | 232 | Thread thread1(speaker_thread); // start speaker thread |
Mpmart08 | 0:cd1d2540aaf4 | 233 | |
Mpmart08 | 0:cd1d2540aaf4 | 234 | while (1) |
Mpmart08 | 0:cd1d2540aaf4 | 235 | { |
Mpmart08 | 0:cd1d2540aaf4 | 236 | switch (gameState) |
Mpmart08 | 0:cd1d2540aaf4 | 237 | { |
Mpmart08 | 0:cd1d2540aaf4 | 238 | case START: |
Mpmart08 | 0:cd1d2540aaf4 | 239 | |
Mpmart08 | 0:cd1d2540aaf4 | 240 | // read current high score from a text file on the sd card |
Mpmart08 | 0:cd1d2540aaf4 | 241 | FILE *fp = fopen("/sd/highscore.txt", "r"); |
Mpmart08 | 0:cd1d2540aaf4 | 242 | if(fp == NULL) { |
Mpmart08 | 0:cd1d2540aaf4 | 243 | error("Could not open file for read\n"); |
Mpmart08 | 0:cd1d2540aaf4 | 244 | } |
Mpmart08 | 0:cd1d2540aaf4 | 245 | fscanf(fp, "%i", &highscore); |
Mpmart08 | 0:cd1d2540aaf4 | 246 | fclose(fp); |
Mpmart08 | 0:cd1d2540aaf4 | 247 | |
Mpmart08 | 0:cd1d2540aaf4 | 248 | // display start screen on lcd |
Mpmart08 | 0:cd1d2540aaf4 | 249 | uLCD.cls(); |
Mpmart08 | 0:cd1d2540aaf4 | 250 | uLCD.locate(0,0); |
Mpmart08 | 0:cd1d2540aaf4 | 251 | uLCD.printf("Flappy Bird(ish)!\n\n"); |
Mpmart08 | 0:cd1d2540aaf4 | 252 | uLCD.printf("Press Fire\nto Start\n\n"); |
Mpmart08 | 0:cd1d2540aaf4 | 253 | uLCD.printf("High Score: %i", highscore); |
Mpmart08 | 0:cd1d2540aaf4 | 254 | gameState = WAIT; |
Mpmart08 | 0:cd1d2540aaf4 | 255 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 256 | |
Mpmart08 | 0:cd1d2540aaf4 | 257 | case GAME_SETUP: |
Mpmart08 | 0:cd1d2540aaf4 | 258 | |
Mpmart08 | 0:cd1d2540aaf4 | 259 | // initialize game objects and draw initial frame on the lcd |
Mpmart08 | 0:cd1d2540aaf4 | 260 | uLCD.cls(); |
Mpmart08 | 0:cd1d2540aaf4 | 261 | pipe = Pipe(); |
Mpmart08 | 0:cd1d2540aaf4 | 262 | drawScreen(); |
Mpmart08 | 0:cd1d2540aaf4 | 263 | srand(i); |
Mpmart08 | 0:cd1d2540aaf4 | 264 | score = 0; |
Mpmart08 | 0:cd1d2540aaf4 | 265 | oldScore = 0; |
Mpmart08 | 0:cd1d2540aaf4 | 266 | gameState = GAME; |
Mpmart08 | 0:cd1d2540aaf4 | 267 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 268 | |
Mpmart08 | 0:cd1d2540aaf4 | 269 | case GAME: |
Mpmart08 | 0:cd1d2540aaf4 | 270 | |
Mpmart08 | 0:cd1d2540aaf4 | 271 | // read the game speed from the potentiometer |
Mpmart08 | 0:cd1d2540aaf4 | 272 | gameSpeed = (int) (pot + 1) * 5; |
Mpmart08 | 0:cd1d2540aaf4 | 273 | |
Mpmart08 | 0:cd1d2540aaf4 | 274 | // if there is a collision, the player loses |
Mpmart08 | 0:cd1d2540aaf4 | 275 | if (checkCollision()) { |
Mpmart08 | 0:cd1d2540aaf4 | 276 | gameState = LOSE; |
Mpmart08 | 0:cd1d2540aaf4 | 277 | } |
Mpmart08 | 0:cd1d2540aaf4 | 278 | |
Mpmart08 | 0:cd1d2540aaf4 | 279 | // if the player dodges a pipe, increase the score and create a new pipe |
Mpmart08 | 0:cd1d2540aaf4 | 280 | if (pipe.getX() + pipe.getWidth() < 0) { |
Mpmart08 | 0:cd1d2540aaf4 | 281 | score++; |
Mpmart08 | 0:cd1d2540aaf4 | 282 | pipe = Pipe(); |
Mpmart08 | 0:cd1d2540aaf4 | 283 | } |
Mpmart08 | 0:cd1d2540aaf4 | 284 | |
Mpmart08 | 0:cd1d2540aaf4 | 285 | // draw the current frame of the game on the lcd |
Mpmart08 | 0:cd1d2540aaf4 | 286 | drawScreen(); |
Mpmart08 | 0:cd1d2540aaf4 | 287 | |
Mpmart08 | 0:cd1d2540aaf4 | 288 | // move the pipe across the screen according the game speed |
Mpmart08 | 0:cd1d2540aaf4 | 289 | pipe.move(gameSpeed); |
Mpmart08 | 0:cd1d2540aaf4 | 290 | |
Mpmart08 | 0:cd1d2540aaf4 | 291 | // wait for lcd to finish drawing images |
Mpmart08 | 0:cd1d2540aaf4 | 292 | wait(0.25); |
Mpmart08 | 0:cd1d2540aaf4 | 293 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 294 | |
Mpmart08 | 0:cd1d2540aaf4 | 295 | case LOSE: |
Mpmart08 | 0:cd1d2540aaf4 | 296 | |
Mpmart08 | 0:cd1d2540aaf4 | 297 | // display game over screen on lcd |
Mpmart08 | 0:cd1d2540aaf4 | 298 | uLCD.cls(); |
Mpmart08 | 0:cd1d2540aaf4 | 299 | uLCD.printf("YOU LOSE D:\n\n"); |
Mpmart08 | 0:cd1d2540aaf4 | 300 | |
Mpmart08 | 0:cd1d2540aaf4 | 301 | // if the user beat the high score, save and display high score info |
Mpmart08 | 0:cd1d2540aaf4 | 302 | if (score > highscore){ |
Mpmart08 | 0:cd1d2540aaf4 | 303 | uLCD.printf("CONGRATZ THO NEW HIGH SCORE!"); |
Mpmart08 | 0:cd1d2540aaf4 | 304 | uLCD.printf(" %i", score); |
Mpmart08 | 0:cd1d2540aaf4 | 305 | // overwrite previous high score |
Mpmart08 | 0:cd1d2540aaf4 | 306 | fp = fopen("/sd/highscore.txt", "w"); |
Mpmart08 | 0:cd1d2540aaf4 | 307 | fprintf(fp, "%i", score); |
Mpmart08 | 0:cd1d2540aaf4 | 308 | fclose(fp); |
Mpmart08 | 0:cd1d2540aaf4 | 309 | } |
Mpmart08 | 0:cd1d2540aaf4 | 310 | |
Mpmart08 | 0:cd1d2540aaf4 | 311 | // restart game after 5 seconds |
Mpmart08 | 0:cd1d2540aaf4 | 312 | wait(5.0); |
Mpmart08 | 0:cd1d2540aaf4 | 313 | gameState = START; |
Mpmart08 | 0:cd1d2540aaf4 | 314 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 315 | case WAIT: |
Mpmart08 | 0:cd1d2540aaf4 | 316 | |
Mpmart08 | 0:cd1d2540aaf4 | 317 | i++; // Used to seed the rand() function so we don't get the same positions for the pipes every time |
Mpmart08 | 0:cd1d2540aaf4 | 318 | break; |
Mpmart08 | 0:cd1d2540aaf4 | 319 | } |
Mpmart08 | 0:cd1d2540aaf4 | 320 | } |
Mpmart08 | 0:cd1d2540aaf4 | 321 | } |