Ikenna Adrian Ozoemena 201157039

Dependencies:   mbed

Enemy/Enemy.cpp

Committer:
ikenna1
Date:
2019-05-09
Revision:
53:3fdc4486f672
Parent:
51:2231e2e141b9

File content as of revision 53:3fdc4486f672:

#include "Enemy.h"

Enemy::Enemy()
{

}

Enemy::~Enemy()
{

}
// enemy sprites
const int seeker[7][9] = {
    {1,1,0,0,0,0,0,1,1},
    {1,0,1,0,0,0,1,0,1},
    {1,0,0,1,1,1,0,0,1},
    {0,1,0,0,0,0,0,1,0},
    {0,0,1,0,0,0,1,0,0},
    {0,0,1,1,0,1,1,0,0},
    {0,0,0,0,1,0,0,0,0},
};
const int shooter[10][11] = {
    {0,0,1,0,0,0,0,0,1,0,0},
    {0,1,0,1,0,0,0,1,0,1,0},
    {1,0,0,1,0,1,0,1,0,0,1},
    {1,0,0,1,1,0,1,1,0,0,1},
    {0,1,0,0,0,0,0,0,0,1,0},
    {0,1,0,0,1,1,1,0,0,1,0},
    {0,0,1,0,0,1,0,0,1,0,0},
    {0,0,0,1,0,0,0,1,0,0,0},
    {0,0,0,0,1,0,1,0,0,0,0},
    {0,0,0,0,0,1,0,0,0,0,0},
};
void Enemy::init(int noShooters, int noSeekers)
{
    // initialize the number of seekers and shooters
    _noSeekers = noSeekers;
    _noShooters = noShooters;
    // initialize seeker at top of screen whith a random x position
    _seekerPos[0].x = rand_no(68);
    _seekerPos[0].y = 0;
    _seekerPos[1].x = rand_no(68);
    _seekerPos[1].y = 0;
    _seekerPos[2].x = rand_no(68);
    _seekerPos[2].y = 0;

    // initialize shooter at top of screen whith a random x position
    _shooterPos[0].x = rand_no(68);
    _shooterPos[0].y = 1;
    _shooterPos[1].x = rand_no(68);
    _shooterPos[1].y = 1;
    _shooterPos[2].x = rand_no(68);
    _shooterPos[2].y = 1;
    // initialize shooter speed
    _shooterSpeed[0].x = 1;
    _shooterSpeed[1].x = 1;
    _shooterSpeed[2].x = 1;
    _shooterSpeed[0].y = 1;
    _shooterSpeed[1].y = 1;
    _shooterSpeed[2].y = 1;

}
void Enemy::set_noshooters(int noShooters)
{
    // set the number of enemy shooters
    _noShooters = noShooters;
}
void Enemy::set_noseekers(int noSeekers)
{
    // set the number of enemy seekers
    _noSeekers = noSeekers;
}
void Enemy::draw_seeker(N5110 &lcd)
{
    // Draw seekers based on _noSeekers with a maximum of three seekers
    switch (_noSeekers) {
        case 1:
            lcd.drawSprite( _seekerPos[0].x, _seekerPos[0].y,7,9,(int *)seeker);
            break;
        case 2:
            lcd.drawSprite( _seekerPos[0].x, _seekerPos[0].y,7,9,(int *)seeker);
            lcd.drawSprite( _seekerPos[1].x, _seekerPos[1].y,7,9,(int *)seeker);
            break;
        case 3:
            lcd.drawSprite( _seekerPos[0].x, _seekerPos[0].y,7,9,(int *)seeker);
            lcd.drawSprite( _seekerPos[1].x, _seekerPos[1].y,7,9,(int *)seeker);
            lcd.drawSprite( _seekerPos[2].x, _seekerPos[2].y,7,9,(int *)seeker);
            break;
    }
}
void Enemy::draw_shooter(N5110 &lcd)
{
    // Draw shooters based on _noShooters with a maximum of three shooters
    switch (_noShooters) {
        case 1:
            lcd.drawSprite(_shooterPos[0].x,_shooterPos[0].y,10,11,(int *)shooter);
            break;
        case 2:
            lcd.drawSprite(_shooterPos[0].x,_shooterPos[0].y,10,11,(int *)shooter);
            lcd.drawSprite(_shooterPos[1].x,_shooterPos[1].y,10,11,(int *)shooter);
            break;
        case 3:
            lcd.drawSprite(_shooterPos[0].x,_shooterPos[0].y,10,11,(int *)shooter);
            lcd.drawSprite(_shooterPos[1].x,_shooterPos[1].y,10,11,(int *)shooter);
            lcd.drawSprite(_shooterPos[2].x,_shooterPos[2].y,10,11,(int *)shooter);
            break;
    }
}
void Enemy::update_seeker(int ship_xpos, int ship_ypos)
{
    // Update seekers based on _noSeekers with a maximum of three seekers
    switch (_noSeekers) {
        case 1:
            _seekerPos[0] = seeker_motion(_seekerPos[0].x,_seekerPos[0].y,ship_xpos,ship_ypos,2,2);
            break;
        case 2:
            _seekerPos[0] = seeker_motion(_seekerPos[0].x,_seekerPos[0].y,ship_xpos,ship_ypos,2,2);
            _seekerPos[1] = seeker_motion(_seekerPos[1].x,_seekerPos[1].y,ship_xpos,ship_ypos,2,2);
            break;
        case 3:
            _seekerPos[0] = seeker_motion(_seekerPos[0].x,_seekerPos[0].y,ship_xpos,ship_ypos,2,2);
            _seekerPos[1] = seeker_motion(_seekerPos[1].x,_seekerPos[1].y,ship_xpos,ship_ypos,2,2);
            _seekerPos[2] = seeker_motion(_seekerPos[2].x,_seekerPos[2].y,ship_xpos,ship_ypos,2,2);
            break;
    }
}
void Enemy::update_shooter(int ship_xpos, int ship_ypos)
{
    // Update shooters based on _noShooters with a maximum of three shooters
    switch (_noShooters) {
        case 1:
            _shooterPos[0] = shooter_motion(_shooterPos[0].x,_shooterPos[0].y,ship_xpos,ship_ypos,_shooterWPos[0].x,_shooterWPos[0].y,_shooterSpeed[0].x,_shooterSpeed[0].y);
            break;
        case 2:
            _shooterPos[0] = shooter_motion(_shooterPos[0].x,_shooterPos[0].y,ship_xpos,ship_ypos,_shooterWPos[0].x,_shooterWPos[0].y,_shooterSpeed[0].x,_shooterSpeed[0].y);
            _shooterPos[1] = shooter_motion(_shooterPos[1].x,_shooterPos[1].y,ship_xpos,ship_ypos,_shooterWPos[1].x,_shooterWPos[1].y,_shooterSpeed[1].x,_shooterSpeed[1].y);
            break;
        case 3:
             _shooterPos[0] = shooter_motion(_shooterPos[0].x,_shooterPos[0].y,ship_xpos,ship_ypos,_shooterWPos[0].x,_shooterWPos[0].y,_shooterSpeed[0].x,_shooterSpeed[0].y);
             _shooterPos[1] = shooter_motion(_shooterPos[1].x,_shooterPos[1].y,ship_xpos,ship_ypos,_shooterWPos[1].x,_shooterWPos[1].y,_shooterSpeed[1].x,_shooterSpeed[1].y);
             _shooterPos[2] = shooter_motion(_shooterPos[2].x,_shooterPos[2].y,ship_xpos,ship_ypos,_shooterWPos[2].x,_shooterWPos[2].y,_shooterSpeed[2].x,_shooterSpeed[2].y);
            break;
    }
}
Vector2D Enemy::seeker_motion(int seeker_xpos,int seeker_ypos,int ship_xpos,int ship_ypos,int vx,int vy)
{
    int rangex =  seeker_xpos - ship_xpos;
    int rangey =  seeker_ypos - ship_ypos;

    // make seeker move towards ship
    if(rangey < 0) {
        if(rangex < 0) {
            seeker_xpos =  seeker_xpos + vx;
        } else if(rangex == 0) {
            seeker_xpos =  seeker_xpos + vx;
        } else {
            seeker_xpos =  seeker_xpos - vx;
        }
    }

    // reset seeker to top once it has left the screen
    if( seeker_ypos > 54) {
        seeker_xpos = rand_no(68);
        seeker_ypos = 0;
    }
    seeker_ypos =  seeker_ypos + vy;
    return{seeker_xpos,seeker_ypos};
}
Vector2D Enemy::shooter_motion(int shooter_xpos,int shooter_ypos,int ship_xpos, int ship_ypos, int projx, int projy,int vx, int vy)
{
    // The shooter tracks the ship based on where the bullet it has fired is
    int high_bar =10;
    int low_bar = 25;
    int rangex = shooter_xpos - ship_xpos;
    int rangey = shooter_ypos - ship_ypos;
    // is the bullet has left the shooter and is around the middle of the screen it will avoid the ship
    if(high_bar <= projy &&  projy <= low_bar) {
        if(rangex > 0) {
            // avoid ship
            shooter_xpos = shooter_xpos + vx;
        }
        if(rangex < 0) {
            shooter_xpos = shooter_xpos - vx;
        }
    } else {
        // if it has past a certain point the shooter will try to line up the next shot
        // track ship
        if(rangex > 0) {
            shooter_xpos = shooter_xpos - vx;
        }
        if(rangex < 0) {
            shooter_xpos = shooter_xpos + vx;
        }
    }
    // dont let the shooter leave the screen
    if(shooter_xpos < 1) {
        shooter_xpos = 1;
    }
    if(shooter_xpos > 84 - 8 - 11) {
        shooter_xpos = 84 - 8 - 11;
    }
    return{shooter_xpos,shooter_ypos};
}

