ELEC2645 (2018/19) / Mbed 2 deprecated el17aio

Dependencies:   mbed

RosenEngine/RosenEngine.cpp

Committer:
ikenna1
Date:
2019-05-08
Revision:
41:e1fa36c0492e
Parent:
40:90c7a893d513
Child:
42:ee13e1d103d8
Child:
43:500b8cff3715

File content as of revision 41:e1fa36c0492e:

#include "RosenEngine.h"

DigitalIn A(PTB9);

// Constructor
RosenEngine::RosenEngine()
{

}
// Destructor
RosenEngine::~RosenEngine()
{

}


void RosenEngine::init(int ship_width,int ship_height,int ship_speed,int ship_xpos,int ship_ypos)
{
    // initialise the game parameters
    _ship.init(ship_width,ship_height,ship_speed,ship_xpos,ship_ypos);
    _no_shooters = 0;
    _no_seekers = 0;
    _enemy.init(_no_shooters,_no_seekers);
    _menu.init(16);
    _health.init(_shipno);
    _times_run = 0;
    _score = 0;
    _dead = false;
    _intro = false;
    _wait_time = 2.25;

}
void RosenEngine::reset()
{
    _enemy.init(_no_shooters,_no_seekers);
    _health.init(_shipno);
    _wait_time = 2.25;
    _times_run = 0;
    _score = 0;
    _no_shooters = 0;
    _dead = false;
    _no_seekers = 0;
}

void RosenEngine::read_input(Gamepad &pad)
{
    Vector2D mapped_coord = pad.get_coord();
    _joystick.x = mapped_coord.x;
    _joystick.y = mapped_coord.y;
    _d = pad.get_direction();
    wait(0.1);
    // printf("_joystick.x ,_joystick.y = %f , %f\n",_joystick.x, _joystick.y);
}

void RosenEngine::draw(N5110 &lcd, Gamepad &pad)
{
    lcd.drawRect(0,0,78,48,FILL_TRANSPARENT);
    _health.draw_health(lcd,_shipno);
    _health.draw_shields(lcd);
    _enemy.draw_seeker(lcd);
    _enemy.draw_shooter(lcd);
    _enemy.draw_shw(lcd,pad);
    draw_ship(lcd,pad);
    if(_dead == true) {
        game_over(lcd);
    }
    disp_points(lcd);
}
void RosenEngine::draw_ship(N5110 &lcd, Gamepad &pad)
{
        // find the closest enemy (used in orions firing)
        Vector2D inde = find_closest1();
        int index = inde.x;
        Vector2D closest = find_closest2(index);
        // Draw ships and weapons depending on the ship being used
        switch (_shipno) {
        case 0:
            _ship.set_dimensions(9,6);
            _ship.draw_ship(lcd,_shipno);
            _weapons.draw(lcd,pad,_shipno,closest);
            break;
        case 1:
            _ship.set_dimensions(7,10);
            _ship.draw_ship(lcd,_shipno);
            _weapons.draw(lcd,pad,_shipno,closest);
            break;
        case 2:
            _ship.set_dimensions(7,10);
            _ship.draw_ship(lcd,_shipno);
            _weapons.draw(lcd,pad,_shipno,closest);
            break;
    }
}

