HaoZhang SID: 201199702

Dependencies:   mbed

ETank/ETank.cpp

Committer:
zh870524589
Date:
2020-05-14
Revision:
2:867fdea920c1
Parent:
1:47fadd485c70

File content as of revision 2:867fdea920c1:

#include "ETank.h"

using namespace std;
//four directions of ETank 
const int run_up[5][5] =   
{
    {1,0,1,0,1},
    {1,0,1,0,1},
    {1,1,1,1,1},
    {1,1,1,1,1},
    {1,0,1,0,1},
};

const int run_down[5][5] =   
{
    {1,0,1,0,1},
    {1,1,1,1,1},
    {1,1,1,1,1},
    {1,0,1,0,1},
    {1,0,1,0,1},
};
const int run_left[5][5] = 
{
    {1,1,1,1,1},
    {0,0,1,1,0},
    {1,1,1,1,1},
    {0,0,1,1,0},
    {1,1,1,1,1},
};
const int run_right[5][5] =   
{
    {1,1,1,1,1},
    {0,1,1,0,0},
    {1,1,1,1,1},
    {0,1,1,0,0},
    {1,1,1,1,1},
};


// create the ETank
ETank::ETank(N5110 &lcd,Gamepad &pad)
{
     while(1){
      //The position ETanks are allowed to be born in 
     int x = rand()%79;
     int y = 5+rand()%35;
     //Make sure ETank avoid overlap
    if(!(lcd.getPixel(x,y)||lcd.getPixel(x+1,y)||lcd.getPixel(x+2,y)||lcd.getPixel(x+3,y)||lcd.getPixel(x,y+4)
       ||lcd.getPixel(x+1,y)||lcd.getPixel(x+1,y+1)||lcd.getPixel(x+1,y+2)||lcd.getPixel(x+1,y+3)||lcd.getPixel(x+1,y+4)
       ||lcd.getPixel(x+2,y)||lcd.getPixel(x+2,y+1)||lcd.getPixel(x+2,y+2)||lcd.getPixel(x+2,y+3)||lcd.getPixel(x+2,y+4)
       ||lcd.getPixel(x+3,y)||lcd.getPixel(x+3,y+1)||lcd.getPixel(x+3,y+2)||lcd.getPixel(x+3,y+3)||lcd.getPixel(x+3,y+4)
       ||lcd.getPixel(x+4,y)||lcd.getPixel(x+4,y+1)||lcd.getPixel(x+4,y+2)||lcd.getPixel(x+4,y+3)||lcd.getPixel(x+4,y+4)))
       {
        _x = x;
        _y = y;
        count = 0;//To limit attack spacing
        _d = S;//init the direction of ETank
        pad.tone(100.0,0.1);
        break;
      }
    }   
}

ETank::~ETank()
{

}

void ETank::setpos(int x, int y)
{
    this->_x = x;
    this->_y = y;
}

Vector2D ETank::get_pos()
{
    Vector2D p = {_x,_y};
    return p;
}

void ETank::direction(MyTank &mt)
{
    int et_move = rand()%101; // The direction of movement is random
    Vector2D mt_pos = mt.get_pos();//get position of MyTank
    //Make sure the ETank is moving in the direction of the target
    if(_x<mt_pos.x)
    {
        if(_y<mt_pos.y && mt_pos.x -_x<60 && mt_pos.y -_y <40) //Make sure the ETank only moves towards MyTank when the target is nearby
        {
            if(et_move<62)  
            _d = E;
            else if(et_move>62)
            _d = S;
        }
        else if(_y>mt_pos.y && mt_pos.x -_x<60 && _y-mt_pos.y <40)//Make sure the ETank only moves towards MyTank when the target is nearby
        {
            if(et_move<62)
            _d = E;
            else if(et_move>62)
            _d = N;
        } else if(_y==mt_pos.y)
          _d = E;
        else if(et_move<50)  
            _d = E; 
          //  if 1
    } else if(_x>mt_pos.x)
      {
        if(_y<mt_pos.y && _x -mt_pos.x <60 && mt_pos.y -_y <40)//Make sure the ETank only moves towards MyTank when the target is nearby
        {
            if(et_move<62)
            _d = W;
            else if(et_move>62)
            _d = S;         
        } else if(_y>mt_pos.y && _x -mt_pos.x <60 && _y - mt_pos.y <40)//Make sure the ETank only moves towards MyTank when the target is nearby
         {
            if(et_move<62)
            _d = W;
            else if(et_move>62)
            _d = N;
         } else if(_y==mt_pos.y)
            _d = W;
         else if(et_move<50)  
            _d = W;  
     }    // else if 2
    else if(_x==mt_pos.x)
        {  
         if(_y<mt_pos.y)
         {
            _d = S;
         }
         else if(_y>mt_pos.y)
         {
            _d = N;
         }    
        } 
}

