Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
Diff: TanksEngine/TanksEngine.cpp
- 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);
}
+ }
}