void RosenEngine::update(Gamepad &pad)
{
    _enemy.update_seeker(_shipPos.x, _shipPos.y);
    _enemy.update_shooter(_shipPos.x, _shipPos.y);
    _enemy.update_shw();
    update_shooter_weapon(pad);
    shooter_ship_collision(pad);
    seeker_ship_collision(pad);
    shooterw_ship_collision(pad);
    imperionw_seeker_collision(pad);
    kestrelw_shooter_collision(pad);
    imperionw_shooter_collision(pad);
    orionw_collision(pad);
    check_health();
    rand_no();
    scaling(timer(12));

}
void RosenEngine::update_shooter_weapon(Gamepad &pad)
{
    if(_shipno == 0) {
        _ship.update_ship(_joystick.x,_joystick.y);
        _weapons.update();
        kestrelw_seeker_collision(pad);
    }
    //printf("if shipno == 0\n");
    if(_shipno == 1 && A == false) {
        _ship.update_ship(_joystick.x,_joystick.y);
        _weapons.update();
    }
    //printf("if shipno == 1\n");
    if(_shipno == 2) {
        _ship.update_ship(_joystick.x,_joystick.y);
        _weapons.update();
    }
}
void RosenEngine::get_pos()
{
    _shipPos = _ship.get_pos();
    _seekerPos[0] = _enemy.get_seekerpos(1);
    _seekerPos[1] = _enemy.get_seekerpos(2);
    _seekerPos[2] = _enemy.get_seekerpos(3);
    _shooterPos[0] = _enemy.get_shooterpos(1);
    _shooterPos[1] = _enemy.get_shooterpos(2);
    _shooterPos[2] = _enemy.get_shooterpos(3);
    _shooterWPos[0] = _enemy.get_shwpos(1);
    _shooterWPos[1] = _enemy.get_shwpos(2);
    _shooterWPos[2] = _enemy.get_shwpos(3);

    _weapons.init(_shipPos.x, _shipPos.y, _shipWidth);
    _ycursor = _menu.get_ycursor();
    set_ship_size();
}
void RosenEngine::set_ship_size()
{
    switch (_shipno) {
        case 0:
            _shipWidth = 9;
            _shipHeight = 6;
            break;
        case 1:
            _shipWidth = 7;
            _shipHeight = 10;
            break;
        case 2:
            _shipWidth = 7;
            _shipHeight = 10;
            break;
    }

}
void RosenEngine::title(N5110 &lcd)
{
    _menu.title(lcd,_shipno);
    _menu.update(_d);
}
int RosenEngine::get_ycursor()
{
    _ycursor = _menu.get_ycursor();
    return _ycursor;
}
int RosenEngine::get_shipno()
{
    _shipno = _menu.get_xcursor();
    return _shipno;
}
void RosenEngine::ship_select(N5110 &lcd)
{
    _menu.update(_d);
    _menu.disp_ships(lcd);
}
bool RosenEngine::check_collision(int xpos1, int ypos1,int width1,int height1,int xpos2, int ypos2,int width2,int height2)
{
    // Create arrays of all positions with appropriate height and length
    int xpos1_array[width1];
    int ypos1_array[height1];
    int xpos2_array[width2];
    int ypos2_array[height2];
    bool xcol = false;
    bool ycol = false;
    bool col = false;
    //printf("variables declared\n");
    // Loop through both height and width to get a 2D aray of the sprites position
    for(int cx = 0; cx<width1; cx=cx+1) {
        xpos1_array[cx]= xpos1 + cx;
        for(int nx = 0; nx<width2; nx=nx+1) {
            xpos2_array[nx]= xpos2 + nx;
            if(xpos2_array[nx] == xpos1_array[cx]) {
                xcol = true;
            }
            // printf("xarray = %d,x2array = %d,xcol = %d\n",xpos2_array[nx],xpos1_array[cx],xcol);
        }
    }
    //printf("first loop done\n");
    for(int cy = 0; cy<height1; cy=cy+1) {
        ypos1_array[cy]= ypos1 + cy;
        for(int ny = 0; ny<height2; ny=ny+1) {
            ypos2_array[ny]= ypos2 + ny;
            if(ypos2_array[ny] == ypos1_array[cy]) {
                ycol = true;
            }
            // printf("yarray = %d,y2array = %d,ycol = %d\n",ypos2_array[ny],ypos1_array[cy],ycol);
        }
    }
    // if both the hight and width position values are equal a collision has occured
    col = (xcol & ycol);
    //printf("col gotten, col = %d\n",col);
    return col;
}
bool RosenEngine::check_collision1(int xpos1,int width1,int xpos2,int width2)
{
    // Create arrays of all positions with appropriate height and length
    int xpos1_array[width1];
    int xpos2_array[width2];
    bool xcol = false;

    for(int cx = 0; cx<width1; cx=cx+1) {
        xpos1_array[cx]= xpos1 + cx;
        for(int nx = 0; nx<width2; nx=nx+1) {
            xpos2_array[nx]= xpos2 + nx;
            if(xpos2_array[nx] == xpos1_array[cx]) {
                xcol = true;
            }
            // printf("xarray = %d,x2array = %d,xcol = %d\n",xpos2_array[nx],xpos1_array[cx],xcol);
        }
    }
    return xcol;
}

void RosenEngine::test()
{
    bool test;
    test = check_collision(5,5,5,5,5,5,5,5);
    if (test == false) {
        printf("fail\n");
    } else {
        printf("pass\n");
    }
    test = check_collision(0,0,1,1,24,24,1,1);
    if (test == true) {
        printf("fail\n");
    } else {
        printf("pass\n");
    }
}
// make function resemble test

