Space Invaders - Embedded Systems Project 15/16 - Avinash Patel 200860407
Dependencies: Joystick N5110 SDFileSystem mbed
main.cpp@6:89d4a7f7588b, 2016-04-28 (annotated)
- Committer:
- avi23
- Date:
- Thu Apr 28 14:14:54 2016 +0000
- Revision:
- 6:89d4a7f7588b
- Parent:
- 5:34855f712350
- Child:
- 7:babc367a3333
Menu Cursors work
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 | 1:b300d052d549 | 9 | */ |
avi23 | 0:427469992efe | 10 | #include "mbed.h" |
avi23 | 0:427469992efe | 11 | #include "N5110.h" |
avi23 | 0:427469992efe | 12 | |
avi23 | 2:d34c95990605 | 13 | //Direction invaders are travelling |
avi23 | 2:d34c95990605 | 14 | #define LEFT 0 |
avi23 | 2:d34c95990605 | 15 | #define RIGHT 1 |
avi23 | 2:d34c95990605 | 16 | |
avi23 | 0:427469992efe | 17 | //Joystick Class |
avi23 | 0:427469992efe | 18 | class Joystick |
avi23 | 0:427469992efe | 19 | { |
avi23 | 0:427469992efe | 20 | public: |
avi23 | 5:34855f712350 | 21 | //Constructor |
avi23 | 0:427469992efe | 22 | Joystick(PinName x_axis_pin, PinName y_axis_pin, PinName button_pin) { |
avi23 | 5:34855f712350 | 23 | //Dynamically allocates the pins and button debounce ticker |
avi23 | 0:427469992efe | 24 | x_axis_ = new AnalogIn(x_axis_pin); |
avi23 | 0:427469992efe | 25 | y_axis_ = new AnalogIn(y_axis_pin); |
avi23 | 0:427469992efe | 26 | button_ = new InterruptIn(button_pin); |
avi23 | 5:34855f712350 | 27 | button_debounce_ = new Timeout(); |
avi23 | 5:34855f712350 | 28 | } |
avi23 | 5:34855f712350 | 29 | |
avi23 | 5:34855f712350 | 30 | //Deconstructor |
avi23 | 5:34855f712350 | 31 | ~Joystick() { |
avi23 | 5:34855f712350 | 32 | //Clears all dynamically allocated memory |
avi23 | 5:34855f712350 | 33 | delete x_axis_; |
avi23 | 5:34855f712350 | 34 | delete y_axis_; |
avi23 | 5:34855f712350 | 35 | delete button_; |
avi23 | 5:34855f712350 | 36 | delete button_debounce_; |
avi23 | 0:427469992efe | 37 | } |
avi23 | 0:427469992efe | 38 | |
avi23 | 0:427469992efe | 39 | //Initalises the Joystick |
avi23 | 0:427469992efe | 40 | //Sets up the ISRs and grabs the offsets for each axis |
avi23 | 0:427469992efe | 41 | void init() { |
avi23 | 0:427469992efe | 42 | //Sets up the button ISR |
avi23 | 5:34855f712350 | 43 | button_->mode(PullDown); |
avi23 | 5:34855f712350 | 44 | button_->rise(this, &Joystick::button_isr); |
avi23 | 0:427469992efe | 45 | |
avi23 | 0:427469992efe | 46 | //Initalises the vairables and flags |
avi23 | 0:427469992efe | 47 | x_offset_ = 0; |
avi23 | 0:427469992efe | 48 | y_offset_ = 0; |
avi23 | 5:34855f712350 | 49 | g_button_flag_ = false; |
avi23 | 5:34855f712350 | 50 | g_button_debounce_flag_ = false; |
avi23 | 0:427469992efe | 51 | |
avi23 | 0:427469992efe | 52 | //Samples the joystick 5 times and takes an average to get the offset |
avi23 | 0:427469992efe | 53 | float x_sum = 0; |
avi23 | 0:427469992efe | 54 | float y_sum = 0; |
avi23 | 0:427469992efe | 55 | |
avi23 | 5:34855f712350 | 56 | for (int i = 0; i < 5; ++i) { |
avi23 | 0:427469992efe | 57 | x_sum += x_axis_->read(); |
avi23 | 0:427469992efe | 58 | y_sum += y_axis_->read(); |
avi23 | 0:427469992efe | 59 | } |
avi23 | 0:427469992efe | 60 | |
avi23 | 0:427469992efe | 61 | x_offset_ = 0.5f - x_sum/5.0f; |
avi23 | 0:427469992efe | 62 | y_offset_ = 0.5f - y_sum/5.0f; |
avi23 | 0:427469992efe | 63 | } |
avi23 | 0:427469992efe | 64 | |
avi23 | 0:427469992efe | 65 | //Take 5 readings and returns the average measurement, accounting for joystick offset x and y values |
avi23 | 0:427469992efe | 66 | float GetXValue() { |
avi23 | 0:427469992efe | 67 | |
avi23 | 0:427469992efe | 68 | float x_sum = 0; |
avi23 | 0:427469992efe | 69 | |
avi23 | 5:34855f712350 | 70 | for (int i = 0; i < 5; ++i) { |
avi23 | 0:427469992efe | 71 | x_sum += x_axis_->read(); |
avi23 | 0:427469992efe | 72 | } |
avi23 | 0:427469992efe | 73 | |
avi23 | 0:427469992efe | 74 | float x_value = x_sum/5.0f + x_offset_; |
avi23 | 0:427469992efe | 75 | |
avi23 | 0:427469992efe | 76 | //Caps the value for the POT between 0 and 1 |
avi23 | 0:427469992efe | 77 | if (x_value < 0.0f) { |
avi23 | 0:427469992efe | 78 | return 0; |
avi23 | 0:427469992efe | 79 | } else if (x_value > 1.0f) { |
avi23 | 0:427469992efe | 80 | return 1; |
avi23 | 0:427469992efe | 81 | } else { |
avi23 | 0:427469992efe | 82 | return x_value; |
avi23 | 0:427469992efe | 83 | } |
avi23 | 0:427469992efe | 84 | } |
avi23 | 0:427469992efe | 85 | |
avi23 | 0:427469992efe | 86 | float GetYValue() { |
avi23 | 0:427469992efe | 87 | |
avi23 | 0:427469992efe | 88 | float y_sum = 0; |
avi23 | 0:427469992efe | 89 | |
avi23 | 5:34855f712350 | 90 | for (int i = 0; i < 5; ++i) { |
avi23 | 0:427469992efe | 91 | y_sum += y_axis_->read(); |
avi23 | 0:427469992efe | 92 | } |
avi23 | 0:427469992efe | 93 | |
avi23 | 0:427469992efe | 94 | float y_value = y_sum/5.0f + y_offset_; |
avi23 | 0:427469992efe | 95 | |
avi23 | 0:427469992efe | 96 | //Caps the value for the POT between 0 and 1 |
avi23 | 0:427469992efe | 97 | if (y_value < 0.0f) { |
avi23 | 0:427469992efe | 98 | return 0; |
avi23 | 0:427469992efe | 99 | } else if (y_value > 1.0f) { |
avi23 | 0:427469992efe | 100 | return 1; |
avi23 | 0:427469992efe | 101 | } else { |
avi23 | 0:427469992efe | 102 | return y_value; |
avi23 | 0:427469992efe | 103 | } |
avi23 | 0:427469992efe | 104 | } |
avi23 | 0:427469992efe | 105 | |
avi23 | 0:427469992efe | 106 | //Getter and setters for flags |
avi23 | 0:427469992efe | 107 | int get_button_flag() { |
avi23 | 0:427469992efe | 108 | return g_button_flag_; |
avi23 | 0:427469992efe | 109 | } |
avi23 | 0:427469992efe | 110 | |
avi23 | 0:427469992efe | 111 | void set_button_flag(int value) { |
avi23 | 0:427469992efe | 112 | g_button_flag_ = value; |
avi23 | 0:427469992efe | 113 | } |
avi23 | 0:427469992efe | 114 | |
avi23 | 0:427469992efe | 115 | private: |
avi23 | 0:427469992efe | 116 | //Button ISR Method |
avi23 | 0:427469992efe | 117 | void button_isr() { |
avi23 | 5:34855f712350 | 118 | if (!g_button_debounce_flag_) { |
avi23 | 5:34855f712350 | 119 | g_button_flag_ = true; |
avi23 | 5:34855f712350 | 120 | g_button_debounce_flag_ = true; |
avi23 | 5:34855f712350 | 121 | |
avi23 | 5:34855f712350 | 122 | //Sets up the debounce ticker |
avi23 | 5:34855f712350 | 123 | button_debounce_->attach(this, &Joystick::button_debounce_isr, 0.2); |
avi23 | 5:34855f712350 | 124 | } |
avi23 | 5:34855f712350 | 125 | } |
avi23 | 5:34855f712350 | 126 | |
avi23 | 5:34855f712350 | 127 | //Button debounce ISR method |
avi23 | 5:34855f712350 | 128 | void button_debounce_isr() { |
avi23 | 5:34855f712350 | 129 | g_button_debounce_flag_ = false; |
avi23 | 0:427469992efe | 130 | } |
avi23 | 0:427469992efe | 131 | |
avi23 | 0:427469992efe | 132 | private: |
avi23 | 0:427469992efe | 133 | //Pin inputs |
avi23 | 0:427469992efe | 134 | AnalogIn* x_axis_; |
avi23 | 0:427469992efe | 135 | AnalogIn* y_axis_; |
avi23 | 0:427469992efe | 136 | InterruptIn* button_; |
avi23 | 0:427469992efe | 137 | |
avi23 | 6:89d4a7f7588b | 138 | //Timeout to prevent joystick button bounce |
avi23 | 5:34855f712350 | 139 | Timeout* button_debounce_; |
avi23 | 5:34855f712350 | 140 | |
avi23 | 0:427469992efe | 141 | //Stores X and Y offsets |
avi23 | 0:427469992efe | 142 | float x_offset_; |
avi23 | 0:427469992efe | 143 | float y_offset_; |
avi23 | 0:427469992efe | 144 | |
avi23 | 0:427469992efe | 145 | //Stores interrupt flags |
avi23 | 5:34855f712350 | 146 | volatile bool g_button_flag_; |
avi23 | 5:34855f712350 | 147 | volatile bool g_button_debounce_flag_; |
avi23 | 0:427469992efe | 148 | }; |
avi23 | 0:427469992efe | 149 | |
avi23 | 0:427469992efe | 150 | // K64F on-board LEDs |
avi23 | 0:427469992efe | 151 | DigitalOut r_led(LED_RED); |
avi23 | 0:427469992efe | 152 | DigitalOut g_led(LED_GREEN); |
avi23 | 0:427469992efe | 153 | DigitalOut b_led(LED_BLUE); |
avi23 | 0:427469992efe | 154 | |
avi23 | 0:427469992efe | 155 | // K64F on-board switches |
avi23 | 0:427469992efe | 156 | InterruptIn sw2(SW2); |
avi23 | 0:427469992efe | 157 | InterruptIn sw3(SW3); |
avi23 | 0:427469992efe | 158 | |
avi23 | 0:427469992efe | 159 | // UART connection for PC |
avi23 | 0:427469992efe | 160 | Serial pc(USBTX,USBRX); |
avi23 | 0:427469992efe | 161 | |
avi23 | 0:427469992efe | 162 | //Joystick |
avi23 | 5:34855f712350 | 163 | Joystick joystick(PTB3, PTB2, PTB11); |
avi23 | 2:d34c95990605 | 164 | |
avi23 | 2:d34c95990605 | 165 | //Shoot button |
avi23 | 2:d34c95990605 | 166 | InterruptIn shoot_button(PTB18); |
avi23 | 0:427469992efe | 167 | |
avi23 | 0:427469992efe | 168 | //LCD object |
avi23 | 0:427469992efe | 169 | // VCC, SCE, RST, D/C, MOSI, SCLK, LED |
avi23 | 0:427469992efe | 170 | N5110 lcd (PTE26 , PTA0 , PTC4 , PTD0 , PTD2 , PTD1 , PTC3); |
avi23 | 2:d34c95990605 | 171 | |
avi23 | 5:34855f712350 | 172 | //Tickers |
avi23 | 5:34855f712350 | 173 | Ticker update_screen; |
avi23 | 5:34855f712350 | 174 | Ticker move_joystick; |
avi23 | 5:34855f712350 | 175 | Ticker move_cannon_missile; |
avi23 | 5:34855f712350 | 176 | Ticker move_enemies; |
avi23 | 5:34855f712350 | 177 | Ticker move_invader_normal_missile[2]; |
avi23 | 5:34855f712350 | 178 | |
avi23 | 5:34855f712350 | 179 | //Timeout |
avi23 | 5:34855f712350 | 180 | Timeout joystick_cursor_regulator; //Stops the cursor from jumping |
avi23 | 6:89d4a7f7588b | 181 | Timeout shoot_button_debounce; //Stops the cannon from firing when transitioning from a menu to the game |
avi23 | 5:34855f712350 | 182 | |
avi23 | 5:34855f712350 | 183 | //Buffer holding pixel data of screen with point representations |
avi23 | 5:34855f712350 | 184 | int screen_buffer[84][48]; |
avi23 | 4:a99953ef9e42 | 185 | const int empty_pixel = 0; |
avi23 | 4:a99953ef9e42 | 186 | const int cannon_pixel = 1; |
avi23 | 4:a99953ef9e42 | 187 | const int first_barrier_pixel = 2; |
avi23 | 4:a99953ef9e42 | 188 | const int first_large_invader_pixel = 5; |
avi23 | 4:a99953ef9e42 | 189 | const int first_medium_invader_pixel = 10; |
avi23 | 4:a99953ef9e42 | 190 | const int first_small_invader_pixel = 15; |
avi23 | 4:a99953ef9e42 | 191 | const int ufo_pixel = 20; |
avi23 | 5:34855f712350 | 192 | const int cannon_missile_pixel = 21; |
avi23 | 5:34855f712350 | 193 | const int invader_normal_missile_pixel = 22; |
avi23 | 0:427469992efe | 194 | |
avi23 | 5:34855f712350 | 195 | //Booleans |
avi23 | 5:34855f712350 | 196 | //Invader related bools |
avi23 | 5:34855f712350 | 197 | bool invaders_in_state2 = true; |
avi23 | 5:34855f712350 | 198 | bool invader_direction = RIGHT; |
avi23 | 5:34855f712350 | 199 | //Cannon missile bool |
avi23 | 5:34855f712350 | 200 | bool cannon_missile_on_screen = false; |
avi23 | 5:34855f712350 | 201 | |
avi23 | 5:34855f712350 | 202 | //Integers |
avi23 | 5:34855f712350 | 203 | int score = 0; //Stores the score |
avi23 | 5:34855f712350 | 204 | int fsm_state = 0; //Stores the state for menu fsm's |
avi23 | 5:34855f712350 | 205 | int cursor_y_pos = 0; //Stores the cursor position |
avi23 | 5:34855f712350 | 206 | //Cannon related integers |
avi23 | 6:89d4a7f7588b | 207 | int number_of_lives = 3; |
avi23 | 1:b300d052d549 | 208 | int cannon_xpos = 24; |
avi23 | 1:b300d052d549 | 209 | const int cannon_ypos = 43; |
avi23 | 5:34855f712350 | 210 | //Cannon missile related integers |
avi23 | 5:34855f712350 | 211 | int cannon_missile_x_pos = 28; |
avi23 | 5:34855f712350 | 212 | int cannon_missile_y_pos = 40; |
avi23 | 6:89d4a7f7588b | 213 | //Invader related integers |
avi23 | 5:34855f712350 | 214 | int no_of_alive_invaders = 15; |
avi23 | 5:34855f712350 | 215 | //Invader missile related integers |
avi23 | 5:34855f712350 | 216 | int invader_strong_missile_x_pos; |
avi23 | 5:34855f712350 | 217 | int invader_strong_missile_y_pos; |
avi23 | 5:34855f712350 | 218 | |
avi23 | 5:34855f712350 | 219 | //Floats |
avi23 | 5:34855f712350 | 220 | float ticker_period = 1; //Stores the period of the invader move ticker |
avi23 | 5:34855f712350 | 221 | |
avi23 | 5:34855f712350 | 222 | //Enums |
avi23 | 5:34855f712350 | 223 | enum Status {dead, dying, alive}; //Contains the status of invaders |
avi23 | 5:34855f712350 | 224 | enum Invader {small, medium, large, none}; //Contains the type of invader passed into |
avi23 | 5:34855f712350 | 225 | //Contains the current state of the game |
avi23 | 6:89d4a7f7588b | 226 | enum GameState {menu, game, paused, save, load, scores, settings}; |
avi23 | 5:34855f712350 | 227 | GameState game_state = menu; |
avi23 | 5:34855f712350 | 228 | |
avi23 | 5:34855f712350 | 229 | //Bit-maps |
avi23 | 5:34855f712350 | 230 | //Cannon bit-map |
avi23 | 1:b300d052d549 | 231 | const bool cannon_bitmap[5][9] = { |
avi23 | 0:427469992efe | 232 | {0, 0, 0, 0, 1, 0, 0, 0, 0}, |
avi23 | 0:427469992efe | 233 | {0, 0, 0, 1, 1, 1, 0, 0, 0}, |
avi23 | 0:427469992efe | 234 | {0, 1, 1, 1, 1, 1, 1, 1, 0}, |
avi23 | 0:427469992efe | 235 | {1, 1, 1, 1, 1, 1, 1, 1, 1}, |
avi23 | 0:427469992efe | 236 | {1, 1, 1, 1, 1, 1, 1, 1, 1} |
avi23 | 0:427469992efe | 237 | }; |
avi23 | 1:b300d052d549 | 238 | //Bitmaps for small invaders |
avi23 | 5:34855f712350 | 239 | const bool small_invader_bitmap_1[6][8] = { //First state |
avi23 | 0:427469992efe | 240 | {0, 0, 0, 1, 1, 0, 0, 0}, |
avi23 | 0:427469992efe | 241 | {0, 1, 1, 1, 1, 1, 1, 0}, |
avi23 | 0:427469992efe | 242 | {1, 1, 0, 1, 1, 0, 1, 1}, |
avi23 | 0:427469992efe | 243 | {1, 1, 1, 1, 1, 1, 1, 1}, |
avi23 | 0:427469992efe | 244 | {0, 1, 0, 1, 1, 0, 1, 0}, |
avi23 | 0:427469992efe | 245 | {1, 0, 1, 0, 0, 1, 0, 1} |
avi23 | 0:427469992efe | 246 | }; |
avi23 | 5:34855f712350 | 247 | const bool small_invader_bitmap_2[6][8] = { //Second state |
avi23 | 0:427469992efe | 248 | {0, 0, 0, 1, 1, 0, 0, 0}, |
avi23 | 0:427469992efe | 249 | {0, 1, 1, 1, 1, 1, 1, 0}, |
avi23 | 0:427469992efe | 250 | {1, 1, 0, 1, 1, 0, 1, 1}, |
avi23 | 0:427469992efe | 251 | {1, 1, 1, 1, 1, 1, 1, 1}, |
avi23 | 0:427469992efe | 252 | {1, 0, 0, 0, 0, 0, 0, 1}, |
avi23 | 0:427469992efe | 253 | {0, 1, 0, 0, 0, 0, 1, 0} |
avi23 | 0:427469992efe | 254 | }; |
avi23 | 1:b300d052d549 | 255 | //Bitmaps for medium invaders |
avi23 | 5:34855f712350 | 256 | const bool medium_invader_bitmap_1[6][10] = { //First state |
avi23 | 1:b300d052d549 | 257 | {1, 0, 0, 1, 0, 0, 1, 0, 0, 1}, |
avi23 | 1:b300d052d549 | 258 | {1, 0, 1, 1, 1, 1, 1, 1, 0, 1}, |
avi23 | 1:b300d052d549 | 259 | {1, 1, 1, 0, 1, 1, 0, 1, 1, 1}, |
avi23 | 1:b300d052d549 | 260 | {0, 1, 1, 1, 1, 1, 1, 1, 1, 0}, |
avi23 | 1:b300d052d549 | 261 | {0, 0, 1, 0, 0, 0, 0, 1, 0, 0}, |
avi23 | 1:b300d052d549 | 262 | {0, 1, 0, 0, 0, 0, 0, 0, 1, 0} |
avi23 | 1:b300d052d549 | 263 | }; |
avi23 | 5:34855f712350 | 264 | const bool medium_invader_bitmap_2[6][10] = { //Second state |
avi23 | 1:b300d052d549 | 265 | {0, 0, 0, 1, 0, 0, 1, 0, 0, 0}, |
avi23 | 1:b300d052d549 | 266 | {0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, |
avi23 | 1:b300d052d549 | 267 | {0, 1, 1, 0, 1, 1, 0, 1, 1, 0}, |
avi23 | 1:b300d052d549 | 268 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, |
avi23 | 1:b300d052d549 | 269 | {1, 0, 1, 0, 0, 0, 0, 1, 0, 1}, |
avi23 | 1:b300d052d549 | 270 | {0, 0, 0, 1, 1, 1, 1, 0, 0, 0} |
avi23 | 1:b300d052d549 | 271 | }; |
avi23 | 1:b300d052d549 | 272 | //Bitmaps for large invaders |
avi23 | 5:34855f712350 | 273 | const bool large_invader_bitmap_1[6][12] = { //First state |
avi23 | 2:d34c95990605 | 274 | {0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0}, |
avi23 | 1:b300d052d549 | 275 | {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, |
avi23 | 1:b300d052d549 | 276 | {1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1}, |
avi23 | 1:b300d052d549 | 277 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, |
avi23 | 1:b300d052d549 | 278 | {0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0}, |
avi23 | 1:b300d052d549 | 279 | {0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0} |
avi23 | 1:b300d052d549 | 280 | }; |
avi23 | 5:34855f712350 | 281 | const bool large_invader_bitmap_2[6][12] = { //Second state |
avi23 | 2:d34c95990605 | 282 | {0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0}, |
avi23 | 1:b300d052d549 | 283 | {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, |
avi23 | 1:b300d052d549 | 284 | {1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1}, |
avi23 | 1:b300d052d549 | 285 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, |
avi23 | 1:b300d052d549 | 286 | {0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0}, |
avi23 | 1:b300d052d549 | 287 | {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1} |
avi23 | 1:b300d052d549 | 288 | }; |
avi23 | 5:34855f712350 | 289 | //Normal invader missile bitmap |
avi23 | 5:34855f712350 | 290 | const bool invader_normal_missile_bitmap[4][3] = { |
avi23 | 5:34855f712350 | 291 | {0, 1, 0}, |
avi23 | 5:34855f712350 | 292 | {1, 1, 1}, |
avi23 | 5:34855f712350 | 293 | {0, 1, 0}, |
avi23 | 5:34855f712350 | 294 | {0, 1, 0} |
avi23 | 5:34855f712350 | 295 | }; |
avi23 | 5:34855f712350 | 296 | //Strong invader missile bitmap |
avi23 | 5:34855f712350 | 297 | const bool invader_strong_missile_bitmap_1[4][3] = { //First state |
avi23 | 5:34855f712350 | 298 | {0, 0, 1}, |
avi23 | 5:34855f712350 | 299 | {0, 1, 0}, |
avi23 | 5:34855f712350 | 300 | {1, 0, 0}, |
avi23 | 5:34855f712350 | 301 | {0, 1, 0} |
avi23 | 5:34855f712350 | 302 | }; |
avi23 | 5:34855f712350 | 303 | const bool invader_strong_missile_bitmap_2[4][3] = { //Second state |
avi23 | 5:34855f712350 | 304 | {0, 1, 0}, |
avi23 | 5:34855f712350 | 305 | {1, 0, 0}, |
avi23 | 5:34855f712350 | 306 | {0, 1, 0}, |
avi23 | 5:34855f712350 | 307 | {0, 1, 1} |
avi23 | 5:34855f712350 | 308 | }; |
avi23 | 5:34855f712350 | 309 | //Barrier bitmap |
avi23 | 2:d34c95990605 | 310 | const bool barrier_bitmap[8][14] = { |
avi23 | 2:d34c95990605 | 311 | {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}, |
avi23 | 2:d34c95990605 | 312 | {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, |
avi23 | 2:d34c95990605 | 313 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, |
avi23 | 2:d34c95990605 | 314 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, |
avi23 | 2:d34c95990605 | 315 | {1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1}, |
avi23 | 2:d34c95990605 | 316 | {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}, |
avi23 | 2:d34c95990605 | 317 | {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}, |
avi23 | 2:d34c95990605 | 318 | {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1} |
avi23 | 2:d34c95990605 | 319 | }; |
avi23 | 5:34855f712350 | 320 | //Cannon barrier damage bitmap |
avi23 | 5:34855f712350 | 321 | const bool barrier_cannon_missile_damage_bitmap[3][3] = { |
avi23 | 5:34855f712350 | 322 | {0, 1, 0}, |
avi23 | 5:34855f712350 | 323 | {1, 0, 0}, |
avi23 | 5:34855f712350 | 324 | {1, 0, 1} |
avi23 | 5:34855f712350 | 325 | }; |
avi23 | 5:34855f712350 | 326 | //Normal invader barrier damage bitmap |
avi23 | 5:34855f712350 | 327 | const bool barrier_invader_normal_missile_damage_bitmap[2][3] = { |
avi23 | 5:34855f712350 | 328 | {1, 0, 1}, |
avi23 | 5:34855f712350 | 329 | {0, 1, 0} |
avi23 | 5:34855f712350 | 330 | }; |
avi23 | 5:34855f712350 | 331 | //UFO Bitmap |
avi23 | 2:d34c95990605 | 332 | const bool ufo_bitmap[5][14] = { |
avi23 | 2:d34c95990605 | 333 | {0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0}, |
avi23 | 2:d34c95990605 | 334 | {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, |
avi23 | 2:d34c95990605 | 335 | {0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0}, |
avi23 | 2:d34c95990605 | 336 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, |
avi23 | 2:d34c95990605 | 337 | {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0} |
avi23 | 2:d34c95990605 | 338 | }; |
avi23 | 2:d34c95990605 | 339 | |
avi23 | 5:34855f712350 | 340 | //Structs |
avi23 | 5:34855f712350 | 341 | //Contains invader data |
avi23 | 5:34855f712350 | 342 | struct Invaders { |
avi23 | 5:34855f712350 | 343 | int x_pos; |
avi23 | 5:34855f712350 | 344 | int y_pos; |
avi23 | 5:34855f712350 | 345 | enum Status status; |
avi23 | 5:34855f712350 | 346 | } small_invader[5], medium_invader[5], large_invader[5]; //Five of each invader |
avi23 | 5:34855f712350 | 347 | //Contains data for Invader normal missiles |
avi23 | 5:34855f712350 | 348 | struct InvaderNormalMissiles { |
avi23 | 5:34855f712350 | 349 | int x_pos; |
avi23 | 5:34855f712350 | 350 | int y_pos; |
avi23 | 5:34855f712350 | 351 | bool fired; |
avi23 | 5:34855f712350 | 352 | } invader_normal_missile[2]; |
avi23 | 5:34855f712350 | 353 | //Contains data for barriers |
avi23 | 5:34855f712350 | 354 | struct Barriers { |
avi23 | 5:34855f712350 | 355 | int x_pos; |
avi23 | 5:34855f712350 | 356 | int y_pos; |
avi23 | 5:34855f712350 | 357 | bool before_bitmap[8][14]; |
avi23 | 5:34855f712350 | 358 | bool after_bitmap[8][14]; |
avi23 | 5:34855f712350 | 359 | } barrier[3]; |
avi23 | 6:89d4a7f7588b | 360 | //FSM for menus |
avi23 | 6:89d4a7f7588b | 361 | struct FSMMenus { |
avi23 | 5:34855f712350 | 362 | GameState output; |
avi23 | 5:34855f712350 | 363 | int next_state[2]; |
avi23 | 5:34855f712350 | 364 | }; |
avi23 | 6:89d4a7f7588b | 365 | FSMMenus fsm_main_menu[4] = { |
avi23 | 6:89d4a7f7588b | 366 | {game, {1, 3}}, |
avi23 | 6:89d4a7f7588b | 367 | {load, {2, 0}}, |
avi23 | 6:89d4a7f7588b | 368 | {scores, {3, 1}}, |
avi23 | 6:89d4a7f7588b | 369 | {settings, {0, 2}} |
avi23 | 6:89d4a7f7588b | 370 | }; |
avi23 | 6:89d4a7f7588b | 371 | FSMMenus fsm_paused[3] = { //Pause menu FSM |
avi23 | 5:34855f712350 | 372 | {game, {1, 2}}, |
avi23 | 5:34855f712350 | 373 | {save, {2, 0}}, |
avi23 | 5:34855f712350 | 374 | {menu, {0, 1}} |
avi23 | 5:34855f712350 | 375 | }; |
avi23 | 0:427469992efe | 376 | |
avi23 | 0:427469992efe | 377 | //ISR Flags |
avi23 | 2:d34c95990605 | 378 | volatile bool g_update_screen_flag = true; |
avi23 | 5:34855f712350 | 379 | volatile bool g_move_joystick_flag = true; |
avi23 | 5:34855f712350 | 380 | volatile bool g_move_enemies_flag = true; |
avi23 | 2:d34c95990605 | 381 | volatile bool g_shoot_pressed_flag = false; |
avi23 | 5:34855f712350 | 382 | volatile bool g_move_cannon_missile_flag = false; |
avi23 | 5:34855f712350 | 383 | volatile bool g_move_invader_normal_missile_flag[2] = {false, false}; |
avi23 | 5:34855f712350 | 384 | volatile bool g_cannon_hit_flag = false; |
avi23 | 5:34855f712350 | 385 | volatile bool g_joystick_cursor_regulator_flag = false; |
avi23 | 6:89d4a7f7588b | 386 | volatile bool g_shoot_button_debounce_flag = false; |
avi23 | 0:427469992efe | 387 | |
avi23 | 0:427469992efe | 388 | // function prototypes |
avi23 | 0:427469992efe | 389 | // error function hangs flashing an LED |
avi23 | 0:427469992efe | 390 | void error(); |
avi23 | 0:427469992efe | 391 | // setup serial port |
avi23 | 0:427469992efe | 392 | void init_serial(); |
avi23 | 0:427469992efe | 393 | // set-up the on-board LEDs and switches |
avi23 | 0:427469992efe | 394 | void init_K64F(); |
avi23 | 2:d34c95990605 | 395 | //Init shoot button |
avi23 | 2:d34c95990605 | 396 | void init_shoot(); |
avi23 | 5:34855f712350 | 397 | //Init Random Number Generator |
avi23 | 5:34855f712350 | 398 | void init_rng(); |
avi23 | 0:427469992efe | 399 | // Added functions |
avi23 | 5:34855f712350 | 400 | void InitaliseGame(); |
avi23 | 5:34855f712350 | 401 | void Game(); |
avi23 | 5:34855f712350 | 402 | void UpdateScreen(); |
avi23 | 2:d34c95990605 | 403 | void MoveCannon(); |
avi23 | 0:427469992efe | 404 | void InitSmallInvaders(); |
avi23 | 2:d34c95990605 | 405 | void ClearSmallInvaders(); |
avi23 | 5:34855f712350 | 406 | void ClearSingleSmallInvader(int invader_no); |
avi23 | 0:427469992efe | 407 | void DrawSmallInvaders(); |
avi23 | 5:34855f712350 | 408 | void DrawSingleSmallInvader(int invader_no); |
avi23 | 5:34855f712350 | 409 | void InitMediumInvaders(); |
avi23 | 2:d34c95990605 | 410 | void ClearMediumInvaders(); |
avi23 | 5:34855f712350 | 411 | void ClearSingleMediumInvader(int invader_no); |
avi23 | 1:b300d052d549 | 412 | void DrawMediumInvaders(); |
avi23 | 5:34855f712350 | 413 | void DrawSingleMediumInvader(int invader_no); |
avi23 | 1:b300d052d549 | 414 | void InitLargeInvaders(); |
avi23 | 5:34855f712350 | 415 | void ClearLargeInvaders(); |
avi23 | 5:34855f712350 | 416 | void ClearSingleLargeInvader(int invader_no); |
avi23 | 1:b300d052d549 | 417 | void DrawLargeInvaders(); |
avi23 | 5:34855f712350 | 418 | void DrawSingleLargeInvader(int invader_no); |
avi23 | 2:d34c95990605 | 419 | void InitBarriers(); |
avi23 | 2:d34c95990605 | 420 | void DrawBarriers(); |
avi23 | 5:34855f712350 | 421 | void MoveInvaderXPositions(); |
avi23 | 5:34855f712350 | 422 | int CalculateInvaderLeftLimit(); |
avi23 | 5:34855f712350 | 423 | int CalculateInvaderRightLimit(); |
avi23 | 5:34855f712350 | 424 | void MoveInvadersLeft(int limit); |
avi23 | 5:34855f712350 | 425 | void MoveInvadersRight(int limit); |
avi23 | 5:34855f712350 | 426 | void MoveInvaderYPositions(bool new_direction); |
avi23 | 5:34855f712350 | 427 | Invader CalculateInvaderYLimit(); |
avi23 | 5:34855f712350 | 428 | Invader LowestInvaderInColumn(int column); |
avi23 | 5:34855f712350 | 429 | void FireCannonMissile(); |
avi23 | 5:34855f712350 | 430 | void MoveCannonMissile(); |
avi23 | 5:34855f712350 | 431 | void CollisionDetectionCannonMissile(); |
avi23 | 5:34855f712350 | 432 | int CannonMissileHitInvader(int first_pixel, int row, struct Invaders (&invader)[5]); |
avi23 | 5:34855f712350 | 433 | void CannonMissileHitBarrier(int first_pixel, int row); |
avi23 | 5:34855f712350 | 434 | void InvaderNormalMissileHitBarrier(int first_pixel, const struct InvaderNormalMissiles (&missile)); |
avi23 | 5:34855f712350 | 435 | void AttemptToFireInvaderNormalMissiles(); |
avi23 | 5:34855f712350 | 436 | void FireNormalInvaderMissile(int missile_no, Invader source, const struct Invaders (&invader)); |
avi23 | 5:34855f712350 | 437 | void MoveInvaderNormalMissile(int missile_no); |
avi23 | 5:34855f712350 | 438 | void CollisionDetectionInvaderNormalMissile(int missile_no); |
avi23 | 5:34855f712350 | 439 | void DetachTickers(); |
avi23 | 5:34855f712350 | 440 | void AttachTickers(); |
avi23 | 6:89d4a7f7588b | 441 | //Pause Menu Functions |
avi23 | 6:89d4a7f7588b | 442 | void PauseScreen(); |
avi23 | 6:89d4a7f7588b | 443 | void PrintPauseScreen(); |
avi23 | 6:89d4a7f7588b | 444 | void MoveCursor(const struct FSMMenus *fsm); |
avi23 | 2:d34c95990605 | 445 | //void InitUFO(); |
avi23 | 2:d34c95990605 | 446 | void DrawUFO(); |
avi23 | 0:427469992efe | 447 | //ISR's |
avi23 | 2:d34c95990605 | 448 | void update_screen_isr(); |
avi23 | 5:34855f712350 | 449 | void move_joystick_isr(); |
avi23 | 0:427469992efe | 450 | void move_enemies_isr(); |
avi23 | 2:d34c95990605 | 451 | void shoot_pressed_isr(); |
avi23 | 5:34855f712350 | 452 | void move_cannon_missile_isr(); |
avi23 | 5:34855f712350 | 453 | void cannon_hit_isr(); |
avi23 | 5:34855f712350 | 454 | void joystick_cursor_regulator_isr(); |
avi23 | 6:89d4a7f7588b | 455 | void shoot_button_debounce_isr(); |
avi23 | 5:34855f712350 | 456 | //Function pointer to move invader normal missile isr |
avi23 | 5:34855f712350 | 457 | void (*move_invader_normal_missile_isr[2])(); |
avi23 | 5:34855f712350 | 458 | void move_invader_normal_missile_0_isr(); |
avi23 | 5:34855f712350 | 459 | void move_invader_normal_missile_1_isr(); |
avi23 | 0:427469992efe | 460 | |
avi23 | 5:34855f712350 | 461 | int row_no = 5; |
avi23 | 5:34855f712350 | 462 | int col_no = 14; |
avi23 | 0:427469992efe | 463 | |
avi23 | 0:427469992efe | 464 | int main() |
avi23 | 0:427469992efe | 465 | { |
avi23 | 5:34855f712350 | 466 | //Wait for 2 seconds to allow power to settle |
avi23 | 5:34855f712350 | 467 | wait(1); |
avi23 | 0:427469992efe | 468 | //Initalises the board and perhiperals |
avi23 | 0:427469992efe | 469 | init_K64F(); |
avi23 | 0:427469992efe | 470 | init_serial(); |
avi23 | 2:d34c95990605 | 471 | init_shoot(); |
avi23 | 5:34855f712350 | 472 | init_rng(); |
avi23 | 5:34855f712350 | 473 | joystick.init(); |
avi23 | 0:427469992efe | 474 | lcd.init(); |
avi23 | 0:427469992efe | 475 | lcd.clear(); |
avi23 | 0:427469992efe | 476 | |
avi23 | 5:34855f712350 | 477 | //Configures the function pointer for the invaders normal missile |
avi23 | 5:34855f712350 | 478 | move_invader_normal_missile_isr[0] = &move_invader_normal_missile_0_isr; |
avi23 | 5:34855f712350 | 479 | move_invader_normal_missile_isr[1] = &move_invader_normal_missile_1_isr; |
avi23 | 0:427469992efe | 480 | |
avi23 | 5:34855f712350 | 481 | //Samples joystick every 0.05 second |
avi23 | 5:34855f712350 | 482 | move_joystick.attach(&move_joystick_isr, 0.05); |
avi23 | 2:d34c95990605 | 483 | |
avi23 | 6:89d4a7f7588b | 484 | |
avi23 | 6:89d4a7f7588b | 485 | |
avi23 | 2:d34c95990605 | 486 | while (true) { |
avi23 | 5:34855f712350 | 487 | if (game_state == menu) { //Menu screen |
avi23 | 2:d34c95990605 | 488 | lcd.clear(); |
avi23 | 6:89d4a7f7588b | 489 | fsm_state = 0; //Sets the fsm state to 0 |
avi23 | 6:89d4a7f7588b | 490 | while (game_state == menu) { |
avi23 | 6:89d4a7f7588b | 491 | lcd.printString("Space Invaders", 0, 0); |
avi23 | 6:89d4a7f7588b | 492 | lcd.printString("Menu", 28, 1); |
avi23 | 6:89d4a7f7588b | 493 | lcd.drawLine(0, 15, 83, 15, 2); |
avi23 | 6:89d4a7f7588b | 494 | |
avi23 | 6:89d4a7f7588b | 495 | lcd.printString("New Game", 5, 2); |
avi23 | 6:89d4a7f7588b | 496 | lcd.printString("Load Game", 5, 3); |
avi23 | 6:89d4a7f7588b | 497 | lcd.printString("High Scores", 5, 4); |
avi23 | 6:89d4a7f7588b | 498 | lcd.printString("Settings", 5, 5); |
avi23 | 6:89d4a7f7588b | 499 | |
avi23 | 6:89d4a7f7588b | 500 | //Draws the cursor |
avi23 | 6:89d4a7f7588b | 501 | 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 | 502 | lcd.drawRect(74, cursor_y_pos, 2, 2, 1); |
avi23 | 6:89d4a7f7588b | 503 | |
avi23 | 6:89d4a7f7588b | 504 | if (g_move_joystick_flag) { |
avi23 | 6:89d4a7f7588b | 505 | g_move_joystick_flag = false; |
avi23 | 6:89d4a7f7588b | 506 | |
avi23 | 6:89d4a7f7588b | 507 | //Moves the cursor to match the selected option, only if the joystick isn't centred |
avi23 | 6:89d4a7f7588b | 508 | MoveCursor(fsm_main_menu); |
avi23 | 6:89d4a7f7588b | 509 | } |
avi23 | 6:89d4a7f7588b | 510 | |
avi23 | 6:89d4a7f7588b | 511 | if (g_shoot_pressed_flag) { |
avi23 | 6:89d4a7f7588b | 512 | g_shoot_pressed_flag = false; |
avi23 | 6:89d4a7f7588b | 513 | |
avi23 | 6:89d4a7f7588b | 514 | game_state = fsm_main_menu[fsm_state].output; |
avi23 | 2:d34c95990605 | 515 | |
avi23 | 6:89d4a7f7588b | 516 | //If the game state is equal to the game initalise it |
avi23 | 6:89d4a7f7588b | 517 | if (game_state == game) { |
avi23 | 6:89d4a7f7588b | 518 | //Clears the screen buffer and runs init functions |
avi23 | 6:89d4a7f7588b | 519 | memset(screen_buffer, 0, sizeof(screen_buffer)); |
avi23 | 6:89d4a7f7588b | 520 | no_of_alive_invaders = 15; |
avi23 | 6:89d4a7f7588b | 521 | score = 0; |
avi23 | 6:89d4a7f7588b | 522 | number_of_lives = 3; |
avi23 | 6:89d4a7f7588b | 523 | InitSmallInvaders(); |
avi23 | 6:89d4a7f7588b | 524 | InitMediumInvaders(); |
avi23 | 6:89d4a7f7588b | 525 | InitLargeInvaders(); |
avi23 | 6:89d4a7f7588b | 526 | InitBarriers(); |
avi23 | 6:89d4a7f7588b | 527 | //Sets the flags so enemies pop up straight away |
avi23 | 6:89d4a7f7588b | 528 | g_update_screen_flag = true; |
avi23 | 6:89d4a7f7588b | 529 | g_move_joystick_flag = true; |
avi23 | 6:89d4a7f7588b | 530 | g_move_enemies_flag = true; |
avi23 | 6:89d4a7f7588b | 531 | //Forces the missiles to have the fired flags to flase |
avi23 | 6:89d4a7f7588b | 532 | cannon_missile_on_screen = false; |
avi23 | 6:89d4a7f7588b | 533 | invader_normal_missile[0].fired = false; |
avi23 | 6:89d4a7f7588b | 534 | invader_normal_missile[1].fired = false; |
avi23 | 6:89d4a7f7588b | 535 | } |
avi23 | 6:89d4a7f7588b | 536 | } |
avi23 | 5:34855f712350 | 537 | |
avi23 | 6:89d4a7f7588b | 538 | if(joystick.get_button_flag()) { |
avi23 | 6:89d4a7f7588b | 539 | joystick.set_button_flag(0); |
avi23 | 6:89d4a7f7588b | 540 | } |
avi23 | 6:89d4a7f7588b | 541 | |
avi23 | 6:89d4a7f7588b | 542 | lcd.refresh(); |
avi23 | 6:89d4a7f7588b | 543 | sleep(); |
avi23 | 1:b300d052d549 | 544 | } |
avi23 | 5:34855f712350 | 545 | } else if (game_state == paused) { //Paused screen |
avi23 | 6:89d4a7f7588b | 546 | //Clears the screen |
avi23 | 6:89d4a7f7588b | 547 | lcd.clear(); |
avi23 | 6:89d4a7f7588b | 548 | //Resets the fsm state to 0 |
avi23 | 6:89d4a7f7588b | 549 | fsm_state = 0; |
avi23 | 6:89d4a7f7588b | 550 | PauseScreen(); |
avi23 | 5:34855f712350 | 551 | } else if (game_state == game) { //Game screen |
avi23 | 5:34855f712350 | 552 | AttachTickers(); |
avi23 | 5:34855f712350 | 553 | Game(); |
avi23 | 0:427469992efe | 554 | } |
avi23 | 2:d34c95990605 | 555 | |
avi23 | 0:427469992efe | 556 | sleep(); |
avi23 | 0:427469992efe | 557 | } |
avi23 | 0:427469992efe | 558 | } |
avi23 | 0:427469992efe | 559 | |
avi23 | 0:427469992efe | 560 | void init_K64F() |
avi23 | 0:427469992efe | 561 | { |
avi23 | 0:427469992efe | 562 | // on-board LEDs are active-low, so set pin high to turn them off. |
avi23 | 0:427469992efe | 563 | r_led = 1; |
avi23 | 0:427469992efe | 564 | g_led = 1; |
avi23 | 0:427469992efe | 565 | b_led = 1; |
avi23 | 0:427469992efe | 566 | |
avi23 | 0:427469992efe | 567 | // since the on-board switches have external pull-ups, we should disable the internal pull-down |
avi23 | 0:427469992efe | 568 | // resistors that are enabled by default using InterruptIn |
avi23 | 0:427469992efe | 569 | sw2.mode(PullNone); |
avi23 | 0:427469992efe | 570 | sw3.mode(PullNone); |
avi23 | 0:427469992efe | 571 | } |
avi23 | 0:427469992efe | 572 | |
avi23 | 0:427469992efe | 573 | void error() |
avi23 | 0:427469992efe | 574 | { |
avi23 | 0:427469992efe | 575 | while(1) { // if error, hang while flashing error message |
avi23 | 0:427469992efe | 576 | r_led = 0; |
avi23 | 0:427469992efe | 577 | wait(0.2); |
avi23 | 0:427469992efe | 578 | r_led = 1; |
avi23 | 0:427469992efe | 579 | wait(0.2); |
avi23 | 0:427469992efe | 580 | } |
avi23 | 0:427469992efe | 581 | } |
avi23 | 0:427469992efe | 582 | |
avi23 | 0:427469992efe | 583 | void init_serial() |
avi23 | 0:427469992efe | 584 | { |
avi23 | 0:427469992efe | 585 | // set to highest baud - ensure terminal software matches |
avi23 | 0:427469992efe | 586 | pc.baud(115200); |
avi23 | 0:427469992efe | 587 | } |
avi23 | 0:427469992efe | 588 | |
avi23 | 5:34855f712350 | 589 | //Seeds the random number generator with noise from an analog in pin |
avi23 | 5:34855f712350 | 590 | void init_rng() |
avi23 | 5:34855f712350 | 591 | { |
avi23 | 5:34855f712350 | 592 | AnalogIn rng_seed(PTC10); |
avi23 | 5:34855f712350 | 593 | srand(floor(10000*rng_seed.read())); |
avi23 | 5:34855f712350 | 594 | } |
avi23 | 5:34855f712350 | 595 | |
avi23 | 2:d34c95990605 | 596 | void init_shoot() |
avi23 | 0:427469992efe | 597 | { |
avi23 | 2:d34c95990605 | 598 | shoot_button.mode(PullUp); |
avi23 | 2:d34c95990605 | 599 | shoot_button.fall(&shoot_pressed_isr); |
avi23 | 2:d34c95990605 | 600 | } |
avi23 | 2:d34c95990605 | 601 | |
avi23 | 2:d34c95990605 | 602 | void update_screen_isr() |
avi23 | 2:d34c95990605 | 603 | { |
avi23 | 2:d34c95990605 | 604 | g_update_screen_flag = true; |
avi23 | 0:427469992efe | 605 | } |
avi23 | 0:427469992efe | 606 | |
avi23 | 5:34855f712350 | 607 | void move_enemies_isr() |
avi23 | 5:34855f712350 | 608 | { |
avi23 | 5:34855f712350 | 609 | g_move_enemies_flag = true; |
avi23 | 5:34855f712350 | 610 | } |
avi23 | 5:34855f712350 | 611 | |
avi23 | 2:d34c95990605 | 612 | void shoot_pressed_isr() |
avi23 | 2:d34c95990605 | 613 | { |
avi23 | 6:89d4a7f7588b | 614 | //Only sets the shoot pressed flag 0.1s after the last press |
avi23 | 6:89d4a7f7588b | 615 | if (!g_shoot_button_debounce_flag) { |
avi23 | 6:89d4a7f7588b | 616 | g_shoot_pressed_flag = true; |
avi23 | 6:89d4a7f7588b | 617 | g_shoot_button_debounce_flag = true; |
avi23 | 6:89d4a7f7588b | 618 | |
avi23 | 6:89d4a7f7588b | 619 | //Attaches a timeout to clear the debounce flag 0.125 seconds after it was set |
avi23 | 6:89d4a7f7588b | 620 | shoot_button_debounce.attach(&shoot_button_debounce_isr, 0.125); |
avi23 | 6:89d4a7f7588b | 621 | } |
avi23 | 5:34855f712350 | 622 | } |
avi23 | 5:34855f712350 | 623 | |
avi23 | 5:34855f712350 | 624 | void move_cannon_missile_isr() |
avi23 | 5:34855f712350 | 625 | { |
avi23 | 5:34855f712350 | 626 | g_move_cannon_missile_flag = true; |
avi23 | 5:34855f712350 | 627 | } |
avi23 | 5:34855f712350 | 628 | |
avi23 | 5:34855f712350 | 629 | void move_joystick_isr() |
avi23 | 5:34855f712350 | 630 | { |
avi23 | 5:34855f712350 | 631 | //Always set the move flag in a game |
avi23 | 5:34855f712350 | 632 | if (game_state == game) { |
avi23 | 5:34855f712350 | 633 | g_move_joystick_flag = true; |
avi23 | 5:34855f712350 | 634 | } else if (!g_joystick_cursor_regulator_flag) { |
avi23 | 6:89d4a7f7588b | 635 | //Only sets the flag if the regulator is not set |
avi23 | 5:34855f712350 | 636 | g_move_joystick_flag = true; |
avi23 | 5:34855f712350 | 637 | g_joystick_cursor_regulator_flag = true; |
avi23 | 5:34855f712350 | 638 | |
avi23 | 6:89d4a7f7588b | 639 | //Attachs a timeout to clear the regulator in 0.1s to prevent the cursor from behaving erratically |
avi23 | 6:89d4a7f7588b | 640 | joystick_cursor_regulator.attach(&joystick_cursor_regulator_isr, 0.1); |
avi23 | 5:34855f712350 | 641 | } |
avi23 | 5:34855f712350 | 642 | } |
avi23 | 5:34855f712350 | 643 | |
avi23 | 6:89d4a7f7588b | 644 | void joystick_cursor_regulator_isr() |
avi23 | 6:89d4a7f7588b | 645 | { |
avi23 | 5:34855f712350 | 646 | g_joystick_cursor_regulator_flag = false; |
avi23 | 5:34855f712350 | 647 | } |
avi23 | 5:34855f712350 | 648 | |
avi23 | 6:89d4a7f7588b | 649 | void shoot_button_debounce_isr() |
avi23 | 6:89d4a7f7588b | 650 | { |
avi23 | 6:89d4a7f7588b | 651 | g_shoot_button_debounce_flag = false; |
avi23 | 6:89d4a7f7588b | 652 | } |
avi23 | 6:89d4a7f7588b | 653 | |
avi23 | 5:34855f712350 | 654 | void move_invader_normal_missile_0_isr() |
avi23 | 5:34855f712350 | 655 | { |
avi23 | 5:34855f712350 | 656 | g_move_invader_normal_missile_flag[0] = true; |
avi23 | 5:34855f712350 | 657 | } |
avi23 | 5:34855f712350 | 658 | |
avi23 | 5:34855f712350 | 659 | void move_invader_normal_missile_1_isr() |
avi23 | 5:34855f712350 | 660 | { |
avi23 | 5:34855f712350 | 661 | g_move_invader_normal_missile_flag[1] = true; |
avi23 | 5:34855f712350 | 662 | } |
avi23 | 5:34855f712350 | 663 | |
avi23 | 5:34855f712350 | 664 | void cannon_hit_isr() |
avi23 | 5:34855f712350 | 665 | { |
avi23 | 5:34855f712350 | 666 | g_cannon_hit_flag = false; |
avi23 | 2:d34c95990605 | 667 | } |
avi23 | 2:d34c95990605 | 668 | |
avi23 | 5:34855f712350 | 669 | void Game() |
avi23 | 6:89d4a7f7588b | 670 | { |
avi23 | 5:34855f712350 | 671 | //Stays within the loop while the selected state is game |
avi23 | 5:34855f712350 | 672 | while (game_state == game) { |
avi23 | 5:34855f712350 | 673 | //If the game is over detach all the tickers |
avi23 | 5:34855f712350 | 674 | if (number_of_lives == 0) { |
avi23 | 5:34855f712350 | 675 | DetachTickers(); |
avi23 | 5:34855f712350 | 676 | |
avi23 | 5:34855f712350 | 677 | lcd.clear(); |
avi23 | 5:34855f712350 | 678 | lcd.printString("Game Over.", 1, 2); |
avi23 | 5:34855f712350 | 679 | } else if (no_of_alive_invaders == 0) { //If the player wins a round |
avi23 | 5:34855f712350 | 680 | //Resets the no of alive invaders |
avi23 | 5:34855f712350 | 681 | no_of_alive_invaders = 15; |
avi23 | 5:34855f712350 | 682 | //Detaches the enemy ticker while reinitalising invaders |
avi23 | 5:34855f712350 | 683 | move_enemies.detach(); |
avi23 | 5:34855f712350 | 684 | //Reinitalises objects |
avi23 | 5:34855f712350 | 685 | InitSmallInvaders(); |
avi23 | 5:34855f712350 | 686 | InitMediumInvaders(); |
avi23 | 5:34855f712350 | 687 | InitLargeInvaders(); |
avi23 | 5:34855f712350 | 688 | //Reattaches enemy ticker |
avi23 | 5:34855f712350 | 689 | move_enemies.attach(&move_enemies_isr, 1); |
avi23 | 5:34855f712350 | 690 | } else { |
avi23 | 5:34855f712350 | 691 | //Updates pixels on the screen |
avi23 | 5:34855f712350 | 692 | if (g_update_screen_flag) { |
avi23 | 5:34855f712350 | 693 | g_update_screen_flag = false; |
avi23 | 5:34855f712350 | 694 | |
avi23 | 5:34855f712350 | 695 | UpdateScreen(); |
avi23 | 5:34855f712350 | 696 | } |
avi23 | 5:34855f712350 | 697 | |
avi23 | 5:34855f712350 | 698 | //Controls cannon movement |
avi23 | 5:34855f712350 | 699 | if (g_move_joystick_flag) { |
avi23 | 5:34855f712350 | 700 | g_move_joystick_flag = false; |
avi23 | 5:34855f712350 | 701 | |
avi23 | 5:34855f712350 | 702 | MoveCannon(); |
avi23 | 5:34855f712350 | 703 | DrawBarriers(); |
avi23 | 5:34855f712350 | 704 | } |
avi23 | 5:34855f712350 | 705 | |
avi23 | 5:34855f712350 | 706 | //Controls enemy movement |
avi23 | 5:34855f712350 | 707 | if (g_move_enemies_flag) { |
avi23 | 5:34855f712350 | 708 | g_move_enemies_flag = false; |
avi23 | 5:34855f712350 | 709 | |
avi23 | 5:34855f712350 | 710 | //Increses the speed the invaders move |
avi23 | 5:34855f712350 | 711 | move_enemies.detach(); |
avi23 | 5:34855f712350 | 712 | ticker_period = 0.1+(no_of_alive_invaders*0.06); |
avi23 | 5:34855f712350 | 713 | move_enemies.attach(&move_enemies_isr, ticker_period); |
avi23 | 5:34855f712350 | 714 | |
avi23 | 5:34855f712350 | 715 | //Clears the old bitmaps |
avi23 | 5:34855f712350 | 716 | ClearSmallInvaders(); |
avi23 | 5:34855f712350 | 717 | ClearMediumInvaders(); |
avi23 | 5:34855f712350 | 718 | ClearLargeInvaders(); |
avi23 | 5:34855f712350 | 719 | |
avi23 | 5:34855f712350 | 720 | MoveInvaderXPositions(); |
avi23 | 5:34855f712350 | 721 | //Switches the bitmap state |
avi23 | 5:34855f712350 | 722 | invaders_in_state2 = !invaders_in_state2; |
avi23 | 5:34855f712350 | 723 | |
avi23 | 5:34855f712350 | 724 | //Draws the invaders |
avi23 | 5:34855f712350 | 725 | DrawSmallInvaders(); |
avi23 | 5:34855f712350 | 726 | DrawMediumInvaders(); |
avi23 | 5:34855f712350 | 727 | DrawLargeInvaders(); |
avi23 | 5:34855f712350 | 728 | |
avi23 | 5:34855f712350 | 729 | //Attemots to fire the invaders missiles |
avi23 | 5:34855f712350 | 730 | AttemptToFireInvaderNormalMissiles(); |
avi23 | 5:34855f712350 | 731 | } |
avi23 | 5:34855f712350 | 732 | |
avi23 | 5:34855f712350 | 733 | //Spawns a player bullet if the shoot button is pressed and there isn't a bullet on the screen |
avi23 | 5:34855f712350 | 734 | if (g_shoot_pressed_flag) { |
avi23 | 5:34855f712350 | 735 | g_shoot_pressed_flag = false; |
avi23 | 5:34855f712350 | 736 | |
avi23 | 5:34855f712350 | 737 | if (!cannon_missile_on_screen) { |
avi23 | 5:34855f712350 | 738 | FireCannonMissile(); |
avi23 | 5:34855f712350 | 739 | } |
avi23 | 5:34855f712350 | 740 | } |
avi23 | 5:34855f712350 | 741 | |
avi23 | 5:34855f712350 | 742 | //Move the cannon shot |
avi23 | 5:34855f712350 | 743 | if (g_move_cannon_missile_flag) { |
avi23 | 5:34855f712350 | 744 | g_move_cannon_missile_flag = false; |
avi23 | 5:34855f712350 | 745 | |
avi23 | 5:34855f712350 | 746 | MoveCannonMissile(); |
avi23 | 5:34855f712350 | 747 | } |
avi23 | 5:34855f712350 | 748 | |
avi23 | 5:34855f712350 | 749 | //Moves the invaders 1st normal missile |
avi23 | 5:34855f712350 | 750 | if (g_move_invader_normal_missile_flag[0]) { |
avi23 | 5:34855f712350 | 751 | g_move_invader_normal_missile_flag[0] = false; |
avi23 | 5:34855f712350 | 752 | |
avi23 | 5:34855f712350 | 753 | MoveInvaderNormalMissile(0); |
avi23 | 5:34855f712350 | 754 | } |
avi23 | 5:34855f712350 | 755 | |
avi23 | 5:34855f712350 | 756 | //Moves the invaders 2nd normal missile |
avi23 | 5:34855f712350 | 757 | if (g_move_invader_normal_missile_flag[1]) { |
avi23 | 5:34855f712350 | 758 | g_move_invader_normal_missile_flag[1] = false; |
avi23 | 5:34855f712350 | 759 | |
avi23 | 5:34855f712350 | 760 | MoveInvaderNormalMissile(1); |
avi23 | 5:34855f712350 | 761 | } |
avi23 | 5:34855f712350 | 762 | |
avi23 | 5:34855f712350 | 763 | if (joystick.get_button_flag()) { |
avi23 | 5:34855f712350 | 764 | joystick.set_button_flag(0); |
avi23 | 5:34855f712350 | 765 | |
avi23 | 5:34855f712350 | 766 | //Detach all game tickers |
avi23 | 5:34855f712350 | 767 | DetachTickers(); |
avi23 | 5:34855f712350 | 768 | game_state = paused; |
avi23 | 5:34855f712350 | 769 | } |
avi23 | 5:34855f712350 | 770 | } |
avi23 | 5:34855f712350 | 771 | |
avi23 | 5:34855f712350 | 772 | sleep(); |
avi23 | 5:34855f712350 | 773 | } |
avi23 | 2:d34c95990605 | 774 | } |
avi23 | 2:d34c95990605 | 775 | |
avi23 | 5:34855f712350 | 776 | void UpdateScreen() |
avi23 | 2:d34c95990605 | 777 | { |
avi23 | 5:34855f712350 | 778 | //Loops through the screen buffer and sets pixels on the LCD |
avi23 | 5:34855f712350 | 779 | for (int col = 0; col < 84; ++col) { |
avi23 | 5:34855f712350 | 780 | for (int row = 0; row < 48; ++row) { |
avi23 | 5:34855f712350 | 781 | if (screen_buffer[col][row]) { |
avi23 | 5:34855f712350 | 782 | lcd.setPixel(col, row); |
avi23 | 5:34855f712350 | 783 | } else { |
avi23 | 5:34855f712350 | 784 | lcd.clearPixel(col, row); |
avi23 | 5:34855f712350 | 785 | } |
avi23 | 5:34855f712350 | 786 | } |
avi23 | 5:34855f712350 | 787 | } |
avi23 | 5:34855f712350 | 788 | |
avi23 | 5:34855f712350 | 789 | lcd.refresh(); |
avi23 | 2:d34c95990605 | 790 | } |
avi23 | 2:d34c95990605 | 791 | |
avi23 | 2:d34c95990605 | 792 | void MoveCannon() |
avi23 | 0:427469992efe | 793 | { |
avi23 | 0:427469992efe | 794 | //Clears the ship |
avi23 | 5:34855f712350 | 795 | for (int col = 0; col < 9; ++col) { |
avi23 | 5:34855f712350 | 796 | for (int row = 0; row < 5; ++row) { |
avi23 | 1:b300d052d549 | 797 | if(cannon_bitmap[row][col]) { |
avi23 | 5:34855f712350 | 798 | screen_buffer[cannon_xpos+col][cannon_ypos+row] = empty_pixel; |
avi23 | 0:427469992efe | 799 | } |
avi23 | 0:427469992efe | 800 | } |
avi23 | 0:427469992efe | 801 | } |
avi23 | 0:427469992efe | 802 | |
avi23 | 0:427469992efe | 803 | //Changes the position of the ship when the joystick is moved, capping at 0 and 75 so it always fits on the screen |
avi23 | 0:427469992efe | 804 | if (joystick.GetXValue() < 0.25f) { |
avi23 | 1:b300d052d549 | 805 | cannon_xpos--; |
avi23 | 1:b300d052d549 | 806 | if (cannon_xpos < 0) { |
avi23 | 1:b300d052d549 | 807 | cannon_xpos = 0; |
avi23 | 0:427469992efe | 808 | } |
avi23 | 0:427469992efe | 809 | } else if (joystick.GetXValue() > 0.75f) { |
avi23 | 1:b300d052d549 | 810 | cannon_xpos++; |
avi23 | 1:b300d052d549 | 811 | if (cannon_xpos > 75) { |
avi23 | 1:b300d052d549 | 812 | cannon_xpos = 75; |
avi23 | 0:427469992efe | 813 | } |
avi23 | 0:427469992efe | 814 | } |
avi23 | 0:427469992efe | 815 | |
avi23 | 0:427469992efe | 816 | //Redraws the ship |
avi23 | 5:34855f712350 | 817 | for (int col = 0; col < 9; ++col) { |
avi23 | 5:34855f712350 | 818 | for (int row = 0; row < 5; ++row) { |
avi23 | 1:b300d052d549 | 819 | if(cannon_bitmap[row][col]) { |
avi23 | 5:34855f712350 | 820 | screen_buffer[cannon_xpos+col][cannon_ypos+row] = cannon_pixel; |
avi23 | 0:427469992efe | 821 | } |
avi23 | 0:427469992efe | 822 | } |
avi23 | 0:427469992efe | 823 | } |
avi23 | 0:427469992efe | 824 | } |
avi23 | 0:427469992efe | 825 | |
avi23 | 0:427469992efe | 826 | //Sets the position and aliveness of the small invaders |
avi23 | 0:427469992efe | 827 | void InitSmallInvaders() |
avi23 | 0:427469992efe | 828 | { |
avi23 | 5:34855f712350 | 829 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 830 | small_invader[i].x_pos = 2 + (i*13); |
avi23 | 2:d34c95990605 | 831 | small_invader[i].y_pos = 1; |
avi23 | 5:34855f712350 | 832 | small_invader[i].status = alive; |
avi23 | 0:427469992efe | 833 | } |
avi23 | 0:427469992efe | 834 | } |
avi23 | 0:427469992efe | 835 | |
avi23 | 5:34855f712350 | 836 | //Cycles through all the small invaders. If they're not already dead clear them |
avi23 | 2:d34c95990605 | 837 | void ClearSmallInvaders() |
avi23 | 2:d34c95990605 | 838 | { |
avi23 | 5:34855f712350 | 839 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 840 | if (small_invader[i].status) { |
avi23 | 5:34855f712350 | 841 | ClearSingleSmallInvader(i); |
avi23 | 5:34855f712350 | 842 | } |
avi23 | 5:34855f712350 | 843 | } |
avi23 | 5:34855f712350 | 844 | } |
avi23 | 5:34855f712350 | 845 | |
avi23 | 5:34855f712350 | 846 | //Cycles through the the screen invader bitmap and sets the pixels in the buffer to 0 |
avi23 | 5:34855f712350 | 847 | void ClearSingleSmallInvader(int invader_no) |
avi23 | 5:34855f712350 | 848 | { |
avi23 | 5:34855f712350 | 849 | for (int col = 0; col < 8; ++col) { |
avi23 | 5:34855f712350 | 850 | for (int row = 0; row < 6; ++row) { |
avi23 | 5:34855f712350 | 851 | if (invaders_in_state2) { |
avi23 | 5:34855f712350 | 852 | if (small_invader_bitmap_1[row][col]) { |
avi23 | 5:34855f712350 | 853 | screen_buffer[small_invader[invader_no].x_pos + col][small_invader[invader_no].y_pos + row] = empty_pixel; |
avi23 | 2:d34c95990605 | 854 | } |
avi23 | 5:34855f712350 | 855 | } else { |
avi23 | 5:34855f712350 | 856 | if (small_invader_bitmap_2[row][col]) { |
avi23 | 5:34855f712350 | 857 | screen_buffer[small_invader[invader_no].x_pos + col][small_invader[invader_no].y_pos + row] = empty_pixel; |
avi23 | 2:d34c95990605 | 858 | } |
avi23 | 2:d34c95990605 | 859 | } |
avi23 | 2:d34c95990605 | 860 | } |
avi23 | 2:d34c95990605 | 861 | } |
avi23 | 5:34855f712350 | 862 | |
avi23 | 5:34855f712350 | 863 | small_invader[invader_no].status = (small_invader[invader_no].status == dying) ? dead : alive; |
avi23 | 2:d34c95990605 | 864 | } |
avi23 | 2:d34c95990605 | 865 | |
avi23 | 0:427469992efe | 866 | void DrawSmallInvaders() |
avi23 | 0:427469992efe | 867 | { |
avi23 | 5:34855f712350 | 868 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 869 | if (small_invader[i].status == alive) { |
avi23 | 5:34855f712350 | 870 | DrawSingleSmallInvader(i); |
avi23 | 5:34855f712350 | 871 | } |
avi23 | 5:34855f712350 | 872 | } |
avi23 | 5:34855f712350 | 873 | } |
avi23 | 5:34855f712350 | 874 | |
avi23 | 5:34855f712350 | 875 | //Cycles through the the screen invader bitmap and sets the pixels in the buffer |
avi23 | 5:34855f712350 | 876 | void DrawSingleSmallInvader(int invader_no) |
avi23 | 5:34855f712350 | 877 | { |
avi23 | 5:34855f712350 | 878 | for (int col = 0; col < 8; ++col) { |
avi23 | 5:34855f712350 | 879 | for (int row = 0; row < 6; ++row) { |
avi23 | 2:d34c95990605 | 880 | if (invaders_in_state2) { |
avi23 | 5:34855f712350 | 881 | if (small_invader_bitmap_1[row][col]) { |
avi23 | 5:34855f712350 | 882 | 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 | 883 | } |
avi23 | 0:427469992efe | 884 | } else { |
avi23 | 5:34855f712350 | 885 | if (small_invader_bitmap_2[row][col]) { |
avi23 | 5:34855f712350 | 886 | 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 | 887 | } |
avi23 | 0:427469992efe | 888 | } |
avi23 | 0:427469992efe | 889 | } |
avi23 | 0:427469992efe | 890 | } |
avi23 | 1:b300d052d549 | 891 | } |
avi23 | 1:b300d052d549 | 892 | |
avi23 | 1:b300d052d549 | 893 | //Sets the position and aliveness of the medium invaders |
avi23 | 1:b300d052d549 | 894 | void InitMediumInvaders() |
avi23 | 1:b300d052d549 | 895 | { |
avi23 | 5:34855f712350 | 896 | for (int i = 0; i < 5; ++i) { |
avi23 | 1:b300d052d549 | 897 | medium_invader[i].x_pos = 1 + (i*13); |
avi23 | 2:d34c95990605 | 898 | medium_invader[i].y_pos = 8; |
avi23 | 5:34855f712350 | 899 | medium_invader[i].status = alive; |
avi23 | 1:b300d052d549 | 900 | } |
avi23 | 1:b300d052d549 | 901 | } |
avi23 | 1:b300d052d549 | 902 | |
avi23 | 2:d34c95990605 | 903 | void ClearMediumInvaders() |
avi23 | 2:d34c95990605 | 904 | { |
avi23 | 5:34855f712350 | 905 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 906 | if (medium_invader[i].status) { |
avi23 | 5:34855f712350 | 907 | ClearSingleMediumInvader(i); |
avi23 | 2:d34c95990605 | 908 | } |
avi23 | 2:d34c95990605 | 909 | } |
avi23 | 2:d34c95990605 | 910 | } |
avi23 | 2:d34c95990605 | 911 | |
avi23 | 5:34855f712350 | 912 | void ClearSingleMediumInvader(int invader_no) |
avi23 | 5:34855f712350 | 913 | { |
avi23 | 5:34855f712350 | 914 | for (int col = 0; col < 10; ++col) { |
avi23 | 5:34855f712350 | 915 | for (int row = 0; row < 6; ++row) { |
avi23 | 5:34855f712350 | 916 | if (invaders_in_state2) { |
avi23 | 5:34855f712350 | 917 | if (medium_invader_bitmap_1[row][col]) { |
avi23 | 5:34855f712350 | 918 | screen_buffer[medium_invader[invader_no].x_pos + col][medium_invader[invader_no].y_pos + row] = empty_pixel; |
avi23 | 5:34855f712350 | 919 | } |
avi23 | 5:34855f712350 | 920 | } else { |
avi23 | 5:34855f712350 | 921 | if (medium_invader_bitmap_2[row][col]) { |
avi23 | 5:34855f712350 | 922 | screen_buffer[medium_invader[invader_no].x_pos + col][medium_invader[invader_no].y_pos + row] = empty_pixel; |
avi23 | 5:34855f712350 | 923 | } |
avi23 | 5:34855f712350 | 924 | } |
avi23 | 5:34855f712350 | 925 | } |
avi23 | 5:34855f712350 | 926 | } |
avi23 | 5:34855f712350 | 927 | |
avi23 | 5:34855f712350 | 928 | medium_invader[invader_no].status = (medium_invader[invader_no].status == dying) ? dead : alive; |
avi23 | 5:34855f712350 | 929 | } |
avi23 | 5:34855f712350 | 930 | |
avi23 | 1:b300d052d549 | 931 | void DrawMediumInvaders() |
avi23 | 1:b300d052d549 | 932 | { |
avi23 | 5:34855f712350 | 933 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 934 | if (medium_invader[i].status == alive) { |
avi23 | 5:34855f712350 | 935 | DrawSingleMediumInvader(i); |
avi23 | 5:34855f712350 | 936 | } |
avi23 | 5:34855f712350 | 937 | } |
avi23 | 5:34855f712350 | 938 | } |
avi23 | 5:34855f712350 | 939 | |
avi23 | 5:34855f712350 | 940 | void DrawSingleMediumInvader(int invader_no) |
avi23 | 5:34855f712350 | 941 | { |
avi23 | 5:34855f712350 | 942 | for (int col = 0; col < 10; ++col) { |
avi23 | 5:34855f712350 | 943 | for (int row = 0; row < 6; ++row) { |
avi23 | 2:d34c95990605 | 944 | if (invaders_in_state2) { |
avi23 | 5:34855f712350 | 945 | if (medium_invader_bitmap_1[row][col]) { |
avi23 | 5:34855f712350 | 946 | 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 | 947 | } |
avi23 | 1:b300d052d549 | 948 | } else { |
avi23 | 5:34855f712350 | 949 | if (medium_invader_bitmap_2[row][col]) { |
avi23 | 5:34855f712350 | 950 | 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 | 951 | } |
avi23 | 1:b300d052d549 | 952 | } |
avi23 | 1:b300d052d549 | 953 | } |
avi23 | 1:b300d052d549 | 954 | } |
avi23 | 1:b300d052d549 | 955 | } |
avi23 | 1:b300d052d549 | 956 | |
avi23 | 1:b300d052d549 | 957 | //Sets the position and aliveness of the large invaders |
avi23 | 1:b300d052d549 | 958 | void InitLargeInvaders() |
avi23 | 1:b300d052d549 | 959 | { |
avi23 | 5:34855f712350 | 960 | for (int i = 0; i < 5; ++i) { |
avi23 | 1:b300d052d549 | 961 | large_invader[i].x_pos = 0 + (i*13); |
avi23 | 2:d34c95990605 | 962 | large_invader[i].y_pos = 15; |
avi23 | 5:34855f712350 | 963 | large_invader[i].status = alive; |
avi23 | 5:34855f712350 | 964 | } |
avi23 | 5:34855f712350 | 965 | } |
avi23 | 5:34855f712350 | 966 | |
avi23 | 5:34855f712350 | 967 | void ClearLargeInvaders() |
avi23 | 5:34855f712350 | 968 | { |
avi23 | 5:34855f712350 | 969 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 970 | if (large_invader[i].status) { |
avi23 | 5:34855f712350 | 971 | ClearSingleLargeInvader(i); |
avi23 | 5:34855f712350 | 972 | } |
avi23 | 1:b300d052d549 | 973 | } |
avi23 | 1:b300d052d549 | 974 | } |
avi23 | 1:b300d052d549 | 975 | |
avi23 | 5:34855f712350 | 976 | //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 | 977 | void ClearSingleLargeInvader(int invader_no) |
avi23 | 2:d34c95990605 | 978 | { |
avi23 | 5:34855f712350 | 979 | for (int col = 0; col < 12; ++col) { |
avi23 | 5:34855f712350 | 980 | for (int row = 0; row < 6; ++row) { |
avi23 | 5:34855f712350 | 981 | if (invaders_in_state2) { |
avi23 | 5:34855f712350 | 982 | if (large_invader_bitmap_1[row][col]) { |
avi23 | 5:34855f712350 | 983 | screen_buffer[large_invader[invader_no].x_pos + col][large_invader[invader_no].y_pos + row] = empty_pixel; |
avi23 | 5:34855f712350 | 984 | } |
avi23 | 5:34855f712350 | 985 | } else { |
avi23 | 5:34855f712350 | 986 | if (large_invader_bitmap_2[row][col]) { |
avi23 | 5:34855f712350 | 987 | screen_buffer[large_invader[invader_no].x_pos + col][large_invader[invader_no].y_pos + row] = empty_pixel; |
avi23 | 2:d34c95990605 | 988 | } |
avi23 | 2:d34c95990605 | 989 | } |
avi23 | 5:34855f712350 | 990 | } |
avi23 | 5:34855f712350 | 991 | } |
avi23 | 5:34855f712350 | 992 | |
avi23 | 5:34855f712350 | 993 | large_invader[invader_no].status = (large_invader[invader_no].status == dying) ? dead : alive; |
avi23 | 5:34855f712350 | 994 | } |
avi23 | 5:34855f712350 | 995 | |
avi23 | 5:34855f712350 | 996 | void DrawLargeInvaders() |
avi23 | 5:34855f712350 | 997 | { |
avi23 | 5:34855f712350 | 998 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 999 | if (large_invader[i].status == alive) { |
avi23 | 5:34855f712350 | 1000 | DrawSingleLargeInvader(i); |
avi23 | 5:34855f712350 | 1001 | } |
avi23 | 5:34855f712350 | 1002 | } |
avi23 | 5:34855f712350 | 1003 | } |
avi23 | 5:34855f712350 | 1004 | |
avi23 | 5:34855f712350 | 1005 | void DrawSingleLargeInvader(int invader_no) |
avi23 | 5:34855f712350 | 1006 | { |
avi23 | 5:34855f712350 | 1007 | for (int col = 0; col < 12; ++col) { |
avi23 | 5:34855f712350 | 1008 | for (int row = 0; row < 6; ++row) { |
avi23 | 5:34855f712350 | 1009 | if (invaders_in_state2) { |
avi23 | 5:34855f712350 | 1010 | if (large_invader_bitmap_1[row][col]) { |
avi23 | 5:34855f712350 | 1011 | 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 | 1012 | } |
avi23 | 5:34855f712350 | 1013 | } else { |
avi23 | 5:34855f712350 | 1014 | if (large_invader_bitmap_2[row][col]) { |
avi23 | 5:34855f712350 | 1015 | 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 | 1016 | } |
avi23 | 2:d34c95990605 | 1017 | } |
avi23 | 2:d34c95990605 | 1018 | } |
avi23 | 2:d34c95990605 | 1019 | } |
avi23 | 2:d34c95990605 | 1020 | } |
avi23 | 2:d34c95990605 | 1021 | |
avi23 | 2:d34c95990605 | 1022 | void InitBarriers() |
avi23 | 2:d34c95990605 | 1023 | { |
avi23 | 5:34855f712350 | 1024 | for (int i = 0; i < 3; ++i) { |
avi23 | 2:d34c95990605 | 1025 | barrier[i].x_pos = 10 + (i*25); |
avi23 | 2:d34c95990605 | 1026 | barrier[i].y_pos = 33; |
avi23 | 2:d34c95990605 | 1027 | //Copies the bitmap into the structs |
avi23 | 2:d34c95990605 | 1028 | memcpy(barrier[i].before_bitmap, barrier_bitmap, sizeof(barrier_bitmap)); |
avi23 | 2:d34c95990605 | 1029 | memcpy(barrier[i].after_bitmap, barrier_bitmap, sizeof(barrier_bitmap)); |
avi23 | 2:d34c95990605 | 1030 | } |
avi23 | 2:d34c95990605 | 1031 | } |
avi23 | 2:d34c95990605 | 1032 | |
avi23 | 2:d34c95990605 | 1033 | void DrawBarriers() |
avi23 | 2:d34c95990605 | 1034 | { |
avi23 | 2:d34c95990605 | 1035 | //Clears the barrier and redraws it with damage applied |
avi23 | 5:34855f712350 | 1036 | for (int i = 0; i < 3; ++i) { |
avi23 | 5:34855f712350 | 1037 | for (int col = 0; col < 14; ++col) { |
avi23 | 5:34855f712350 | 1038 | for (int row = 0; row < 8; ++row) { |
avi23 | 2:d34c95990605 | 1039 | if (barrier[i].before_bitmap[row][col]) { |
avi23 | 5:34855f712350 | 1040 | screen_buffer[barrier[i].x_pos + col][barrier[i].y_pos + row] = empty_pixel; |
avi23 | 2:d34c95990605 | 1041 | } |
avi23 | 2:d34c95990605 | 1042 | if (barrier[i].after_bitmap[row][col]) { |
avi23 | 5:34855f712350 | 1043 | screen_buffer[barrier[i].x_pos + col][barrier[i].y_pos + row] = first_barrier_pixel + i; |
avi23 | 2:d34c95990605 | 1044 | } |
avi23 | 2:d34c95990605 | 1045 | } |
avi23 | 2:d34c95990605 | 1046 | } |
avi23 | 2:d34c95990605 | 1047 | //Copies the after array to the before array |
avi23 | 2:d34c95990605 | 1048 | memcpy(barrier[i].before_bitmap, barrier[i].after_bitmap, sizeof(barrier[i].after_bitmap)); |
avi23 | 2:d34c95990605 | 1049 | } |
avi23 | 2:d34c95990605 | 1050 | } |
avi23 | 2:d34c95990605 | 1051 | |
avi23 | 5:34855f712350 | 1052 | void MoveInvaderXPositions() |
avi23 | 2:d34c95990605 | 1053 | { |
avi23 | 5:34855f712350 | 1054 | //Checks the left limit |
avi23 | 5:34855f712350 | 1055 | int left_invader_limit = CalculateInvaderLeftLimit(); |
avi23 | 5:34855f712350 | 1056 | |
avi23 | 5:34855f712350 | 1057 | //Checking the right limit |
avi23 | 5:34855f712350 | 1058 | int right_invader_limit = CalculateInvaderRightLimit(); |
avi23 | 5:34855f712350 | 1059 | |
avi23 | 5:34855f712350 | 1060 | //End of block |
avi23 | 2:d34c95990605 | 1061 | if (invader_direction == RIGHT) { |
avi23 | 5:34855f712350 | 1062 | MoveInvadersRight(right_invader_limit); |
avi23 | 5:34855f712350 | 1063 | } else { |
avi23 | 2:d34c95990605 | 1064 | //Checks the first large invader to see if it can travel anymore |
avi23 | 5:34855f712350 | 1065 | MoveInvadersLeft(left_invader_limit); |
avi23 | 5:34855f712350 | 1066 | } |
avi23 | 5:34855f712350 | 1067 | } |
avi23 | 5:34855f712350 | 1068 | |
avi23 | 5:34855f712350 | 1069 | int CalculateInvaderLeftLimit() |
avi23 | 5:34855f712350 | 1070 | { |
avi23 | 5:34855f712350 | 1071 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 1072 | if (small_invader[i].status == alive || medium_invader[i].status == alive || large_invader[i].status == alive) { |
avi23 | 5:34855f712350 | 1073 | return i; |
avi23 | 5:34855f712350 | 1074 | } |
avi23 | 5:34855f712350 | 1075 | } |
avi23 | 5:34855f712350 | 1076 | |
avi23 | 5:34855f712350 | 1077 | //Sort gameover out stuff after |
avi23 | 5:34855f712350 | 1078 | return 4; |
avi23 | 5:34855f712350 | 1079 | } |
avi23 | 5:34855f712350 | 1080 | |
avi23 | 5:34855f712350 | 1081 | int CalculateInvaderRightLimit() |
avi23 | 5:34855f712350 | 1082 | { |
avi23 | 5:34855f712350 | 1083 | for (int i = 4; i >= 0; --i) { |
avi23 | 5:34855f712350 | 1084 | if (small_invader[i].status == alive || medium_invader[i].status == alive || large_invader[i].status == alive) { |
avi23 | 5:34855f712350 | 1085 | return i; |
avi23 | 5:34855f712350 | 1086 | } |
avi23 | 5:34855f712350 | 1087 | } |
avi23 | 5:34855f712350 | 1088 | |
avi23 | 5:34855f712350 | 1089 | //Sort gameover stuff |
avi23 | 5:34855f712350 | 1090 | return 0; |
avi23 | 5:34855f712350 | 1091 | } |
avi23 | 5:34855f712350 | 1092 | |
avi23 | 5:34855f712350 | 1093 | void MoveInvadersLeft(int limit) |
avi23 | 5:34855f712350 | 1094 | { |
avi23 | 5:34855f712350 | 1095 | //Checks the first large invader to see if it can travel anymore |
avi23 | 5:34855f712350 | 1096 | if (large_invader[limit].x_pos > 1) { |
avi23 | 5:34855f712350 | 1097 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 1098 | small_invader[i].x_pos -= 2; |
avi23 | 5:34855f712350 | 1099 | medium_invader[i].x_pos -= 2; |
avi23 | 5:34855f712350 | 1100 | large_invader[i].x_pos -= 2; |
avi23 | 2:d34c95990605 | 1101 | } |
avi23 | 2:d34c95990605 | 1102 | } else { |
avi23 | 5:34855f712350 | 1103 | //Shifts the Invaders down and passes in the new direction |
avi23 | 5:34855f712350 | 1104 | MoveInvaderYPositions(RIGHT); |
avi23 | 2:d34c95990605 | 1105 | } |
avi23 | 2:d34c95990605 | 1106 | } |
avi23 | 2:d34c95990605 | 1107 | |
avi23 | 5:34855f712350 | 1108 | void MoveInvadersRight(int limit) |
avi23 | 2:d34c95990605 | 1109 | { |
avi23 | 5:34855f712350 | 1110 | //Checks the first large invader to see if it can travel anymore |
avi23 | 5:34855f712350 | 1111 | if (large_invader[limit].x_pos < 71) { |
avi23 | 5:34855f712350 | 1112 | for (int i = 0; i < 5; ++i) { |
avi23 | 5:34855f712350 | 1113 | small_invader[i].x_pos += 2; |
avi23 | 5:34855f712350 | 1114 | medium_invader[i].x_pos += 2; |
avi23 | 5:34855f712350 | 1115 | large_invader[i].x_pos += 2; |
avi23 | 5:34855f712350 | 1116 | } |
avi23 | 2:d34c95990605 | 1117 | } else { |
avi23 | 5:34855f712350 | 1118 | //Shifts the Invaders down and passes in the new direction |
avi23 | 5:34855f712350 | 1119 | MoveInvaderYPositions(LEFT); |
avi23 | 2:d34c95990605 | 1120 | } |
avi23 | 5:34855f712350 | 1121 | } |
avi23 | 5:34855f712350 | 1122 | |
avi23 | 5:34855f712350 | 1123 | void MoveInvaderYPositions(bool new_direction) |
avi23 | 5:34855f712350 | 1124 | { |
avi23 | 5:34855f712350 | 1125 | //Finds the invaders lower limit |
avi23 | 5:34855f712350 | 1126 | Invader lowest_invader = CalculateInvaderYLimit(); |
avi23 | 5:34855f712350 | 1127 | |
avi23 | 5:34855f712350 | 1128 | //When moving down lowest_invader should not equal none |
avi23 | 5:34855f712350 | 1129 | if (lowest_invader == none) { |
avi23 | 5:34855f712350 | 1130 | error(); |
avi23 | 5:34855f712350 | 1131 | } |
avi23 | 5:34855f712350 | 1132 | |
avi23 | 2:d34c95990605 | 1133 | //If an invader touches the bottom the game ends, otherwise the invaders descend |
avi23 | 5:34855f712350 | 1134 | if (small_invader[0].y_pos < 33 - (7*lowest_invader)) { |
avi23 | 5:34855f712350 | 1135 | for (int i = 0; i < 5; ++i) { |
avi23 | 2:d34c95990605 | 1136 | small_invader[i].y_pos += 3; |
avi23 | 2:d34c95990605 | 1137 | medium_invader[i].y_pos += 3; |
avi23 | 2:d34c95990605 | 1138 | large_invader[i].y_pos += 3; |
avi23 | 2:d34c95990605 | 1139 | } |
avi23 | 5:34855f712350 | 1140 | invader_direction = new_direction; |
avi23 | 5:34855f712350 | 1141 | } else { |
avi23 | 5:34855f712350 | 1142 | number_of_lives = 0; |
avi23 | 5:34855f712350 | 1143 | } |
avi23 | 5:34855f712350 | 1144 | } |
avi23 | 5:34855f712350 | 1145 | |
avi23 | 5:34855f712350 | 1146 | Invader CalculateInvaderYLimit() |
avi23 | 5:34855f712350 | 1147 | { |
avi23 | 5:34855f712350 | 1148 | //Checks to see which row of invaders are still alive to work out maximum y positions |
avi23 | 5:34855f712350 | 1149 | 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 | 1150 | return large; |
avi23 | 5:34855f712350 | 1151 | } 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 | 1152 | return medium; |
avi23 | 2:d34c95990605 | 1153 | } else { |
avi23 | 5:34855f712350 | 1154 | return small; |
avi23 | 2:d34c95990605 | 1155 | } |
avi23 | 5:34855f712350 | 1156 | } |
avi23 | 2:d34c95990605 | 1157 | |
avi23 | 5:34855f712350 | 1158 | //Queries the invaders on their status and returns the type of invader which is alive |
avi23 | 5:34855f712350 | 1159 | Invader LowestInvaderInColumn(int column) |
avi23 | 5:34855f712350 | 1160 | { |
avi23 | 5:34855f712350 | 1161 | if (large_invader[column].status == alive) { |
avi23 | 5:34855f712350 | 1162 | return large; |
avi23 | 5:34855f712350 | 1163 | } else if (medium_invader[column].status == alive) { |
avi23 | 5:34855f712350 | 1164 | return medium; |
avi23 | 5:34855f712350 | 1165 | } else if (small_invader[column].status == alive) { |
avi23 | 5:34855f712350 | 1166 | return small; |
avi23 | 5:34855f712350 | 1167 | } else { |
avi23 | 5:34855f712350 | 1168 | return none; |
avi23 | 5:34855f712350 | 1169 | } |
avi23 | 2:d34c95990605 | 1170 | } |
avi23 | 2:d34c95990605 | 1171 | |
avi23 | 2:d34c95990605 | 1172 | /* |
avi23 | 2:d34c95990605 | 1173 | void InitUFO() |
avi23 | 2:d34c95990605 | 1174 | { |
avi23 | 2:d34c95990605 | 1175 | |
avi23 | 2:d34c95990605 | 1176 | } |
avi23 | 2:d34c95990605 | 1177 | */ |
avi23 | 2:d34c95990605 | 1178 | |
avi23 | 2:d34c95990605 | 1179 | void DrawUFO() |
avi23 | 2:d34c95990605 | 1180 | { |
avi23 | 2:d34c95990605 | 1181 | //Draws the UFO |
avi23 | 2:d34c95990605 | 1182 | int x_pos = 20; |
avi23 | 2:d34c95990605 | 1183 | int y_pos = 25; |
avi23 | 5:34855f712350 | 1184 | for (int col = 0; col < col_no; ++col) { |
avi23 | 5:34855f712350 | 1185 | for (int row = 0; row < row_no; ++row) { |
avi23 | 2:d34c95990605 | 1186 | if(ufo_bitmap[row][col]) { |
avi23 | 5:34855f712350 | 1187 | screen_buffer[x_pos + col][y_pos + row] = ufo_pixel; |
avi23 | 2:d34c95990605 | 1188 | } |
avi23 | 2:d34c95990605 | 1189 | } |
avi23 | 2:d34c95990605 | 1190 | } |
avi23 | 5:34855f712350 | 1191 | } |
avi23 | 5:34855f712350 | 1192 | |
avi23 | 5:34855f712350 | 1193 | void FireCannonMissile() |
avi23 | 5:34855f712350 | 1194 | { |
avi23 | 5:34855f712350 | 1195 | cannon_missile_on_screen = true; |
avi23 | 5:34855f712350 | 1196 | |
avi23 | 5:34855f712350 | 1197 | //Add 4 to cannon x_pos to get shot x_pos |
avi23 | 5:34855f712350 | 1198 | cannon_missile_x_pos = cannon_xpos + 4; |
avi23 | 5:34855f712350 | 1199 | cannon_missile_y_pos = 40; |
avi23 | 5:34855f712350 | 1200 | move_cannon_missile.attach(&move_cannon_missile_isr, 0.05); |
avi23 | 5:34855f712350 | 1201 | } |
avi23 | 5:34855f712350 | 1202 | |
avi23 | 5:34855f712350 | 1203 | void MoveCannonMissile() |
avi23 | 5:34855f712350 | 1204 | { |
avi23 | 5:34855f712350 | 1205 | //Checks bullet will not go beyond the bounds of the screen buffer |
avi23 | 5:34855f712350 | 1206 | if (cannon_missile_y_pos > -1) { |
avi23 | 5:34855f712350 | 1207 | //Loops throught the shot bitmap and clears the pixels in the screen buffer |
avi23 | 5:34855f712350 | 1208 | for (int row = 0; row < 4; ++row) { |
avi23 | 5:34855f712350 | 1209 | //Clears the position where the bullet was |
avi23 | 5:34855f712350 | 1210 | screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] = empty_pixel; |
avi23 | 5:34855f712350 | 1211 | } |
avi23 | 5:34855f712350 | 1212 | |
avi23 | 5:34855f712350 | 1213 | //Increments the shot going up the screen |
avi23 | 5:34855f712350 | 1214 | --cannon_missile_y_pos; |
avi23 | 5:34855f712350 | 1215 | |
avi23 | 5:34855f712350 | 1216 | //Checks to see if the shot will hit anything |
avi23 | 5:34855f712350 | 1217 | CollisionDetectionCannonMissile(); |
avi23 | 5:34855f712350 | 1218 | } else { |
avi23 | 5:34855f712350 | 1219 | //Loops throught the shot bitmap and clears the pixels in the screen buffer |
avi23 | 5:34855f712350 | 1220 | for (int row = 1; row < 4; ++row) { |
avi23 | 5:34855f712350 | 1221 | //Clears the position where the bullet was |
avi23 | 5:34855f712350 | 1222 | screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] = empty_pixel; |
avi23 | 5:34855f712350 | 1223 | } |
avi23 | 5:34855f712350 | 1224 | |
avi23 | 5:34855f712350 | 1225 | cannon_missile_on_screen = false; |
avi23 | 5:34855f712350 | 1226 | move_cannon_missile.detach(); |
avi23 | 5:34855f712350 | 1227 | } |
avi23 | 5:34855f712350 | 1228 | } |
avi23 | 5:34855f712350 | 1229 | |
avi23 | 5:34855f712350 | 1230 | void MoveInvaderNormalMissile(int missile_no) |
avi23 | 5:34855f712350 | 1231 | { |
avi23 | 5:34855f712350 | 1232 | //Checks missile will not exceed screen buffer |
avi23 | 5:34855f712350 | 1233 | if (invader_normal_missile[missile_no].y_pos < 44) { |
avi23 | 5:34855f712350 | 1234 | //Loops through the bitmap and clears the missile from the screen buffer |
avi23 | 5:34855f712350 | 1235 | for (int col = 0; col < 3; ++col) { |
avi23 | 5:34855f712350 | 1236 | for (int row = 0; row < 4; ++row) { |
avi23 | 5:34855f712350 | 1237 | if (invader_normal_missile_bitmap[row][col]) { |
avi23 | 5:34855f712350 | 1238 | screen_buffer[invader_normal_missile[missile_no].x_pos + col][invader_normal_missile[missile_no].y_pos + row] = empty_pixel; |
avi23 | 5:34855f712350 | 1239 | } |
avi23 | 5:34855f712350 | 1240 | } |
avi23 | 5:34855f712350 | 1241 | } |
avi23 | 5:34855f712350 | 1242 | |
avi23 | 5:34855f712350 | 1243 | //Increments the position of the missile |
avi23 | 5:34855f712350 | 1244 | ++invader_normal_missile[missile_no].y_pos; |
avi23 | 5:34855f712350 | 1245 | |
avi23 | 5:34855f712350 | 1246 | //Collision detection |
avi23 | 5:34855f712350 | 1247 | CollisionDetectionInvaderNormalMissile(missile_no); |
avi23 | 5:34855f712350 | 1248 | |
avi23 | 5:34855f712350 | 1249 | } else { |
avi23 | 5:34855f712350 | 1250 | //Loops through the bitmap and clears the pixels still on the screen |
avi23 | 5:34855f712350 | 1251 | for (int col = 0; col < 3; ++col) { |
avi23 | 5:34855f712350 | 1252 | for (int row = 0; row < 4; ++row) { |
avi23 | 5:34855f712350 | 1253 | if (invader_normal_missile_bitmap[row][col]) { |
avi23 | 5:34855f712350 | 1254 | screen_buffer[invader_normal_missile[missile_no].x_pos + col][invader_normal_missile[missile_no].y_pos + row] = empty_pixel; |
avi23 | 5:34855f712350 | 1255 | } |
avi23 | 5:34855f712350 | 1256 | } |
avi23 | 5:34855f712350 | 1257 | } |
avi23 | 5:34855f712350 | 1258 | |
avi23 | 5:34855f712350 | 1259 | invader_normal_missile[missile_no].fired = false; |
avi23 | 5:34855f712350 | 1260 | move_invader_normal_missile[missile_no].detach(); |
avi23 | 5:34855f712350 | 1261 | } |
avi23 | 5:34855f712350 | 1262 | } |
avi23 | 5:34855f712350 | 1263 | |
avi23 | 5:34855f712350 | 1264 | //Checks to see what the shot hits. If it hits nothing the shot gets pushed to the screen buffer |
avi23 | 5:34855f712350 | 1265 | void CollisionDetectionCannonMissile() |
avi23 | 5:34855f712350 | 1266 | { |
avi23 | 5:34855f712350 | 1267 | for (int row = 0; row < 4; ++row) { |
avi23 | 5:34855f712350 | 1268 | int object_no; |
avi23 | 5:34855f712350 | 1269 | if (screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] >= first_small_invader_pixel && screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] < (first_small_invader_pixel + 5)) { //Collides with a small invader |
avi23 | 5:34855f712350 | 1270 | object_no = CannonMissileHitInvader(first_small_invader_pixel, row, small_invader); |
avi23 | 5:34855f712350 | 1271 | ClearSingleSmallInvader(object_no); |
avi23 | 5:34855f712350 | 1272 | score += 40; |
avi23 | 5:34855f712350 | 1273 | break; |
avi23 | 5:34855f712350 | 1274 | } else if (screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] >= first_medium_invader_pixel && screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] < (first_medium_invader_pixel + 5)) { //Collides with a medium invader |
avi23 | 5:34855f712350 | 1275 | object_no = CannonMissileHitInvader(first_medium_invader_pixel, row, medium_invader); |
avi23 | 5:34855f712350 | 1276 | ClearSingleMediumInvader(object_no); |
avi23 | 5:34855f712350 | 1277 | score += 20; |
avi23 | 5:34855f712350 | 1278 | break; |
avi23 | 5:34855f712350 | 1279 | } else if (screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] >= first_large_invader_pixel && screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] < (first_large_invader_pixel + 5)) { //Collides with a large invader |
avi23 | 5:34855f712350 | 1280 | object_no = CannonMissileHitInvader(first_large_invader_pixel, row, large_invader); |
avi23 | 5:34855f712350 | 1281 | ClearSingleLargeInvader(object_no); |
avi23 | 5:34855f712350 | 1282 | score += 10; |
avi23 | 5:34855f712350 | 1283 | break; |
avi23 | 5:34855f712350 | 1284 | } else if (screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] >= first_barrier_pixel && screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] < (first_barrier_pixel + 3)) { //Collides with a barrier |
avi23 | 5:34855f712350 | 1285 | CannonMissileHitBarrier(first_barrier_pixel, row); |
avi23 | 5:34855f712350 | 1286 | DrawBarriers(); |
avi23 | 5:34855f712350 | 1287 | break; |
avi23 | 5:34855f712350 | 1288 | } else if (screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] == ufo_pixel) { //Collides with a UFO |
avi23 | 5:34855f712350 | 1289 | pc.printf("UFO Hit\n"); |
avi23 | 5:34855f712350 | 1290 | cannon_missile_on_screen = false; |
avi23 | 5:34855f712350 | 1291 | move_cannon_missile.detach(); |
avi23 | 5:34855f712350 | 1292 | break; |
avi23 | 5:34855f712350 | 1293 | } else { |
avi23 | 5:34855f712350 | 1294 | screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] = cannon_missile_pixel; |
avi23 | 5:34855f712350 | 1295 | } |
avi23 | 5:34855f712350 | 1296 | } |
avi23 | 5:34855f712350 | 1297 | } |
avi23 | 5:34855f712350 | 1298 | |
avi23 | 5:34855f712350 | 1299 | //Checks the bottom centre point for a collision. If it doesn't push the bitmap to the screen buffer |
avi23 | 5:34855f712350 | 1300 | void CollisionDetectionInvaderNormalMissile(int missile_no) |
avi23 | 5:34855f712350 | 1301 | { |
avi23 | 5:34855f712350 | 1302 | //Invader missile coordinates shifted to match centre bottom of bitmap |
avi23 | 5:34855f712350 | 1303 | int relative_x_pos = invader_normal_missile[missile_no].x_pos + 1; |
avi23 | 5:34855f712350 | 1304 | int relative_y_pos = invader_normal_missile[missile_no].y_pos + 3; |
avi23 | 5:34855f712350 | 1305 | if (screen_buffer[relative_x_pos][relative_y_pos] == cannon_pixel) { |
avi23 | 5:34855f712350 | 1306 | //Decrements the number of lives, pauses the game for 2 seconds |
avi23 | 5:34855f712350 | 1307 | //Marks the cannon as hit |
avi23 | 5:34855f712350 | 1308 | g_cannon_hit_flag = true; |
avi23 | 5:34855f712350 | 1309 | //Detaches all tickers |
avi23 | 5:34855f712350 | 1310 | DetachTickers(); |
avi23 | 6:89d4a7f7588b | 1311 | //Creates a Timeout object on the stack with a period of 2 seconds to pause the game for 2 seconds |
avi23 | 6:89d4a7f7588b | 1312 | Timeout cannon_hit; |
avi23 | 5:34855f712350 | 1313 | cannon_hit.attach(&cannon_hit_isr, 2); |
avi23 | 5:34855f712350 | 1314 | while (g_cannon_hit_flag) { |
avi23 | 5:34855f712350 | 1315 | sleep(); |
avi23 | 5:34855f712350 | 1316 | } |
avi23 | 5:34855f712350 | 1317 | AttachTickers(); |
avi23 | 5:34855f712350 | 1318 | --number_of_lives; |
avi23 | 5:34855f712350 | 1319 | invader_normal_missile[missile_no].fired = false; |
avi23 | 5:34855f712350 | 1320 | move_invader_normal_missile[missile_no].detach(); |
avi23 | 5:34855f712350 | 1321 | } 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 | 5:34855f712350 | 1322 | //Finds barrier number |
avi23 | 5:34855f712350 | 1323 | InvaderNormalMissileHitBarrier(first_barrier_pixel, invader_normal_missile[missile_no]); |
avi23 | 5:34855f712350 | 1324 | invader_normal_missile[missile_no].fired = false; |
avi23 | 5:34855f712350 | 1325 | move_invader_normal_missile[missile_no].detach(); |
avi23 | 5:34855f712350 | 1326 | } else { |
avi23 | 5:34855f712350 | 1327 | for (int col = 0; col < 3; ++col) { |
avi23 | 5:34855f712350 | 1328 | for (int row = 0; row < 4; ++row) { |
avi23 | 5:34855f712350 | 1329 | if (invader_normal_missile_bitmap[row][col]) { |
avi23 | 5:34855f712350 | 1330 | screen_buffer[invader_normal_missile[missile_no].x_pos + col][invader_normal_missile[missile_no].y_pos + row] = invader_normal_missile_pixel; |
avi23 | 5:34855f712350 | 1331 | } |
avi23 | 5:34855f712350 | 1332 | } |
avi23 | 5:34855f712350 | 1333 | } |
avi23 | 5:34855f712350 | 1334 | } |
avi23 | 5:34855f712350 | 1335 | } |
avi23 | 5:34855f712350 | 1336 | |
avi23 | 5:34855f712350 | 1337 | //Finds the invader number the shot 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 | 1338 | int CannonMissileHitInvader(int first_pixel, int row, struct Invaders (&invader)[5]) |
avi23 | 5:34855f712350 | 1339 | { |
avi23 | 5:34855f712350 | 1340 | int invader_no = screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] - first_pixel; |
avi23 | 5:34855f712350 | 1341 | invader[invader_no].status = dying; |
avi23 | 5:34855f712350 | 1342 | cannon_missile_on_screen = false; |
avi23 | 5:34855f712350 | 1343 | --no_of_alive_invaders; |
avi23 | 5:34855f712350 | 1344 | move_cannon_missile.detach(); |
avi23 | 5:34855f712350 | 1345 | |
avi23 | 5:34855f712350 | 1346 | return invader_no; |
avi23 | 5:34855f712350 | 1347 | } |
avi23 | 5:34855f712350 | 1348 | |
avi23 | 5:34855f712350 | 1349 | //Calculates where to start drawing the damage bitmap over the barrier bitmap and performs the operation |
avi23 | 5:34855f712350 | 1350 | void CannonMissileHitBarrier(int first_pixel, int row) |
avi23 | 5:34855f712350 | 1351 | { |
avi23 | 5:34855f712350 | 1352 | int barrier_no = screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] - first_pixel; |
avi23 | 5:34855f712350 | 1353 | //Essentially inverse of barrier init |
avi23 | 5:34855f712350 | 1354 | int relative_x_pos = cannon_missile_x_pos - 10 - (barrier_no*25) - 1; |
avi23 | 5:34855f712350 | 1355 | int relative_y_pos = (cannon_missile_y_pos + row) - 33 - 1; //Don't know why it's -1 and not -2 |
avi23 | 5:34855f712350 | 1356 | //Loops through the damage bitmap and modifies the barrier's after bitmap |
avi23 | 5:34855f712350 | 1357 | for (int col = 0; col < 3; ++col) { |
avi23 | 5:34855f712350 | 1358 | for (int row_bit = 0; row_bit < 3; ++row_bit) { |
avi23 | 5:34855f712350 | 1359 | //Makes sure bitmap index does not go out of bounds. If it does go to the next iteration |
avi23 | 5:34855f712350 | 1360 | 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 | 1361 | 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 | 1362 | } |
avi23 | 5:34855f712350 | 1363 | } |
avi23 | 5:34855f712350 | 1364 | } |
avi23 | 5:34855f712350 | 1365 | cannon_missile_on_screen = false; |
avi23 | 5:34855f712350 | 1366 | move_cannon_missile.detach(); |
avi23 | 5:34855f712350 | 1367 | } |
avi23 | 5:34855f712350 | 1368 | |
avi23 | 5:34855f712350 | 1369 | //Calculates where to start drawing the damage bitmap over the barrier bitmap and performs the operation |
avi23 | 5:34855f712350 | 1370 | void InvaderNormalMissileHitBarrier(int first_pixel, const struct InvaderNormalMissiles (&missile)) |
avi23 | 5:34855f712350 | 1371 | { |
avi23 | 5:34855f712350 | 1372 | int barrier_no = screen_buffer[missile.x_pos + 1][missile.y_pos + 3] - first_pixel; |
avi23 | 5:34855f712350 | 1373 | //Essentially inverse of barrier init |
avi23 | 5:34855f712350 | 1374 | int relative_x_pos = (missile.x_pos + 1) - 10 - (barrier_no*25) - 1; |
avi23 | 5:34855f712350 | 1375 | int relative_y_pos = (missile.y_pos + 3) - 33; |
avi23 | 5:34855f712350 | 1376 | //Loops through the damage bitmap and modifies the barrier's after bitmap |
avi23 | 5:34855f712350 | 1377 | for (int col = 0; col < 3; ++col) { |
avi23 | 5:34855f712350 | 1378 | for (int row_bit = 0; row_bit < 2; ++row_bit) { |
avi23 | 5:34855f712350 | 1379 | //Makes sure bitmap index does not go out of bounds. If it does go to the next iteration |
avi23 | 5:34855f712350 | 1380 | 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 | 1381 | barrier[barrier_no].after_bitmap[relative_y_pos + row_bit][relative_x_pos + col] *= barrier_invader_normal_missile_damage_bitmap[row_bit][col]; |
avi23 | 5:34855f712350 | 1382 | } |
avi23 | 5:34855f712350 | 1383 | } |
avi23 | 5:34855f712350 | 1384 | } |
avi23 | 5:34855f712350 | 1385 | } |
avi23 | 5:34855f712350 | 1386 | |
avi23 | 5:34855f712350 | 1387 | void AttemptToFireInvaderNormalMissiles() |
avi23 | 5:34855f712350 | 1388 | { |
avi23 | 5:34855f712350 | 1389 | //Fires the normal missiles |
avi23 | 5:34855f712350 | 1390 | //Loops through the 2 allowed missiles and if they're not on the screen, randomly fire |
avi23 | 5:34855f712350 | 1391 | for (int i = 0; i < 2; ++i) { |
avi23 | 5:34855f712350 | 1392 | if (!invader_normal_missile[i].fired) { |
avi23 | 5:34855f712350 | 1393 | //If the random mumber is 1, fire a missile |
avi23 | 5:34855f712350 | 1394 | //Higher chance when there are less invaders on the screen, up to a 1/3 chance |
avi23 | 5:34855f712350 | 1395 | if ((rand() % (no_of_alive_invaders + 2)) == 1) { |
avi23 | 5:34855f712350 | 1396 | // if ((rand() % 5) == 1) { |
avi23 | 5:34855f712350 | 1397 | int fired_column; |
avi23 | 5:34855f712350 | 1398 | int loop_limit = 0; //Stops loop from never ending |
avi23 | 5:34855f712350 | 1399 | Invader missile_source; |
avi23 | 5:34855f712350 | 1400 | do { |
avi23 | 5:34855f712350 | 1401 | fired_column = rand() % 5; |
avi23 | 5:34855f712350 | 1402 | missile_source = LowestInvaderInColumn(fired_column); |
avi23 | 5:34855f712350 | 1403 | ++loop_limit; |
avi23 | 5:34855f712350 | 1404 | } while (missile_source == none && loop_limit < 10); |
avi23 | 5:34855f712350 | 1405 | |
avi23 | 5:34855f712350 | 1406 | //Finds the centre point of the chosen invader and fires the missile |
avi23 | 5:34855f712350 | 1407 | //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 | 1408 | if (missile_source == none) { |
avi23 | 5:34855f712350 | 1409 | continue; |
avi23 | 5:34855f712350 | 1410 | } else if (missile_source == large) { |
avi23 | 5:34855f712350 | 1411 | FireNormalInvaderMissile(i, missile_source, large_invader[fired_column]); |
avi23 | 5:34855f712350 | 1412 | } else if (missile_source == medium) { |
avi23 | 5:34855f712350 | 1413 | FireNormalInvaderMissile(i, missile_source, medium_invader[fired_column]); |
avi23 | 5:34855f712350 | 1414 | } else { |
avi23 | 5:34855f712350 | 1415 | FireNormalInvaderMissile(i, missile_source, small_invader[fired_column]); |
avi23 | 5:34855f712350 | 1416 | } |
avi23 | 5:34855f712350 | 1417 | } |
avi23 | 5:34855f712350 | 1418 | } |
avi23 | 5:34855f712350 | 1419 | } |
avi23 | 5:34855f712350 | 1420 | } |
avi23 | 5:34855f712350 | 1421 | |
avi23 | 5:34855f712350 | 1422 | //Pass by reference to re |
avi23 | 5:34855f712350 | 1423 | void FireNormalInvaderMissile(int missile_no, Invader source, const struct Invaders (&invader)) |
avi23 | 5:34855f712350 | 1424 | { |
avi23 | 5:34855f712350 | 1425 | //Finds the centre point of the chosen invader and fires the missile |
avi23 | 5:34855f712350 | 1426 | //Enums are implicity converted to ints --> the middle x position of the invader found by offsetting the invader type by 3 |
avi23 | 5:34855f712350 | 1427 | invader_normal_missile[missile_no].x_pos = invader.x_pos + (3 + source); |
avi23 | 5:34855f712350 | 1428 | invader_normal_missile[missile_no].y_pos = invader.y_pos + 6; |
avi23 | 5:34855f712350 | 1429 | invader_normal_missile[missile_no].fired = true; |
avi23 | 5:34855f712350 | 1430 | |
avi23 | 5:34855f712350 | 1431 | //Uses a function pointer to attach the ticker |
avi23 | 5:34855f712350 | 1432 | move_invader_normal_missile[missile_no].attach(move_invader_normal_missile_isr[missile_no], 0.05); |
avi23 | 5:34855f712350 | 1433 | } |
avi23 | 5:34855f712350 | 1434 | |
avi23 | 5:34855f712350 | 1435 | void DetachTickers() |
avi23 | 5:34855f712350 | 1436 | { |
avi23 | 5:34855f712350 | 1437 | update_screen.detach(); |
avi23 | 5:34855f712350 | 1438 | move_enemies.detach(); |
avi23 | 5:34855f712350 | 1439 | if (cannon_missile_on_screen) { |
avi23 | 5:34855f712350 | 1440 | move_cannon_missile.detach(); |
avi23 | 5:34855f712350 | 1441 | } |
avi23 | 5:34855f712350 | 1442 | for (int i = 0; i < 2; ++i) { |
avi23 | 5:34855f712350 | 1443 | if (invader_normal_missile[i].fired) { |
avi23 | 5:34855f712350 | 1444 | move_invader_normal_missile[i].detach(); |
avi23 | 5:34855f712350 | 1445 | } |
avi23 | 5:34855f712350 | 1446 | } |
avi23 | 5:34855f712350 | 1447 | } |
avi23 | 5:34855f712350 | 1448 | |
avi23 | 5:34855f712350 | 1449 | void AttachTickers() |
avi23 | 5:34855f712350 | 1450 | { |
avi23 | 5:34855f712350 | 1451 | update_screen.attach(&update_screen_isr, 0.05); |
avi23 | 5:34855f712350 | 1452 | move_enemies.attach(&move_enemies_isr, ticker_period); |
avi23 | 5:34855f712350 | 1453 | |
avi23 | 5:34855f712350 | 1454 | if (cannon_missile_on_screen) { |
avi23 | 5:34855f712350 | 1455 | move_cannon_missile.attach(&move_cannon_missile_isr, 0.05); |
avi23 | 5:34855f712350 | 1456 | } |
avi23 | 5:34855f712350 | 1457 | for (int i = 0; i < 2; ++i) { |
avi23 | 5:34855f712350 | 1458 | if (invader_normal_missile[i].fired) { |
avi23 | 5:34855f712350 | 1459 | move_invader_normal_missile[i].attach(move_invader_normal_missile_isr[i], 0.05); |
avi23 | 5:34855f712350 | 1460 | } |
avi23 | 5:34855f712350 | 1461 | } |
avi23 | 6:89d4a7f7588b | 1462 | } |
avi23 | 6:89d4a7f7588b | 1463 | |
avi23 | 6:89d4a7f7588b | 1464 | void PauseScreen() |
avi23 | 6:89d4a7f7588b | 1465 | { |
avi23 | 6:89d4a7f7588b | 1466 | while (game_state == paused) { |
avi23 | 6:89d4a7f7588b | 1467 | //Prints the pause screen, score etc |
avi23 | 6:89d4a7f7588b | 1468 | PrintPauseScreen(); |
avi23 | 6:89d4a7f7588b | 1469 | |
avi23 | 6:89d4a7f7588b | 1470 | //Draws the cursor |
avi23 | 6:89d4a7f7588b | 1471 | 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 | 1472 | lcd.drawRect(74, cursor_y_pos, 2, 2, 1); //Draws the cursor |
avi23 | 6:89d4a7f7588b | 1473 | |
avi23 | 6:89d4a7f7588b | 1474 | if (g_move_joystick_flag) { |
avi23 | 6:89d4a7f7588b | 1475 | g_move_joystick_flag = false; |
avi23 | 6:89d4a7f7588b | 1476 | |
avi23 | 6:89d4a7f7588b | 1477 | //Moves the cursor to match the selected option, only if the joystick isn't centred |
avi23 | 6:89d4a7f7588b | 1478 | MoveCursor(fsm_paused); |
avi23 | 6:89d4a7f7588b | 1479 | } |
avi23 | 6:89d4a7f7588b | 1480 | |
avi23 | 6:89d4a7f7588b | 1481 | //If the button is pressed the selected option will appear on the screen |
avi23 | 6:89d4a7f7588b | 1482 | if (g_shoot_pressed_flag) { |
avi23 | 6:89d4a7f7588b | 1483 | g_shoot_pressed_flag = false; |
avi23 | 6:89d4a7f7588b | 1484 | game_state = fsm_paused[fsm_state].output; |
avi23 | 6:89d4a7f7588b | 1485 | } |
avi23 | 6:89d4a7f7588b | 1486 | |
avi23 | 6:89d4a7f7588b | 1487 | //Resets the joystick flag to false if pressed |
avi23 | 6:89d4a7f7588b | 1488 | if (joystick.get_button_flag()) { |
avi23 | 6:89d4a7f7588b | 1489 | joystick.set_button_flag(0); |
avi23 | 6:89d4a7f7588b | 1490 | } |
avi23 | 6:89d4a7f7588b | 1491 | |
avi23 | 6:89d4a7f7588b | 1492 | lcd.refresh(); |
avi23 | 6:89d4a7f7588b | 1493 | |
avi23 | 6:89d4a7f7588b | 1494 | sleep(); |
avi23 | 6:89d4a7f7588b | 1495 | } |
avi23 | 6:89d4a7f7588b | 1496 | } |
avi23 | 6:89d4a7f7588b | 1497 | |
avi23 | 6:89d4a7f7588b | 1498 | void PrintPauseScreen() |
avi23 | 6:89d4a7f7588b | 1499 | { |
avi23 | 6:89d4a7f7588b | 1500 | //Prints paused and a line underneath |
avi23 | 6:89d4a7f7588b | 1501 | lcd.printString("Paused", 24, 0); |
avi23 | 6:89d4a7f7588b | 1502 | //Displays the current score |
avi23 | 6:89d4a7f7588b | 1503 | char buffer[14]; |
avi23 | 6:89d4a7f7588b | 1504 | sprintf(buffer, "Score: %d", score); |
avi23 | 6:89d4a7f7588b | 1505 | lcd.printString(buffer, 0, 1); |
avi23 | 6:89d4a7f7588b | 1506 | //Displays the no of lives |
avi23 | 6:89d4a7f7588b | 1507 | sprintf(buffer, "Lives: %d", number_of_lives); |
avi23 | 6:89d4a7f7588b | 1508 | lcd.printString(buffer, 0, 2); |
avi23 | 6:89d4a7f7588b | 1509 | lcd.drawLine(0, 23, 83, 23, 2); |
avi23 | 6:89d4a7f7588b | 1510 | //Prints options on pause menu |
avi23 | 6:89d4a7f7588b | 1511 | lcd.printString("Resume", 5, 3); |
avi23 | 6:89d4a7f7588b | 1512 | lcd.printString("Save", 5, 4); |
avi23 | 6:89d4a7f7588b | 1513 | lcd.printString("Quit", 5, 5); |
avi23 | 6:89d4a7f7588b | 1514 | } |
avi23 | 6:89d4a7f7588b | 1515 | |
avi23 | 6:89d4a7f7588b | 1516 | void MoveCursor(const struct FSMMenus *fsm) |
avi23 | 6:89d4a7f7588b | 1517 | { |
avi23 | 6:89d4a7f7588b | 1518 | //If the joystick is is pushed down half way clear the cursor and set the next state |
avi23 | 6:89d4a7f7588b | 1519 | if (joystick.GetYValue() < 0.25f) { |
avi23 | 6:89d4a7f7588b | 1520 | //Clears the cursor |
avi23 | 6:89d4a7f7588b | 1521 | lcd.drawRect(74, cursor_y_pos, 2, 2, 2); |
avi23 | 6:89d4a7f7588b | 1522 | //Sets the new state |
avi23 | 6:89d4a7f7588b | 1523 | fsm_state = fsm[fsm_state].next_state[0]; |
avi23 | 6:89d4a7f7588b | 1524 | } else if (joystick.GetYValue() > 0.75f) { |
avi23 | 6:89d4a7f7588b | 1525 | //Clears the cursor |
avi23 | 6:89d4a7f7588b | 1526 | lcd.drawRect(74, cursor_y_pos, 2, 2, 2); |
avi23 | 6:89d4a7f7588b | 1527 | //Sets the new state |
avi23 | 6:89d4a7f7588b | 1528 | fsm_state = fsm[fsm_state].next_state[1]; |
avi23 | 6:89d4a7f7588b | 1529 | } |
avi23 | 0:427469992efe | 1530 | } |