demo

Dependencies:   mbed Gamepad N5110

Engine/Engine.cpp

Committer:
Ting12138
Date:
2020-05-14
Revision:
0:ba32cfe0051e

File content as of revision 0:ba32cfe0051e:

#include "Engine.h"

Engine::Engine()
{

}

Engine::~Engine()
{

}

void Engine::init(int wall_width,int wall_gap,int foods_size,int velocity) {
    
    // initialise the game parameters
    _wall_width = wall_width;
    _wall_gap = wall_gap; // wall gap presents the distance between the top wall and the bottom wall, which is licked to difficulty
    _foods_size = foods_size; // larger foods means it will have larger area to trigger it "_rocket.add_score();"
    _velocity = velocity; 

    // x position on screen - WIDTH is defined in N5110.h
    _w0x = WIDTH; // there is total 5 walls in the game, all are placed in distributed positions
    _w1x = WIDTH + 30;
    _w2x = WIDTH + 60;
    _w3x = WIDTH + 90;
    _w4x = WIDTH + 120;
    _rocketx = 10;
    _foodsx = WIDTH + 105;

    _w0.init(_w0x,_wall_gap,_wall_width,_velocity); // initiate all walls with random holes
    _w1.init(_w1x,_wall_gap,_wall_width,_velocity);
    _w2.init(_w2x,_wall_gap,_wall_width,_velocity);
    _w3.init(_w3x,_wall_gap,_wall_width,_velocity);
    _w4.init(_w4x,_wall_gap,_wall_width,_velocity);
    _rocket.init(_rocketx); // set the rocket in the middle
    _foods.init(_foodsx,_foods_size,_velocity); // initiate foods size and a random y position
}

void Engine::read_input(Gamepad &pad) { // get joystick reading
    
    _d = pad.get_direction();
    _mag = pad.get_mag();
    _mapped_coord = pad.get_mapped_coord();
}

void Engine::draw(N5110 &lcd) {
    // draw the elements in the LCD buffer
    // pitch
    lcd.drawRect(0,0,WIDTH,HEIGHT,FILL_TRANSPARENT);
    // walls
    _w0.draw1(lcd);
    _w0.draw2(lcd);
    _w1.draw1(lcd);
    _w1.draw2(lcd);
    _w2.draw1(lcd);
    _w2.draw2(lcd);
    _w3.draw1(lcd);
    _w3.draw2(lcd);
    _w4.draw1(lcd);
    _w4.draw2(lcd);
    // the rocket
    _rocket.draw(lcd);
    // foods
    _foods.draw(lcd);
}


void Engine::update(Gamepad &pad) {
    
    //It's important to check that the walls, rockets, and food are updated before the collision, so that it can be fixed before the new food is updated
    _w0.update();
    _w1.update();
    _w2.update();
    _w3.update();
    _w4.update();
    _rocket.replace(_d,_mag,_mapped_coord);
    _foods.update();
    check_wall_collision(pad);
    check_score(pad);
}