//draw the ETank in four kinds of ways
void ETank::drawE(N5110 &lcd)
{    
switch (_d)
   {
    case S:
     lcd.drawSprite(_x,_y,5,5,(int *)run_down);
     break;
     
    case N:
     lcd.drawSprite(_x,_y,5,5,(int *)run_up);
     break;
     
    case W:
     lcd.drawSprite(_x,_y,5,5,(int *)run_left);
     break;
     
    case E:
     lcd.drawSprite(_x,_y,5,5,(int *)run_right);
     break;
   }
}


bool ETank::collsion_check(Vector2D t1,Vector2D t2)
{
    if(( t1.x>=t2.x && t1.x <= t2.x+4) && (t1.y >=  t2.y&& t1.y <=t2.y+4)
        ||( t1.x+4>=t2.x && t1.x <= t2.x) && (t1.y >=  t2.y&& t1.y <=t2.y+4) 
        ||(t1.x>=t2.x && t1.x <= t2.x+4) && (t1.y+4 >=  t2.y&& t1.y <=t2.y)
        ||(t1.x +4>=t2.x && t1.x <= t2.x) && (t1.y+4 >=  t2.y&& t1.y <=t2.y))  
              
    {
        return true;
    }   
    else
        return false;
    
}
//Detect ETank to MyTank collisions
void ETank::check_tank_collsion(N5110 &lcd,MyTank &mt)
{
    Vector2D et_pos = get_pos();
    Vector2D mt_pos = mt.get_pos();
    
    if(collsion_check(et_pos,mt_pos)) 
           
    {
        if(_d == S){        
            _y -= 1; 
            
        }  else if(_d == N){   
            _y += 1;
              
        }  else if(_d == E || _d == SE || _d == NE ){
           _x -= 1; 
        
        }  else if(_d == W || _d == SW || _d == NW){        
           _x += 1; 
        }
    }  
    
      
} 

// Detect collisions among ETanks 
void ETank::check_self_collsion(list<ETank*>&etank)
{
    Vector2D et_pos = get_pos();
    
    for(list<ETank*>::iterator it =etank.begin();it!=etank.end();it++)
    {
     Vector2D eet_pos = (*it)->get_pos();
     if(collsion_check(et_pos,eet_pos)&&eet_pos.x !=et_pos.x)   // Make sure it's not itself   
     {
        if(_d == S){        
            _y -= 1; 
                       
        }  else if(_d == N){   
            _y += 1;
              
        }  else if(_d == E || _d == SE || _d == NE ){
           _x -= 1; 
        
        }  else if(_d == W || _d == SW || _d == NW){        
           _x += 1; 
        }
     } else if(collsion_check(et_pos,eet_pos)&&eet_pos.y !=et_pos.y) // Make sure it's not itself   
        {
           if(_d == S){        
            _y -= 1; 
                       
        }  else if(_d == N){   
            _y += 1;
              
        }  else if(_d == E || _d == SE || _d == NE ){
           _x -= 1; 
        
        }  else if(_d == W || _d == SW || _d == NW){        
           _x += 1; 
        }
     
     }
      
    }  
} 



