Space Invaders - Embedded Systems Project 15/16 - Avinash Patel 200860407
Dependencies: Joystick N5110 SDFileSystem mbed
main.cpp@7:babc367a3333, 2016-05-02 (annotated)
- Committer:
- avi23
- Date:
- Mon May 02 16:28:07 2016 +0000
- Revision:
- 7:babc367a3333
- Parent:
- 6:89d4a7f7588b
- Child:
- 8:b2faec20ed8f
Before main.cpp doxygening
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
avi23 | 1:b300d052d549 | 1 | /* |
avi23 | 1:b300d052d549 | 2 | Space Invaders - Avinash Patel 200860407 |
avi23 | 1:b300d052d549 | 3 | |
avi23 | 1:b300d052d549 | 4 | Week 19 - Set up joystick class |
avi23 | 1:b300d052d549 | 5 | Week 20 - Changed to space invaders as constrained too much by screen resolution |
avi23 | 1:b300d052d549 | 6 | - Core cannon is drawn and can move, enemies are visible and they switch between states every second |
avi23 | 2:d34c95990605 | 7 | Week 21 - Begun to set up barriers |
avi23 | 5:34855f712350 | 8 | Easter - Barriers work, invader and player can shoot. Begun setting up menus |
avi23 | 7:babc367a3333 | 9 | Week 22 - Most menus work |
avi23 | 7:babc367a3333 | 10 | Week 23 - Menus work |
avi23 | 1:b300d052d549 | 11 | */ |
avi23 | 0:427469992efe | 12 | #include "mbed.h" |
avi23 | 7:babc367a3333 | 13 | #include "main.h" |
avi23 | 0:427469992efe | 14 | |
avi23 | 5:34855f712350 | 15 | int row_no = 5; |
avi23 | 5:34855f712350 | 16 | int col_no = 14; |
avi23 | 0:427469992efe | 17 | |
avi23 | 0:427469992efe | 18 | int main() |
avi23 | 0:427469992efe | 19 | { |
avi23 | 5:34855f712350 | 20 | //Wait for 2 seconds to allow power to settle |
avi23 | 5:34855f712350 | 21 | wait(1); |
avi23 | 0:427469992efe | 22 | //Initalises the board and perhiperals |
avi23 | 0:427469992efe | 23 | init_K64F(); |
avi23 | 0:427469992efe | 24 | init_serial(); |
avi23 | 2:d34c95990605 | 25 | init_shoot(); |
avi23 | 5:34855f712350 | 26 | init_rng(); |
avi23 | 5:34855f712350 | 27 | joystick.init(); |
avi23 | 0:427469992efe | 28 | lcd.init(); |
avi23 | 0:427469992efe | 29 | lcd.clear(); |
avi23 | 0:427469992efe | 30 | |
avi23 | 5:34855f712350 | 31 | //Configures the function pointer for the invaders normal missile |
avi23 | 5:34855f712350 | 32 | move_invader_normal_missile_isr[0] = &move_invader_normal_missile_0_isr; |
avi23 | 5:34855f712350 | 33 | move_invader_normal_missile_isr[1] = &move_invader_normal_missile_1_isr; |
avi23 | 0:427469992efe | 34 | |
avi23 | 5:34855f712350 | 35 | //Samples joystick every 0.05 second |
avi23 | 5:34855f712350 | 36 | move_joystick.attach(&move_joystick_isr, 0.05); |
avi23 | 2:d34c95990605 | 37 | |
avi23 | 6:89d4a7f7588b | 38 | |
avi23 | 6:89d4a7f7588b | 39 | |
avi23 | 2:d34c95990605 | 40 | while (true) { |
avi23 | 5:34855f712350 | 41 | if (game_state == menu) { //Menu screen |
avi23 | 2:d34c95990605 | 42 | lcd.clear(); |
avi23 | 6:89d4a7f7588b | 43 | fsm_state = 0; //Sets the fsm state to 0 |
avi23 | 6:89d4a7f7588b | 44 | while (game_state == menu) { |
avi23 | 6:89d4a7f7588b | 45 | lcd.printString("Space Invaders", 0, 0); |
avi23 | 6:89d4a7f7588b | 46 | lcd.printString("Menu", 28, 1); |
avi23 | 6:89d4a7f7588b | 47 | lcd.drawLine(0, 15, 83, 15, 2); |
avi23 | 6:89d4a7f7588b | 48 | |
avi23 | 6:89d4a7f7588b | 49 | lcd.printString("New Game", 5, 2); |
avi23 | 6:89d4a7f7588b | 50 | lcd.printString("Load Game", 5, 3); |
avi23 | 6:89d4a7f7588b | 51 | lcd.printString("High Scores", 5, 4); |
avi23 | 6:89d4a7f7588b | 52 | lcd.printString("Settings", 5, 5); |
avi23 | 6:89d4a7f7588b | 53 | |
avi23 | 6:89d4a7f7588b | 54 | //Draws the cursor |
avi23 | 6:89d4a7f7588b | 55 | cursor_y_pos = ((fsm_state+2)*8)+3; //Adds 2 to the fsm state to get the bank, multiplies it by 8 to get the pixel no and offsets it by 3 |
avi23 | 6:89d4a7f7588b | 56 | lcd.drawRect(74, cursor_y_pos, 2, 2, 1); |
avi23 | 6:89d4a7f7588b | 57 | |
avi23 | 6:89d4a7f7588b | 58 | if (g_move_joystick_flag) { |
avi23 | 6:89d4a7f7588b | 59 | g_move_joystick_flag = false; |
avi23 | 6:89d4a7f7588b | 60 | |
avi23 | 6:89d4a7f7588b | 61 | //Moves the cursor to match the selected option, only if the joystick isn't centred |
avi23 | 6:89d4a7f7588b | 62 | MoveCursor(fsm_main_menu); |
avi23 | 6:89d4a7f7588b | 63 | } |
avi23 | 6:89d4a7f7588b | 64 | |
avi23 | 6:89d4a7f7588b | 65 | if (g_shoot_pressed_flag) { |
avi23 | 6:89d4a7f7588b | 66 | g_shoot_pressed_flag = false; |
avi23 | 6:89d4a7f7588b | 67 | |
avi23 | 6:89d4a7f7588b | 68 | game_state = fsm_main_menu[fsm_state].output; |
avi23 | 2:d34c95990605 | 69 | |
avi23 | 6:89d4a7f7588b | 70 | //If the game state is equal to the game initalise it |
avi23 | 6:89d4a7f7588b | 71 | if (game_state == game) { |
avi23 | 7:babc367a3333 | 72 | InitaliseGame(); |
avi23 | 6:89d4a7f7588b | 73 | } |
avi23 | 6:89d4a7f7588b | 74 | } |
avi23 | 5:34855f712350 | 75 | |
avi23 | 6:89d4a7f7588b | 76 | if(joystick.get_button_flag()) { |
avi23 | 6:89d4a7f7588b | 77 | joystick.set_button_flag(0); |
avi23 | 6:89d4a7f7588b | 78 | } |
avi23 | 6:89d4a7f7588b | 79 | |
avi23 | 6:89d4a7f7588b | 80 | lcd.refresh(); |
avi23 | 6:89d4a7f7588b | 81 | sleep(); |
avi23 | 1:b300d052d549 | 82 | } |
avi23 | 5:34855f712350 | 83 | } else if (game_state == paused) { //Paused screen |
avi23 | 6:89d4a7f7588b | 84 | //Clears the screen |
avi23 | 6:89d4a7f7588b | 85 | lcd.clear(); |
avi23 | 6:89d4a7f7588b | 86 | //Resets the fsm state to 0 |
avi23 | 6:89d4a7f7588b | 87 | fsm_state = 0; |
avi23 | 6:89d4a7f7588b | 88 | PauseScreen(); |
avi23 | 5:34855f712350 | 89 | } else if (game_state == game) { //Game screen |
avi23 | 5:34855f712350 | 90 | AttachTickers(); |
avi23 | 5:34855f712350 | 91 | Game(); |
avi23 | 0:427469992efe | 92 | } |
avi23 | 2:d34c95990605 | 93 | |
avi23 | 0:427469992efe | 94 | sleep(); |
avi23 | 0:427469992efe | 95 | } |
avi23 | 0:427469992efe | 96 | } |
avi23 | 0:427469992efe | 97 | |
avi23 | 0:427469992efe | 98 | void init_K64F() |
avi23 | 0:427469992efe | 99 | { |
avi23 | 0:427469992efe | 100 | // on-board LEDs are active-low, so set pin high to turn them off. |
avi23 | 0:427469992efe | 101 | r_led = 1; |
avi23 | 0:427469992efe | 102 | g_led = 1; |
avi23 | 0:427469992efe | 103 | b_led = 1; |
avi23 | 0:427469992efe | 104 | |
avi23 | 0:427469992efe | 105 | // since the on-board switches have external pull-ups, we should disable the internal pull-down |
avi23 | 0:427469992efe | 106 | // resistors that are enabled by default using InterruptIn |
avi23 | 0:427469992efe | 107 | sw2.mode(PullNone); |
avi23 | 0:427469992efe | 108 | sw3.mode(PullNone); |
avi23 | 0:427469992efe | 109 | } |
avi23 | 0:427469992efe | 110 | |
avi23 | 0:427469992efe | 111 | void error() |
avi23 | 0:427469992efe | 112 | { |
avi23 | 0:427469992efe | 113 | while(1) { // if error, hang while flashing error message |
avi23 | 0:427469992efe | 114 | r_led = 0; |
avi23 | 0:427469992efe | 115 | wait(0.2); |
avi23 | 0:427469992efe | 116 | r_led = 1; |
avi23 | 0:427469992efe | 117 | wait(0.2); |
avi23 | 0:427469992efe | 118 | } |
avi23 | 0:427469992efe | 119 | } |
avi23 | 0:427469992efe | 120 | |
avi23 | 0:427469992efe | 121 | void init_serial() |
avi23 | 0:427469992efe | 122 | { |
avi23 | 0:427469992efe | 123 | // set to highest baud - ensure terminal software matches |
avi23 | 0:427469992efe | 124 | pc.baud(115200); |
avi23 | 0:427469992efe | 125 | } |
avi23 | 0:427469992efe | 126 | |
avi23 | 5:34855f712350 | 127 | //Seeds the random number generator with noise from an analog in pin |
avi23 | 5:34855f712350 | 128 | void init_rng() |
avi23 | 5:34855f712350 | 129 | { |
avi23 | 7:babc367a3333 | 130 | AnalogIn rng_seed(PTC10); //Creates a AnalogIn on a unused pin |
avi23 | 7:babc367a3333 | 131 | srand(floor(10000*rng_seed.read())); //Sets the seed as 10000x the input of the analog in |
avi23 | 5:34855f712350 | 132 | } |
avi23 | 5:34855f712350 | 133 | |
avi23 | 2:d34c95990605 | 134 | void init_shoot() |
avi23 | 0:427469992efe | 135 | { |
avi23 | 2:d34c95990605 | 136 | shoot_button.mode(PullUp); |
avi23 | 2:d34c95990605 | 137 | shoot_button.fall(&shoot_pressed_isr); |
avi23 | 2:d34c95990605 | 138 | } |
avi23 | 2:d34c95990605 | 139 | |
avi23 | 2:d34c95990605 | 140 | void update_screen_isr() |
avi23 | 2:d34c95990605 | 141 | { |
avi23 | 2:d34c95990605 | 142 | g_update_screen_flag = true; |
avi23 | 0:427469992efe | 143 | } |
avi23 | 0:427469992efe | 144 | |
avi23 | 5:34855f712350 | 145 | void move_enemies_isr() |
avi23 | 5:34855f712350 | 146 | { |
avi23 | 5:34855f712350 | 147 | g_move_enemies_flag = true; |
avi23 | 5:34855f712350 | 148 | } |
avi23 | 5:34855f712350 | 149 | |
avi23 | 2:d34c95990605 | 150 | void shoot_pressed_isr() |
avi23 | 2:d34c95990605 | 151 | { |
avi23 | 6:89d4a7f7588b | 152 | //Only sets the shoot pressed flag 0.1s after the last press |
avi23 | 6:89d4a7f7588b | 153 | if (!g_shoot_button_debounce_flag) { |
avi23 | 6:89d4a7f7588b | 154 | g_shoot_pressed_flag = true; |
avi23 | 6:89d4a7f7588b | 155 | g_shoot_button_debounce_flag = true; |
avi23 | 6:89d4a7f7588b | 156 | |
avi23 | 6:89d4a7f7588b | 157 | //Attaches a timeout to clear the debounce flag 0.125 seconds after it was set |
avi23 | 6:89d4a7f7588b | 158 | shoot_button_debounce.attach(&shoot_button_debounce_isr, 0.125); |
avi23 | 6:89d4a7f7588b | 159 | } |
avi23 | 5:34855f712350 | 160 | } |
avi23 | 5:34855f712350 | 161 | |
avi23 | 5:34855f712350 | 162 | void move_cannon_missile_isr() |
avi23 | 5:34855f712350 | 163 | { |
avi23 | 5:34855f712350 | 164 | g_move_cannon_missile_flag = true; |
avi23 | 5:34855f712350 | 165 | } |
avi23 | 5:34855f712350 | 166 | |
avi23 | 5:34855f712350 | 167 | void move_joystick_isr() |
avi23 | 5:34855f712350 | 168 | { |
avi23 | 5:34855f712350 | 169 | //Always set the move flag in a game |
avi23 | 5:34855f712350 | 170 | if (game_state == game) { |
avi23 | 5:34855f712350 | 171 | g_move_joystick_flag = true; |
avi23 | 5:34855f712350 | 172 | } else if (!g_joystick_cursor_regulator_flag) { |
avi23 | 6:89d4a7f7588b | 173 | //Only sets the flag if the regulator is not set |
avi23 | 5:34855f712350 | 174 | g_move_joystick_flag = true; |
avi23 | 5:34855f712350 | 175 | g_joystick_cursor_regulator_flag = true; |
avi23 | 5:34855f712350 | 176 | |
avi23 | 6:89d4a7f7588b | 177 | //Attachs a timeout to clear the regulator in 0.1s to prevent the cursor from behaving erratically |
avi23 | 6:89d4a7f7588b | 178 | joystick_cursor_regulator.attach(&joystick_cursor_regulator_isr, 0.1); |
avi23 | 5:34855f712350 | 179 | } |
avi23 | 5:34855f712350 | 180 | } |
avi23 | 5:34855f712350 | 181 | |
avi23 | 6:89d4a7f7588b | 182 | void joystick_cursor_regulator_isr() |
avi23 | 6:89d4a7f7588b | 183 | { |
avi23 | 5:34855f712350 | 184 | g_joystick_cursor_regulator_flag = false; |
avi23 | 5:34855f712350 | 185 | } |
avi23 | 5:34855f712350 | 186 | |
avi23 | 6:89d4a7f7588b | 187 | void shoot_button_debounce_isr() |
avi23 | 6:89d4a7f7588b | 188 | { |
avi23 | 6:89d4a7f7588b | 189 | g_shoot_button_debounce_flag = false; |
avi23 | 6:89d4a7f7588b | 190 | } |
avi23 | 6:89d4a7f7588b | 191 | |
avi23 | 5:34855f712350 | 192 | void move_invader_normal_missile_0_isr() |
avi23 | 5:34855f712350 | 193 | { |
avi23 | 5:34855f712350 | 194 | g_move_invader_normal_missile_flag[0] = true; |
avi23 | 5:34855f712350 | 195 | } |
avi23 | 5:34855f712350 | 196 | |
avi23 | 5:34855f712350 | 197 | void move_invader_normal_missile_1_isr() |
avi23 | 5:34855f712350 | 198 | { |
avi23 | 5:34855f712350 | 199 | g_move_invader_normal_missile_flag[1] = true; |
avi23 | 5:34855f712350 | 200 | } |
avi23 | 5:34855f712350 | 201 | |
avi23 | 5:34855f712350 | 202 | void cannon_hit_isr() |
avi23 | 5:34855f712350 | 203 | { |
avi23 | 5:34855f712350 | 204 | g_cannon_hit_flag = false; |
avi23 | 2:d34c95990605 | 205 | } |
avi23 | 2:d34c95990605 | 206 | |
avi23 | 5:34855f712350 | 207 | void Game() |
avi23 | 6:89d4a7f7588b | 208 | { |
avi23 | 5:34855f712350 | 209 | //Stays within the loop while the selected state is game |
avi23 | 5:34855f712350 | 210 | while (game_state == game) { |
avi23 | 5:34855f712350 | 211 | //If the game is over detach all the tickers |
avi23 | 5:34855f712350 | 212 | if (number_of_lives == 0) { |
avi23 | 5:34855f712350 | 213 | DetachTickers(); |
avi23 | 5:34855f712350 | 214 | |
avi23 | 5:34855f712350 | 215 | lcd.clear(); |
avi23 | 5:34855f712350 | 216 | lcd.printString("Game Over.", 1, 2); |
avi23 | 7:babc367a3333 | 217 | char buffer[14]; |
avi23 | 7:babc367a3333 | 218 | sprintf(buffer, "Score: %d", score); |
avi23 | 7:babc367a3333 | 219 | lcd.printString(buffer, 1, 3); |
avi23 | 5:34855f712350 | 220 | } else if (no_of_alive_invaders == 0) { //If the player wins a round |
avi23 | 5:34855f712350 | 221 | //Resets the no of alive invaders |
avi23 | 5:34855f712350 | 222 | no_of_alive_invaders = 15; |
avi23 | 5:34855f712350 | 223 | //Detaches the enemy ticker while reinitalising invaders |
avi23 | 5:34855f712350 | 224 | move_enemies.detach(); |
avi23 | 5:34855f712350 | 225 | //Reinitalises objects |
avi23 | 5:34855f712350 | 226 | InitSmallInvaders(); |
avi23 | 5:34855f712350 | 227 | InitMediumInvaders(); |
avi23 | 5:34855f712350 | 228 | InitLargeInvaders(); |
avi23 | 5:34855f712350 | 229 | //Reattaches enemy ticker |
avi23 | 5:34855f712350 | 230 | move_enemies.attach(&move_enemies_isr, 1); |
avi23 | 5:34855f712350 | 231 | } else { |
avi23 | 5:34855f712350 | 232 | //Updates pixels on the screen |
avi23 | 5:34855f712350 | 233 | if (g_update_screen_flag) { |
avi23 | 5:34855f712350 | 234 | g_update_screen_flag = false; |
avi23 | 5:34855f712350 | 235 | |
avi23 | 5:34855f712350 | 236 | UpdateScreen(); |
avi23 | 5:34855f712350 | 237 | } |
avi23 | 5:34855f712350 | 238 | |
avi23 | 5:34855f712350 | 239 | //Controls cannon movement |
avi23 | 5:34855f712350 | 240 | if (g_move_joystick_flag) { |
avi23 | 5:34855f712350 | 241 | g_move_joystick_flag = false; |
avi23 | 5:34855f712350 | 242 | |
avi23 | 5:34855f712350 | 243 | MoveCannon(); |
avi23 | 5:34855f712350 | 244 | DrawBarriers(); |
avi23 | 5:34855f712350 | 245 | } |
avi23 | 5:34855f712350 | 246 | |
avi23 | 5:34855f712350 | 247 | //Controls enemy movement |
avi23 | 5:34855f712350 | 248 | if (g_move_enemies_flag) { |
avi23 | 5:34855f712350 | 249 | g_move_enemies_flag = false; |
avi23 | 5:34855f712350 | 250 | |
avi23 | 5:34855f712350 | 251 | //Increses the speed the invaders move |
avi23 | 5:34855f712350 | 252 | move_enemies.detach(); |
avi23 | 5:34855f712350 | 253 | ticker_period = 0.1+(no_of_alive_invaders*0.06); |
avi23 | 5:34855f712350 | 254 | move_enemies.attach(&move_enemies_isr, ticker_period); |
avi23 | 5:34855f712350 | 255 | |
avi23 | 5:34855f712350 | 256 | //Clears the old bitmaps |
avi23 | 5:34855f712350 | 257 | ClearSmallInvaders(); |
avi23 | 5:34855f712350 | 258 | ClearMediumInvaders(); |
avi23 | 5:34855f712350 | 259 | ClearLargeInvaders(); |
avi23 | 5:34855f712350 | 260 | |
avi23 | 5:34855f712350 | 261 | MoveInvaderXPositions(); |
avi23 | 5:34855f712350 | 262 | //Switches the bitmap state |
avi23 | 5:34855f712350 | 263 | invaders_in_state2 = !invaders_in_state2; |
avi23 | 5:34855f712350 | 264 | |
avi23 | 5:34855f712350 | 265 | //Draws the invaders |
avi23 | 5:34855f712350 | 266 | DrawSmallInvaders(); |
avi23 | 5:34855f712350 | 267 | DrawMediumInvaders(); |
avi23 | 5:34855f712350 | 268 | DrawLargeInvaders(); |
avi23 | 5:34855f712350 | 269 | |
avi23 | 5:34855f712350 | 270 | //Attemots to fire the invaders missiles |
avi23 | 5:34855f712350 | 271 | AttemptToFireInvaderNormalMissiles(); |
avi23 | 5:34855f712350 | 272 | } |
avi23 | 5:34855f712350 | 273 | |
avi23 | 5:34855f712350 | 274 | //Spawns a player bullet if the shoot button is pressed and there isn't a bullet on the screen |
avi23 | 5:34855f712350 | 275 | if (g_shoot_pressed_flag) { |
avi23 | 5:34855f712350 | 276 | g_shoot_pressed_flag = false; |
avi23 | 5:34855f712350 | 277 | |
avi23 | 5:34855f712350 | 278 | if (!cannon_missile_on_screen) { |
avi23 | 5:34855f712350 | 279 | FireCannonMissile(); |
avi23 | 5:34855f712350 | 280 | } |
avi23 | 5:34855f712350 | 281 | } |
avi23 | 5:34855f712350 | 282 | |
avi23 | 5:34855f712350 | 283 | //Move the cannon shot |
avi23 | 5:34855f712350 | 284 | if (g_move_cannon_missile_flag) { |
avi23 | 5:34855f712350 | 285 | g_move_cannon_missile_flag = false; |
avi23 | 5:34855f712350 | 286 | |
avi23 | 5:34855f712350 | 287 | MoveCannonMissile(); |
avi23 | 5:34855f712350 | 288 | } |
avi23 | 5:34855f712350 | 289 | |
avi23 | 5:34855f712350 | 290 | //Moves the invaders 1st normal missile |
avi23 | 5:34855f712350 | 291 | if (g_move_invader_normal_missile_flag[0]) { |
avi23 | 5:34855f712350 | 292 | g_move_invader_normal_missile_flag[0] = false; |
avi23 | 5:34855f712350 | 293 | |
avi23 | 5:34855f712350 | 294 | MoveInvaderNormalMissile(0); |
avi23 | 5:34855f712350 | 295 | } |
avi23 | 5:34855f712350 | 296 | |
avi23 | 5:34855f712350 | 297 | //Moves the invaders 2nd normal missile |
avi23 | 5:34855f712350 | 298 | if (g_move_invader_normal_missile_flag[1]) { |
avi23 | 5:34855f712350 | 299 | g_move_invader_normal_missile_flag[1] = false; |
avi23 | 5:34855f712350 | 300 | |
avi23 | 5:34855f712350 | 301 | MoveInvaderNormalMissile(1); |
avi23 | 5:34855f712350 | 302 | } |
avi23 | 5:34855f712350 | 303 | |
avi23 | 5:34855f712350 | 304 | if (joystick.get_button_flag()) { |
avi23 | 5:34855f712350 | 305 | joystick.set_button_flag(0); |
avi23 | 5:34855f712350 | 306 | |
avi23 | 5:34855f712350 | 307 | //Detach all game tickers |
avi23 | 5:34855f712350 | 308 | DetachTickers(); |
avi23 | 5:34855f712350 | 309 | game_state = paused; |
avi23 | 5:34855f712350 | 310 | } |
avi23 | 5:34855f712350 | 311 | } |
avi23 | 5:34855f712350 | 312 | |
avi23 | 5:34855f712350 | 313 | sleep(); |
avi23 | 5:34855f712350 | 314 | } |
avi23 | 2:d34c95990605 | 315 | } |
avi23 | 2:d34c95990605 | 316 | |
avi23 | 7:babc367a3333 | 317 | void InitaliseGame() |
avi23 | 7:babc367a3333 | 318 | { |
avi23 | 7:babc367a3333 | 319 | //Clears the screen buffer and runs init functions |
avi23 | 7:babc367a3333 | 320 | memset(screen_buffer, 0, sizeof(screen_buffer)); |
avi23 | 7:babc367a3333 | 321 | no_of_alive_invaders = 15; |
avi23 | 7:babc367a3333 | 322 | score = 0; |
avi23 | 7:babc367a3333 | 323 | number_of_lives = 3; |
avi23 | 7:babc367a3333 | 324 | InitSmallInvaders(); |
avi23 | 7:babc367a3333 | 325 | InitMediumInvaders(); |
avi23 | 7:babc367a3333 | 326 | InitLargeInvaders(); |
avi23 | 7:babc367a3333 | 327 | InitBarriers(); |
avi23 | 7:babc367a3333 | 328 | //Sets the flags so enemies pop up straight away |
avi23 | 7:babc367a3333 | 329 | g_update_screen_flag = true; |
avi23 | 7:babc367a3333 | 330 | g_move_joystick_flag = true; |
avi23 | 7:babc367a3333 | 331 | g_move_enemies_flag = true; |
avi23 | 7:babc367a3333 | 332 | //Forces the missiles to have the fired flags to flase |
avi23 | 7:babc367a3333 | 333 | cannon_missile_on_screen = false; |
avi23 | 7:babc367a3333 | 334 | invader_normal_missile[0].fired = false; |
avi23 | 7:babc367a3333 | 335 | invader_normal_missile[1].fired = false; |
avi23 | 7:babc367a3333 | 336 | } |
avi23 | 7:babc367a3333 | 337 | |
avi23 | 5:34855f712350 | 338 | void UpdateScreen() |
avi23 | 2:d34c95990605 | 339 | { |
avi23 | 5:34855f712350 | 340 | //Loops through the screen buffer and sets pixels on the LCD |
avi23 | 5:34855f712350 | 341 | for (int col = 0; col < 84; ++col) { |
avi23 | 5:34855f712350 | 342 | for (int row = 0; row < 48; ++row) { |
avi23 | 5:34855f712350 | 343 | if (screen_buffer[col][row]) { |
avi23 | 5:34855f712350 | 344 | lcd.setPixel(col, row); |
avi23 | 5:34855f712350 | 345 | } else { |
avi23 | 5:34855f712350 | 346 | lcd.clearPixel(col, row); |
avi23 | 5:34855f712350 | 347 | } |
avi23 | 5:34855f712350 | 348 | } |
avi23 | 5:34855f712350 | 349 | } |
avi23 | 5:34855f712350 | 350 | |
avi23 | 5:34855f712350 | 351 | lcd.refresh(); |
avi23 | 2:d34c95990605 | 352 | } |
avi23 | 2:d34c95990605 | 353 | |
avi23 | 2:d34c95990605 | 354 | void MoveCannon() |
avi23 | 0:427469992efe | 355 | { |
avi23 | 7:babc367a3333 | 356 | //Clears the cannon |
avi23 | 5:34855f712350 | 357 | for (int col = 0; col < 9; ++col) { |
avi23 | 5:34855f712350 | 358 | for (int row = 0; row < 5; ++row) { |
avi23 | 1:b300d052d549 | 359 | if(cannon_bitmap[row][col]) { |
avi23 | 5:34855f712350 | 360 | screen_buffer[cannon_xpos+col][cannon_ypos+row] = empty_pixel; |
avi23 | 0:427469992efe | 361 | } |
avi23 | 0:427469992efe | 362 | } |
avi23 | 0:427469992efe | 363 | } |
avi23 | 0:427469992efe | 364 | |
avi23 | 7:babc367a3333 | 365 | //Changes the position of the cannon when the joystick is moved, capping at 0 and 75 so it always fits on the screen |
avi23 | 0:427469992efe | 366 | if (joystick.GetXValue() < 0.25f) { |
avi23 | 1:b300d052d549 | 367 | cannon_xpos--; |
avi23 | 1:b300d052d549 | 368 | if (cannon_xpos < 0) { |
avi23 | 1:b300d052d549 | 369 | cannon_xpos = 0; |
avi23 | 0:427469992efe | 370 | } |
avi23 | 0:427469992efe | 371 | } else if (joystick.GetXValue() > 0.75f) { |
avi23 | 1:b300d052d549 | 372 | cannon_xpos++; |
avi23 | 1:b300d052d549 | 373 | if (cannon_xpos > 75) { |
avi23 | 1:b300d052d549 | 374 | cannon_xpos = 75; |
avi23 | 0:427469992efe | 375 | } |
avi23 | 0:427469992efe | 376 | } |
avi23 | 0:427469992efe | 377 | |
avi23 | 7:babc367a3333 | 378 | //Redraws the cannon |
avi23 | 5:34855f712350 | 379 | for (int col = 0; col < 9; ++col) { |
avi23 | 5:34855f712350 | 380 | for (int row = 0; row < 5; ++row) { |
avi23 | 1:b300d052d549 | 381 | if(cannon_bitmap[row][col]) { |
avi23 | 5:34855f712350 | 382 | screen_buffer[cannon_xpos+col][cannon_ypos+row] = cannon_pixel; |
avi23 | 0:427469992efe | 383 | } |
avi23 | 0:427469992efe | 384 | } |
avi23 | 0:427469992efe | 385 | } |
avi23 | 0:427469992efe | 386 | } |
avi23 | 0:427469992efe | 387 | |
avi23 | 7:babc367a3333 | 388 | //Sets the position and status of the small invaders |
avi23 | 0:427469992efe | 389 | void InitSmallInvaders() |
avi23 | 0:427469992efe | 390 | { |
avi23 | 5:34855f712350 | 391 | for (int i = 0; i < 5; ++i) { |
avi23 | 7:babc367a3333 | 392 | small_invader[i].x_pos = 2 + (i*13); // Large invaders are 12 across so add 13 for a gap space |
avi23 | 2:d34c95990605 | 393 | small_invader[i].y_pos = 1; |
avi23 | 5:34855f712350 | 394 | small_invader[i].status = alive; |
avi23 | 0:427469992efe | 395 | } |
avi23 | 0:427469992efe | 396 | } |
avi23 | 0:427469992efe | 397 | |
avi23 | 5:34855f712350 | 398 | //Cycles through all the small invaders. If they're not already dead clear them |
avi23 | 2:d34c95990605 | 399 | void ClearSmallInvaders() |
avi23 | 2:d34c95990605 | 400 | { |
avi23 | 5:34855f712350 | 401 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 402 | if (small_invader[i].status) { |
avi23 | 5:34855f712350 | 403 | ClearSingleSmallInvader(i); |
avi23 | 5:34855f712350 | 404 | } |
avi23 | 5:34855f712350 | 405 | } |
avi23 | 5:34855f712350 | 406 | } |
avi23 | 5:34855f712350 | 407 | |
avi23 | 5:34855f712350 | 408 | //Cycles through the the screen invader bitmap and sets the pixels in the buffer to 0 |
avi23 | 5:34855f712350 | 409 | void ClearSingleSmallInvader(int invader_no) |
avi23 | 5:34855f712350 | 410 | { |
avi23 | 5:34855f712350 | 411 | for (int col = 0; col < 8; ++col) { |
avi23 | 5:34855f712350 | 412 | for (int row = 0; row < 6; ++row) { |
avi23 | 5:34855f712350 | 413 | if (invaders_in_state2) { |
avi23 | 5:34855f712350 | 414 | if (small_invader_bitmap_1[row][col]) { |
avi23 | 5:34855f712350 | 415 | screen_buffer[small_invader[invader_no].x_pos + col][small_invader[invader_no].y_pos + row] = empty_pixel; |
avi23 | 2:d34c95990605 | 416 | } |
avi23 | 5:34855f712350 | 417 | } else { |
avi23 | 5:34855f712350 | 418 | if (small_invader_bitmap_2[row][col]) { |
avi23 | 5:34855f712350 | 419 | screen_buffer[small_invader[invader_no].x_pos + col][small_invader[invader_no].y_pos + row] = empty_pixel; |
avi23 | 2:d34c95990605 | 420 | } |
avi23 | 2:d34c95990605 | 421 | } |
avi23 | 2:d34c95990605 | 422 | } |
avi23 | 2:d34c95990605 | 423 | } |
avi23 | 5:34855f712350 | 424 | |
avi23 | 5:34855f712350 | 425 | small_invader[invader_no].status = (small_invader[invader_no].status == dying) ? dead : alive; |
avi23 | 2:d34c95990605 | 426 | } |
avi23 | 2:d34c95990605 | 427 | |
avi23 | 7:babc367a3333 | 428 | //Cycles through all the small invaders. If they're alive set them in the screen buffer |
avi23 | 0:427469992efe | 429 | void DrawSmallInvaders() |
avi23 | 0:427469992efe | 430 | { |
avi23 | 5:34855f712350 | 431 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 432 | if (small_invader[i].status == alive) { |
avi23 | 5:34855f712350 | 433 | DrawSingleSmallInvader(i); |
avi23 | 5:34855f712350 | 434 | } |
avi23 | 5:34855f712350 | 435 | } |
avi23 | 5:34855f712350 | 436 | } |
avi23 | 5:34855f712350 | 437 | |
avi23 | 5:34855f712350 | 438 | //Cycles through the the screen invader bitmap and sets the pixels in the buffer |
avi23 | 5:34855f712350 | 439 | void DrawSingleSmallInvader(int invader_no) |
avi23 | 5:34855f712350 | 440 | { |
avi23 | 5:34855f712350 | 441 | for (int col = 0; col < 8; ++col) { |
avi23 | 5:34855f712350 | 442 | for (int row = 0; row < 6; ++row) { |
avi23 | 2:d34c95990605 | 443 | if (invaders_in_state2) { |
avi23 | 5:34855f712350 | 444 | if (small_invader_bitmap_1[row][col]) { |
avi23 | 5:34855f712350 | 445 | screen_buffer[small_invader[invader_no].x_pos + col][small_invader[invader_no].y_pos + row] = first_small_invader_pixel + invader_no; |
avi23 | 0:427469992efe | 446 | } |
avi23 | 0:427469992efe | 447 | } else { |
avi23 | 5:34855f712350 | 448 | if (small_invader_bitmap_2[row][col]) { |
avi23 | 5:34855f712350 | 449 | screen_buffer[small_invader[invader_no].x_pos + col][small_invader[invader_no].y_pos + row] = first_small_invader_pixel + invader_no; |
avi23 | 0:427469992efe | 450 | } |
avi23 | 0:427469992efe | 451 | } |
avi23 | 0:427469992efe | 452 | } |
avi23 | 0:427469992efe | 453 | } |
avi23 | 1:b300d052d549 | 454 | } |
avi23 | 1:b300d052d549 | 455 | |
avi23 | 1:b300d052d549 | 456 | //Sets the position and aliveness of the medium invaders |
avi23 | 1:b300d052d549 | 457 | void InitMediumInvaders() |
avi23 | 1:b300d052d549 | 458 | { |
avi23 | 5:34855f712350 | 459 | for (int i = 0; i < 5; ++i) { |
avi23 | 7:babc367a3333 | 460 | medium_invader[i].x_pos = 1 + (i*13); // Large invaders are 12 across so add 13 for a gap space |
avi23 | 2:d34c95990605 | 461 | medium_invader[i].y_pos = 8; |
avi23 | 5:34855f712350 | 462 | medium_invader[i].status = alive; |
avi23 | 1:b300d052d549 | 463 | } |
avi23 | 1:b300d052d549 | 464 | } |
avi23 | 1:b300d052d549 | 465 | |
avi23 | 7:babc367a3333 | 466 | //Cycles through all the medium invaders. If they're not already dead clear them |
avi23 | 2:d34c95990605 | 467 | void ClearMediumInvaders() |
avi23 | 2:d34c95990605 | 468 | { |
avi23 | 5:34855f712350 | 469 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 470 | if (medium_invader[i].status) { |
avi23 | 5:34855f712350 | 471 | ClearSingleMediumInvader(i); |
avi23 | 2:d34c95990605 | 472 | } |
avi23 | 2:d34c95990605 | 473 | } |
avi23 | 2:d34c95990605 | 474 | } |
avi23 | 2:d34c95990605 | 475 | |
avi23 | 7:babc367a3333 | 476 | //Cycles through the the screen invader bitmap and sets the pixels in the buffer to 0 |
avi23 | 5:34855f712350 | 477 | void ClearSingleMediumInvader(int invader_no) |
avi23 | 5:34855f712350 | 478 | { |
avi23 | 5:34855f712350 | 479 | for (int col = 0; col < 10; ++col) { |
avi23 | 5:34855f712350 | 480 | for (int row = 0; row < 6; ++row) { |
avi23 | 5:34855f712350 | 481 | if (invaders_in_state2) { |
avi23 | 5:34855f712350 | 482 | if (medium_invader_bitmap_1[row][col]) { |
avi23 | 5:34855f712350 | 483 | screen_buffer[medium_invader[invader_no].x_pos + col][medium_invader[invader_no].y_pos + row] = empty_pixel; |
avi23 | 5:34855f712350 | 484 | } |
avi23 | 5:34855f712350 | 485 | } else { |
avi23 | 5:34855f712350 | 486 | if (medium_invader_bitmap_2[row][col]) { |
avi23 | 5:34855f712350 | 487 | screen_buffer[medium_invader[invader_no].x_pos + col][medium_invader[invader_no].y_pos + row] = empty_pixel; |
avi23 | 5:34855f712350 | 488 | } |
avi23 | 5:34855f712350 | 489 | } |
avi23 | 5:34855f712350 | 490 | } |
avi23 | 5:34855f712350 | 491 | } |
avi23 | 5:34855f712350 | 492 | |
avi23 | 5:34855f712350 | 493 | medium_invader[invader_no].status = (medium_invader[invader_no].status == dying) ? dead : alive; |
avi23 | 5:34855f712350 | 494 | } |
avi23 | 5:34855f712350 | 495 | |
avi23 | 7:babc367a3333 | 496 | //Cycles through all the medium invaders. If they're alive set them in the screen buffer |
avi23 | 1:b300d052d549 | 497 | void DrawMediumInvaders() |
avi23 | 1:b300d052d549 | 498 | { |
avi23 | 5:34855f712350 | 499 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 500 | if (medium_invader[i].status == alive) { |
avi23 | 5:34855f712350 | 501 | DrawSingleMediumInvader(i); |
avi23 | 5:34855f712350 | 502 | } |
avi23 | 5:34855f712350 | 503 | } |
avi23 | 5:34855f712350 | 504 | } |
avi23 | 5:34855f712350 | 505 | |
avi23 | 7:babc367a3333 | 506 | //Cycles through the the screen invader bitmap and sets the pixels in the buffer |
avi23 | 5:34855f712350 | 507 | void DrawSingleMediumInvader(int invader_no) |
avi23 | 5:34855f712350 | 508 | { |
avi23 | 5:34855f712350 | 509 | for (int col = 0; col < 10; ++col) { |
avi23 | 5:34855f712350 | 510 | for (int row = 0; row < 6; ++row) { |
avi23 | 2:d34c95990605 | 511 | if (invaders_in_state2) { |
avi23 | 5:34855f712350 | 512 | if (medium_invader_bitmap_1[row][col]) { |
avi23 | 5:34855f712350 | 513 | screen_buffer[medium_invader[invader_no].x_pos + col][medium_invader[invader_no].y_pos + row] = first_medium_invader_pixel + invader_no; |
avi23 | 1:b300d052d549 | 514 | } |
avi23 | 1:b300d052d549 | 515 | } else { |
avi23 | 5:34855f712350 | 516 | if (medium_invader_bitmap_2[row][col]) { |
avi23 | 5:34855f712350 | 517 | screen_buffer[medium_invader[invader_no].x_pos + col][medium_invader[invader_no].y_pos + row] = first_medium_invader_pixel + invader_no; |
avi23 | 1:b300d052d549 | 518 | } |
avi23 | 1:b300d052d549 | 519 | } |
avi23 | 1:b300d052d549 | 520 | } |
avi23 | 1:b300d052d549 | 521 | } |
avi23 | 1:b300d052d549 | 522 | } |
avi23 | 1:b300d052d549 | 523 | |
avi23 | 7:babc367a3333 | 524 | //Sets the position and status of the large invaders |
avi23 | 1:b300d052d549 | 525 | void InitLargeInvaders() |
avi23 | 1:b300d052d549 | 526 | { |
avi23 | 5:34855f712350 | 527 | for (int i = 0; i < 5; ++i) { |
avi23 | 1:b300d052d549 | 528 | large_invader[i].x_pos = 0 + (i*13); |
avi23 | 2:d34c95990605 | 529 | large_invader[i].y_pos = 15; |
avi23 | 5:34855f712350 | 530 | large_invader[i].status = alive; |
avi23 | 5:34855f712350 | 531 | } |
avi23 | 5:34855f712350 | 532 | } |
avi23 | 5:34855f712350 | 533 | |
avi23 | 7:babc367a3333 | 534 | //Cycles through all the large invaders. If they're not already dead clear them |
avi23 | 5:34855f712350 | 535 | void ClearLargeInvaders() |
avi23 | 5:34855f712350 | 536 | { |
avi23 | 5:34855f712350 | 537 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 538 | if (large_invader[i].status) { |
avi23 | 5:34855f712350 | 539 | ClearSingleLargeInvader(i); |
avi23 | 5:34855f712350 | 540 | } |
avi23 | 1:b300d052d549 | 541 | } |
avi23 | 1:b300d052d549 | 542 | } |
avi23 | 1:b300d052d549 | 543 | |
avi23 | 5:34855f712350 | 544 | //Loops through the large invader bitmap, if the pixel in the bitmap is set to 1, set the pixel in the buffer to 0 |
avi23 | 5:34855f712350 | 545 | void ClearSingleLargeInvader(int invader_no) |
avi23 | 2:d34c95990605 | 546 | { |
avi23 | 5:34855f712350 | 547 | for (int col = 0; col < 12; ++col) { |
avi23 | 5:34855f712350 | 548 | for (int row = 0; row < 6; ++row) { |
avi23 | 5:34855f712350 | 549 | if (invaders_in_state2) { |
avi23 | 5:34855f712350 | 550 | if (large_invader_bitmap_1[row][col]) { |
avi23 | 5:34855f712350 | 551 | screen_buffer[large_invader[invader_no].x_pos + col][large_invader[invader_no].y_pos + row] = empty_pixel; |
avi23 | 5:34855f712350 | 552 | } |
avi23 | 5:34855f712350 | 553 | } else { |
avi23 | 5:34855f712350 | 554 | if (large_invader_bitmap_2[row][col]) { |
avi23 | 5:34855f712350 | 555 | screen_buffer[large_invader[invader_no].x_pos + col][large_invader[invader_no].y_pos + row] = empty_pixel; |
avi23 | 2:d34c95990605 | 556 | } |
avi23 | 2:d34c95990605 | 557 | } |
avi23 | 5:34855f712350 | 558 | } |
avi23 | 5:34855f712350 | 559 | } |
avi23 | 5:34855f712350 | 560 | |
avi23 | 5:34855f712350 | 561 | large_invader[invader_no].status = (large_invader[invader_no].status == dying) ? dead : alive; |
avi23 | 5:34855f712350 | 562 | } |
avi23 | 5:34855f712350 | 563 | |
avi23 | 7:babc367a3333 | 564 | //Cycles through all the large invaders. If they're alive set them in the screen buffer |
avi23 | 5:34855f712350 | 565 | void DrawLargeInvaders() |
avi23 | 5:34855f712350 | 566 | { |
avi23 | 5:34855f712350 | 567 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 568 | if (large_invader[i].status == alive) { |
avi23 | 5:34855f712350 | 569 | DrawSingleLargeInvader(i); |
avi23 | 5:34855f712350 | 570 | } |
avi23 | 5:34855f712350 | 571 | } |
avi23 | 5:34855f712350 | 572 | } |
avi23 | 5:34855f712350 | 573 | |
avi23 | 7:babc367a3333 | 574 | //Cycles through the the screen invader bitmap and sets the pixels in the buffer |
avi23 | 5:34855f712350 | 575 | void DrawSingleLargeInvader(int invader_no) |
avi23 | 5:34855f712350 | 576 | { |
avi23 | 5:34855f712350 | 577 | for (int col = 0; col < 12; ++col) { |
avi23 | 5:34855f712350 | 578 | for (int row = 0; row < 6; ++row) { |
avi23 | 5:34855f712350 | 579 | if (invaders_in_state2) { |
avi23 | 5:34855f712350 | 580 | if (large_invader_bitmap_1[row][col]) { |
avi23 | 5:34855f712350 | 581 | screen_buffer[large_invader[invader_no].x_pos + col][large_invader[invader_no].y_pos + row] = first_large_invader_pixel + invader_no; |
avi23 | 5:34855f712350 | 582 | } |
avi23 | 5:34855f712350 | 583 | } else { |
avi23 | 5:34855f712350 | 584 | if (large_invader_bitmap_2[row][col]) { |
avi23 | 5:34855f712350 | 585 | screen_buffer[large_invader[invader_no].x_pos + col][large_invader[invader_no].y_pos + row] = first_large_invader_pixel + invader_no; |
avi23 | 2:d34c95990605 | 586 | } |
avi23 | 2:d34c95990605 | 587 | } |
avi23 | 2:d34c95990605 | 588 | } |
avi23 | 2:d34c95990605 | 589 | } |
avi23 | 2:d34c95990605 | 590 | } |
avi23 | 2:d34c95990605 | 591 | |
avi23 | 7:babc367a3333 | 592 | //Sets the position and loads the bitmap into the barrier objects |
avi23 | 2:d34c95990605 | 593 | void InitBarriers() |
avi23 | 2:d34c95990605 | 594 | { |
avi23 | 5:34855f712350 | 595 | for (int i = 0; i < 3; ++i) { |
avi23 | 2:d34c95990605 | 596 | barrier[i].x_pos = 10 + (i*25); |
avi23 | 2:d34c95990605 | 597 | barrier[i].y_pos = 33; |
avi23 | 2:d34c95990605 | 598 | //Copies the bitmap into the structs |
avi23 | 2:d34c95990605 | 599 | memcpy(barrier[i].before_bitmap, barrier_bitmap, sizeof(barrier_bitmap)); |
avi23 | 2:d34c95990605 | 600 | memcpy(barrier[i].after_bitmap, barrier_bitmap, sizeof(barrier_bitmap)); |
avi23 | 2:d34c95990605 | 601 | } |
avi23 | 2:d34c95990605 | 602 | } |
avi23 | 2:d34c95990605 | 603 | |
avi23 | 2:d34c95990605 | 604 | void DrawBarriers() |
avi23 | 2:d34c95990605 | 605 | { |
avi23 | 2:d34c95990605 | 606 | //Clears the barrier and redraws it with damage applied |
avi23 | 5:34855f712350 | 607 | for (int i = 0; i < 3; ++i) { |
avi23 | 5:34855f712350 | 608 | for (int col = 0; col < 14; ++col) { |
avi23 | 5:34855f712350 | 609 | for (int row = 0; row < 8; ++row) { |
avi23 | 2:d34c95990605 | 610 | if (barrier[i].before_bitmap[row][col]) { |
avi23 | 5:34855f712350 | 611 | screen_buffer[barrier[i].x_pos + col][barrier[i].y_pos + row] = empty_pixel; |
avi23 | 2:d34c95990605 | 612 | } |
avi23 | 2:d34c95990605 | 613 | if (barrier[i].after_bitmap[row][col]) { |
avi23 | 5:34855f712350 | 614 | screen_buffer[barrier[i].x_pos + col][barrier[i].y_pos + row] = first_barrier_pixel + i; |
avi23 | 2:d34c95990605 | 615 | } |
avi23 | 2:d34c95990605 | 616 | } |
avi23 | 2:d34c95990605 | 617 | } |
avi23 | 2:d34c95990605 | 618 | //Copies the after array to the before array |
avi23 | 2:d34c95990605 | 619 | memcpy(barrier[i].before_bitmap, barrier[i].after_bitmap, sizeof(barrier[i].after_bitmap)); |
avi23 | 2:d34c95990605 | 620 | } |
avi23 | 2:d34c95990605 | 621 | } |
avi23 | 2:d34c95990605 | 622 | |
avi23 | 5:34855f712350 | 623 | void MoveInvaderXPositions() |
avi23 | 2:d34c95990605 | 624 | { |
avi23 | 7:babc367a3333 | 625 | //Moves the invader in the current direction |
avi23 | 2:d34c95990605 | 626 | if (invader_direction == RIGHT) { |
avi23 | 7:babc367a3333 | 627 | //Checking the right limit |
avi23 | 7:babc367a3333 | 628 | int right_invader_limit = CalculateInvaderRightLimit(); |
avi23 | 5:34855f712350 | 629 | MoveInvadersRight(right_invader_limit); |
avi23 | 5:34855f712350 | 630 | } else { |
avi23 | 7:babc367a3333 | 631 | //Checks the left limit |
avi23 | 7:babc367a3333 | 632 | int left_invader_limit = CalculateInvaderLeftLimit(); |
avi23 | 5:34855f712350 | 633 | MoveInvadersLeft(left_invader_limit); |
avi23 | 5:34855f712350 | 634 | } |
avi23 | 5:34855f712350 | 635 | } |
avi23 | 5:34855f712350 | 636 | |
avi23 | 7:babc367a3333 | 637 | //Checks the status off the invaders per column, starting from the left |
avi23 | 7:babc367a3333 | 638 | //If they're alive return the row number |
avi23 | 5:34855f712350 | 639 | int CalculateInvaderLeftLimit() |
avi23 | 5:34855f712350 | 640 | { |
avi23 | 5:34855f712350 | 641 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 642 | if (small_invader[i].status == alive || medium_invader[i].status == alive || large_invader[i].status == alive) { |
avi23 | 5:34855f712350 | 643 | return i; |
avi23 | 5:34855f712350 | 644 | } |
avi23 | 5:34855f712350 | 645 | } |
avi23 | 5:34855f712350 | 646 | |
avi23 | 5:34855f712350 | 647 | //Sort gameover out stuff after |
avi23 | 5:34855f712350 | 648 | return 4; |
avi23 | 5:34855f712350 | 649 | } |
avi23 | 5:34855f712350 | 650 | |
avi23 | 7:babc367a3333 | 651 | //Checks the status off the invaders per column, starting from the right |
avi23 | 7:babc367a3333 | 652 | //If they're alive return the row number |
avi23 | 5:34855f712350 | 653 | int CalculateInvaderRightLimit() |
avi23 | 5:34855f712350 | 654 | { |
avi23 | 5:34855f712350 | 655 | for (int i = 4; i >= 0; --i) { |
avi23 | 5:34855f712350 | 656 | if (small_invader[i].status == alive || medium_invader[i].status == alive || large_invader[i].status == alive) { |
avi23 | 5:34855f712350 | 657 | return i; |
avi23 | 5:34855f712350 | 658 | } |
avi23 | 5:34855f712350 | 659 | } |
avi23 | 5:34855f712350 | 660 | |
avi23 | 5:34855f712350 | 661 | //Sort gameover stuff |
avi23 | 5:34855f712350 | 662 | return 0; |
avi23 | 5:34855f712350 | 663 | } |
avi23 | 5:34855f712350 | 664 | |
avi23 | 5:34855f712350 | 665 | void MoveInvadersLeft(int limit) |
avi23 | 5:34855f712350 | 666 | { |
avi23 | 5:34855f712350 | 667 | //Checks the first large invader to see if it can travel anymore |
avi23 | 5:34855f712350 | 668 | if (large_invader[limit].x_pos > 1) { |
avi23 | 5:34855f712350 | 669 | for (int i = 0; i < 5; ++i) { |
avi23 | 7:babc367a3333 | 670 | //Moves the invaders 2 to the left |
avi23 | 5:34855f712350 | 671 | small_invader[i].x_pos -= 2; |
avi23 | 5:34855f712350 | 672 | medium_invader[i].x_pos -= 2; |
avi23 | 5:34855f712350 | 673 | large_invader[i].x_pos -= 2; |
avi23 | 2:d34c95990605 | 674 | } |
avi23 | 2:d34c95990605 | 675 | } else { |
avi23 | 5:34855f712350 | 676 | //Shifts the Invaders down and passes in the new direction |
avi23 | 5:34855f712350 | 677 | MoveInvaderYPositions(RIGHT); |
avi23 | 2:d34c95990605 | 678 | } |
avi23 | 2:d34c95990605 | 679 | } |
avi23 | 2:d34c95990605 | 680 | |
avi23 | 5:34855f712350 | 681 | void MoveInvadersRight(int limit) |
avi23 | 2:d34c95990605 | 682 | { |
avi23 | 5:34855f712350 | 683 | //Checks the first large invader to see if it can travel anymore |
avi23 | 5:34855f712350 | 684 | if (large_invader[limit].x_pos < 71) { |
avi23 | 7:babc367a3333 | 685 | //Moves the invaders 2 to the right |
avi23 | 5:34855f712350 | 686 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 687 | small_invader[i].x_pos += 2; |
avi23 | 5:34855f712350 | 688 | medium_invader[i].x_pos += 2; |
avi23 | 5:34855f712350 | 689 | large_invader[i].x_pos += 2; |
avi23 | 5:34855f712350 | 690 | } |
avi23 | 2:d34c95990605 | 691 | } else { |
avi23 | 5:34855f712350 | 692 | //Shifts the Invaders down and passes in the new direction |
avi23 | 5:34855f712350 | 693 | MoveInvaderYPositions(LEFT); |
avi23 | 2:d34c95990605 | 694 | } |
avi23 | 5:34855f712350 | 695 | } |
avi23 | 5:34855f712350 | 696 | |
avi23 | 5:34855f712350 | 697 | void MoveInvaderYPositions(bool new_direction) |
avi23 | 5:34855f712350 | 698 | { |
avi23 | 5:34855f712350 | 699 | //Finds the invaders lower limit |
avi23 | 5:34855f712350 | 700 | Invader lowest_invader = CalculateInvaderYLimit(); |
avi23 | 5:34855f712350 | 701 | |
avi23 | 5:34855f712350 | 702 | //When moving down lowest_invader should not equal none |
avi23 | 5:34855f712350 | 703 | if (lowest_invader == none) { |
avi23 | 5:34855f712350 | 704 | error(); |
avi23 | 5:34855f712350 | 705 | } |
avi23 | 5:34855f712350 | 706 | |
avi23 | 2:d34c95990605 | 707 | //If an invader touches the bottom the game ends, otherwise the invaders descend |
avi23 | 5:34855f712350 | 708 | if (small_invader[0].y_pos < 33 - (7*lowest_invader)) { |
avi23 | 5:34855f712350 | 709 | for (int i = 0; i < 5; ++i) { |
avi23 | 2:d34c95990605 | 710 | small_invader[i].y_pos += 3; |
avi23 | 2:d34c95990605 | 711 | medium_invader[i].y_pos += 3; |
avi23 | 2:d34c95990605 | 712 | large_invader[i].y_pos += 3; |
avi23 | 2:d34c95990605 | 713 | } |
avi23 | 5:34855f712350 | 714 | invader_direction = new_direction; |
avi23 | 5:34855f712350 | 715 | } else { |
avi23 | 5:34855f712350 | 716 | number_of_lives = 0; |
avi23 | 5:34855f712350 | 717 | } |
avi23 | 5:34855f712350 | 718 | } |
avi23 | 5:34855f712350 | 719 | |
avi23 | 5:34855f712350 | 720 | Invader CalculateInvaderYLimit() |
avi23 | 5:34855f712350 | 721 | { |
avi23 | 5:34855f712350 | 722 | //Checks to see which row of invaders are still alive to work out maximum y positions |
avi23 | 5:34855f712350 | 723 | if (large_invader[0].status == alive || large_invader[1].status == alive || large_invader[2].status == alive || large_invader[3].status == alive || large_invader[4].status == alive) { |
avi23 | 5:34855f712350 | 724 | return large; |
avi23 | 5:34855f712350 | 725 | } else if (medium_invader[0].status == alive || medium_invader[1].status == alive || medium_invader[2].status == alive || medium_invader[3].status == alive || medium_invader[4].status == alive) { |
avi23 | 5:34855f712350 | 726 | return medium; |
avi23 | 2:d34c95990605 | 727 | } else { |
avi23 | 5:34855f712350 | 728 | return small; |
avi23 | 2:d34c95990605 | 729 | } |
avi23 | 5:34855f712350 | 730 | } |
avi23 | 2:d34c95990605 | 731 | |
avi23 | 5:34855f712350 | 732 | //Queries the invaders on their status and returns the type of invader which is alive |
avi23 | 5:34855f712350 | 733 | Invader LowestInvaderInColumn(int column) |
avi23 | 5:34855f712350 | 734 | { |
avi23 | 5:34855f712350 | 735 | if (large_invader[column].status == alive) { |
avi23 | 5:34855f712350 | 736 | return large; |
avi23 | 5:34855f712350 | 737 | } else if (medium_invader[column].status == alive) { |
avi23 | 5:34855f712350 | 738 | return medium; |
avi23 | 5:34855f712350 | 739 | } else if (small_invader[column].status == alive) { |
avi23 | 5:34855f712350 | 740 | return small; |
avi23 | 5:34855f712350 | 741 | } else { |
avi23 | 5:34855f712350 | 742 | return none; |
avi23 | 5:34855f712350 | 743 | } |
avi23 | 2:d34c95990605 | 744 | } |
avi23 | 2:d34c95990605 | 745 | |
avi23 | 2:d34c95990605 | 746 | /* |
avi23 | 2:d34c95990605 | 747 | void InitUFO() |
avi23 | 2:d34c95990605 | 748 | { |
avi23 | 2:d34c95990605 | 749 | |
avi23 | 2:d34c95990605 | 750 | } |
avi23 | 2:d34c95990605 | 751 | */ |
avi23 | 2:d34c95990605 | 752 | |
avi23 | 2:d34c95990605 | 753 | void DrawUFO() |
avi23 | 2:d34c95990605 | 754 | { |
avi23 | 2:d34c95990605 | 755 | //Draws the UFO |
avi23 | 2:d34c95990605 | 756 | int x_pos = 20; |
avi23 | 2:d34c95990605 | 757 | int y_pos = 25; |
avi23 | 5:34855f712350 | 758 | for (int col = 0; col < col_no; ++col) { |
avi23 | 5:34855f712350 | 759 | for (int row = 0; row < row_no; ++row) { |
avi23 | 2:d34c95990605 | 760 | if(ufo_bitmap[row][col]) { |
avi23 | 5:34855f712350 | 761 | screen_buffer[x_pos + col][y_pos + row] = ufo_pixel; |
avi23 | 2:d34c95990605 | 762 | } |
avi23 | 2:d34c95990605 | 763 | } |
avi23 | 2:d34c95990605 | 764 | } |
avi23 | 5:34855f712350 | 765 | } |
avi23 | 5:34855f712350 | 766 | |
avi23 | 5:34855f712350 | 767 | void FireCannonMissile() |
avi23 | 5:34855f712350 | 768 | { |
avi23 | 7:babc367a3333 | 769 | //Sets the cannon fired flag to true |
avi23 | 5:34855f712350 | 770 | cannon_missile_on_screen = true; |
avi23 | 5:34855f712350 | 771 | |
avi23 | 7:babc367a3333 | 772 | //Offset cannon missile x position by 4 of the cannons x pos |
avi23 | 5:34855f712350 | 773 | cannon_missile_x_pos = cannon_xpos + 4; |
avi23 | 7:babc367a3333 | 774 | //Will always have a starting y of 40 |
avi23 | 5:34855f712350 | 775 | cannon_missile_y_pos = 40; |
avi23 | 7:babc367a3333 | 776 | //Attach the move cannon missile |
avi23 | 5:34855f712350 | 777 | move_cannon_missile.attach(&move_cannon_missile_isr, 0.05); |
avi23 | 5:34855f712350 | 778 | } |
avi23 | 5:34855f712350 | 779 | |
avi23 | 5:34855f712350 | 780 | void MoveCannonMissile() |
avi23 | 5:34855f712350 | 781 | { |
avi23 | 5:34855f712350 | 782 | //Checks bullet will not go beyond the bounds of the screen buffer |
avi23 | 5:34855f712350 | 783 | if (cannon_missile_y_pos > -1) { |
avi23 | 5:34855f712350 | 784 | //Loops throught the shot bitmap and clears the pixels in the screen buffer |
avi23 | 5:34855f712350 | 785 | for (int row = 0; row < 4; ++row) { |
avi23 | 5:34855f712350 | 786 | //Clears the position where the bullet was |
avi23 | 5:34855f712350 | 787 | screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] = empty_pixel; |
avi23 | 5:34855f712350 | 788 | } |
avi23 | 5:34855f712350 | 789 | |
avi23 | 5:34855f712350 | 790 | //Increments the shot going up the screen |
avi23 | 5:34855f712350 | 791 | --cannon_missile_y_pos; |
avi23 | 5:34855f712350 | 792 | |
avi23 | 5:34855f712350 | 793 | //Checks to see if the shot will hit anything |
avi23 | 5:34855f712350 | 794 | CollisionDetectionCannonMissile(); |
avi23 | 5:34855f712350 | 795 | } else { |
avi23 | 5:34855f712350 | 796 | //Loops throught the shot bitmap and clears the pixels in the screen buffer |
avi23 | 5:34855f712350 | 797 | for (int row = 1; row < 4; ++row) { |
avi23 | 5:34855f712350 | 798 | //Clears the position where the bullet was |
avi23 | 5:34855f712350 | 799 | screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] = empty_pixel; |
avi23 | 5:34855f712350 | 800 | } |
avi23 | 5:34855f712350 | 801 | |
avi23 | 5:34855f712350 | 802 | cannon_missile_on_screen = false; |
avi23 | 5:34855f712350 | 803 | move_cannon_missile.detach(); |
avi23 | 5:34855f712350 | 804 | } |
avi23 | 5:34855f712350 | 805 | } |
avi23 | 5:34855f712350 | 806 | |
avi23 | 5:34855f712350 | 807 | //Checks to see what the shot hits. If it hits nothing the shot gets pushed to the screen buffer |
avi23 | 5:34855f712350 | 808 | void CollisionDetectionCannonMissile() |
avi23 | 5:34855f712350 | 809 | { |
avi23 | 5:34855f712350 | 810 | for (int row = 0; row < 4; ++row) { |
avi23 | 5:34855f712350 | 811 | int object_no; |
avi23 | 7:babc367a3333 | 812 | int pixel_check = screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row]; |
avi23 | 7:babc367a3333 | 813 | pc.printf("Pixel check: %d\n", pixel_check); |
avi23 | 7:babc367a3333 | 814 | if (pixel_check >= first_small_invader_pixel && pixel_check < ufo_pixel) { //Collides with a small invader |
avi23 | 7:babc367a3333 | 815 | //Find the object no of the small invader it hit, clears it and increments the score |
avi23 | 5:34855f712350 | 816 | object_no = CannonMissileHitInvader(first_small_invader_pixel, row, small_invader); |
avi23 | 5:34855f712350 | 817 | ClearSingleSmallInvader(object_no); |
avi23 | 5:34855f712350 | 818 | score += 40; |
avi23 | 5:34855f712350 | 819 | break; |
avi23 | 7:babc367a3333 | 820 | } else if (pixel_check >= first_medium_invader_pixel && pixel_check < first_small_invader_pixel) { //Collides with a medium invader |
avi23 | 7:babc367a3333 | 821 | //Find the object no of the medium invader it hit, clears it and increments the score |
avi23 | 5:34855f712350 | 822 | object_no = CannonMissileHitInvader(first_medium_invader_pixel, row, medium_invader); |
avi23 | 5:34855f712350 | 823 | ClearSingleMediumInvader(object_no); |
avi23 | 5:34855f712350 | 824 | score += 20; |
avi23 | 5:34855f712350 | 825 | break; |
avi23 | 7:babc367a3333 | 826 | } else if (pixel_check >= first_large_invader_pixel && pixel_check < first_medium_invader_pixel) { //Collides with a large invader |
avi23 | 7:babc367a3333 | 827 | //Find the object no of the large invader it hit, clears it and increments the score |
avi23 | 5:34855f712350 | 828 | object_no = CannonMissileHitInvader(first_large_invader_pixel, row, large_invader); |
avi23 | 5:34855f712350 | 829 | ClearSingleLargeInvader(object_no); |
avi23 | 5:34855f712350 | 830 | score += 10; |
avi23 | 5:34855f712350 | 831 | break; |
avi23 | 7:babc367a3333 | 832 | } else if (pixel_check >= first_barrier_pixel && pixel_check < (first_barrier_pixel + 3)) { //Collides with a barrier |
avi23 | 7:babc367a3333 | 833 | //Adds the destruction done to the barrier to the bitmap and redraws the barriers |
avi23 | 7:babc367a3333 | 834 | CannonMissileHitBarrier(row); |
avi23 | 5:34855f712350 | 835 | DrawBarriers(); |
avi23 | 5:34855f712350 | 836 | break; |
avi23 | 7:babc367a3333 | 837 | } else if (pixel_check == ufo_pixel) { //Collides with a UFO |
avi23 | 5:34855f712350 | 838 | pc.printf("UFO Hit\n"); |
avi23 | 5:34855f712350 | 839 | cannon_missile_on_screen = false; |
avi23 | 5:34855f712350 | 840 | move_cannon_missile.detach(); |
avi23 | 5:34855f712350 | 841 | break; |
avi23 | 5:34855f712350 | 842 | } else { |
avi23 | 5:34855f712350 | 843 | screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] = cannon_missile_pixel; |
avi23 | 5:34855f712350 | 844 | } |
avi23 | 5:34855f712350 | 845 | } |
avi23 | 5:34855f712350 | 846 | } |
avi23 | 5:34855f712350 | 847 | |
avi23 | 7:babc367a3333 | 848 | //Finds the invader number the missile hits, sets the hit invader to dying, decrements the no_of_alive_invaders and stops the shot from travalling up the screen |
avi23 | 5:34855f712350 | 849 | int CannonMissileHitInvader(int first_pixel, int row, struct Invaders (&invader)[5]) |
avi23 | 5:34855f712350 | 850 | { |
avi23 | 5:34855f712350 | 851 | int invader_no = screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] - first_pixel; |
avi23 | 5:34855f712350 | 852 | invader[invader_no].status = dying; |
avi23 | 5:34855f712350 | 853 | cannon_missile_on_screen = false; |
avi23 | 5:34855f712350 | 854 | --no_of_alive_invaders; |
avi23 | 5:34855f712350 | 855 | move_cannon_missile.detach(); |
avi23 | 5:34855f712350 | 856 | |
avi23 | 5:34855f712350 | 857 | return invader_no; |
avi23 | 5:34855f712350 | 858 | } |
avi23 | 5:34855f712350 | 859 | |
avi23 | 5:34855f712350 | 860 | //Calculates where to start drawing the damage bitmap over the barrier bitmap and performs the operation |
avi23 | 7:babc367a3333 | 861 | void CannonMissileHitBarrier(int row) |
avi23 | 5:34855f712350 | 862 | { |
avi23 | 7:babc367a3333 | 863 | int barrier_no = screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] - first_barrier_pixel; |
avi23 | 5:34855f712350 | 864 | //Essentially inverse of barrier init |
avi23 | 5:34855f712350 | 865 | int relative_x_pos = cannon_missile_x_pos - 10 - (barrier_no*25) - 1; |
avi23 | 5:34855f712350 | 866 | int relative_y_pos = (cannon_missile_y_pos + row) - 33 - 1; //Don't know why it's -1 and not -2 |
avi23 | 5:34855f712350 | 867 | //Loops through the damage bitmap and modifies the barrier's after bitmap |
avi23 | 5:34855f712350 | 868 | for (int col = 0; col < 3; ++col) { |
avi23 | 5:34855f712350 | 869 | for (int row_bit = 0; row_bit < 3; ++row_bit) { |
avi23 | 5:34855f712350 | 870 | //Makes sure bitmap index does not go out of bounds. If it does go to the next iteration |
avi23 | 7:babc367a3333 | 871 | //Element by element multiplication of the 2 bitmaps to clear the required pixals |
avi23 | 5:34855f712350 | 872 | if (relative_x_pos + col >= 0 && relative_x_pos + col < 14 && relative_y_pos + row_bit >= 0 && relative_y_pos + row_bit < 8) { |
avi23 | 5:34855f712350 | 873 | barrier[barrier_no].after_bitmap[relative_y_pos + row_bit][relative_x_pos + col] *= barrier_cannon_missile_damage_bitmap[row_bit][col]; |
avi23 | 5:34855f712350 | 874 | } |
avi23 | 5:34855f712350 | 875 | } |
avi23 | 5:34855f712350 | 876 | } |
avi23 | 5:34855f712350 | 877 | cannon_missile_on_screen = false; |
avi23 | 5:34855f712350 | 878 | move_cannon_missile.detach(); |
avi23 | 5:34855f712350 | 879 | } |
avi23 | 5:34855f712350 | 880 | |
avi23 | 5:34855f712350 | 881 | void AttemptToFireInvaderNormalMissiles() |
avi23 | 5:34855f712350 | 882 | { |
avi23 | 5:34855f712350 | 883 | //Fires the normal missiles |
avi23 | 5:34855f712350 | 884 | //Loops through the 2 allowed missiles and if they're not on the screen, randomly fire |
avi23 | 5:34855f712350 | 885 | for (int i = 0; i < 2; ++i) { |
avi23 | 5:34855f712350 | 886 | if (!invader_normal_missile[i].fired) { |
avi23 | 5:34855f712350 | 887 | //If the random mumber is 1, fire a missile |
avi23 | 5:34855f712350 | 888 | //Higher chance when there are less invaders on the screen, up to a 1/3 chance |
avi23 | 5:34855f712350 | 889 | if ((rand() % (no_of_alive_invaders + 2)) == 1) { |
avi23 | 5:34855f712350 | 890 | // if ((rand() % 5) == 1) { |
avi23 | 5:34855f712350 | 891 | int fired_column; |
avi23 | 5:34855f712350 | 892 | int loop_limit = 0; //Stops loop from never ending |
avi23 | 5:34855f712350 | 893 | Invader missile_source; |
avi23 | 5:34855f712350 | 894 | do { |
avi23 | 5:34855f712350 | 895 | fired_column = rand() % 5; |
avi23 | 5:34855f712350 | 896 | missile_source = LowestInvaderInColumn(fired_column); |
avi23 | 5:34855f712350 | 897 | ++loop_limit; |
avi23 | 5:34855f712350 | 898 | } while (missile_source == none && loop_limit < 10); |
avi23 | 5:34855f712350 | 899 | |
avi23 | 5:34855f712350 | 900 | //Finds the centre point of the chosen invader and fires the missile |
avi23 | 5:34855f712350 | 901 | //If the loop limit is reached, the missile source will be none and the for loop will jump to the next iteration |
avi23 | 5:34855f712350 | 902 | if (missile_source == none) { |
avi23 | 5:34855f712350 | 903 | continue; |
avi23 | 5:34855f712350 | 904 | } else if (missile_source == large) { |
avi23 | 5:34855f712350 | 905 | FireNormalInvaderMissile(i, missile_source, large_invader[fired_column]); |
avi23 | 5:34855f712350 | 906 | } else if (missile_source == medium) { |
avi23 | 5:34855f712350 | 907 | FireNormalInvaderMissile(i, missile_source, medium_invader[fired_column]); |
avi23 | 5:34855f712350 | 908 | } else { |
avi23 | 5:34855f712350 | 909 | FireNormalInvaderMissile(i, missile_source, small_invader[fired_column]); |
avi23 | 5:34855f712350 | 910 | } |
avi23 | 5:34855f712350 | 911 | } |
avi23 | 5:34855f712350 | 912 | } |
avi23 | 5:34855f712350 | 913 | } |
avi23 | 5:34855f712350 | 914 | } |
avi23 | 5:34855f712350 | 915 | |
avi23 | 5:34855f712350 | 916 | void FireNormalInvaderMissile(int missile_no, Invader source, const struct Invaders (&invader)) |
avi23 | 5:34855f712350 | 917 | { |
avi23 | 5:34855f712350 | 918 | //Finds the centre point of the chosen invader and fires the missile |
avi23 | 5:34855f712350 | 919 | //Enums are implicity converted to ints --> the middle x position of the invader found by offsetting the invader type by 3 |
avi23 | 5:34855f712350 | 920 | invader_normal_missile[missile_no].x_pos = invader.x_pos + (3 + source); |
avi23 | 5:34855f712350 | 921 | invader_normal_missile[missile_no].y_pos = invader.y_pos + 6; |
avi23 | 5:34855f712350 | 922 | invader_normal_missile[missile_no].fired = true; |
avi23 | 5:34855f712350 | 923 | |
avi23 | 5:34855f712350 | 924 | //Uses a function pointer to attach the ticker |
avi23 | 5:34855f712350 | 925 | move_invader_normal_missile[missile_no].attach(move_invader_normal_missile_isr[missile_no], 0.05); |
avi23 | 5:34855f712350 | 926 | } |
avi23 | 5:34855f712350 | 927 | |
avi23 | 7:babc367a3333 | 928 | void MoveInvaderNormalMissile(int missile_no) |
avi23 | 7:babc367a3333 | 929 | { |
avi23 | 7:babc367a3333 | 930 | //Loops through the bitmap and clears the missile from the screen buffer |
avi23 | 7:babc367a3333 | 931 | for (int col = 0; col < 3; ++col) { |
avi23 | 7:babc367a3333 | 932 | for (int row = 0; row < 4; ++row) { |
avi23 | 7:babc367a3333 | 933 | if (invader_normal_missile_bitmap[row][col]) { |
avi23 | 7:babc367a3333 | 934 | screen_buffer[invader_normal_missile[missile_no].x_pos + col][invader_normal_missile[missile_no].y_pos + row] = empty_pixel; |
avi23 | 7:babc367a3333 | 935 | } |
avi23 | 7:babc367a3333 | 936 | } |
avi23 | 7:babc367a3333 | 937 | } |
avi23 | 7:babc367a3333 | 938 | |
avi23 | 7:babc367a3333 | 939 | //Checks missile will not exceed screen buffer |
avi23 | 7:babc367a3333 | 940 | if (invader_normal_missile[missile_no].y_pos < 44) { |
avi23 | 7:babc367a3333 | 941 | //Increments the position of the missile |
avi23 | 7:babc367a3333 | 942 | ++invader_normal_missile[missile_no].y_pos; |
avi23 | 7:babc367a3333 | 943 | |
avi23 | 7:babc367a3333 | 944 | //Collision detection |
avi23 | 7:babc367a3333 | 945 | CollisionDetectionInvaderNormalMissile(missile_no); |
avi23 | 7:babc367a3333 | 946 | |
avi23 | 7:babc367a3333 | 947 | } else { |
avi23 | 7:babc367a3333 | 948 | //Sets the missiles fired flag as false and detaches the tickers |
avi23 | 7:babc367a3333 | 949 | invader_normal_missile[missile_no].fired = false; |
avi23 | 7:babc367a3333 | 950 | move_invader_normal_missile[missile_no].detach(); |
avi23 | 7:babc367a3333 | 951 | } |
avi23 | 7:babc367a3333 | 952 | } |
avi23 | 7:babc367a3333 | 953 | |
avi23 | 7:babc367a3333 | 954 | //Checks the bottom centre point for a collision. If it doesn't push the bitmap to the screen buffer |
avi23 | 7:babc367a3333 | 955 | void CollisionDetectionInvaderNormalMissile(int missile_no) |
avi23 | 7:babc367a3333 | 956 | { |
avi23 | 7:babc367a3333 | 957 | //Invader missile coordinates shifted to match centre bottom of bitmap |
avi23 | 7:babc367a3333 | 958 | int relative_x_pos = invader_normal_missile[missile_no].x_pos + 1; |
avi23 | 7:babc367a3333 | 959 | int relative_y_pos = invader_normal_missile[missile_no].y_pos + 3; |
avi23 | 7:babc367a3333 | 960 | if (screen_buffer[relative_x_pos][relative_y_pos] == cannon_pixel) { |
avi23 | 7:babc367a3333 | 961 | InvaderNormalMissileHitCannon(); |
avi23 | 7:babc367a3333 | 962 | invader_normal_missile[missile_no].fired = false; |
avi23 | 7:babc367a3333 | 963 | move_invader_normal_missile[missile_no].detach(); |
avi23 | 7:babc367a3333 | 964 | } else if (screen_buffer[relative_x_pos][relative_y_pos] >= first_barrier_pixel && screen_buffer[relative_x_pos][relative_y_pos] < (first_barrier_pixel + 3)) { |
avi23 | 7:babc367a3333 | 965 | //Finds barrier number |
avi23 | 7:babc367a3333 | 966 | InvaderNormalMissileHitBarrier(invader_normal_missile[missile_no]); |
avi23 | 7:babc367a3333 | 967 | invader_normal_missile[missile_no].fired = false; |
avi23 | 7:babc367a3333 | 968 | move_invader_normal_missile[missile_no].detach(); |
avi23 | 7:babc367a3333 | 969 | } else { |
avi23 | 7:babc367a3333 | 970 | for (int col = 0; col < 3; ++col) { |
avi23 | 7:babc367a3333 | 971 | for (int row = 0; row < 4; ++row) { |
avi23 | 7:babc367a3333 | 972 | if (invader_normal_missile_bitmap[row][col]) { |
avi23 | 7:babc367a3333 | 973 | screen_buffer[invader_normal_missile[missile_no].x_pos + col][invader_normal_missile[missile_no].y_pos + row] = invader_normal_missile_pixel; |
avi23 | 7:babc367a3333 | 974 | } |
avi23 | 7:babc367a3333 | 975 | } |
avi23 | 7:babc367a3333 | 976 | } |
avi23 | 7:babc367a3333 | 977 | } |
avi23 | 7:babc367a3333 | 978 | } |
avi23 | 7:babc367a3333 | 979 | |
avi23 | 7:babc367a3333 | 980 | void InvaderNormalMissileHitCannon() |
avi23 | 7:babc367a3333 | 981 | { |
avi23 | 7:babc367a3333 | 982 | //Decrements the number of lives, pauses the game for 2 seconds |
avi23 | 7:babc367a3333 | 983 | //Marks the cannon as hit |
avi23 | 7:babc367a3333 | 984 | g_cannon_hit_flag = true; |
avi23 | 7:babc367a3333 | 985 | //Detaches all tickers |
avi23 | 7:babc367a3333 | 986 | DetachTickers(); |
avi23 | 7:babc367a3333 | 987 | //Creates a Timeout object on the stack with a period of 2 seconds to pause the game for 2 seconds |
avi23 | 7:babc367a3333 | 988 | Timeout cannon_hit; |
avi23 | 7:babc367a3333 | 989 | cannon_hit.attach(&cannon_hit_isr, 2); |
avi23 | 7:babc367a3333 | 990 | while (g_cannon_hit_flag) { |
avi23 | 7:babc367a3333 | 991 | sleep(); |
avi23 | 7:babc367a3333 | 992 | } |
avi23 | 7:babc367a3333 | 993 | AttachTickers(); |
avi23 | 7:babc367a3333 | 994 | --number_of_lives; |
avi23 | 7:babc367a3333 | 995 | } |
avi23 | 7:babc367a3333 | 996 | |
avi23 | 7:babc367a3333 | 997 | //Calculates where to start drawing the damage bitmap over the barrier bitmap and performs the operation |
avi23 | 7:babc367a3333 | 998 | void InvaderNormalMissileHitBarrier(const struct InvaderNormalMissiles (&missile)) |
avi23 | 7:babc367a3333 | 999 | { |
avi23 | 7:babc367a3333 | 1000 | int barrier_no = screen_buffer[missile.x_pos + 1][missile.y_pos + 3] - first_barrier_pixel; |
avi23 | 7:babc367a3333 | 1001 | //Essentially inverse of barrier init |
avi23 | 7:babc367a3333 | 1002 | int relative_x_pos = (missile.x_pos + 1) - 10 - (barrier_no*25) - 1; |
avi23 | 7:babc367a3333 | 1003 | int relative_y_pos = (missile.y_pos + 3) - 33; |
avi23 | 7:babc367a3333 | 1004 | //Loops through the damage bitmap and modifies the barrier's after bitmap |
avi23 | 7:babc367a3333 | 1005 | for (int col = 0; col < 3; ++col) { |
avi23 | 7:babc367a3333 | 1006 | for (int row_bit = 0; row_bit < 2; ++row_bit) { |
avi23 | 7:babc367a3333 | 1007 | //Makes sure bitmap index does not go out of bounds. If it does go to the next iteration |
avi23 | 7:babc367a3333 | 1008 | if (relative_x_pos + col >= 0 && relative_x_pos + col < 14 && relative_y_pos + row_bit >= 0 && relative_y_pos + row_bit < 8) { |
avi23 | 7:babc367a3333 | 1009 | barrier[barrier_no].after_bitmap[relative_y_pos + row_bit][relative_x_pos + col] *= barrier_invader_normal_missile_damage_bitmap[row_bit][col]; |
avi23 | 7:babc367a3333 | 1010 | } |
avi23 | 7:babc367a3333 | 1011 | } |
avi23 | 7:babc367a3333 | 1012 | } |
avi23 | 7:babc367a3333 | 1013 | } |
avi23 | 7:babc367a3333 | 1014 | |
avi23 | 7:babc367a3333 | 1015 | //Detaches game related tickers |
avi23 | 5:34855f712350 | 1016 | void DetachTickers() |
avi23 | 5:34855f712350 | 1017 | { |
avi23 | 5:34855f712350 | 1018 | update_screen.detach(); |
avi23 | 5:34855f712350 | 1019 | move_enemies.detach(); |
avi23 | 7:babc367a3333 | 1020 | //Only detaches if missiles are on the screen |
avi23 | 5:34855f712350 | 1021 | if (cannon_missile_on_screen) { |
avi23 | 5:34855f712350 | 1022 | move_cannon_missile.detach(); |
avi23 | 5:34855f712350 | 1023 | } |
avi23 | 5:34855f712350 | 1024 | for (int i = 0; i < 2; ++i) { |
avi23 | 5:34855f712350 | 1025 | if (invader_normal_missile[i].fired) { |
avi23 | 5:34855f712350 | 1026 | move_invader_normal_missile[i].detach(); |
avi23 | 5:34855f712350 | 1027 | } |
avi23 | 5:34855f712350 | 1028 | } |
avi23 | 5:34855f712350 | 1029 | } |
avi23 | 5:34855f712350 | 1030 | |
avi23 | 7:babc367a3333 | 1031 | //Attaches game related tickers |
avi23 | 5:34855f712350 | 1032 | void AttachTickers() |
avi23 | 5:34855f712350 | 1033 | { |
avi23 | 5:34855f712350 | 1034 | update_screen.attach(&update_screen_isr, 0.05); |
avi23 | 5:34855f712350 | 1035 | move_enemies.attach(&move_enemies_isr, ticker_period); |
avi23 | 7:babc367a3333 | 1036 | //Only attaches if missiles were on the screen |
avi23 | 5:34855f712350 | 1037 | if (cannon_missile_on_screen) { |
avi23 | 5:34855f712350 | 1038 | move_cannon_missile.attach(&move_cannon_missile_isr, 0.05); |
avi23 | 5:34855f712350 | 1039 | } |
avi23 | 5:34855f712350 | 1040 | for (int i = 0; i < 2; ++i) { |
avi23 | 5:34855f712350 | 1041 | if (invader_normal_missile[i].fired) { |
avi23 | 5:34855f712350 | 1042 | move_invader_normal_missile[i].attach(move_invader_normal_missile_isr[i], 0.05); |
avi23 | 5:34855f712350 | 1043 | } |
avi23 | 5:34855f712350 | 1044 | } |
avi23 | 6:89d4a7f7588b | 1045 | } |
avi23 | 6:89d4a7f7588b | 1046 | |
avi23 | 6:89d4a7f7588b | 1047 | void PauseScreen() |
avi23 | 6:89d4a7f7588b | 1048 | { |
avi23 | 7:babc367a3333 | 1049 | //Prints the pause screen, score etc |
avi23 | 7:babc367a3333 | 1050 | PrintPauseScreen(); |
avi23 | 7:babc367a3333 | 1051 | |
avi23 | 6:89d4a7f7588b | 1052 | while (game_state == paused) { |
avi23 | 6:89d4a7f7588b | 1053 | //Draws the cursor |
avi23 | 6:89d4a7f7588b | 1054 | cursor_y_pos = ((fsm_state+3)*8)+3; //Adds 3 to the fsm state to get the bank, multiplies it by 8 to get the pixel no and offsets it by 3 |
avi23 | 6:89d4a7f7588b | 1055 | lcd.drawRect(74, cursor_y_pos, 2, 2, 1); //Draws the cursor |
avi23 | 6:89d4a7f7588b | 1056 | |
avi23 | 6:89d4a7f7588b | 1057 | if (g_move_joystick_flag) { |
avi23 | 6:89d4a7f7588b | 1058 | g_move_joystick_flag = false; |
avi23 | 6:89d4a7f7588b | 1059 | |
avi23 | 6:89d4a7f7588b | 1060 | //Moves the cursor to match the selected option, only if the joystick isn't centred |
avi23 | 6:89d4a7f7588b | 1061 | MoveCursor(fsm_paused); |
avi23 | 6:89d4a7f7588b | 1062 | } |
avi23 | 6:89d4a7f7588b | 1063 | |
avi23 | 6:89d4a7f7588b | 1064 | //If the button is pressed the selected option will appear on the screen |
avi23 | 6:89d4a7f7588b | 1065 | if (g_shoot_pressed_flag) { |
avi23 | 6:89d4a7f7588b | 1066 | g_shoot_pressed_flag = false; |
avi23 | 6:89d4a7f7588b | 1067 | game_state = fsm_paused[fsm_state].output; |
avi23 | 6:89d4a7f7588b | 1068 | } |
avi23 | 6:89d4a7f7588b | 1069 | |
avi23 | 6:89d4a7f7588b | 1070 | //Resets the joystick flag to false if pressed |
avi23 | 6:89d4a7f7588b | 1071 | if (joystick.get_button_flag()) { |
avi23 | 6:89d4a7f7588b | 1072 | joystick.set_button_flag(0); |
avi23 | 6:89d4a7f7588b | 1073 | } |
avi23 | 6:89d4a7f7588b | 1074 | |
avi23 | 6:89d4a7f7588b | 1075 | lcd.refresh(); |
avi23 | 6:89d4a7f7588b | 1076 | |
avi23 | 6:89d4a7f7588b | 1077 | sleep(); |
avi23 | 6:89d4a7f7588b | 1078 | } |
avi23 | 6:89d4a7f7588b | 1079 | } |
avi23 | 6:89d4a7f7588b | 1080 | |
avi23 | 6:89d4a7f7588b | 1081 | void PrintPauseScreen() |
avi23 | 6:89d4a7f7588b | 1082 | { |
avi23 | 6:89d4a7f7588b | 1083 | //Prints paused and a line underneath |
avi23 | 6:89d4a7f7588b | 1084 | lcd.printString("Paused", 24, 0); |
avi23 | 6:89d4a7f7588b | 1085 | //Displays the current score |
avi23 | 6:89d4a7f7588b | 1086 | char buffer[14]; |
avi23 | 6:89d4a7f7588b | 1087 | sprintf(buffer, "Score: %d", score); |
avi23 | 6:89d4a7f7588b | 1088 | lcd.printString(buffer, 0, 1); |
avi23 | 6:89d4a7f7588b | 1089 | //Displays the no of lives |
avi23 | 6:89d4a7f7588b | 1090 | sprintf(buffer, "Lives: %d", number_of_lives); |
avi23 | 6:89d4a7f7588b | 1091 | lcd.printString(buffer, 0, 2); |
avi23 | 6:89d4a7f7588b | 1092 | lcd.drawLine(0, 23, 83, 23, 2); |
avi23 | 6:89d4a7f7588b | 1093 | //Prints options on pause menu |
avi23 | 6:89d4a7f7588b | 1094 | lcd.printString("Resume", 5, 3); |
avi23 | 6:89d4a7f7588b | 1095 | lcd.printString("Save", 5, 4); |
avi23 | 6:89d4a7f7588b | 1096 | lcd.printString("Quit", 5, 5); |
avi23 | 6:89d4a7f7588b | 1097 | } |
avi23 | 6:89d4a7f7588b | 1098 | |
avi23 | 6:89d4a7f7588b | 1099 | void MoveCursor(const struct FSMMenus *fsm) |
avi23 | 6:89d4a7f7588b | 1100 | { |
avi23 | 6:89d4a7f7588b | 1101 | //If the joystick is is pushed down half way clear the cursor and set the next state |
avi23 | 6:89d4a7f7588b | 1102 | if (joystick.GetYValue() < 0.25f) { |
avi23 | 6:89d4a7f7588b | 1103 | //Clears the cursor |
avi23 | 6:89d4a7f7588b | 1104 | lcd.drawRect(74, cursor_y_pos, 2, 2, 2); |
avi23 | 6:89d4a7f7588b | 1105 | //Sets the new state |
avi23 | 6:89d4a7f7588b | 1106 | fsm_state = fsm[fsm_state].next_state[0]; |
avi23 | 6:89d4a7f7588b | 1107 | } else if (joystick.GetYValue() > 0.75f) { |
avi23 | 6:89d4a7f7588b | 1108 | //Clears the cursor |
avi23 | 6:89d4a7f7588b | 1109 | lcd.drawRect(74, cursor_y_pos, 2, 2, 2); |
avi23 | 6:89d4a7f7588b | 1110 | //Sets the new state |
avi23 | 6:89d4a7f7588b | 1111 | fsm_state = fsm[fsm_state].next_state[1]; |
avi23 | 6:89d4a7f7588b | 1112 | } |
avi23 | 0:427469992efe | 1113 | } |