Musallam Bseiso / Engine

Engine.cpp

Committer:
musallambseiso
Date:
2017-05-03
Revision:
13:f3560c403397
Parent:
12:d68c757d829a
Child:
14:94011e4a0624

File content as of revision 13:f3560c403397:

#include "Engine.h"

#define LEVEL_ONE 2
#define LEVEL_TWO 3
#define LEVEL_THREE 4
#define LEVEL_FOUR 5
#define LEVEL_FIVE 6

Engine::Engine()
{
    collisions = 0;     // Collisions variable. Maximum value of 5.
    wave_counter = 0;   // Wave counter variable.
    ammo = 3;           // Ammo variable. Shows if rockets (first weapon choice) are available. Maximum value of 3.
    star = true;        // Star variable. Shows if a star (second weapon choice) is available.
    pauses = 3;         // Pauses variable. Shows how many pauses the player has left.
}

Engine::~Engine()
{
}


// Initialization method:

void Engine::init(int speed, N5110 &lcd, Gamepad &pad, int _collisions, int _wave_counter, int _ammo, bool _star, int _pauses)
{
    _speed = speed;
    _friendly.init();       // Friendly ship initialization.
    
    // Enemy ships initialization:
    _enemy1.init(_speed);   
    _enemy2.init(_speed);
    _enemy3.init(_speed);
    _enemy4.init(_speed);
    _enemy5.init(_speed);
    _enemy6.init(_speed);
    printf("%s \n", "Friendly and enemy ships initialized.");
    
    // Initializing variable values:
    collisions = _collisions;         
    wave_counter = _wave_counter;
    ammo = _ammo;
    star = _star;
    pauses = _pauses;
}


// Method for reading the input from the gamepad analog stick:

void Engine::read_input(Gamepad &pad)
{
    _d = pad.get_direction();
    _mag = pad.get_mag();
}


// Drawing method:

void Engine::draw_all(N5110 &lcd)
{
    _stats.draw_grid(lcd);                          // Draws initial grid and border.
    _stats.draw_health(lcd);                        // Draws health counter (initial state).
    _stats.check_health_high(lcd, collisions);      // Checks and draws health counter (later states, high health).
    _stats.check_health_low(lcd, collisions);       // Checks and draws health counter (later states, low health).
    _stats.check_star(lcd, star);                   // Checks and draws star.
    _stats.check_rocket(lcd, ammo);                 // Checks and draws rocket.
    _stats.draw_wave_counter(lcd, wave_counter);    // Draws wave counter.
    _friendly.draw(lcd);                            // Draws friendly ship.
    
    // Draws enemy ships:
    _enemy1.draw(lcd);                              
    _enemy2.draw(lcd);
    _enemy3.draw(lcd);
    _enemy4.draw(lcd);
    _enemy5.draw(lcd);
    _enemy6.draw(lcd);
}


// Checks for changes in the game:

void Engine::check_all(N5110 &lcd, Gamepad &pad)
{
    check_enemy_pass_high(pad);             // Checks if upper enemy ships passed screen border and generates others.
    check_enemy_pass_low(pad);              // Checks if lower enemy ships passed screen border and generates others.
    check_friendly_death_all(lcd, pad);     // Checks for collisions and eventual friendly death.
    check_health_replenish();               // Checks if health should be replenished.
    check_rocket_replenish();               // Checks if rockets should be replenished.
    check_star_replenish();                 // Checks if star should be replenished.
    check_level_two(lcd, pad);              // Checks if level 2 has been reached.
    check_level_three(lcd, pad);            // Checks if level 3 has been reached.
    check_level_four(lcd, pad);             // Checks if level 4 has been reached.
    check_level_five(lcd, pad);             // Checks if level 5 has been reached.
    check_pause(lcd, pad);                  // Checks if the game has been paused/unpaused.
    check_mode_toggle(lcd, pad);            // Checks if the LCD mode has been toggled.
}


// Dynamic object position/velocity updater:

