ELEC2645 (2018/19) / Mbed 2 deprecated EL17MCD

Dependencies:   mbed

TanksEngine/TanksEngine.cpp

Committer:
el17mcd
Date:
2019-04-19
Revision:
15:fa5282fcd134
Parent:
14:fe2e16cdf219
Child:
16:a2c945279b79

File content as of revision 15:fa5282fcd134:

/* TanksEngine.cpp
Game Engine
9.4.19
*/
#include "TanksEngine.h"

TanksEngine::TanksEngine()

{
    _tankl.set_movement_limits(0, 21);
    _tankr.set_movement_limits(0, 21);
    _grav = 0.035;
}

TanksEngine::~TanksEngine()
{

}

void TanksEngine::initgame(Menus &menus)
{
    _initial_health = menus.get_lives();
    _mute = menus.get_mute();
    _tankl.set_position(0, 0);
    _tankr.set_position(84-10, 0);
    _tankl.set_health(_initial_health);
    _tankr.set_health(_initial_health);
    _turn = 1; 
    _wind = 0.00005 * (-100 + rand() % 201);
    _fire = false;
    _move = 0;
    _score = 0;
    _cooldown_l = -1;
    _cooldown_r = -1;
    
}

void TanksEngine::game_loop(Graphics &graphics, N5110 &lcd, Gamepad &pad)
{
    while (_turn != 0) {
        _score++;
        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);
        }            
        _render(graphics, lcd);
        lcd.refresh();
        wait_ms(1000/60); 
    } 
}

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(), 6, pad);
}

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(), 6, pad);
}

void TanksEngine::_render(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::_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);
    }
}

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(lcd, pad);    
}

void TanksEngine::_change_turn()
{
    if (_tankl.get_health() == 0 || _tankr.get_health() == 0) { _turn = 5; }
    else if (_turn == 2) { _turn = 3; }
    else if (_turn == 4) { _turn = 1; }
    srand(time(0));
    _wind = 0.00005 * (-100 + rand() % 201);
}

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();   
}

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; }               
        }
    }
    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;
}

bool TanksEngine::_collision_pm(N5110 &lcd, Projectile _proj) // detects projectile hitting the MAP
{
    int x = _proj.get_position_x();
    int y = _proj.get_position_y();
    if (x >= 31 && x <= 54) {
        if (lcd.getPixel(x, 48 - y) == 1) { 
            return true;
        } else if (lcd.getPixel(x + 1,48 - y) == 1) {
            return true; 
        } else { return false ;}
    }
    else {return false ; }
}

void TanksEngine::_object_hit(N5110 &lcd, Gamepad &pad)
{
    if (_collision_pl(_tankl, _proj) == true) {               
        _tankl.lose_health();
        _change_turn();
        _sounds(1, pad);
    }
    else if (_collision_pr(_tankr, _proj) == true) {
        _tankr.lose_health();
        _change_turn();
        _sounds(1, pad);
    }
    else if (_collision_pm(lcd, _proj) == true) {
        _change_turn();
        _sounds(2, pad);
    }
}

void TanksEngine::_sounds(int n, Gamepad &pad)
{
    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);
        }
    }
}

int TanksEngine::get_turn()
{
    return _turn;
}

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; }
}

void TanksEngine::_end(Graphics &graphics, N5110 &lcd, Gamepad &pad) 
{
    _turn = 0;
    while(pad.check_event(Gamepad::BACK_PRESSED) == false) {
        
        lcd.clear();
        _score = _score * 100 / _initial_health;
        if (_tankl.get_health() == 0) { 
            graphics.draw_tank_r(37, 20, lcd);
            graphics.draw_turret_r(37, 20, 180, lcd);
        } 
        else if  (_tankr.get_health() == 0) { 
            graphics.draw_tank_l(37, 20, lcd);
            graphics.draw_turret_l(37, 20, 180, lcd);         
        }
        char buffer[14]; 
        sprintf(buffer,"%d",_score);  
        lcd.printString(buffer, 48, 5);
        lcd.refresh();
    }
}