void RosenEngine::seeker_ship_collision(Gamepad &pad)
{
    bool col1,col2,col3;

    col1 = check_collision(_shipPos.x,_shipPos.y,9,6,_seekerPos[0].x, _seekerPos[0].y,10,7);
    col2 = check_collision(_shipPos.x,_shipPos.y,9,6,_seekerPos[1].x, _seekerPos[1].y,10,7);
    col3 = check_collision(_shipPos.x,_shipPos.y,9,6,_seekerPos[2].x, _seekerPos[2].y,10,7);
    int sel = 0;

    if (col1 == true && _no_seekers >= 1) {
        sel = 1;
    }
    if (col2 == true && _no_seekers >= 2) {
        sel = 2;
    }
    if (col3 == true && _no_seekers >= 3) {
        sel = 3;
    }
    // printf("col1 = %d, col2 = %d, col3 = %d, no_seekers = %d\n",col1,col2,col3,_no_seekers);
    if(sel != 0) {
        _health.update(5,pad);
        _health.seekerh_update(sel,10);
        pad.tone(500,0.05);
        wait(0.05);
    }
}
void RosenEngine::shooter_ship_collision(Gamepad &pad)
{
    bool col1,col2,col3;
    int sel = 0;
    col1 = check_collision(_shipPos.x,_shipPos.y,9,6,_shooterPos[0].x, _shooterPos[1].y,10,7);
    col2 = check_collision(_shipPos.x,_shipPos.y,9,6,_shooterPos[1].x, _shooterPos[0].y,10,7);
    col3 = check_collision(_shipPos.x,_shipPos.y,9,6,_shooterPos[2].x, _shooterPos[0].y,10,7);

    if(col1 == true && _no_shooters >= 1) {
        sel = 1;
    }
    if(col2 == true && _no_shooters >= 2) {
        sel = 2;
    }
    if(col3 == true && _no_shooters >= 3) {
        sel = 3;
    }
    if(sel != 0) {
        _health.update(1,pad);
        _health.shooterh_update(sel,10);
        pad.tone(500,0.05);
        wait(0.05);
    }
}
void RosenEngine::shooterw_ship_collision(Gamepad &pad)
{
    bool col1,col2,col3;
    int sel = 0;
    col1 = check_collision(_shipPos.x,_shipPos.y,9,6,_shooterWPos[0].x, _shooterWPos[1].y,2,2);
    col2 = check_collision(_shipPos.x,_shipPos.y,9,6,_shooterWPos[1].x, _shooterWPos[2].y,2,2);
    col3 = check_collision(_shipPos.x,_shipPos.y,9,6,_shooterWPos[2].x, _shooterWPos[2].y,2,2);

    if(col1 == true && _no_shooters >= 1) {
        sel = 1;
    }
    if(col2 == true && _no_shooters >= 2) {
        sel = 2;
    }
    if(col3 == true && _no_shooters >= 3) {
        sel = 3;
    }
    if(sel != 0) {
        _health.update(1,pad);
        pad.tone(500,0.05);
        wait(0.05);
    }
}
void RosenEngine::kestrelw_seeker_collision(Gamepad &pad)
{
    bool col1, col2, col3;
    int sel = 0;
    Vector2D missle_pos = _weapons.get_pos(_shipno);
    col1 = check_collision(_seekerPos[0].x,_seekerPos[0].y,9,6,missle_pos.x,missle_pos.y,1,1);
    col2 = check_collision(_seekerPos[1].x,_seekerPos[1].y,9,6,missle_pos.x,missle_pos.y,1,1);
    col3 = check_collision(_seekerPos[2].x,_seekerPos[2].y,9,6,missle_pos.x,missle_pos.y,1,1);
    if (col1 == true && _no_seekers >= 1) {
        sel = 1;
    }
    if (col2 == true && _no_seekers >= 2) {
        sel = 2;
    }
    if (col3 == true && _no_seekers >= 3) {
        sel = 3;
    }
    if(sel != 0) {
        pad.tone(500,0.05);
        _health.seekerh_update(sel,5);
        wait(0.05);
    }
}
void RosenEngine::imperionw_seeker_collision(Gamepad &pad)
{
    bool col1,col2,col3;
    int sel = 0;
    if(_shipno == 1) {
        if(_shipPos.y > _seekerPos[0].y + 6) {
            col1 = check_collision1(_seekerPos[0].x,9,_shipPos.x  + 2,3);
            if (col1 == true && A == true && _no_seekers >= 1) {
                sel = 1;
            }
        }
        if(_shipPos.y > _seekerPos[1].y + 6) {
            col2 = check_collision1(_seekerPos[1].x,9,_shipPos.x  + 2,3);
            if (col2 == true && A == true && _no_seekers >= 2) {
                sel = 2;
            }
        }
        if(_shipPos.y > _seekerPos[0].y + 6) {
            col3 = check_collision1(_seekerPos[2].x,9,_shipPos.x  + 2,3);
            if (col3 == true && A == true && _no_seekers >= 3) {
                sel = 3;
            }
        }
    }
    if(sel != 0) {
        _health.seekerh_update(sel,10);
        pad.tone(500,0.05);
        wait(0.05);
    }
}
void RosenEngine::kestrelw_shooter_collision(Gamepad &pad)
{
    Vector2D missle_pos = _weapons.get_pos(_shipno);
    bool col1, col2, col3;
    int sel = 0;
    col1 = check_collision(_shooterPos[0].x,_shooterPos[0].y,9,6,missle_pos.x,missle_pos.y,1,1);
    col2 = check_collision(_shooterPos[1].x,_shooterPos[1].y,9,6,missle_pos.x,missle_pos.y,1,1);
    col3 = check_collision(_shooterPos[2].x,_shooterPos[2].y,9,6,missle_pos.x,missle_pos.y,1,1);
    if (col1 == true && _no_shooters >= 1) {
        sel = 1;
    }
    if (col2 == true && _no_shooters >= 2) {
        sel = 2;
    }
    if (col3 == true && _no_shooters >= 3) {
        sel = 3;
    }
    // printf("col1 = %d,col2 = %d,col3 = %d, no_shooters = %d\n",col1,col2,col3,_no_shooters);
    if(sel != 0) {
        pad.tone(500,0.05);
        _health.shooterh_update(sel,5);
        wait(0.05);
    }
}
void RosenEngine::imperionw_shooter_collision(Gamepad &pad)
{
    bool col1,col2,col3;
    int sel = 0;
    if(_shipno == 1) {
        if(_shipPos.y > _shooterPos[0].y + 6) {
            col1 = check_collision1(_shooterPos[0].x,9,_shipPos.x  + 2,3);
            if (col1 == true && A == true && _no_shooters >= 1) {
                sel = 1;
            }
        }
        if(_shipPos.y > _shooterPos[1].y + 6) {
            col2 = check_collision1(_shooterPos[1].x,9,_shipPos.x  + 2,3);
            if (col2 == true && A == true && _no_shooters >= 2) {
                sel = 2;
            }
        }
        if(_shipPos.y > _shooterPos[2].y + 6) {
            col3 = check_collision1(_shooterPos[2].x,9,_shipPos.x  + 2,3);
            if (col3 == true && A == true && _no_shooters >= 3) {
                sel = 3;
            }
        }
    }
    if(sel != 0) {
        _health.shooterh_update(sel,10);
        pad.tone(500,0.05);
        wait(0.05);
    }
}
void RosenEngine::orionw_collision(Gamepad &pad)
{
    Vector2D inde = find_closest1();
    int index1 = inde.x;
    int index2 = inde.x - 3;
    int distance = inde.y;

    // enemy 1,2 and 3 are shooters
    if(_no_shooters >= index1 && A == true && distance < 15) {
        _health.shooterh_update(index1,10);
        pad.tone(500,0.05);
        wait(0.05);
    }
    // enemy 4,5 and 6 are seekers so 3 is subtracted from inde.x to compensate
    if(_no_seekers >= index2 && A == true && distance < 15) {
        _health.seekerh_update(index2,10);
        pad.tone(500,0.05);
        wait(0.05);
    }


}
void RosenEngine::check_health()
{
    // check player and enemy health
    check_se_health();
    check_sh_health();
    Vector2D hp = _health.get_hp();
    if(hp.x <= 0) {
        // printf("player deaad\n");
        _dead = true;
    }

}
void RosenEngine::check_se_health()
{
    int sel = 0;
    int seeker1_health = _health.get_seekerh(1);
    int seeker2_health = _health.get_seekerh(2);
    int seeker3_health = _health.get_seekerh(3);
    // printf("seeker1_h = %d, seeker2_h = %d, seeker3_h = %d\n",seeker1_health,seeker2_health,seeker3_health);
    if(seeker1_health == 0) {
        sel = 1;
    }
    if(seeker2_health == 0) {
        sel = 2;
    }
    if(seeker3_health == 0) {
        sel = 3;
    }
    // reset seeker and update score when shooter health goes to zero
    if(sel != 0) {
        _enemy.reset_seeker(sel);
        _health.reset_seekerh(sel);
        _score = _score + 10;
    }
}
void RosenEngine::check_sh_health()
{
    int sel = 0;
    int shooter1_health = _health.get_shooterh(1);
    int shooter2_health = _health.get_shooterh(2);
    int shooter3_health = _health.get_shooterh(3);

    if(shooter1_health == 0) {
        sel = 1;
    }
    if(shooter2_health == 0) {
        sel = 2;
    }
    if(shooter3_health == 0) {
        sel = 3;
    }
    // reset shooter and update score when shooter health goes to zero
    if(sel != 0) {
        _enemy.reset_shooter(sel);
        _health.reset_shooterh(sel);
        _score = _score + 20;
    }
}
int RosenEngine::rand_no()
{
    // seeds and returns a random number using the ctime library
    srand(time(NULL));
    int rand_no = (rand() %45) + 1;
    return rand_no;
}
float RosenEngine::timer(int fps)
{
    _times_run = _times_run + 1;
    float time_frame = 1.0f/fps;
    float time_elapsed = _times_run * time_frame;
    // printf("time elapsed = %f,time frame = %f, _times_run = %d\n",time_elapsed,time_frame,_times_run);
    return time_elapsed;
}
void RosenEngine::score(int points)
{
    _score = _score + points;
}
bool RosenEngine::dead()
{
    return _dead;
}