void Engine::update_all(N5110 &lcd, Gamepad &pad)
{
    _friendly.update_basic(_d,_mag);        // Updates position of friendly ship based on basic horizontal/vertical movements.
    _friendly.update_diagonal(_d,_mag);     // Updates position of friendly ship based on diagonal movements.
    _friendly.check_pos();                  // Prevents the friendly ship from going off-screen.
    
    // Updates enemy position:
    _enemy1.update();                       
    _enemy2.update();
    _enemy3.update();
    _enemy4.update();
    _enemy5.update();
    _enemy6.update();
}


// Method to enable shooting rockets:

void Engine::shoot_rocket(N5110 &lcd, Gamepad &pad)
{
    Vector2D friendly_pos = _friendly.get_pos();    // Obtains friendly ship's position.
    int _x = friendly_pos.x+6;                      // Sets the variables as the nose of the friendly ship.
    int _y = friendly_pos.y+3;
    _rocket.init(_x, _y);                           // Initializes the rocket at those variables.
    
    if ((pad.check_event(Gamepad::B_PRESSED) == true) &&    
        (ammo > 0))
    {   
        _rocket.draw(lcd);              // Draws the rocket beam.
        check_enemy_death_high(pad);    // Checks for upper enemy ship death.
        check_enemy_death_low(pad);     // Checks for lower enemy ship death.
        pad.tone(1500.0,0.1);           // Outputs a tone.
        ammo = ammo - 1;                // Removes a rocket from the inventory.
        printf("A rocket has been shot. Remaining ammo: %d \n", ammo);
    }
}


// Method to enable shooting rockets:

void Engine::shoot_star(N5110 &lcd, Gamepad &pad)
{   
    if ((pad.check_event(Gamepad::A_PRESSED) == true) &&
        (star == true))
    {    
        // Reinitializes all enemies when a star is shot:
        _enemy1.init(_speed);
        _enemy2.init(_speed);
        _enemy3.init(_speed);
        _enemy4.init(_speed);
        _enemy5.init(_speed);
        _enemy6.init(_speed);
        
        wave_counter = wave_counter + 1;            // Sends the player to the next wave.
        pad.tone(2000.0,0.5);                       
        star = false;                               // Removes the star from the inventory.
        printf("%s \n", "A star has been shot.");
    }
}


// Checks if upper enemy ships passed off screen and re-initializes ones that have:

void Engine::check_enemy_pass_high(Gamepad &pad)
{
    Vector2D enemy1_pos = _enemy1.get_pos();
    Vector2D enemy2_pos = _enemy2.get_pos();
    Vector2D enemy3_pos = _enemy3.get_pos();
    
    if (enemy1_pos.x < 0) {                 // Checks if the Enemy1 ship's x position is negative (off-screen).
        _enemy1.init(_speed);               // Reinitializes Enemy1.
        wave_counter = wave_counter + 1;    // Wave counter is associated to Enemy1.
        health_regen_trigger = false;       // Sets the regen triggers to false to allow for further regeneration in next waves.
        rocket_regen_trigger = false;       
        star_regen_trigger = false;
        printf("A wave has passed. Current wave: %d \n", wave_counter);
    }
    if (enemy2_pos.x < 0) {
        _enemy2.init(_speed);
    }
    if (enemy3_pos.x < 0) {
        _enemy3.init(_speed);
    }
}


// Checks if lower enemy ships passed off screen and re-initializes ones that have:

void Engine::check_enemy_pass_low(Gamepad &pad)
{
    Vector2D enemy4_pos = _enemy4.get_pos();
    Vector2D enemy5_pos = _enemy5.get_pos();
    Vector2D enemy6_pos = _enemy6.get_pos();
    
    if (enemy4_pos.x < 0) {
        _enemy4.init(_speed);
    }
    
    if (enemy5_pos.x < 0) {
        _enemy5.init(_speed);
    }
    
    if (enemy6_pos.x < 0) {
        _enemy6.init(_speed);
    }
}