void Enemy::draw_shw1(N5110 &lcd,Gamepad &pad)
{
    _shooterWSpeed[0].x = 0; //Projectile doesn't move sideways.
    _shooterWSpeed[0].y = 2; //Projectile donwards

//resets once projectile reaches bottom of screen
    if(_shooterWPos[0].y >= 48) {
        _reset[0] = 0;
    }

    if(_reset[0] == 0) {
        _shooterWPos[0].x = _shooterPos[0].x + 5;
        _shooterWPos[0].y = _shooterPos[0].y + 11;
        _reset[0] = _reset[0] + 1;
    }
    lcd.drawRect(_shooterWPos[0].x,_shooterWPos[0].y,1,1,FILL_BLACK);
// printf("Ship x and y pos, reset = %d , %d ,%d \n", _ship_xpos, _ship_ypos, reset);
}
void Enemy::draw_shw2(N5110 &lcd,Gamepad &pad)
{
    _shooterWSpeed[1].x = 0; //Projectile doesn't move sideways.
    _shooterWSpeed[1].y = 5; //Projectile moves downwards

    //resets once projectile reaches bottom of screen
    if(_shooterWPos[1].y >= 48) {
        _reset[1]= 0;
    }

    if(_reset[1] == 0) {
        _shooterWPos[1].x = _shooterPos[1].x + 5;
        _shooterWPos[1].y = _shooterPos[1].y + 11;
        _reset[1] = _reset[1] + 1;
    }
    lcd.drawRect(_shooterWPos[1].x,_shooterWPos[1].y,1,1,FILL_BLACK);
    // printf("Ship x and y pos, reset = %d , %d ,%d \n", _ship_xpos, _ship_ypos, reset);
}
void Enemy::draw_shw3(N5110 &lcd,Gamepad &pad)
{
    _shooterWSpeed[2].x = 0; //Projectile doesn't move sideways.
    _shooterWSpeed[2].y = 3; //Projectile moves upwards on screen.

    //resets once projectile reaches bottom of screen
    if(_shooterWPos[2].y >= 48) {
        _reset[2] = 0;
    }

    if(_reset[2] == 0) {
        _shooterWPos[2].x = _shooterPos[2].x + 5;
        _shooterWPos[2].y = _shooterPos[2].y + 11;
        _reset[2] = _reset[2] + 1;
    }
    lcd.drawRect(_shooterWPos[2].x,_shooterWPos[2].y,1,1,FILL_BLACK);
}
void Enemy::draw_shw(N5110 &lcd,Gamepad &pad)
{
    // Draw projectiles depending on the number of shooters
    switch (_noShooters) {
        case 1:
            draw_shw1(lcd,pad);
            break;
        case 2:
            draw_shw1(lcd,pad);
            draw_shw2(lcd,pad);
            break;
        case 3:
            draw_shw1(lcd,pad);
            draw_shw2(lcd,pad);
            draw_shw3(lcd,pad);
            break;
    }
}
void Enemy::update_shw()
{
    // update the shooters position based on the shooter projectile speed
    _shooterWPos[0].x =  _shooterWPos[0].x + _shooterWSpeed[0].x;
    _shooterWPos[0].y =  _shooterWPos[0].y + _shooterWSpeed[0].y;
    _shooterWPos[1].x =  _shooterWPos[1].x + _shooterWSpeed[1].x;
    _shooterWPos[1].y =  _shooterWPos[1].y + _shooterWSpeed[1].y;
    _shooterWPos[2].x =  _shooterWPos[2].x + _shooterWSpeed[2].x;
    _shooterWPos[2].y =  _shooterWPos[2].y + _shooterWSpeed[2].y;
}