void RosenEngine::scaling(float time_elapsed)
{
    // increases difficulty as game progresses
    if(time_elapsed == _wait_time) {
        _no_shooters = _no_shooters + 1;
        _no_seekers = _no_seekers + 1;
        _enemy.sh_scaling(time_elapsed);
        _wait_time = _wait_time + 10.00;
    }
    if(_no_shooters > 3) {
        _no_shooters = 3;
    }
    if(_no_seekers > 3) {
        _no_seekers = 3;
    }
    _enemy.set_noshooters(_no_shooters);
    _enemy.set_noseekers(_no_seekers);
    // printf("time_elapsed = %f, no_shooters = %d, wait_time = %f\n",time_elapsed,_no_shooters,_wait_time);
}
void RosenEngine::game_over(N5110 &lcd)
{
    // Display random tips after every loss
    _lore.display(lcd,rand_no());
}
void RosenEngine::intro(N5110 &lcd)
{
    _lore.intro(lcd);
    _intro = true;
}
void RosenEngine::disp_points(N5110 &lcd)
{
    char buffer[10];
    sprintf(buffer,"%d",_score);
    lcd.printString(buffer,2,0);
}
Vector2D RosenEngine::get_enemynum()
{
    // return the number of enemy shooters and seekers currently on play
    return{_no_shooters,_no_seekers};
}
int RosenEngine::range(int x1, int y1, float x2, float y2)
{
    // calculates average distance between two points
    float rangex = (abs(x1 - x2));
    float rangey = (abs(y1 - y2));
    int distance = floor((rangex+rangey)/2);
    return distance;
}
Vector2D RosenEngine::find_closest1()
{
    // get the distance for all enemies
    int sh1 = range(_shipPos.x,_shipPos.y,_shooterPos[0].x,_shooterPos[0].y);
    int sh2 = range(_shipPos.x,_shipPos.y,_shooterPos[1].x,_shooterPos[1].y);
    int sh3 = range(_shipPos.x,_shipPos.y,_shooterPos[2].x,_shooterPos[2].y);
    int se1 = range(_shipPos.x,_shipPos.y,_seekerPos[0].x,_seekerPos[0].y);
    int se2 = range(_shipPos.x,_shipPos.y,_seekerPos[1].x,_seekerPos[1].y);
    int se3 = range(_shipPos.x,_shipPos.y,_seekerPos[2].x,_seekerPos[2].y);

    int close[6] = {sh1,sh2,sh3,se1,se2,se3};
    // find index of the smallest element
    int index = 0;
    int smallest = close[0];
    for(int i=0; i<6; i=i+1) {
        if(smallest>close[i]) {
            smallest=close[i];
            index = i;
        }
    }
    // return the index, so we know what the closest enemy, and the distance to check its in range
    return {(index + 1),smallest};
}
Vector2D RosenEngine::find_closest2(int index)
{
    // return the position of the closest enemy
    if(index == 1 && _no_shooters >= 1) {
        return {_shooterPos[0].x,_shooterPos[0].y};
    }
    if(index == 2 && _no_shooters >= 2) {
        return {_shooterPos[1].x,_shooterPos[1].y};
    }
    if(index == 3 && _no_shooters >= 3) {
        return {_shooterPos[2].x,_shooterPos[2].y};
    }
    if(index == 4 && _no_seekers >= 1 ) {
        return {_seekerPos[0].x,_seekerPos[0].y};
    }
    if(index == 5 && _no_seekers >= 2) {
        return {_seekerPos[1].x,_seekerPos[1].y};
    }
    if(index == 6 && _no_seekers >= 3) {
        return {_seekerPos[2].x,_seekerPos[2].y};
    }

}