void Engine::check_wall_collision(Gamepad &pad) {
    
    // read the position of rocket
    Vector2D rocket_pos = _rocket.get_pos();
    
    //read all of these positions of the wall
    int w0_x = _w0.get_x();
    int w1_x = _w1.get_x();
    int w2_x = _w2.get_x();
    int w3_x = _w3.get_x();
    int w4_x = _w4.get_x();
    
    if (w0_x <= 1) {  //  When the rocket passes behind the wall, it will reset to its original position to continue the game
        _w0.reset();
    }
    if (w1_x <= 1) {
        _w1.reset();
    }
    if (w2_x <= 1) {
        _w2.reset();
    }
    if (w3_x <= 1) {
        _w3.reset();
    }
    if (w4_x <= 1) {
        _w4.reset();
    }
    
    int w0_height = _w0.get_height(); // get the specific, random height for each of the walls
    int w1_height = _w1.get_height();
    int w2_height = _w2.get_height();
    int w3_height = _w3.get_height();
    int w4_height = _w4.get_height();
    
    if ((
         (rocket_pos.y + 5 >= 0) && (rocket_pos.y + 1 <= w0_height) && // check all the top wall corner collision and the bottom for all the walls
         (rocket_pos.x + 10 >= _w0.get_x()) && (rocket_pos.x + 10 <= _w0.get_x() + 1) // left and right collisions
        ) || (
         (rocket_pos.y + 5 >= 0) && (rocket_pos.y + 1 <= w1_height) &&
         (rocket_pos.x + 10 >= _w1.get_x()) && (rocket_pos.x + 10 <= _w1.get_x() + 1)
        ) || (
         (rocket_pos.y + 5 >= 0) && (rocket_pos.x + 1 <= w2_height) &&
         (rocket_pos.x + 10 >= _w2.get_x()) && (rocket_pos.x + 10 <= _w2.get_x() + 1)
        ) || (
         (rocket_pos.y + 5 >= 0) && (rocket_pos.y + 1 <= w3_height) &&
         (rocket_pos.x + 10 >= _w3.get_x()) && (rocket_pos.x + 10 <= _w3.get_x() + 1)
        ) || (
         (rocket_pos.y + 5 >= 0) && (rocket_pos.y + 1 <= w4_height) &&
         (rocket_pos.x + 10 >= _w4.get_x()) && (rocket_pos.x + 10 <= _w4.get_x() + 1)
        )
       ) {
        _rocket.lose_score(); // if collision does happen, foods are lost because of the unnecessary time of interference
        
        pad.tone(130.0,0.1); // sad sound playing
        wait(0.1);
        pad.tone(230.0,0.1);
        wait(0.1);
        pad.tone(330.0,0.1);
        wait(0.1);
        pad.tone(430.0,0.1);
        wait(0.1);
        pad.tone(530.0,0.1);
        wait(0.1);
    }
    
    if ((
         (rocket_pos.y + 5 >= _wall_gap + w0_height) && (rocket_pos.y + 1 <= HEIGHT) && // check collisions for the bottom wall
         (rocket_pos.x + 10 >= _w0.get_x()) && (rocket_pos.x + 10 <= _w0.get_x() + 1) // left and right side
        ) || (
         (rocket_pos.y + 5 >= _wall_gap + w1_height) && (rocket_pos.y + 1 <= HEIGHT) &&
         (rocket_pos.x + 10 >= _w1.get_x()) && (rocket_pos.x + 10 <= _w1.get_x() + 1)
        ) || (
         (rocket_pos.y + 5 >= _wall_gap + w2_height) && (rocket_pos.y + 1 <= HEIGHT) &&
         (rocket_pos.x + 10 >= _w2.get_x()) && (rocket_pos.x + 10 <= _w2.get_x() + 1)
        ) || (
         (rocket_pos.y + 5 >= _wall_gap + w3_height) && (rocket_pos.y + 1 <= HEIGHT) &&
         (rocket_pos.x + 10 >= _w3.get_x()) && (rocket_pos.x + 10 <= _w3.get_x() + 1)
        ) || (
         (rocket_pos.y + 5 >= _wall_gap + w4_height) && (rocket_pos.y + 1 <= HEIGHT) &&
         (rocket_pos.x + 10 >= _w4.get_x()) && (rocket_pos.x + 10 <= _w4.get_x() + 1)
        )
       ) {
        _rocket.lose_score(); // score lost
        
        pad.tone(100.0,0.1); // sad sound
        wait(0.1);
        pad.tone(200.0,0.1);
        wait(0.1);
        pad.tone(300.0,0.1);
        wait(0.1);
        pad.tone(400.0,0.1);
        wait(0.1);
        pad.tone(500.0,0.1);
        wait(0.1);
    }
}

void Engine::check_score(Gamepad &pad) { //check the score to trigger how many leds should be turned on
    
    int rocket_score = _rocket.get_final_score(); // get score
    
    if (rocket_score == 0) { // 7 if statements represents 7 conditions
        pad.leds_off();
    }
    if (rocket_score == 1) { // getting one food turns on 1 led
        pad.led(1,1.0f);
        pad.led(2,0.0f);
        pad.led(2,0.0f);
        pad.led(2,0.0f);
        pad.led(2,0.0f);
        pad.led(2,0.0f);
    }
    if (rocket_score == 2) { // two foodds, two led
        pad.led(1,1.0f);
        pad.led(2,0.0f);
        pad.led(3,0.0f);
        pad.led(4,0.0f);
        pad.led(5,0.0f);
        pad.led(6,1.0f);
    }
    if (rocket_score == 3) {
        pad.led(1,1.0f);
        pad.led(2,1.0f);
        pad.led(3,0.0f);
        pad.led(4,0.0f);
        pad.led(5,0.0f);
        pad.led(6,1.0f);
    }
    if (rocket_score == 4) {
        pad.led(1,1.0f);
        pad.led(2,1.0f);
        pad.led(3,0.0f);
        pad.led(4,0.0f);
        pad.led(5,1.0f);
        pad.led(6,1.0f);
    }
    if (rocket_score == 5) {
        pad.led(1,1.0f);
        pad.led(2,1.0f);
        pad.led(3,1.0f);
        pad.led(4,0.0f);
        pad.led(5,1.0f);
        pad.led(6,1.0f);
    }
    if (rocket_score == 6) {
        pad.led(1,1.0f);
        pad.led(2,1.0f);
        pad.led(3,1.0f);
        pad.led(4,1.0f);
        pad.led(5,1.0f);
        pad.led(6,1.0f);
    }
    
    Vector2D rocket_pos = _rocket.get_pos(); // This section also checks the contact between the rocket and the food, where the current position of the rocket and the food is obtained

    Vector2D foods_pos = _foods.get_pos();
    
    if (foods_pos.x <= 1) {  // if the food leaves the left side of the screen, replace it to the right side for the next foods retrieval
        _foods.replace();
    }

    if (
        (rocket_pos.y + 4 >= foods_pos.y - _foods_size) && (rocket_pos.y + 2 <= foods_pos.y + _foods_size) // check if rrocket and the foods are overlap
        && //bottom
        (rocket_pos.x + 10 >= foods_pos.x) && (rocket_pos.x + 10 <= foods_pos.x + 1)  //right
    ) {
        // if it has, fix position and reflect x velocity
        _rocket.add_score();
        pad.tone(550.0,0.25);
        wait(0.25);
        pad.tone(1500.0,0.25);
        wait(0.25);
    }
}

int Engine::get_final_score() { // get score for the main function to determine the ending
    return _rocket.get_final_score();
}