void ETank::check_pixel(N5110 &lcd)
{       
      Vector2D mt_pos = get_pos();
                                                                                 
        if((lcd.getPixel(mt_pos.x-1,mt_pos.y)&&_d == W )   // Left of top left corner 
        ||(lcd.getPixel(mt_pos.x-1,mt_pos.y+4)&&_d == W )   // Left of bottom left corner     
        ||(lcd.getPixel(mt_pos.x+5,mt_pos.y)&&_d == E )    // Right of top right corner 
        ||(lcd.getPixel(mt_pos.x+5,mt_pos.y+4)&&_d == E )   //Right of bottom right corner 
        ||(lcd.getPixel(mt_pos.x,mt_pos.y-1)&&_d==N)    // Top of Top left corner
        ||(lcd.getPixel(mt_pos.x+4,mt_pos.y-1)&&_d==N)   //Top of Top right corner                                                                             
        ||(lcd.getPixel(mt_pos.x,mt_pos.y+5)&&_d==S)    //Bottom of left corner 
        ||(lcd.getPixel(mt_pos.x+4,mt_pos.y+5)&&_d==S))   //Bottom of right corner     
     {
        if(_d == S){        
            _y -= 1; 
            
            
        }  else if(_d == N){   
            _y += 1;
           
              
        }  else if(_d == E || _d == SE || _d == NE ){
           _x -= 1; 
           
        
        }  else if(_d == W || _d == SW || _d == NW){        
           _x += 1; 
           
        }
     } 
    
}


void ETank::update(N5110 &lcd,MyTank &mt,list<ETank*>&etank)
{
    check_pixel(lcd);
    check_tank_collsion(lcd,mt);
    Vector2D mt_pos = mt.get_pos();
    if(_x!= mt_pos.x && _y!= mt_pos.y)
    {      
     if (_d == S) {      
       this-> _y+=1;
    } else if (_d == N) { 
        this-> _y-=1;
    } else if (_d == E || _d == SE || _d == NE) {  
       this->  _x+=1;
    } else if (_d == W || _d == SW || _d == NW) { 
        this-> _x-=1;
    }
    // ensure the ETank will not move out of the scope
    if (_y < 6 && _y >=5) {
        this-> _y = 6;
    }
    if (_x < 1 && _x >=0) {
       this-> _x = 1;
    }
    if(_y>43){
       this-> _y=43;
    }
    if(_x>79){
        this-> _x=79;
    } 
    //step of destroy the ETank
    if(_x == -5||_y == -5){
        this-> _x = -5;
        this-> _y = -5;
    }
    }
    
    check_self_collsion(etank);    
}

void  ETank::attack(Vector2D v,Gamepad &pad,N5110 &lcd,MyTank &mt,list<Bullet*> &mtbullet,int et_attack,int timegap) 
{
    count++;
    if(count>timegap) // Time interval between attacks
    if(et_attack>40){//possibility of attack
       v = get_pos(); // get the position of the ETank 
       Bullet* bullet = new Bullet(pad,v); // create the bullets when attack
       lstBullets.push_back(bullet);
       count = 0;
    }
    Vector2D mt_pos = mt.get_pos();
    for(list<Bullet*>::iterator it = lstBullets.begin(); it != lstBullets.end();)
    {
        if((*it)->destroy())
        {
            delete *it;
            it = lstBullets.erase(it); // delete the bullet
            continue;
        }    
        else if ((*it)->destroyT(mt_pos))  
        {
            delete *it;
            it = lstBullets.erase(it);
            mt.subHP();
            int M_HP = mt.MT_HP(); // MyTank's health is reduced when the bullet hits the target 
            pad.tone(500.0,0.1);
            if(M_HP == 5)
               pad.led(6,0);
            if(M_HP == 4)
               pad.led(5,0);
            if(M_HP == 3)
               pad.led(4,0);
            if(M_HP==2)
               pad.led(3,0); 
            if(M_HP==1)
              pad.led(2,0);
            if(M_HP==0){
              pad.led(1,0);
              mt.draw(lcd);
            }
            continue;
        }              
        (*it)->et_update(lcd,_d);//update the bullet
        (*it)->bullet_collison(lstBullets,mtbullet); //check the collsion between bulltes
        it++;
    }      
}