Vector2D Enemy::get_shwpos(int shno)
{
    // get appropriate shooter projectile position
    if(shno == 1) {
        Vector2D pos = {_shooterWPos[0].x,_shooterWPos[0].y};
        return pos;
    }
    if(shno == 2) {
        Vector2D pos = {_shooterWPos[1].x,_shooterWPos[1].y};
        return pos;
    }
    if(shno == 3) {
        Vector2D pos = {_shooterWPos[2].x,_shooterWPos[2].y};
        return pos;
    }
}

void Enemy::reset_seeker(int seno)
{
    // reset seeker to top of screen
    switch (seno) {
        case 1:
            _seekerPos[0].x = rand_no(68);
            _seekerPos[0].y = 0;
            break;
        case 2:
            _seekerPos[1].x = rand_no(68);
            _seekerPos[1].y = 0;
            break;
        case 3:
            _seekerPos[2].x = rand_no(68);
            _seekerPos[2].y = 0;
            break;
    }

}
void Enemy::reset_shooter(int shno)
{
    // reset shooter to top of screen
    switch (shno) {
        case 1:
            _shooterPos[0].x = rand_no(68);
            _shooterPos[0].y = 5;
            break;
        case 2:
            _shooterPos[1].x = rand_no(68);
            _shooterPos[1].y = 5;
            break;
        case 3:
            _shooterPos[2].x = rand_no(68);
            _shooterPos[2].y = 5;
            break;
    }
}
Vector2D Enemy::get_seekerpos(int seno)
{
    // get appropriate seeker position
    if(seno == 1) {
        Vector2D seeker_pos = { _seekerPos[0].x, _seekerPos[0].y};
        return seeker_pos;
    }
    if(seno == 2) {
        Vector2D seeker_pos = { _seekerPos[1].x, _seekerPos[1].y};
        return seeker_pos;
    }
    if(seno == 3) {
        Vector2D seeker_pos = { _seekerPos[2].x, _seekerPos[2].y};
        return seeker_pos;
    }
}
Vector2D Enemy::get_shooterpos(int shno)
{
    // get appropriate shooter  position
    if(shno == 1) {
        Vector2D shooter_pos = {_shooterPos[0].x,_shooterPos[0].y};
        return shooter_pos;
    }
    if(shno == 2) {
        Vector2D shooter_pos = {_shooterPos[1].x,_shooterPos[1].y};
        return shooter_pos;
    }
    if(shno == 3) {
        Vector2D shooter_pos = {_shooterPos[2].x,_shooterPos[2].y};
        return shooter_pos;
    }
}
int Enemy::rand_no(int scale)
{
    // seed the srand function using time from the <ctime> library
    srand(time(NULL));
    int rand_no = (rand() %scale) + 1; // use scale to limit the output of the random number
    // printf("random no = %d\n",rand_no);
    return rand_no;
}
void Enemy::sh_scaling(float time_elapsed)
{
    int vmax = 3;
    int time = floor(time_elapsed);
    // Increase the shooters speed every 20 seconds to a maximum of 3
    if(time%20 == 0) {
        if(_shooterSpeed[0].x > -vmax && _shooterSpeed[0].x < vmax) {
            _shooterSpeed[0].x = _shooterSpeed[0].x * 1.1;
        }
        if(_shooterSpeed[1].x > - vmax && _shooterSpeed[1].x < vmax) {
            _shooterSpeed[1].x = _shooterSpeed[1].x * 1.1;
        }
        if(_shooterSpeed[2].x > -vmax && _shooterSpeed[2].x < vmax) {
            _shooterSpeed[2].x = _shooterSpeed[2].x * 1.1;
        }
        if(_shooterSpeed[0].y > -vmax && _shooterSpeed[0].y < vmax) {
            _shooterSpeed[0].y = _shooterSpeed[0].y * 1.1;
        }
        if(_shooterSpeed[1].y > -vmax && _shooterSpeed[1].y < vmax) {
            _shooterSpeed[1].y = _shooterSpeed[1].y * 1.1;
        }
        if(_shooterSpeed[2].y > -vmax && _shooterSpeed[2].y < vmax) {
            _shooterSpeed[2].y = _shooterSpeed[2].y * 1.1;
        }
    }
    // printf("time = %d, _shooterSpeed[0].x = %f\n",time,_shooterSpeed[0].x);
}
int Enemy::distance(int x1, int y1, int x2, int y2)
{
    // get the absolute difference between x1 and x2, and y1 and y2
    // then average that
    int rangex = abs(x1 - x2);
    int rangey = abs(y1 - y2);
    int dis = (rangex+rangey)/2;
    return dis;
}

