ELEC2645 (2018/19) / Mbed 2 deprecated EL17MCD

Dependencies:   mbed

Revision:
17:cb39d9fa08dc
Parent:
16:a2c945279b79
Child:
18:165e3d49daa8
--- a/TanksEngine/TanksEngine.cpp	Wed Apr 24 13:44:12 2019 +0000
+++ b/TanksEngine/TanksEngine.cpp	Sat Apr 27 17:43:46 2019 +0000
@@ -7,9 +7,9 @@
 TanksEngine::TanksEngine()
 
 {
-    _tankl.set_movement_limits(0, 21);
-    _tankr.set_movement_limits(54, 74);
-    _grav = 0.035;
+  _tankl.set_movement_limits(0, 21);            // Prevent tanks from leaving the screen
+  _tankr.set_movement_limits(54, 74);           // or passing through map obstacle
+  _grav = 0.035;
 }
 
 TanksEngine::~TanksEngine()
@@ -17,240 +17,263 @@
 
 }
 
-void TanksEngine::initgame(Menus &menus)
-{
-    // Player Preferences:
-    _initial_health = menus.get_health();
-    _mute = menus.get_mute();
-    _tankl.set_health(_initial_health);
-    _tankr.set_health(_initial_health);
+void TanksEngine::initgame(Menus &menus)         // initialise a game based on preferences
+{                                                // set in the menus, reset member variable's
+    // Player Preferences:                       // values from the previous game.
+  _initial_health = menus.get_health();
+  _mute = menus.get_mute();
+  _tankl.set_health(_initial_health);
+  _tankr.set_health(_initial_health);
     // Set up Game:
-    _tankl.set_position(0, 0);
-    _tankr.set_position(84-10, 0);
-    _turn = 1; 
-    _wind = 0.00005 * (-100 + rand() % 201);
-    _fire = false;
-    _move = 0;
-    _cooldown_l = -1;
-    _cooldown_r = -1;
-    _turn_counter = 1;
+  _tankl.set_position(0, 0);
+  _tankr.set_position(84-10, 0);
+  _turn = 1; 
+  _wind = 0.00005 * (-100 + rand() % 201);       // Determines "strength" of wind in horizontal
+  _fire = false;                                 // x direction.
+  _move = 0;
+  _cooldown_l = -1;
+  _cooldown_r = -1;
+  _turn_counter = 1;
     
 }
 
-void TanksEngine::game_loop(Graphics &graphics, N5110 &lcd, Gamepad &pad, Menus &menus, Scores &scores)
-{
-    while (_turn != 0) {
-        
-        lcd.clear();  
-        _read_input(pad); 
-        graphics.draw_parkinson_map(31, 17, lcd);    
-        if (_turn == 1) {
-            _left_tank_turn(graphics, pad);
-        } else if (_turn == 2 || _turn == 4) {
-            _projectile_phase(lcd, pad);
-        } else if (_turn == 3) {
-            _right_tank_turn(graphics, pad); 
-        } else if (_turn == 5) {
-            _end(graphics, lcd, pad, scores);
-        }   
-        _draw(graphics, lcd);
-        lcd.refresh();
-        wait_ms(1000/60); 
-    } 
+void TanksEngine::game_loop(Graphics &graphics, N5110 &lcd, Gamepad &pad,   // The fundemental game loop,
+                            Menus &menus, Scores &scores)                   // the phase of the game is determined
+{                                                                           // by _turn. Read's gamepad and writes
+  while (_turn != 0) {                                                      // to lcd.
+    lcd.clear();  
+    _read_input(pad); 
+    graphics.draw_parkinson_map(31, 17, lcd); // Draws map obstacle on the screen.
+    if (_turn == 1) {
+      _left_tank_turn(graphics, pad);
+    } else if (_turn == 2 || _turn == 4) {
+      _projectile_phase(lcd, pad);            
+    } else if (_turn == 3) {                  
+      _right_tank_turn(graphics, pad);        
+    } else if (_turn == 5) {
+      _end(graphics, lcd, pad, scores);       // When either player drops to zero health, the 
+    }                                         // game stops and an end screen is shown.
+    _draw(graphics, lcd);
+    lcd.refresh();
+    wait_ms(1000/60); 
+  } 
 }
+
 // Game Flow
+
 void TanksEngine::_left_tank_turn(Graphics &graphics, Gamepad &pad)
 {
-        _tankl.move_position(_move); 
-        if (_angle >= 355 && _angle <= 360 || _angle >= 0 && _angle <= 90) {// turret must be at acceptable angle
-            _tank_shoots(_tankl.get_position_x(), _tankl.get_position_y(), 2, pad);
-        }
-        graphics.show_health(_tankl.get_health(), pad); // Show player's health in LEDs
+  _tankl.move_position(_move); 
+  if (_angle >= 355 && _angle <= 360 || _angle >= 0 && _angle <= 90) {         // turret must be at acceptable angle
+      _tank_shoots(_tankl.get_position_x(), _tankl.get_position_y(), 2, pad);
+  }
+  graphics.show_health(_tankl.get_health(), pad);                              // Show player's health in LEDs
 }
 
 void TanksEngine::_right_tank_turn(Graphics &graphics, Gamepad &pad)
 {
-        _tankr.move_position(_move);
-        if (_angle >= 270 && _angle <= 360 || _angle >= 0 && _angle <= 5) {// turret must be at acceptable angle
-            _tank_shoots(_tankr.get_position_x(), _tankr.get_position_y(), 4, pad);
-        }
-        graphics.show_health(_tankr.get_health(), pad); // Show player's health in LEDs
+  _tankr.move_position(_move);
+  if (_angle >= 270 && _angle <= 360 || _angle >= 0 && _angle <= 5) {          // turret must be at acceptable angle
+      _tank_shoots(_tankr.get_position_x(), _tankr.get_position_y(), 4, pad);
+  }
+  graphics.show_health(_tankr.get_health(), pad);                              // Show player's health in LEDs
 }
 
-void TanksEngine::_projectile_phase(N5110 &lcd, Gamepad &pad)
-{
-    _proj.update_flight();
-    _proj.generate_hitbox();
-    if (_proj.check_boundaries() == true) { _change_turn(); } // change turn if projectile falls off left,
-    _object_hit(_proj.get_position_x(), _proj.get_position_y(), lcd, pad);    
-}
+void TanksEngine::_projectile_phase(N5110 &lcd, Gamepad &pad)             // Projectile phase; where player's cannot impact game
+{                                                                         // and await the projectile to leave boundaries or
+  _proj.update_flight();                                                  // collide with an object.
+  _proj.generate_hitbox();
+  if (_proj.check_boundaries() == true) {                                 // change turn if projectile falls off left
+    _change_turn();                                                       // or right side of screen.
+  }               
+  _object_hit(_proj.get_position_x(), _proj.get_position_y(), lcd, pad);  // Check collision with other objects based on
+}                                                                         // projectile's current x and y position.
 
-void TanksEngine::_change_turn()
+void TanksEngine::_change_turn()                               // Determines who's turn is next or if game should end.
 {
-    if (_tankl.get_health() == 0 || _tankr.get_health() == 0) { _turn = 5; }
-    else if (_turn == 2) { _turn = 3; }
-    else if (_turn == 4) { 
-        _turn = 1; 
-        _turn_counter++;
-    }   
-    srand(time(0));   // Change wind
-    _wind = 0.00005 * (-100 + rand() % 201);
+  if (_tankl.get_health() == 0 || _tankr.get_health() == 0) { 
+    _turn = 5;
+  } else if (_turn == 2) { 
+    _turn = 3; 
+  } else if (_turn == 4) { 
+    _turn = 1; 
+    _turn_counter++;                                           // Increase turn counter for scoring purposes.
+  }   
+  srand(time(0));                                              // Randomly change wind in either positive or negative
+  _wind = 0.00005 * (-100 + rand() % 201);                     // horizontal x direction. srand seeds the rand function.
 }
 
-void TanksEngine::_end(Graphics &graphics, N5110 &lcd, Gamepad &pad, Scores &scores) 
+void TanksEngine::_end(Graphics &graphics, N5110 &lcd, Gamepad &pad,     // End screen that shows who won and their score.
+                       Scores &scores) 
 {
-    _turn = 0;
-    int score = scores.score_calculator(_turn_counter, _initial_health);
-    pad.check_event(Gamepad::BACK_PRESSED); // clears trigger
-    
-    while(pad.check_event(Gamepad::BACK_PRESSED) == false) {
-        
-        lcd.clear();
-        scores.display_score(score, lcd);
-        pad.check_event(Gamepad::START_PRESSED);
-        
-        if (_tankl.get_health() == 0) { 
-            graphics.draw_right_victory(lcd);
-        } 
-        else if  (_tankr.get_health() == 0) { 
-            graphics.draw_left_victory(lcd);        
-        } 
-        lcd.refresh();
-    }
-}
-// Game Mechanics
-void TanksEngine::_tank_shoots(int x, int y, int turn, Gamepad &pad)
-{
-    if (_fire == true) {  // _fire determined by A button; pressed= true
-        int angle = _angle; // change to an int
-        angle = (-angle + 90) % 360; // gamepad's convention is N = 0 clockwise changed into E = 0 anticlockwise
-        x = x + 5;
-        y = y + 5;
-        _proj.set_launch_parameters(x, y, angle, _vel, _grav, _wind); // set launch parameters for projectile based on tank/game parameters
-        _tankl.generate_hitbox(); // generate hitboxes ready to determine collision during projectile phase
-        _tankr.generate_hitbox();      
-        _turn = turn; // change to projectile phase
-        _sounds(3, pad);
-    }
+  _turn = 0;                                                             // This allows game loop to end and top-level loop to progress
+  int score = scores.score_calculator(_turn_counter, _initial_health);
+  pad.check_event(Gamepad::BACK_PRESSED);                                // Clears trigger so that the end screen is not skipped due to a 
+                                                                         // prevous button press.
+  while(pad.check_event(Gamepad::BACK_PRESSED) == false) {    
+    lcd.clear();
+    scores.display_score(score, lcd);
+    pad.check_event(Gamepad::START_PRESSED);                             // Clear trigger so start screen is not skipped.
+
+    if (_tankl.get_health() == 0) { 
+        graphics.draw_right_victory(lcd);
+    } 
+    else if  (_tankr.get_health() == 0) { 
+        graphics.draw_left_victory(lcd);        
+    } 
+    lcd.refresh();
+  }
 }
 
-void TanksEngine::_object_hit(int x, int y, N5110 &lcd, Gamepad &pad)
+// Game Mechanics
+
+void TanksEngine::_tank_shoots(int x, int y, int turn, Gamepad &pad)  // Govern's the shooting mechanic for the tanks.
 {
-    if (x >= 0 && x <= 30 && _collision_pl(_tankl, _proj) == true) {               
-        _tankl.lose_health();
-        _change_turn();
-        _sounds(1, pad);
+  if (_fire == true) {                                                // _fire determined by A button; pressed = true.
+    int angle = _angle;                                               // changes float _angle to an int angle for use in modulo arithmetic below.
+    angle = (-angle + 90) % 360;                                      // gamepad's convention is N = 0 clockwise changed into E = 0 anticlockwise.
+    x = x + 5;
+    y = y + 5;
+    _proj.set_launch_parameters(x, y, angle, _vel, _grav, _wind);     // set launch parameters for projectile based on tank/game parameters.
+    _tankl.generate_hitbox();                                         // generate hitboxes ready to determine collision during projectile phase.
+    _tankr.generate_hitbox();      
+    _turn = turn;                                                     // change to projectile phase.
+    _sounds(3, pad);
+  }
+}
+
+void TanksEngine::_object_hit(int x, int y, N5110 &lcd, Gamepad &pad)        // Decides when to check for collsions and
+{                                                                            // their impact.
+  if (x >= 0 && x <= 30 && _collision_pl(_tankl, _proj) == true) {               
+    _tankl.lose_health();
+    _change_turn();
+    _sounds(1, pad);
+  } else if (x >= 55 && x <= 83 && _collision_pr(_tankr, _proj) == true) {
+    _tankr.lose_health();
+    _change_turn();
+    _sounds(1, pad);
+  } else if (x >= 31 && x <= 54 && _collision_pm(x, y, lcd, _proj) == true) {
+    _change_turn();
+    _sounds(2, pad);
+  }
+}
+
+bool TanksEngine::_collision_pl(Tank _tankl, Projectile _proj) // Detects projectile hitting LEFT tank by comparing every 
+{                                                              // element in the projectile's hitbox array to that of the 
+  for (int i0 = 0; i0 < 4; i0++) {                             // tank's hitbox array.
+    for (int i1 = 0; i1 < 40; i1++) {
+      if (_proj.get_hitbox(i0) == _tankl.get_hitbox(i1)) { 
+        return true; 
+      }               
     }
-    else if (x >= 55 && x <= 83 && _collision_pr(_tankr, _proj) == true) {
-        _tankr.lose_health();
-        _change_turn();
-        _sounds(1, pad);
-    }
-    else if (x >= 31 && x <= 54 && _collision_pm(x, y, lcd, _proj) == true) {
-        _change_turn();
-        _sounds(2, pad);
-    }
+  }
+  return false;
 }
 
-bool TanksEngine::_collision_pl(Tank _tankl, Projectile _proj) // detects projectile hitting LEFT tank
-{
-    for (int i0 = 0; i0 < 4; i0++) {
-        for (int i1 = 0; i1 < 40; i1++) {
-            if (_proj.get_hitbox(i0) == _tankl.get_hitbox(i1)) { return true; }               
-        }
+bool TanksEngine::_collision_pr(Tank _tankr, Projectile _proj) // Detects projectile hitting RIGHT tank by comparing every 
+{                                                              // element in the projectile's hitbox array to that of the 
+  for (int i0 = 0; i0 < 4; i0++) {                             // tank's hitbox array.
+    for (int i1 = 0; i1 < 40; i1++) {
+      if (_proj.get_hitbox(i0) == _tankr.get_hitbox(i1)) {      
+        return true;
+      }               
     }
-    return false;
+  }
+  return false;
+}
+
+bool TanksEngine::_collision_pm(int x, int y, N5110 &lcd, Projectile _proj) // Detects projectiles hitting the MAP by comparing the
+{                                                                           // position of the projectile's bottom two pixels
+  if (lcd.getPixel(x, 48 - y) == 1) {                                       // to the positions on the screen. If they are occupied a 
+    return true;                                                            // pixel the map obstacle has been hit.
+  } else if (lcd.getPixel(x + 1,48 - y) == 1) {
+    return true; 
+  } else { 
+    return false ; 
+  }
 }
 
-bool TanksEngine::_collision_pr(Tank _tankr, Projectile _proj) // detects projectile hitting RIGHT tank
-{
-    for (int i0 = 0; i0 < 4; i0++) {
-        for (int i1 = 0; i1 < 40; i1++) {
-            if (_proj.get_hitbox(i0) == _tankr.get_hitbox(i1)) { return true; }               
-        }
-    }
-    return false;
+// Game Inputs
+
+void TanksEngine::_read_input(Gamepad &pad)                                    // Detects gamepad activity and it's bearing
+{                                                                              // on the game.
+  _vel = 1.15 + pad.read_pot(); 
+  _angle = pad.get_angle();
+  _mag = pad.get_mag();   
+  if (pad.check_event(Gamepad::L_PRESSED) == true && _cooldown_l < 0) {        // toggle movement to the left.
+    _move = -1 * !_move; 
+    _cooldown_l = 10;                                                          // Cooldown prevents multiple button presses being resistered.
+  } else if (pad.check_event(Gamepad::R_PRESSED) == true && _cooldown_r < 0) { // toggle movement to the right.
+    _move = 1 * !_move; 
+    _cooldown_r = 10;
+  } else if (_turn == 2 || _turn == 4) { 
+    _move = 0;                                                                 // movement cannot be triggered during projectile phase    
+  } 
+  if (pad.check_event(Gamepad::A_PRESSED) == true) {                           // Tank shoots if A button is pressed (assuming turret
+    _fire = true;                                                              // is at an acceptable angle).
+  } else { 
+  _fire = false; 
+  }   
+  _decrement_cooldowns();                                                      
 }
 
-bool TanksEngine::_collision_pm(int x, int y, N5110 &lcd, Projectile _proj) // detects projectile hitting the MAP
+void TanksEngine::_decrement_cooldowns() // Prevents buttons being pressed multiple times in quick succession.
 {
-    if (lcd.getPixel(x, 48 - y) == 1) { 
-        return true;
-    } else if (lcd.getPixel(x + 1,48 - y) == 1) {
-        return true; 
-    } else { return false ; }
-}
-// Game Inputs
-void TanksEngine::_read_input(Gamepad &pad)
-{ 
-    _vel = 1.15 + pad.read_pot(); 
-    _angle = pad.get_angle();
-    _mag = pad.get_mag();
-    
-    if (pad.check_event(Gamepad::L_PRESSED) == true && _cooldown_l < 0) {
-        _move = -1 * !_move; // toggle movement to the left 
-        _cooldown_l = 10;        
-    }
-    else if (pad.check_event(Gamepad::R_PRESSED) == true && _cooldown_r < 0) {
-        _move = 1 * !_move; // toggle movement to the right 
-        _cooldown_r = 10;
-    } 
-    else if (_turn == 2 || _turn == 4) { _move = 0; } // movement cannot be triggered during projectile phase
-    
-    if (pad.check_event(Gamepad::A_PRESSED) == true) { _fire = true; } 
-    else { _fire = false; }   
-    
-    _decrement_cooldowns();   
+  _cooldown_l--;
+  _cooldown_r--;
+  if (_cooldown_l < -100) { 
+    _cooldown_l = -1; 
+  }
+  if (_cooldown_r < -100) { 
+    _cooldown_r = -1; 
+  }
 }
 
-void TanksEngine::_decrement_cooldowns() // Prevents buttons being pressed multiple times in quick succession
-{
-    _cooldown_l--;
-    _cooldown_r--;
-    if (_cooldown_l < -100) { _cooldown_l = -1; }
-    if (_cooldown_r < -100) { _cooldown_r = -1; }
-}
 // Game Outputs
-void TanksEngine::_draw(Graphics graphics, N5110 &lcd) // Draw graphics for all objects, turrets rotate 
-{                                                       // depending on current turn
-        graphics.draw_tank_l(_tankl.get_position_x(), _tankl.get_position_y(), lcd);
-        if (_turn == 1) {
-            graphics.draw_turret_l(_tankl.get_position_x(), _tankl.get_position_y(), _angle, lcd); 
-            graphics.draw_wind_bar(_wind, lcd);
-            if (_mag >= 0.5) {
-            graphics.draw_reticle(_tankl.get_position_x(), _tankl.get_position_y(), _angle, lcd);       
-            }   
-        }
-        if (_turn == 2 || _turn == 4) {
-            graphics.draw_projectile(_proj.get_position_x(), _proj.get_position_y(), lcd);
-        }
-        graphics.draw_tank_r(_tankr.get_position_x(), _tankr.get_position_y(), lcd);
-        if (_turn == 3) {
-            graphics.draw_turret_r(_tankr.get_position_x(), _tankr.get_position_y(), _angle, lcd);
-            graphics.draw_wind_bar(_wind, lcd);
-            if (_mag >= 0.5) {
-            graphics.draw_reticle(_tankr.get_position_x(), _tankr.get_position_y(), _angle, lcd);       
-            }  
-        }
+
+void TanksEngine::_draw(Graphics graphics, N5110 &lcd)                         // Draw graphics for all objects, turrets rotate 
+{                                                                              // depending on current turn
+  graphics.draw_tank_l(_tankl.get_position_x(), _tankl.get_position_y(), lcd);
+  if (_turn == 1) {
+    graphics.draw_turret_l(_tankl.get_position_x(), _tankl.get_position_y(), 
+                           _angle, lcd); 
+    graphics.draw_wind_bar(_wind, lcd);
+    if (_mag >= 0.5) {                                                         // only draw the reticle if the joystick is not in
+      graphics.draw_reticle(_tankl.get_position_x(), _tankl.get_position_y(),  // a neutral position.
+                            _angle, lcd);       
+    }   
+  }
+  if (_turn == 2 || _turn == 4) {
+    graphics.draw_projectile(_proj.get_position_x(), _proj.get_position_y(), 
+                                                     lcd);
+  }
+  graphics.draw_tank_r(_tankr.get_position_x(), _tankr.get_position_y(), lcd);
+  if (_turn == 3) {
+    graphics.draw_turret_r(_tankr.get_position_x(), _tankr.get_position_y(), 
+                                                    _angle, lcd);
+    graphics.draw_wind_bar(_wind, lcd);
+    if (_mag >= 0.5) {
+      graphics.draw_reticle(_tankr.get_position_x(), _tankr.get_position_y(), 
+                            _angle, lcd);       
+    }  
+  }
 }
 
-void TanksEngine::_sounds(int n, Gamepad &pad)
+void TanksEngine::_sounds(int n, Gamepad &pad)  // Play sound relating to game event.
 {
-    if (_mute == false) {
-        if (n == 1) {            // tank's hit   
-            pad.tone(300, 0.125);
-            pad.tone(400, 0.125);
-            pad.tone(500, 0.125);
-        }
-        else if (n == 2) {     // building hit
-            pad.tone(500, 0.125);
-            pad.tone(400, 0.125);
-            pad.tone(300, 0.125);
-        } 
-        else if (n == 3) {    // tank shoots
-            pad.tone(200, 0.125);
-        }
+  if (_mute == false) {
+    if (n == 1) {                               // tank is hit.
+      pad.tone(300, 0.125);
+      pad.tone(400, 0.125);
+      pad.tone(500, 0.125);
+    } else if (n == 2) {                        // building hit.
+      pad.tone(500, 0.125);
+      pad.tone(400, 0.125);
+      pad.tone(300, 0.125);
+    } else if (n == 3) {                        // tank shoots.
+      pad.tone(200, 0.125);
     }
+  }
 }