Space Invaders - Embedded Systems Project 15/16 - Avinash Patel 200860407

Dependencies:   Joystick N5110 SDFileSystem mbed

Revision:
7:babc367a3333
Parent:
6:89d4a7f7588b
Child:
8:b2faec20ed8f
diff -r 89d4a7f7588b -r babc367a3333 main.cpp
--- a/main.cpp	Thu Apr 28 14:14:54 2016 +0000
+++ b/main.cpp	Mon May 02 16:28:07 2016 +0000
@@ -6,457 +6,11 @@
         - Core cannon is drawn and can move, enemies are visible and they switch between states every second
 Week 21 - Begun to set up barriers
 Easter  - Barriers work, invader and player can shoot. Begun setting up menus
+Week 22 - Most menus work
+Week 23 - Menus work
 */
 #include "mbed.h"
-#include "N5110.h"
-
-//Direction invaders are travelling
-#define LEFT 0
-#define RIGHT 1
-
-//Joystick Class
-class Joystick
-{
-public:
-    //Constructor
-    Joystick(PinName x_axis_pin, PinName y_axis_pin, PinName button_pin) {
-        //Dynamically allocates the pins and button debounce ticker
-        x_axis_ = new AnalogIn(x_axis_pin);
-        y_axis_ = new AnalogIn(y_axis_pin);
-        button_ = new InterruptIn(button_pin);
-        button_debounce_ = new Timeout();
-    }
-
-    //Deconstructor
-    ~Joystick() {
-        //Clears all dynamically allocated memory
-        delete x_axis_;
-        delete y_axis_;
-        delete button_;
-        delete button_debounce_;
-    }
-
-    //Initalises the Joystick
-    //Sets up the ISRs and grabs the offsets for each axis
-    void init() {
-        //Sets up the button ISR
-        button_->mode(PullDown);
-        button_->rise(this, &Joystick::button_isr);
-
-        //Initalises the vairables and flags
-        x_offset_ = 0;
-        y_offset_ = 0;
-        g_button_flag_ = false;
-        g_button_debounce_flag_ = false;
-
-        //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() {
-        if (!g_button_debounce_flag_) {
-            g_button_flag_ = true;
-            g_button_debounce_flag_ = true;
-
-            //Sets up the debounce ticker
-            button_debounce_->attach(this, &Joystick::button_debounce_isr, 0.2);
-        }
-    }
-
-    //Button debounce ISR method
-    void button_debounce_isr() {
-        g_button_debounce_flag_ = false;
-    }
-
-private:
-    //Pin inputs
-    AnalogIn* x_axis_;
-    AnalogIn* y_axis_;
-    InterruptIn* button_;
-
-    //Timeout to prevent joystick button bounce
-    Timeout* button_debounce_;
-
-    //Stores X and Y offsets
-    float x_offset_;
-    float y_offset_;
-
-    //Stores interrupt flags
-    volatile bool g_button_flag_;
-    volatile bool g_button_debounce_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(PTB3, PTB2, 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);
-
-//Tickers
-Ticker update_screen;
-Ticker move_joystick;
-Ticker move_cannon_missile;
-Ticker move_enemies;
-Ticker move_invader_normal_missile[2];
-
-//Timeout
-Timeout joystick_cursor_regulator; //Stops the cursor from jumping
-Timeout shoot_button_debounce; //Stops the cannon from firing when transitioning from a menu to the game
-
-//Buffer holding pixel data of screen with point representations
-int screen_buffer[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_missile_pixel = 21;
-const int invader_normal_missile_pixel = 22;
-
-//Booleans
-//Invader related bools
-bool invaders_in_state2 = true;
-bool invader_direction = RIGHT;
-//Cannon missile bool
-bool cannon_missile_on_screen = false;
-
-//Integers
-int score = 0; //Stores the score
-int fsm_state = 0; //Stores the state for menu fsm's
-int cursor_y_pos = 0; //Stores the cursor position
-//Cannon related integers
-int number_of_lives = 3;
-int cannon_xpos = 24;
-const int cannon_ypos = 43;
-//Cannon missile related integers
-int cannon_missile_x_pos = 28;
-int cannon_missile_y_pos = 40;
-//Invader related integers
-int no_of_alive_invaders = 15;
-//Invader missile related integers
-int invader_strong_missile_x_pos;
-int invader_strong_missile_y_pos;
-
-//Floats
-float ticker_period = 1; //Stores the period of the invader move ticker
-
-//Enums
-enum Status {dead, dying, alive}; //Contains the status of invaders
-enum Invader {small, medium, large, none}; //Contains the type of invader passed into
-//Contains the current state of the game
-enum GameState {menu, game, paused, save, load, scores, settings};
-GameState game_state = menu;
-
-//Bit-maps
-//Cannon bit-map
-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}
-};
-//Bitmaps for small invaders
-const bool small_invader_bitmap_1[6][8] = { //First state
-    {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] = { //Second state
-    {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] = { //First state
-    {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] = { //Second state
-    {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] = { //First state
-    {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] = { //Second state
-    {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}
-};
-//Normal invader missile bitmap
-const bool invader_normal_missile_bitmap[4][3] = {
-    {0, 1, 0},
-    {1, 1, 1},
-    {0, 1, 0},
-    {0, 1, 0}
-};
-//Strong invader missile bitmap
-const bool invader_strong_missile_bitmap_1[4][3] = { //First state
-    {0, 0, 1},
-    {0, 1, 0},
-    {1, 0, 0},
-    {0, 1, 0}
-};
-const bool invader_strong_missile_bitmap_2[4][3] = { //Second state
-    {0, 1, 0},
-    {1, 0, 0},
-    {0, 1, 0},
-    {0, 1, 1}
-};
-//Barrier bitmap
-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}
-};
-//Cannon barrier damage bitmap
-const bool barrier_cannon_missile_damage_bitmap[3][3] = {
-    {0, 1, 0},
-    {1, 0, 0},
-    {1, 0, 1}
-};
-//Normal invader barrier damage bitmap
-const bool barrier_invader_normal_missile_damage_bitmap[2][3] = {
-    {1, 0, 1},
-    {0, 1, 0}
-};
-//UFO Bitmap
-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}
-};
-
-//Structs
-//Contains invader data
-struct Invaders {
-    int x_pos;
-    int y_pos;
-    enum Status status;
-} small_invader[5], medium_invader[5], large_invader[5]; //Five of each invader
-//Contains data for Invader normal missiles
-struct InvaderNormalMissiles {
-    int x_pos;
-    int y_pos;
-    bool fired;
-} invader_normal_missile[2];
-//Contains data for barriers
-struct Barriers {
-    int x_pos;
-    int y_pos;
-    bool before_bitmap[8][14];
-    bool after_bitmap[8][14];
-} barrier[3];
-//FSM for menus
-struct FSMMenus {
-    GameState output;
-    int next_state[2];
-};
-FSMMenus fsm_main_menu[4] = {
-    {game, {1, 3}},
-    {load, {2, 0}},
-    {scores, {3, 1}},
-    {settings, {0, 2}}
-};
-FSMMenus fsm_paused[3] = { //Pause menu FSM
-    {game, {1, 2}},
-    {save, {2, 0}},
-    {menu, {0, 1}}
-};
-
-//ISR Flags
-volatile bool g_update_screen_flag = true;
-volatile bool g_move_joystick_flag = true;
-volatile bool g_move_enemies_flag = true;
-volatile bool g_shoot_pressed_flag = false;
-volatile bool g_move_cannon_missile_flag = false;
-volatile bool g_move_invader_normal_missile_flag[2] = {false, false};
-volatile bool g_cannon_hit_flag = false;
-volatile bool g_joystick_cursor_regulator_flag = false;
-volatile bool g_shoot_button_debounce_flag = false;
-
-// 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();
-//Init Random Number Generator
-void init_rng();
-// Added functions
-void InitaliseGame();
-void Game();
-void UpdateScreen();
-void MoveCannon();
-void InitSmallInvaders();
-void ClearSmallInvaders();
-void ClearSingleSmallInvader(int invader_no);
-void DrawSmallInvaders();
-void DrawSingleSmallInvader(int invader_no);
-void InitMediumInvaders();
-void ClearMediumInvaders();
-void ClearSingleMediumInvader(int invader_no);
-void DrawMediumInvaders();
-void DrawSingleMediumInvader(int invader_no);
-void InitLargeInvaders();
-void ClearLargeInvaders();
-void ClearSingleLargeInvader(int invader_no);
-void DrawLargeInvaders();
-void DrawSingleLargeInvader(int invader_no);
-void InitBarriers();
-void DrawBarriers();
-void MoveInvaderXPositions();
-int CalculateInvaderLeftLimit();
-int CalculateInvaderRightLimit();
-void MoveInvadersLeft(int limit);
-void MoveInvadersRight(int limit);
-void MoveInvaderYPositions(bool new_direction);
-Invader CalculateInvaderYLimit();
-Invader LowestInvaderInColumn(int column);
-void FireCannonMissile();
-void MoveCannonMissile();
-void CollisionDetectionCannonMissile();
-int CannonMissileHitInvader(int first_pixel, int row, struct Invaders (&invader)[5]);
-void CannonMissileHitBarrier(int first_pixel, int row);
-void InvaderNormalMissileHitBarrier(int first_pixel, const struct InvaderNormalMissiles (&missile));
-void AttemptToFireInvaderNormalMissiles();
-void FireNormalInvaderMissile(int missile_no, Invader source, const struct Invaders (&invader));
-void MoveInvaderNormalMissile(int missile_no);
-void CollisionDetectionInvaderNormalMissile(int missile_no);
-void DetachTickers();
-void AttachTickers();
-//Pause Menu Functions
-void PauseScreen();
-void PrintPauseScreen();
-void MoveCursor(const struct FSMMenus *fsm);
-//void InitUFO();
-void DrawUFO();
-//ISR's
-void update_screen_isr();
-void move_joystick_isr();
-void move_enemies_isr();
-void shoot_pressed_isr();
-void move_cannon_missile_isr();
-void cannon_hit_isr();
-void joystick_cursor_regulator_isr();
-void shoot_button_debounce_isr();
-//Function pointer to move invader normal missile isr
-void (*move_invader_normal_missile_isr[2])();
-void move_invader_normal_missile_0_isr();
-void move_invader_normal_missile_1_isr();
+#include "main.h"
 
 int row_no = 5;
 int col_no = 14;
@@ -515,23 +69,7 @@
 
                     //If the game state is equal to the game initalise it
                     if (game_state == game) {
-                        //Clears the screen buffer and runs init functions
-                        memset(screen_buffer, 0, sizeof(screen_buffer));
-                        no_of_alive_invaders = 15;
-                        score = 0;
-                        number_of_lives = 3;
-                        InitSmallInvaders();
-                        InitMediumInvaders();
-                        InitLargeInvaders();
-                        InitBarriers();
-                        //Sets the flags so enemies pop up straight away
-                        g_update_screen_flag = true;
-                        g_move_joystick_flag = true;
-                        g_move_enemies_flag = true;
-                        //Forces the missiles to have the fired flags to flase
-                        cannon_missile_on_screen = false;
-                        invader_normal_missile[0].fired = false;
-                        invader_normal_missile[1].fired = false;
+                        InitaliseGame();
                     }
                 }
 
