Space Invaders - Embedded Systems Project 15/16 - Avinash Patel 200860407
Dependencies: Joystick N5110 SDFileSystem mbed
main.cpp
- Committer:
- avi23
- Date:
- 2016-03-31
- Revision:
- 4:a99953ef9e42
- Parent:
- 3:544b59d60ab8
- Child:
- 5:34855f712350
File content as of revision 4:a99953ef9e42:
/* Space Invaders - Avinash Patel 200860407 Week 19 - Set up joystick class Week 20 - Changed to space invaders as constrained too much by screen resolution - Core cannon is drawn and can move, enemies are visible and they switch between states every second Week 21 - Begun to set up barriers */ #include "mbed.h" #include "N5110.h" //Direction invaders are travelling #define LEFT 0 #define RIGHT 1 //Preprocessor for screen map /* #define EMPTY 0 #define CANNON 1 #define SMALL 2 #define MEDIUM 3 #define LARGE 4 #define BARRIER 5 #define UFO 6 #define CANNON_SHOT 7 */ //Joystick Class class Joystick { public: Joystick(PinName x_axis_pin, PinName y_axis_pin, PinName button_pin) { //Dynamically allocates the pins x_axis_ = new AnalogIn(x_axis_pin); y_axis_ = new AnalogIn(y_axis_pin); button_ = new InterruptIn(button_pin); } //Initalises the Joystick //Sets up the ISRs and grabs the offsets for each axis void init() { //Sets up the button ISR button_->mode(PullUp); button_->fall(this, &Joystick::button_isr); //Initalises the vairables and flags x_offset_ = 0; y_offset_ = 0; g_button_flag_ = 0; //Samples the joystick 5 times and takes an average to get the offset float x_sum = 0; float y_sum = 0; for (int i = 0; i < 5; i++) { x_sum += x_axis_->read(); y_sum += y_axis_->read(); } x_offset_ = 0.5f - x_sum/5.0f; y_offset_ = 0.5f - y_sum/5.0f; } //Take 5 readings and returns the average measurement, accounting for joystick offset x and y values float GetXValue() { float x_sum = 0; for (int i = 0; i < 5; i++) { x_sum += x_axis_->read(); } float x_value = x_sum/5.0f + x_offset_; //Caps the value for the POT between 0 and 1 if (x_value < 0.0f) { return 0; } else if (x_value > 1.0f) { return 1; } else { return x_value; } } float GetYValue() { float y_sum = 0; for (int i = 0; i < 5; i++) { y_sum += y_axis_->read(); } float y_value = y_sum/5.0f + y_offset_; //Caps the value for the POT between 0 and 1 if (y_value < 0.0f) { return 0; } else if (y_value > 1.0f) { return 1; } else { return y_value; } } //Getter and setters for flags int get_button_flag() { return g_button_flag_; } void set_button_flag(int value) { g_button_flag_ = value; } private: //Button ISR Method void button_isr() { g_button_flag_ = 1; } private: //Pin inputs AnalogIn* x_axis_; AnalogIn* y_axis_; InterruptIn* button_; //Stores X and Y offsets float x_offset_; float y_offset_; //Stores interrupt flags volatile int g_button_flag_; }; // K64F on-board LEDs DigitalOut r_led(LED_RED); DigitalOut g_led(LED_GREEN); DigitalOut b_led(LED_BLUE); // K64F on-board switches InterruptIn sw2(SW2); InterruptIn sw3(SW3); // UART connection for PC Serial pc(USBTX,USBRX); //Joystick Joystick joystick(PTB2, PTB3, PTB11); //Shoot button InterruptIn shoot_button(PTB18); //LCD object // VCC, SCE, RST, D/C, MOSI, SCLK, LED N5110 lcd (PTE26 , PTA0 , PTC4 , PTD0 , PTD2 , PTD1 , PTC3); Ticker update_screen; //Map holding pixel data of screen int screen_map[84][48]; const int empty_pixel = 0; const int cannon_pixel = 1; const int first_barrier_pixel = 2; const int first_large_invader_pixel = 5; const int first_medium_invader_pixel = 10; const int first_small_invader_pixel = 15; const int ufo_pixel = 20; const int cannon_shot_pixel = 21; //Ship bit-map and location int cannon_xpos = 24; const int cannon_ypos = 43; Ticker move_cannon; const bool cannon_bitmap[5][9] = { {0, 0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 1, 1, 1, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 0}, {1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1} }; Ticker move_cannon_shot; bool cannon_shot_on_screen = false; int cannon_shot_x_pos = 28; int cannon_shot_y_pos = 40; bool game_over = false; //Enemies Ticker move_enemies; bool invaders_in_state2 = true; bool invader_direction = RIGHT; //Struct to store enemy data struct Invaders { int x_pos; int y_pos; bool is_alive; } small_invader[5], medium_invader[5], large_invader[5]; int right_column_alive = 4; int left_column_alive = 0; enum LowestInvaderRow {small, medium, large}; LowestInvaderRow lowest_invader_row_alive = large; //Limits the first invader can travel int minimum_invader_x_pos = 0; int maximum_invader_x_pos = 20; //Bitmaps for small invaders const bool small_invader_bitmap_1[6][8] = { {0, 0, 0, 1, 1, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 0}, {1, 1, 0, 1, 1, 0, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, {0, 1, 0, 1, 1, 0, 1, 0}, {1, 0, 1, 0, 0, 1, 0, 1} }; const bool small_invader_bitmap_2[6][8] = { {0, 0, 0, 1, 1, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 0}, {1, 1, 0, 1, 1, 0, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 0, 1}, {0, 1, 0, 0, 0, 0, 1, 0} }; //Bitmaps for medium invaders const bool medium_invader_bitmap_1[6][10] = { {1, 0, 0, 1, 0, 0, 1, 0, 0, 1}, {1, 0, 1, 1, 1, 1, 1, 1, 0, 1}, {1, 1, 1, 0, 1, 1, 0, 1, 1, 1}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 0}, {0, 0, 1, 0, 0, 0, 0, 1, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 1, 0} }; const bool medium_invader_bitmap_2[6][10] = { {0, 0, 0, 1, 0, 0, 1, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, {0, 1, 1, 0, 1, 1, 0, 1, 1, 0}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 0, 1, 0, 0, 0, 0, 1, 0, 1}, {0, 0, 0, 1, 1, 1, 1, 0, 0, 0} }; //Bitmaps for large invaders const bool large_invader_bitmap_1[6][12] = { {0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, {1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0}, {0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0} }; const bool large_invader_bitmap_2[6][12] = { {0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, {1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0}, {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1} }; //Barriers struct Barriers { int x_pos; int y_pos; bool before_bitmap[8][14]; bool after_bitmap[8][14]; } barrier[3]; int no_of_barriers = 3; const bool barrier_bitmap[8][14] = { {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}, {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}, {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1} }; //TEST FOR SPEC UFO const bool ufo_bitmap[5][14] = { {0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, {0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0} }; int row_no = 5; int col_no = 14; //ISR Flags volatile bool g_update_screen_flag = true; volatile bool g_move_cannon_flag = true; volatile bool g_shoot_pressed_flag = false; volatile bool g_move_cannon_shot_flag = false; volatile bool g_move_enemies_flag = true; // function prototypes // error function hangs flashing an LED void error(); // setup serial port void init_serial(); // set-up the on-board LEDs and switches void init_K64F(); //Init shoot button void init_shoot(); // Added functions void MoveCannon(); void InitSmallInvaders(); void ClearSmallInvaders(); void DrawSmallInvaders(); void ClearMediumInvaders(); void InitMediumInvaders(); void DrawMediumInvaders(); void InitLargeInvaders(); void CLearLargeInvaders(); void DrawLargeInvaders(); void InitBarriers(); void DrawBarriers(); void ShiftInvaderXPositions(); void ShiftInvaderYPositions(bool new_direction); //void InitUFO(); void DrawUFO(); //void DrawEnemies(struct Invaders invader[], int no_of_invaders); //ISR's void update_screen_isr(); void move_cannon_isr(); void move_enemies_isr(); void shoot_pressed_isr(); void move_cannon_shot_isr(); int down_count = 0; int main() { //Initalises the board and perhiperals init_K64F(); init_serial(); init_shoot(); lcd.init(); lcd.clear(); update_screen.attach(&update_screen_isr, 0.05); move_cannon.attach(&move_cannon_isr, 0.05); move_enemies.attach(&move_enemies_isr, 0.5); InitSmallInvaders(); InitMediumInvaders(); InitLargeInvaders(); InitBarriers(); lcd.refresh(); while (true) { //IF the game is over detach all the tickers if (game_over) { move_cannon.detach(); move_enemies.detach(); lcd.clear(); lcd.printString("Game Over", 1, 2); } else { //Updates pixels on the screen if (g_update_screen_flag) { g_update_screen_flag = false; //Loops through the screen map and sets pixels on the LCD for (int col = 0; col < 84; col++) { for (int row = 0; row < 48; row++) { if (screen_map[col][row]) { lcd.setPixel(col, row); } else { lcd.clearPixel(col, row); } } } } //Controls cannon movement if (g_move_cannon_flag) { g_move_cannon_flag = false; MoveCannon(); DrawBarriers(); lcd.refresh(); } //Spawns a player bullet if the shoot button is pressed and there isn't a bullet on the screen if (g_shoot_pressed_flag) { g_shoot_pressed_flag = false; if (!cannon_shot_on_screen) { cannon_shot_on_screen = true; pc.printf("Shot Fired\n"); //Add 4 to cannon x_pos to get shot x_pos cannon_shot_x_pos = cannon_xpos + 4; cannon_shot_y_pos = 40; move_cannon_shot.attach(&move_cannon_shot_isr, 0.05); } } //Move the cannon's shot if (g_move_cannon_shot_flag) { g_move_cannon_shot_flag = false; //Checks bullet will not go beyond the bounds of the screen map if (cannon_shot_y_pos > -1) { //Loops throught the shot bitmap and clears the pixels in the screen map for (int row = 0; row < 3; row++) { //Clears the position where the bullet was screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] = empty_pixel; } //Increments the shot going up the screen cannon_shot_y_pos--; //Checks to see what the shot hits. If it hits nothing the shot gets pushed to the screen map for (int row = 0; row < 3; row++) { int object_no; if (screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] >= first_small_invader_pixel && screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] < (first_small_invader_pixel + 5)) { object_no = screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] - first_small_invader_pixel; small_invader[object_no].is_alive = false; pc.printf("Small (%d) Hit\n", object_no); cannon_shot_on_screen = false; move_cannon_shot.detach(); break; } else if (screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] >= first_medium_invader_pixel && screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] < (first_medium_invader_pixel + 5)) { object_no = screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] - first_medium_invader_pixel; medium_invader[object_no].is_alive = false; pc.printf("Medium (%d) Hit\n", object_no); cannon_shot_on_screen = false; move_cannon_shot.detach(); break; } else if (screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] >= first_large_invader_pixel && screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] < (first_large_invader_pixel + 5)) { object_no = screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] - first_large_invader_pixel; large_invader[object_no].is_alive = false; pc.printf("Large (%d) Hit\n", object_no); cannon_shot_on_screen = false; move_cannon_shot.detach(); break; } else if (screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] >= first_barrier_pixel && screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] < (first_barrier_pixel + 3)) { object_no = screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] - first_barrier_pixel; pc.printf("Barrier (%d) Hit\n", object_no); cannon_shot_on_screen = false; move_cannon_shot.detach(); break; } else if (screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] == ufo_pixel) { pc.printf("UFO Hit\n"); cannon_shot_on_screen = false; move_cannon_shot.detach(); break; } else { screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] = cannon_shot_pixel; } } } else { //Loops throught the shot bitmap and clears the pixels in the screen map for (int row = 1; row < 3; row++) { //Clears the position where the bullet was screen_map[cannon_shot_x_pos][cannon_shot_y_pos + row] = empty_pixel; } cannon_shot_on_screen = false; } } } //Controls enemy movement if (g_move_enemies_flag) { g_move_enemies_flag = false; //Added stuff to move to function //Checks which columns of invaders are alive on the right and left sides and changes the limits of the first invader //MOVE TO COLLISION DETECTION WHEN IT'S DONE //Checking the left side for (int i = 0; i < 5; i++) { if (small_invader[i].is_alive || medium_invader[i].is_alive || large_invader[i].is_alive) { left_column_alive = i; break; } } minimum_invader_x_pos = 0 - left_column_alive*13; //Checking the right side for (int j = 4; j >= 0; j--) { if (small_invader[j].is_alive || medium_invader[j].is_alive || large_invader[j].is_alive) { right_column_alive = j; break; } } maximum_invader_x_pos = 72 - right_column_alive*13; //End of block //Clears the old bitmaps ClearSmallInvaders(); ClearMediumInvaders(); CLearLargeInvaders(); ShiftInvaderXPositions(); DrawSmallInvaders(); DrawMediumInvaders(); DrawLargeInvaders(); //DrawUFO(); invaders_in_state2 = !invaders_in_state2; lcd.refresh(); //TEST CODE //END } sleep(); } } void init_K64F() { // on-board LEDs are active-low, so set pin high to turn them off. r_led = 1; g_led = 1; b_led = 1; // since the on-board switches have external pull-ups, we should disable the internal pull-down // resistors that are enabled by default using InterruptIn sw2.mode(PullNone); sw3.mode(PullNone); } void error() { while(1) { // if error, hang while flashing error message r_led = 0; wait(0.2); r_led = 1; wait(0.2); } } void init_serial() { // set to highest baud - ensure terminal software matches pc.baud(115200); } void init_shoot() { shoot_button.mode(PullUp); shoot_button.fall(&shoot_pressed_isr); } void update_screen_isr() { g_update_screen_flag = true; } void shoot_pressed_isr() { g_shoot_pressed_flag = true; } void move_cannon_shot_isr() { g_move_cannon_shot_flag = true; } void move_cannon_isr() { g_move_cannon_flag = true; } void MoveCannon() { //Clears the ship for (int col = 0; col < 9; col++) { for (int row = 0; row < 5; row++) { if(cannon_bitmap[row][col]) { //lcd.clearPixel(cannon_xpos+col, cannon_ypos+row); screen_map[cannon_xpos+col][cannon_ypos+row] = empty_pixel; } } } //Changes the position of the ship when the joystick is moved, capping at 0 and 75 so it always fits on the screen if (joystick.GetXValue() < 0.25f) { cannon_xpos--; if (cannon_xpos < 0) { cannon_xpos = 0; } } else if (joystick.GetXValue() > 0.75f) { cannon_xpos++; if (cannon_xpos > 75) { cannon_xpos = 75; } } //Redraws the ship for (int col = 0; col < 9; col++) { for (int row = 0; row < 5; row++) { if(cannon_bitmap[row][col]) { //lcd.setPixel(cannon_xpos+col, cannon_ypos+row); screen_map[cannon_xpos+col][cannon_ypos+row] = cannon_pixel; } } } } void move_enemies_isr() { g_move_enemies_flag = true; } //Sets the position and aliveness of the small invaders void InitSmallInvaders() { for (int i = 0; i < 5; i++) { small_invader[i].x_pos = 2+ (i*13); small_invader[i].y_pos = 1; small_invader[i].is_alive = true; } } void ClearSmallInvaders() { for (int i = 0; i < 5; i++) { if (!invaders_in_state2) { for (int col = 0; col < 8; col++) { for (int row = 0; row < 6; row++) { if(small_invader_bitmap_1[row][col] && small_invader[i].x_pos + col >= 0 && small_invader[i].x_pos + col < 84) { //lcd.clearPixel(small_invader[i].x_pos + col, small_invader[i].y_pos + row); screen_map[small_invader[i].x_pos + col][small_invader[i].y_pos + row] = empty_pixel; } } } } else { for (int col = 0; col < 8; col++) { for (int row = 0; row < 6; row++) { if(small_invader_bitmap_2[row][col] && small_invader[i].x_pos + col >= 0 && small_invader[i].x_pos + col < 84) { //lcd.clearPixel(small_invader[i].x_pos + col, small_invader[i].y_pos + row); screen_map[small_invader[i].x_pos + col][small_invader[i].y_pos + row] = empty_pixel; } } } } } } void DrawSmallInvaders() { //For each small invader clear and redraws them if they're alive for (int i = 0; i < 5; i++) { //Checks if the invader is alive if (small_invader[i].is_alive) { //Reads off the bitmap and sets the allowed pixels if (invaders_in_state2) { for (int col = 0; col < 8; col++) { for (int row = 0; row < 6; row++) { if(small_invader_bitmap_1[row][col]) { //lcd.setPixel(small_invader[i].x_pos + col, small_invader[i].y_pos + row); screen_map[small_invader[i].x_pos + col][small_invader[i].y_pos + row] = first_small_invader_pixel + i; } } } } else { for (int col = 0; col < 8; col++) { for (int row = 0; row < 6; row++) { if(small_invader_bitmap_2[row][col]) { //lcd.setPixel(small_invader[i].x_pos + col, small_invader[i].y_pos + row); screen_map[small_invader[i].x_pos + col][small_invader[i].y_pos + row] = first_small_invader_pixel + i; } } } } } } } //Sets the position and aliveness of the medium invaders void InitMediumInvaders() { for (int i = 0; i < 5; i++) { medium_invader[i].x_pos = 1 + (i*13); medium_invader[i].y_pos = 8; medium_invader[i].is_alive = true; } } void ClearMediumInvaders() { for (int i = 0; i < 5; i++) { if (!invaders_in_state2) { for (int col = 0; col < 10; col++) { for (int row = 0; row < 6; row++) { if(medium_invader_bitmap_1[row][col] && medium_invader[i].x_pos + col >= 0 && medium_invader[i].x_pos + col < 84) { //lcd.clearPixel(medium_invader[i].x_pos + col, medium_invader[i].y_pos + row); screen_map[medium_invader[i].x_pos + col][medium_invader[i].y_pos + row] = empty_pixel; } } } } else { for (int col = 0; col < 10; col++) { for (int row = 0; row < 6; row++) { if(medium_invader_bitmap_2[row][col] && medium_invader[i].x_pos + col >= 0 && medium_invader[i].x_pos + col < 84) { //lcd.clearPixel(medium_invader[i].x_pos + col, medium_invader[i].y_pos + row); screen_map[medium_invader[i].x_pos + col][medium_invader[i].y_pos + row] = empty_pixel; } } } } } } void DrawMediumInvaders() { //For each small invader clear and redraws them if they're alive for (int i = 0; i < 5; i++) { //Checks if the invader is alive if (medium_invader[i].is_alive) { //Reads off the bitmap and sets the allowed pixels if (invaders_in_state2) { for (int col = 0; col < 10; col++) { for (int row = 0; row < 6; row++) { if(medium_invader_bitmap_1[row][col]) { //lcd.setPixel(medium_invader[i].x_pos + col, medium_invader[i].y_pos + row); screen_map[medium_invader[i].x_pos + col][medium_invader[i].y_pos + row] = first_medium_invader_pixel + i; } } } } else { for (int col = 0; col < 10; col++) { for (int row = 0; row < 6; row++) { if(medium_invader_bitmap_2[row][col]) { //lcd.setPixel(medium_invader[i].x_pos + col, medium_invader[i].y_pos + row); screen_map[medium_invader[i].x_pos + col][medium_invader[i].y_pos + row] = first_medium_invader_pixel + i; } } } } } } } //Sets the position and aliveness of the large invaders void InitLargeInvaders() { for (int i = 0; i < 5; i++) { large_invader[i].x_pos = 0 + (i*13); large_invader[i].y_pos = 15; large_invader[i].is_alive = true; } } void CLearLargeInvaders() { for (int i = 0; i < 5; i++) { //Reads off the bitmap and sets the allowed pixels if (!invaders_in_state2) { for (int col = 0; col < 12; col++) { for (int row = 0; row < 6; row++) { if(large_invader_bitmap_1[row][col] && large_invader[i].x_pos + col >= 0 && large_invader[i].x_pos + col < 84) { ///lcd.clearPixel(large_invader[i].x_pos + col, large_invader[i].y_pos + row); screen_map[large_invader[i].x_pos + col][large_invader[i].y_pos + row] = empty_pixel; } } } } else { for (int col = 0; col < 12; col++) { for (int row = 0; row < 6; row++) { if(large_invader_bitmap_2[row][col] && large_invader[i].x_pos + col >= 0 && large_invader[i].x_pos + col < 84) { //lcd.clearPixel(large_invader[i].x_pos + col, large_invader[i].y_pos + row); screen_map[large_invader[i].x_pos + col][large_invader[i].y_pos + row] = empty_pixel; } } } } } } void DrawLargeInvaders() { //For each small invader clear and redraws them if they're alive for (int i = 0; i < 5; i++) { //Checks if the invader is alive if (large_invader[i].is_alive) { //Reads off the bitmap and sets the allowed pixels if (invaders_in_state2) { for (int col = 0; col < 12; col++) { for (int row = 0; row < 6; row++) { if(large_invader_bitmap_1[row][col]) { //lcd.setPixel(large_invader[i].x_pos + col, large_invader[i].y_pos + row); screen_map[large_invader[i].x_pos + col][large_invader[i].y_pos + row] = first_large_invader_pixel + i; } } } } else { for (int col = 0; col < 12; col++) { for (int row = 0; row < 6; row++) { if(large_invader_bitmap_2[row][col]) { //lcd.setPixel(large_invader[i].x_pos + col, large_invader[i].y_pos + row); screen_map[large_invader[i].x_pos + col][large_invader[i].y_pos + row] = first_large_invader_pixel + i; } } } } } } } /* void DrawInvaders(struct Invaders invader[], int no_of_invaders, bool bitmap[][]) { //For each small invader clear and redraws them if they're alive for (int i = 0; i < no_of_invaders; i++) { //Clears the enemy position lcd.drawRect(invader[i].x_pos, invader[i].y_pos, 12, 6, 2); //Checks if the invader is alive if (invader[i].is_alive) { //Reads off the bitmap and sets the allowed pixels int col = 0; int row = 0; //Flips the bitmap everytime the function is called if (invaders_in_state2) { for (col = 0; col < 12; col++) { for (row = 0; row < 6; row++) { if(large_invader_bitmap_1[row][col]) { lcd.setPixel(large_invader[i].x_pos + col, large_invader[i].y_pos + row); } } } } else { for (col = 0; col < 12; col++) { for (row = 0; row < 6; row++) { if(large_invader_bitmap_2[row][col]) { lcd.setPixel(large_invader[i].x_pos + col, large_invader[i].y_pos + row); } } } } } } } */ void InitBarriers() { for (int i = 0; i < no_of_barriers; i++) { barrier[i].x_pos = 10 + (i*25); barrier[i].y_pos = 33; //Copies the bitmap into the structs memcpy(barrier[i].before_bitmap, barrier_bitmap, sizeof(barrier_bitmap)); memcpy(barrier[i].after_bitmap, barrier_bitmap, sizeof(barrier_bitmap)); } } void DrawBarriers() { //Clears the barrier and redraws it with damage applied for (int i = 0; i < no_of_barriers; i++) { for (int col = 0; col < 14; col++) { for (int row = 0; row < 8; row++) { if (barrier[i].before_bitmap[row][col]) { //lcd.clearPixel(barrier[i].x_pos + col, barrier[i].y_pos + row); screen_map[barrier[i].x_pos + col][barrier[i].y_pos + row] = empty_pixel; } if (barrier[i].after_bitmap[row][col]) { //lcd.setPixel(barrier[i].x_pos + col, barrier[i].y_pos + row); screen_map[barrier[i].x_pos + col][barrier[i].y_pos + row] = first_barrier_pixel + i; } } } //Copies the after array to the before array memcpy(barrier[i].before_bitmap, barrier[i].after_bitmap, sizeof(barrier[i].after_bitmap)); } } void ShiftInvaderXPositions() { if (invader_direction == RIGHT) { //Checks the first large invader to see if it can travel anymore if (large_invader[0].x_pos < maximum_invader_x_pos) { for (int i = 0; i < 5; i++) { small_invader[i].x_pos += 2; medium_invader[i].x_pos += 2; large_invader[i].x_pos += 2; } } else { ShiftInvaderYPositions(LEFT); } } else { //Checks the first large invader to see if it can travel anymore if (large_invader[0].x_pos > minimum_invader_x_pos) { for (int i = 0; i < 5; i++) { small_invader[i].x_pos -= 2; medium_invader[i].x_pos -= 2; large_invader[i].x_pos -= 2; } } else { ShiftInvaderYPositions(RIGHT); } } } void ShiftInvaderYPositions(bool new_direction) { //Checks to see which row of invaders are still alive to work out maximum y positions if (large_invader[0].is_alive || large_invader[1].is_alive || large_invader[2].is_alive || large_invader[3].is_alive || large_invader[4].is_alive) { lowest_invader_row_alive = large; } else if (medium_invader[0].is_alive || medium_invader[1].is_alive || medium_invader[2].is_alive || medium_invader[3].is_alive || medium_invader[4].is_alive) { lowest_invader_row_alive = medium; } else { lowest_invader_row_alive = small; } //If an invader touches the bottom the game ends, otherwise the invaders descend if (small_invader[0].y_pos < 39 - (7*lowest_invader_row_alive)) { for (int i = 0; i < 5; i++) { small_invader[i].y_pos += 3; medium_invader[i].y_pos += 3; large_invader[i].y_pos += 3; invader_direction = new_direction; } } else { game_over = true; } //TEST CODE down_count++; } /* void InitUFO() { } */ void DrawUFO() { //Draws the UFO int x_pos = 20; int y_pos = 25; for (int col = 0; col < col_no; col++) { for (int row = 0; row < row_no; row++) { if(ufo_bitmap[row][col]) { //lcd.setPixel(x_pos + col, y_pos + row); screen_map[x_pos + col][y_pos + row] = ufo_pixel; } } } }