Vector2D Enemy::find_closest(int ship_xpos,int ship_ypos, int noSeekers, int noShooters)
{
    // get the distance for all enemies
    int sh1 = distance(ship_xpos,ship_ypos,_shooterPos[0].x,_shooterPos[0].y);
    int sh2 = distance(ship_xpos,ship_ypos,_shooterPos[1].x,_shooterPos[1].y);
    int sh3 = distance(ship_xpos,ship_ypos,_shooterPos[2].x,_shooterPos[2].y);
    int se1 = distance(ship_xpos,ship_ypos, _seekerPos[0].x, _seekerPos[0].y);
    int se2 = distance(ship_xpos,ship_ypos, _seekerPos[1].x, _seekerPos[1].y);
    int se3 = distance(ship_xpos,ship_ypos, _seekerPos[2].x, _seekerPos[2].y);

    int close[6] = {sh1,sh2,sh3,se1,se2,se3};
    // find index of the smallest element
    int index;
    int smallest = close[0];
    for(int i=0; i<6; i=i+1) {
        if(smallest>close[i]) {
            smallest=close[i];
            index = i;
        }
    }
    // return the position of the closest enemy
    if(index == 0 && noShooters >= 1) {
        return {_shooterPos[0].x,_shooterPos[0].y};
    }
    if(index == 1 && noShooters >= 2) {
        return {_shooterPos[1].x,_shooterPos[1].y};
    }
    if(index == 2 && noShooters >= 3) {
        return {_shooterPos[2].x,_shooterPos[2].y};
    }
    if(index == 3 && noSeekers >= 1 ) {
        return { _seekerPos[0].x, _seekerPos[0].y};
    }
    if(index == 4 && noSeekers >= 2) {
        return { _seekerPos[1].x, _seekerPos[1].y};
    }
    if(index == 5 && noSeekers >= 3) {
        return { _seekerPos[2].x, _seekerPos[2].y};
    }

}