@@ -589,8 +127,8 @@
 //Seeds the random number generator with noise from an analog in pin
 void init_rng()
 {
-    AnalogIn rng_seed(PTC10);
-    srand(floor(10000*rng_seed.read()));
+    AnalogIn rng_seed(PTC10); //Creates a AnalogIn on a unused pin
+    srand(floor(10000*rng_seed.read())); //Sets the seed as 10000x the input of the analog in
 }
 
 void init_shoot()
@@ -676,6 +214,9 @@
 
             lcd.clear();
             lcd.printString("Game Over.", 1, 2);
+            char buffer[14];
+            sprintf(buffer, "Score: %d", score);
+            lcd.printString(buffer, 1, 3);
         } else if (no_of_alive_invaders == 0) { //If the player wins a round
             //Resets the no of alive invaders
             no_of_alive_invaders = 15;
@@ -773,6 +314,27 @@
     }
 }
 
+void InitaliseGame()
+{
+    //Clears the screen buffer and runs init functions
+    memset(screen_buffer, 0, sizeof(screen_buffer));
+    no_of_alive_invaders = 15;
+    score = 0;
+    number_of_lives = 3;
+    InitSmallInvaders();
+    InitMediumInvaders();
+    InitLargeInvaders();
+    InitBarriers();
+    //Sets the flags so enemies pop up straight away
+    g_update_screen_flag = true;
+    g_move_joystick_flag = true;
+    g_move_enemies_flag = true;
+    //Forces the missiles to have the fired flags to flase
+    cannon_missile_on_screen = false;
+    invader_normal_missile[0].fired = false;
+    invader_normal_missile[1].fired = false;
+}
+
 void UpdateScreen()
 {
     //Loops through the screen buffer and sets pixels on the LCD
@@ -791,7 +353,7 @@
 
 void MoveCannon()
 {
-    //Clears the ship
+    //Clears the cannon
     for (int col = 0; col < 9; ++col) {
         for (int row = 0; row < 5; ++row) {
             if(cannon_bitmap[row][col]) {
@@ -800,7 +362,7 @@
         }
     }
 
-    //Changes the position of the ship when the joystick is moved, capping at 0 and 75 so it always fits on the screen
+    //Changes the position of the cannon 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) {
@@ -813,7 +375,7 @@
         }
     }
 
-    //Redraws the ship
+    //Redraws the cannon
     for (int col = 0; col < 9; ++col) {
         for (int row = 0; row < 5; ++row) {
             if(cannon_bitmap[row][col]) {
@@ -823,11 +385,11 @@
     }
 }
 
-//Sets the position and aliveness of the small invaders
+//Sets the position and status of the small invaders
 void InitSmallInvaders()
 {
     for (int i = 0; i < 5; ++i) {
-        small_invader[i].x_pos = 2 + (i*13);
+        small_invader[i].x_pos = 2 + (i*13); // Large invaders are 12 across so add 13 for a gap space
         small_invader[i].y_pos = 1;
         small_invader[i].status = alive;
     }
@@ -863,6 +425,7 @@
     small_invader[invader_no].status = (small_invader[invader_no].status == dying) ? dead : alive;
 }
 
+//Cycles through all the small invaders. If they're alive set them in the screen buffer
 void DrawSmallInvaders()
 {
     for (int i = 0; i < 5; ++i) {
@@ -894,12 +457,13 @@
 void InitMediumInvaders()
 {
     for (int i = 0; i < 5; ++i) {
-        medium_invader[i].x_pos = 1 + (i*13);
+        medium_invader[i].x_pos = 1 + (i*13); // Large invaders are 12 across so add 13 for a gap space
         medium_invader[i].y_pos = 8;
         medium_invader[i].status = alive;
     }
 }
 
+//Cycles through all the medium invaders. If they're not already dead clear them
 void ClearMediumInvaders()
 {
     for (int i = 0; i < 5; ++i) {
@@ -909,6 +473,7 @@
     }
 }
 
+//Cycles through the the screen invader bitmap and sets the pixels in the buffer to 0
 void ClearSingleMediumInvader(int invader_no)
 {
     for (int col = 0; col < 10; ++col) {
@@ -928,6 +493,7 @@
     medium_invader[invader_no].status = (medium_invader[invader_no].status == dying) ? dead : alive;
 }
 
+//Cycles through all the medium invaders. If they're alive set them in the screen buffer
 void DrawMediumInvaders()
 {
     for (int i = 0; i < 5; ++i) {
@@ -937,6 +503,7 @@
     }
 }
 
+//Cycles through the the screen invader bitmap and sets the pixels in the buffer
 void DrawSingleMediumInvader(int invader_no)
 {
     for (int col = 0; col < 10; ++col) {
@@ -954,7 +521,7 @@
     }
 }
 
-//Sets the position and aliveness of the large invaders
+//Sets the position and status of the large invaders
 void InitLargeInvaders()
 {
     for (int i = 0; i < 5; ++i) {
@@ -964,6 +531,7 @@
     }
 }
 
+//Cycles through all the large invaders. If they're not already dead clear them
 void ClearLargeInvaders()
 {
     for (int i = 0; i < 5; ++i) {
@@ -993,6 +561,7 @@
     large_invader[invader_no].status = (large_invader[invader_no].status == dying) ? dead : alive;
 }
 
+//Cycles through all the large invaders. If they're alive set them in the screen buffer
 void DrawLargeInvaders()
 {
     for (int i = 0; i < 5; ++i) {
@@ -1002,6 +571,7 @@
     }
 }
 
+//Cycles through the the screen invader bitmap and sets the pixels in the buffer
 void DrawSingleLargeInvader(int invader_no)
 {
     for (int col = 0; col < 12; ++col) {
@@ -1019,6 +589,7 @@
     }
 }
 
+//Sets the position and loads the bitmap into the barrier objects
 void InitBarriers()
 {
     for (int i = 0; i < 3; ++i) {
@@ -1051,21 +622,20 @@
 
 void MoveInvaderXPositions()
 {
-    //Checks the left limit
-    int left_invader_limit = CalculateInvaderLeftLimit();
-
-    //Checking the right limit
-    int right_invader_limit = CalculateInvaderRightLimit();
-
-    //End of block
+    //Moves the invader in the current direction
     if (invader_direction == RIGHT) {
+        //Checking the right limit
+        int right_invader_limit = CalculateInvaderRightLimit();
         MoveInvadersRight(right_invader_limit);
     } else {
-        //Checks the first large invader to see if it can travel anymore
+        //Checks the left limit
+        int left_invader_limit = CalculateInvaderLeftLimit();
         MoveInvadersLeft(left_invader_limit);
     }
 }
 
+//Checks the status off the invaders per column, starting from the left
+//If they're alive return the row number
 int CalculateInvaderLeftLimit()
 {
     for (int i = 0; i < 5; ++i) {
@@ -1078,6 +648,8 @@
     return 4;
 }
 
+//Checks the status off the invaders per column, starting from the right
+//If they're alive return the row number
 int CalculateInvaderRightLimit()
 {
     for (int i = 4; i >= 0; --i) {
@@ -1095,6 +667,7 @@
     //Checks the first large invader to see if it can travel anymore
     if (large_invader[limit].x_pos > 1) {
         for (int i = 0; i < 5; ++i) {
+            //Moves the invaders 2 to the left
             small_invader[i].x_pos -= 2;
             medium_invader[i].x_pos -= 2;
             large_invader[i].x_pos -= 2;
@@ -1109,6 +682,7 @@
 {
     //Checks the first large invader to see if it can travel anymore
     if (large_invader[limit].x_pos < 71) {
+        //Moves the invaders 2 to the right
         for (int i = 0; i < 5; ++i) {
             small_invader[i].x_pos += 2;
             medium_invader[i].x_pos += 2;
@@ -1192,11 +766,14 @@
 
 void FireCannonMissile()
 {
+    //Sets the cannon fired flag to true
     cannon_missile_on_screen = true;
 
-    //Add 4 to cannon x_pos to get shot x_pos
+    //Offset cannon missile x position by 4 of the cannons x pos
     cannon_missile_x_pos = cannon_xpos + 4;
+    //Will always have a starting y of 40
     cannon_missile_y_pos = 40;
+    //Attach the move cannon missile
     move_cannon_missile.attach(&move_cannon_missile_isr, 0.05);
 }
 
@@ -1227,65 +804,37 @@
     }
 }
 
-void MoveInvaderNormalMissile(int missile_no)
-{
-    //Checks missile will not exceed screen buffer
-    if (invader_normal_missile[missile_no].y_pos < 44) {
-        //Loops through the bitmap and clears the missile from the screen buffer
-        for (int col = 0; col < 3; ++col) {
-            for (int row = 0; row < 4; ++row) {
-                if (invader_normal_missile_bitmap[row][col]) {
-                    screen_buffer[invader_normal_missile[missile_no].x_pos + col][invader_normal_missile[missile_no].y_pos + row] = empty_pixel;
-                }
-            }
-        }
-
-        //Increments the position of the missile
-        ++invader_normal_missile[missile_no].y_pos;
-
-        //Collision detection
-        CollisionDetectionInvaderNormalMissile(missile_no);
-
-    } else {
-        //Loops through the bitmap and clears the pixels still on the screen
-        for (int col = 0; col < 3; ++col) {
-            for (int row = 0; row < 4; ++row) {
-                if (invader_normal_missile_bitmap[row][col]) {
-                    screen_buffer[invader_normal_missile[missile_no].x_pos + col][invader_normal_missile[missile_no].y_pos + row] = empty_pixel;
-                }
-            }
-        }
-
-        invader_normal_missile[missile_no].fired = false;
-        move_invader_normal_missile[missile_no].detach();
-    }
-}
-
 //Checks to see what the shot hits. If it hits nothing the shot gets pushed to the screen buffer
 void CollisionDetectionCannonMissile()
 {
     for (int row = 0; row < 4; ++row) {
         int object_no;
-        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
+        int pixel_check = screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row];
+        pc.printf("Pixel check: %d\n", pixel_check);
+        if (pixel_check >= first_small_invader_pixel && pixel_check < ufo_pixel) { //Collides with a small invader
+            //Find the object no of the small invader it hit, clears it and increments the score
             object_no = CannonMissileHitInvader(first_small_invader_pixel, row, small_invader);
             ClearSingleSmallInvader(object_no);
             score += 40;
             break;
-        } 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
+        } else if (pixel_check >= first_medium_invader_pixel && pixel_check < first_small_invader_pixel) { //Collides with a medium invader
+            //Find the object no of the medium invader it hit, clears it and increments the score
             object_no = CannonMissileHitInvader(first_medium_invader_pixel, row, medium_invader);
             ClearSingleMediumInvader(object_no);
             score += 20;
             break;
-        } 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
+        } else if (pixel_check >= first_large_invader_pixel && pixel_check < first_medium_invader_pixel) { //Collides with a large invader
+            //Find the object no of the large invader it hit, clears it and increments the score
             object_no = CannonMissileHitInvader(first_large_invader_pixel, row, large_invader);
             ClearSingleLargeInvader(object_no);
             score += 10;
             break;
-        } 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
-            CannonMissileHitBarrier(first_barrier_pixel, row);
+        } else if (pixel_check >= first_barrier_pixel && pixel_check < (first_barrier_pixel + 3)) { //Collides with a barrier
+            //Adds the destruction done to the barrier to the bitmap and redraws the barriers
+            CannonMissileHitBarrier(row);
             DrawBarriers();
             break;
-        } else if (screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] == ufo_pixel) { //Collides with a UFO
+        } else if (pixel_check == ufo_pixel) { //Collides with a UFO
             pc.printf("UFO Hit\n");
             cannon_missile_on_screen = false;
             move_cannon_missile.detach();
@@ -1296,45 +845,7 @@
     }
 }
 
-//Checks the bottom centre point for a collision. If it doesn't push the bitmap to the screen buffer
-void CollisionDetectionInvaderNormalMissile(int missile_no)
-{
-    //Invader missile coordinates shifted to match centre bottom of bitmap
-    int relative_x_pos = invader_normal_missile[missile_no].x_pos + 1;
-    int relative_y_pos = invader_normal_missile[missile_no].y_pos + 3;
-    if (screen_buffer[relative_x_pos][relative_y_pos] == cannon_pixel) {
-        //Decrements the number of lives, pauses the game for 2 seconds
-        //Marks the cannon as hit
-        g_cannon_hit_flag = true;
-        //Detaches all tickers
-        DetachTickers();
-        //Creates a Timeout object on the stack with a period of 2 seconds to pause the game for 2 seconds
-        Timeout cannon_hit;
-        cannon_hit.attach(&cannon_hit_isr, 2);
-        while (g_cannon_hit_flag) {
-            sleep();
-        }
-        AttachTickers();
-        --number_of_lives;
-        invader_normal_missile[missile_no].fired = false;
-        move_invader_normal_missile[missile_no].detach();
-    } 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)) {
-        //Finds barrier number
-        InvaderNormalMissileHitBarrier(first_barrier_pixel, invader_normal_missile[missile_no]);
-        invader_normal_missile[missile_no].fired = false;
-        move_invader_normal_missile[missile_no].detach();
-    } else {
-        for (int col = 0; col < 3; ++col) {
-            for (int row = 0; row < 4; ++row) {
-                if (invader_normal_missile_bitmap[row][col]) {
-                    screen_buffer[invader_normal_missile[missile_no].x_pos + col][invader_normal_missile[missile_no].y_pos + row] = invader_normal_missile_pixel;
-                }
-            }
-        }
-    }
-}
-
-//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
+//Finds the invader number the missile hits, sets the hit invader to dying, decrements the no_of_alive_invaders and stops the shot from travalling up the screen
 int CannonMissileHitInvader(int first_pixel, int row, struct Invaders (&invader)[5])
 {
     int invader_no = screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] - first_pixel;
@@ -1347,9 +858,9 @@
 }
 
 //Calculates where to start drawing the damage bitmap over the barrier bitmap and performs the operation
-void CannonMissileHitBarrier(int first_pixel, int row)
+void CannonMissileHitBarrier(int row)
 {
-    int barrier_no = screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] - first_pixel;
+    int barrier_no = screen_buffer[cannon_missile_x_pos][cannon_missile_y_pos + row] - first_barrier_pixel;
     //Essentially inverse of barrier init
     int relative_x_pos = cannon_missile_x_pos - 10 - (barrier_no*25) - 1;
     int relative_y_pos = (cannon_missile_y_pos + row) - 33 - 1; //Don't know why it's -1 and not -2
@@ -1357,6 +868,7 @@
     for (int col = 0; col < 3; ++col) {
         for (int row_bit = 0; row_bit < 3; ++row_bit) {
             //Makes sure bitmap index does not go out of bounds. If it does go to the next iteration
+            //Element by element multiplication of the 2 bitmaps to clear the required pixals
             if (relative_x_pos + col >= 0 && relative_x_pos + col < 14 && relative_y_pos + row_bit >= 0 && relative_y_pos + row_bit < 8) {
                 barrier[barrier_no].after_bitmap[relative_y_pos + row_bit][relative_x_pos + col] *= barrier_cannon_missile_damage_bitmap[row_bit][col];
             }
@@ -1366,24 +878,6 @@
     move_cannon_missile.detach();
 }
 
-//Calculates where to start drawing the damage bitmap over the barrier bitmap and performs the operation
-void InvaderNormalMissileHitBarrier(int first_pixel, const struct InvaderNormalMissiles (&missile))
-{
-    int barrier_no = screen_buffer[missile.x_pos + 1][missile.y_pos + 3] - first_pixel;
-    //Essentially inverse of barrier init
-    int relative_x_pos = (missile.x_pos + 1) - 10 - (barrier_no*25) - 1;
-    int relative_y_pos = (missile.y_pos + 3) - 33;
-    //Loops through the damage bitmap and modifies the barrier's after bitmap
-    for (int col = 0; col < 3; ++col) {
-        for (int row_bit = 0; row_bit < 2; ++row_bit) {
-            //Makes sure bitmap index does not go out of bounds. If it does go to the next iteration
-            if (relative_x_pos + col >= 0 && relative_x_pos + col < 14 && relative_y_pos + row_bit >= 0 && relative_y_pos + row_bit < 8) {
-                barrier[barrier_no].after_bitmap[relative_y_pos + row_bit][relative_x_pos + col] *= barrier_invader_normal_missile_damage_bitmap[row_bit][col];
-            }
-        }
-    }
-}
-
 void AttemptToFireInvaderNormalMissiles()
 {
     //Fires the normal missiles
@@ -1419,7 +913,6 @@
     }
 }
 
-//Pass by reference to re
 void FireNormalInvaderMissile(int missile_no, Invader source, const struct Invaders (&invader))
 {
     //Finds the centre point of the chosen invader and fires the missile
@@ -1432,10 +925,99 @@
     move_invader_normal_missile[missile_no].attach(move_invader_normal_missile_isr[missile_no], 0.05);
 }
 
+void MoveInvaderNormalMissile(int missile_no)
+{
+    //Loops through the bitmap and clears the missile from the screen buffer
+    for (int col = 0; col < 3; ++col) {
+        for (int row = 0; row < 4; ++row) {
+            if (invader_normal_missile_bitmap[row][col]) {
+                screen_buffer[invader_normal_missile[missile_no].x_pos + col][invader_normal_missile[missile_no].y_pos + row] = empty_pixel;
+            }
+        }
+    }
+
+    //Checks missile will not exceed screen buffer
+    if (invader_normal_missile[missile_no].y_pos < 44) {
+        //Increments the position of the missile
+        ++invader_normal_missile[missile_no].y_pos;
+
+        //Collision detection
+        CollisionDetectionInvaderNormalMissile(missile_no);
+
+    } else {
+        //Sets the missiles fired flag as false and detaches the tickers
+        invader_normal_missile[missile_no].fired = false;
+        move_invader_normal_missile[missile_no].detach();
+    }
+}
+
+//Checks the bottom centre point for a collision. If it doesn't push the bitmap to the screen buffer
+void CollisionDetectionInvaderNormalMissile(int missile_no)
+{
+    //Invader missile coordinates shifted to match centre bottom of bitmap
+    int relative_x_pos = invader_normal_missile[missile_no].x_pos + 1;
+    int relative_y_pos = invader_normal_missile[missile_no].y_pos + 3;
+    if (screen_buffer[relative_x_pos][relative_y_pos] == cannon_pixel) {
+        InvaderNormalMissileHitCannon();
+        invader_normal_missile[missile_no].fired = false;
+        move_invader_normal_missile[missile_no].detach();
+    } 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)) {
+        //Finds barrier number
+        InvaderNormalMissileHitBarrier(invader_normal_missile[missile_no]);
+        invader_normal_missile[missile_no].fired = false;
+        move_invader_normal_missile[missile_no].detach();
+    } else {
+        for (int col = 0; col < 3; ++col) {
+            for (int row = 0; row < 4; ++row) {
+                if (invader_normal_missile_bitmap[row][col]) {
+                    screen_buffer[invader_normal_missile[missile_no].x_pos + col][invader_normal_missile[missile_no].y_pos + row] = invader_normal_missile_pixel;
+                }
+            }
+        }
+    }
+}
+
+void InvaderNormalMissileHitCannon()
+{
+    //Decrements the number of lives, pauses the game for 2 seconds
+    //Marks the cannon as hit
+    g_cannon_hit_flag = true;
+    //Detaches all tickers
+    DetachTickers();
+    //Creates a Timeout object on the stack with a period of 2 seconds to pause the game for 2 seconds
+    Timeout cannon_hit;
+    cannon_hit.attach(&cannon_hit_isr, 2);
+    while (g_cannon_hit_flag) {
+        sleep();
+    }
+    AttachTickers();
+    --number_of_lives;
+}
+
+//Calculates where to start drawing the damage bitmap over the barrier bitmap and performs the operation
+void InvaderNormalMissileHitBarrier(const struct InvaderNormalMissiles (&missile))
+{
+    int barrier_no = screen_buffer[missile.x_pos + 1][missile.y_pos + 3] - first_barrier_pixel;
+    //Essentially inverse of barrier init
+    int relative_x_pos = (missile.x_pos + 1) - 10 - (barrier_no*25) - 1;
+    int relative_y_pos = (missile.y_pos + 3) - 33;
+    //Loops through the damage bitmap and modifies the barrier's after bitmap
+    for (int col = 0; col < 3; ++col) {
+        for (int row_bit = 0; row_bit < 2; ++row_bit) {
+            //Makes sure bitmap index does not go out of bounds. If it does go to the next iteration
+            if (relative_x_pos + col >= 0 && relative_x_pos + col < 14 && relative_y_pos + row_bit >= 0 && relative_y_pos + row_bit < 8) {
+                barrier[barrier_no].after_bitmap[relative_y_pos + row_bit][relative_x_pos + col] *= barrier_invader_normal_missile_damage_bitmap[row_bit][col];
+            }
+        }
+    }
+}
+
+//Detaches game related tickers
 void DetachTickers()
 {
     update_screen.detach();
     move_enemies.detach();
+    //Only detaches if missiles are on the screen
     if (cannon_missile_on_screen) {
         move_cannon_missile.detach();
     }
@@ -1446,11 +1028,12 @@
     }
 }
 
+//Attaches game related tickers
 void AttachTickers()
 {
     update_screen.attach(&update_screen_isr, 0.05);
     move_enemies.attach(&move_enemies_isr, ticker_period);
-
+    //Only attaches if missiles were on the screen
     if (cannon_missile_on_screen) {
         move_cannon_missile.attach(&move_cannon_missile_isr, 0.05);
     }
@@ -1463,10 +1046,10 @@
 
 void PauseScreen()
 {
+    //Prints the pause screen, score etc
+    PrintPauseScreen();
+
     while (game_state == paused) {
-        //Prints the pause screen, score etc
-        PrintPauseScreen();
-
         //Draws the cursor
         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
         lcd.drawRect(74, cursor_y_pos, 2, 2, 1); //Draws the cursor