// Checks if upper enemy ships have been destroyed:

void Engine::check_enemy_death_high(Gamepad &pad)
{
    Vector2D friendly_pos = _friendly.get_pos();
    
    if (friendly_pos.y < 5) {   // Checks if the friendly ship is opposite the Enemy1 ship.
        _enemy1.init(_speed);   // Reinitializes the Enemy1 ship.
        printf("%s \n", "Enemy1 has been destroyed by a rocket and reinitialized.");
    } 
    else if ((friendly_pos.y < 11) &&
            (friendly_pos.y > 4)) {
        _enemy2.init(_speed);
        printf("%s \n", "Enemy2 has been destroyed by a rocket and reinitialized.");
    }
    else if ((friendly_pos.y < 17) &&
            (friendly_pos.y > 10)) {
        _enemy3.init(_speed);
        printf("%s \n", "Enemy3 has been destroyed by a rocket and reinitialized.");
    }  
}


// Checks if lower enemy ships have been destroyed:

void Engine::check_enemy_death_low(Gamepad &pad)
{
    Vector2D friendly_pos = _friendly.get_pos();
    
    if ((friendly_pos.y < 25) &&
        (friendly_pos.y > 16)) {
        _enemy4.init(_speed);
        printf("%s \n", "Enemy4 has been destroyed by a rocket and reinitialized.");
    }
    else if ((friendly_pos.y < 31) &&
            (friendly_pos.y > 24)) {
        _enemy5.init(_speed);
        printf("%s \n", "Enemy5 has been destroyed by a rocket and reinitialized.");
    }
    else if (friendly_pos.y > 30) {
        _enemy6.init(_speed);
        printf("%s \n", "Enemy6 has been destroyed by a rocket and reinitialized.");
    }    
}


// Checks for collisions between friendly and an enemy ship:

void Engine::check_friendly_death(Gamepad &pad, Vector2D enemy_pos)
{
    Vector2D friendly_pos = _friendly.get_pos();
    
    if ((friendly_pos.y >= enemy_pos.y-5) &&    // Checks if x and y coordinates of friendly and enemy ships
        (friendly_pos.y <= enemy_pos.y+5) &&    // match, including the friendly and enemy size.
        (friendly_pos.x+6 >= enemy_pos.x) && 
        (friendly_pos.x+6 <= enemy_pos.x+5)) 
    {
        pad.tone(800.0,0.1);
        collisions = collisions + 1;            // Registers a collision.
    }
}


// Checks for collisions between friendly and each enemy ship:

void Engine::check_friendly_death_all(N5110 &lcd, Gamepad &pad)
{
    Vector2D enemy1_pos = _enemy1.get_pos();
    Vector2D enemy2_pos = _enemy2.get_pos();
    Vector2D enemy3_pos = _enemy3.get_pos();
    Vector2D enemy4_pos = _enemy4.get_pos();
    Vector2D enemy5_pos = _enemy5.get_pos();
    Vector2D enemy6_pos = _enemy6.get_pos();
    
    // Executes the "check_friendly_death" method for each enemy ship:
    check_friendly_death(pad, enemy1_pos);
    check_friendly_death(pad, enemy2_pos);
    check_friendly_death(pad, enemy3_pos);
    check_friendly_death(pad, enemy4_pos);
    check_friendly_death(pad, enemy5_pos);
    check_friendly_death(pad, enemy6_pos);
    
    check_gameover(lcd, pad);   // Game over sequence, runs if health subzero.
}


// Checks if it is time for health to be replenished:

void Engine::check_health_replenish()
{
    if (!(collisions == 0) &&               // Checks if player isnt already at full health.
        (rocket_regen_trigger == false)) {  // Checks if health hasn't already been replenished this wave. (to prevent spamming)
            if ((wave_counter == 20) ||     // Checks if the game is at a certain wave:
                (wave_counter == 40) ||
                (wave_counter == 60) ||
                (wave_counter == 80) ||
                (wave_counter == 100) ||
                (wave_counter == 120) ||
                (wave_counter == 140) ||
                (wave_counter == 160) ||
                (wave_counter == 180) ||
                (wave_counter == 200)) {        
            collisions = collisions - 1;    // Adds health to the health bar.
            health_regen_trigger = true;    // Sets the trigger to show health has already been replenished this wave.
            printf("%s \n", "Health has been regenerated.");
            }     
    }
}


// Checks if it is time for a rocket to be replenished:

void Engine::check_rocket_replenish()
{
    if ((ammo < 3) &&                       // Checks if player doesn't already have 3 rockets.
        (rocket_regen_trigger == false)) {  // Checks if a rocket hasn't already been replenished this wave. (to prevent spamming)
            if ((wave_counter == 5) ||      // Checks if the game is at a certain wave:
                (wave_counter == 10) ||
                (wave_counter == 15) ||
                (wave_counter == 20) ||
                (wave_counter == 25) ||
                (wave_counter == 30) ||
                (wave_counter == 50) ||
                (wave_counter == 75) ||
                (wave_counter == 100) ||
                (wave_counter == 150) ||
                (wave_counter == 200)) {        
            ammo = ammo + 1;                // Adds a rocket to the inventory.
            rocket_regen_trigger = true;    // Sets the trigger to show a rocket has already been replenished this wave.
            printf("A rocket has been regenerated. Current number of rockets: %d \n", ammo);
            }     
    }
}


// Checks if it is time for the star to be replenished:

void Engine::check_star_replenish()
{
    if ((star == false) &&                  // Checks if player doesn't already have a star.
        (star_regen_trigger == false))      // Checks if a star hasn't already been replenished this wave. (to prevent spamming)
    {    
            if ((wave_counter == 5) ||      // Checks if the game is at a certain wave:
                (wave_counter == 25) ||
                (wave_counter == 50) ||
                (wave_counter == 100) ||
                (wave_counter == 150) ||
                (wave_counter == 200)) 
            {        
            star = true;                    // Adds the star to the inventory.
            star_regen_trigger = true;      // Sets the trigger to show the star has already been replenished this wave.
            printf("%s \n", "A star has been regenerated."); 
            }     
    }
}


// Level two sequence, occurs if wave 5 is reached:

void Engine::check_level_two(N5110 &lcd, Gamepad &pad)
{
    if (wave_counter == 5) 
    {
        lcd.drawRect(0,0,84,48,FILL_WHITE);
        lcd.printString(" Nice! Level 2",0,1);
        lcd.printString("  Press Back!  ",0,4);
        lcd.refresh();
        wait(1);
        
        while (pad.check_event(Gamepad::BACK_PRESSED) == false) {   // Waits until the back button is pressed.
            wait(0.1);
        }
        
        init(LEVEL_TWO, lcd, pad, collisions, wave_counter, ammo, star, pauses);    // Initializes the ships at an elevated speed.
        wave_counter = 6;               // Increments the wave counter.
        printf("%s \n", "Level two has been reached.");
    }
}


// Level three sequence, occurs if wave 25 is reached:

void Engine::check_level_three(N5110 &lcd, Gamepad &pad)
{
    if (wave_counter == 25) 
    {
        lcd.drawRect(0,0,84,48,FILL_WHITE);
        lcd.printString(" Nice! Level 3",0,1);
        lcd.printString("  Press Back!  ",0,4);
        lcd.refresh();
        wait(1);
        
        while (pad.check_event(Gamepad::BACK_PRESSED) == false) {
            wait(0.1);
        }
        
        init(LEVEL_THREE, lcd, pad, collisions, wave_counter, ammo, star, pauses);
        wave_counter = 26;
        printf("%s \n", "Level three has been reached.");
    }
}


// Level three sequence, occurs if wave 50 is reached:

void Engine::check_level_four(N5110 &lcd, Gamepad &pad)
{
    if (wave_counter == 50) 
    {
        lcd.drawRect(0,0,84,48,FILL_WHITE);
        lcd.printString(" Nice! Level 4",0,1);
        lcd.printString("  Press Back!  ",0,4);
        lcd.refresh();
        wait(1);
        
        while (pad.check_event(Gamepad::BACK_PRESSED) == false) {
            wait(0.1);
        }
        
        init(LEVEL_FOUR, lcd, pad, collisions, wave_counter, ammo, star, pauses);
        wave_counter = 51;
        printf("%s \n", "Level four has been reached.");
    }
}


// Level five sequence, occurs if wave 100 is reached:

void Engine::check_level_five(N5110 &lcd, Gamepad &pad)
{
    if (wave_counter == 100) 
    {
        lcd.drawRect(0,0,84,48,FILL_WHITE);
        lcd.printString(" 5. Good Luck!",0,1);
        lcd.printString("  Press Back!  ",0,4);
        lcd.refresh();
        wait(1);
        
        while (pad.check_event(Gamepad::BACK_PRESSED) == false) {
            wait(0.1);
        }
        
        init(LEVEL_FIVE, lcd, pad, collisions, wave_counter, ammo, star, pauses);
        wave_counter = 101;
        printf("%s \n", "Level five has been reached.");
    }
}


// Pause sequence, checks if the game has been paused/unpaused

void Engine::check_pause(N5110 &lcd, Gamepad &pad)
{   
    if ((pad.check_event(Gamepad::START_PRESSED) == true) &&  // Checks if the start button has been pressed.
        (pauses > 0))       // Checks if the player has remaining pauses.
    {   
        printf("%s \n", "The game has been paused.");   
        while (pad.check_event(Gamepad::START_PRESSED) == false) {  
        // Flashes LEDs, switches between inverse and normal LCD modes, and waits until start button is pressed (unpause):
            pad.leds_on();      
            lcd.inverseMode();
            wait(0.5);
            pad.leds_off();
            lcd.normalMode();
            wait(0.5);
        }
    pauses = pauses - 1;    // Takes a pause from the player.
    printf("%s \n", "The game has been unpaused.");
    }
}


// Checks if the LCD's display mode has been toggled:

void Engine::check_mode_toggle(N5110 &lcd, Gamepad &pad)
{
    if (pad.check_event(Gamepad::R_PRESSED) == true) {  // Checks if right button is pressed.
            lcd.normalMode();                           // Sets the LCD to normal mode.
            pad.tone(1000.0,0.2);
            printf("%s \n", "Normal LCD mode has been toggled on.");
    }
    
    if (pad.check_event(Gamepad::L_PRESSED) == true) {  // Checks if left button is pressed.
            lcd.inverseMode();                          // Sets the LCD to inverse mode.
            pad.tone(1000.0,0.2);
            printf("%s \n", "Inverse LCD mode has been toggled on.");
    }
}


// Game over sequence, ends game if health is below zero:

void Engine::check_gameover(N5110 &lcd, Gamepad &pad)
{
    if (collisions >= 6) {                      // Checks if collisions are above 6 (health zero).
        lcd.drawRect(0,0,84,48,FILL_WHITE);     // Draws a dialog box.
        char buffer[14];
        int length = sprintf(buffer,"  Score: %2d",wave_counter);
        lcd.printString(buffer,0,2);            // Displays how many waves the player survived.
        lcd.printString("  You Lose! ",0,1);
        lcd.printString("  Press Back! ",0,4);
        lcd.refresh();
        
        printf("%s \n", "The player has lost.");    
        
        while (pad.check_event(Gamepad::BACK_PRESSED) == false) {   // Waits until the back button is pressed.
            wait(0.1);
        }
        
        printf("%s \n", "The player has restarted the game.");
        init(LEVEL_ONE, lcd, pad, 0, 0, 3, true, 3);      // Reinitializes the game at the lowest speed. Reinitializes variables.
    }
}