Meteor defense project

Dependencies:   N5110 mbed

Weapon/Weapon.cpp

Committer:
jasper0712
Date:
2017-05-04
Revision:
50:082feedcdd22

File content as of revision 50:082feedcdd22:

#include "Weapon.h"

Weapon::Weapon()
{

}

Weapon::~Weapon()
{

}
void Weapon::init() { //the wonderful thing about structs.
    //printf("ld = %d, bd = %d, br = %d, bc = %d, dd = %d, dr = %d, sc = %d, srr = %d \n",laser.damage, bomb.damage, bomb.range, bomb.cooldown, drone.damage, drone.range, shield.capacity, shield.regenRate);
    _bombRange = 10 + 2 * bomb.range ;
    _laserDamage = 8 + laser.damage * 4;
    _bombDamage = 40 + bomb.damage * 10;
    _bombCooldown = 70 - bomb.cooldown * 5;
    _shieldCapacity = 80 + shield.capacity * 50; 
    _shieldRegenRate = 4 + shield.regenRate;
    _droneDamage = 1 + drone.damage;
    _droneRange = 30 + drone.range;
    _cannonDamage = 20 + 10 * cannon.damage;
    _cannonCapacity = 1280 + 320 * cannon.capacity;
    _cannonRegenRate = 4 + cannon.regenRate;
    //printf("bombRange = %d \n",_bombRange);
    //printf("shield init complete \n");
} 
void Weapon::droneInit(int x, int y, int a, int b, int damage, int range){
    d_x = x;
    d_y = y;
    d_side = a;
    d_scan = b;
    _droneDamage = damage;
    _droneRange = range;
    //printf("drone.damage = %d, drone.range = %d \n",drone.damage.drone.range);
    //printf("actual drone damage = %d, drone range = %d \n",_droneDamage,_droneRange);
    //printf("drone init done");
}
void Weapon::drawPlayer(Gamepad &pad, N5110 &lcd){
        float angle = pad.get_direction();
        int lala = pad.get_angle();
        //printf("Direction = %f, Magnitude = %f \n",angle,mag);
        //player position - fixed.
        lcd.drawRect(42,46,3,2,FILL_BLACK);
        //weapon position
        if (angle == 0) { //
            //printf("do nothing \n");
        } else if (angle == 1) {
            lcd.setPixel(43,45); lcd.setPixel(43,44);
        } else if (angle == 2 ) {
            lcd.setPixel(45,45); lcd.setPixel(46,44);
        } else if (angle == 8){
            lcd.setPixel(41,45); lcd.setPixel(40,44);
        } else if (angle == 7){
            lcd.setPixel(41,46); lcd.setPixel(40,46);
        } else if (angle == 3){
            lcd.setPixel(45,46); lcd.setPixel(46,46);
        } 
}       
void Weapon::weaponMath(Gamepad &pad) {
    //_laserDamage = 8 + var.laserDamage * 2;
    //if button A is pressed. shoot laser 
    int joyangle = pad.get_angle();
    Vector2D mapped_coord = pad.get_mapped_coord();
    //printf("mapped coord = %f, %f\n",mapped_coord.x,mapped_coord.y);
    //printf("pad.get_angle = %d \n",joyangle);

    //calculate the gradient of line 
    m = mapped_coord.y / mapped_coord.x ;
    int x1 = 43;
    int y1 = 46;
    //printf("m = %f \n",m);
    //calculate the y-intercept of the line 
    c = y1 + m * x1;  
}
void Weapon::laser_Main(int Arr2[][Rows], char cArr2[][Rows], N5110 &lcd) {
    //screen is divided into 4 parts for better line resolution 
    //and gradient sign is always changing.
    if ( m > 1) {
        laser1and4(Arr2, cArr2, lcd);        
    }
    else if (m > 0){
        laser2(Arr2, cArr2, lcd);
    }
    else if ( m > -1 ){
        laser3(Arr2, cArr2, lcd);
    } 
    else if (m < -1){
        laser1and4(Arr2, cArr2, lcd);
    }   
    lineBreak = 0;
}       
void Weapon::laser1and4(int Arr2[][Rows], char cArr2[][Rows], N5110 &lcd) {
    for (int y = 46; y > 0; y--) {
        //draw straight line 
        x = -(y - c)/m; 
        lcd.setPixel(x,y);
        if( cArr2[x-1][y-1] == 'r' || cArr2[x+1][y-1] == 'l' ) {
            laser_detectSpawnC(x, y, Arr2, cArr2, lcd);
        } else {   
            laser_detectSpawn(x, y, Arr2, lcd);
        }
        if (lineBreak == 1) {
            break;
        }
    }
    
    //printf("Part 1 is drawing line \n");
}
void Weapon::laser2(int Arr2[][Rows], char cArr2[][Rows], N5110 &lcd) {
    for (int x = 43; x < 83; x++) {
        //draw straight line 
        y = -m * x + c;
        lcd.setPixel(x,y);
        if( cArr2[x-1][y-1] == 'r' || cArr2[x+1][y-1] == 'l' ) {
            laser_detectSpawnC(x, y, Arr2, cArr2, lcd);
        } else {   
            laser_detectSpawn(x, y, Arr2, lcd);
        }
        if (lineBreak == 1) {
            break;
        }
    }
    //printf("Part 2 is drawing line \n"); 
}
void Weapon::laser3(int Arr2[][Rows], char cArr2[][Rows], N5110 &lcd) {
    for (int x = 43; x > 0; x--) {
        //draw a straight line for the laser
        y = -m * x + c;
        lcd.setPixel(x,y);
        if( cArr2[x-1][y-1] == 'r' || cArr2[x+1][y-1] == 'l') {
            laser_detectSpawnC(x, y, Arr2, cArr2, lcd);
        } else {   
            laser_detectSpawn(x, y, Arr2, lcd);
        }
        if (lineBreak == 1) {
            break;
        }
    }    
    //printf("part 3 is drawing line \n");  
}
//this piece of code to stop drawing the line when a spawn is detected.
//hit box of the laser is only 5 pixel.
void Weapon::laser_detectSpawn(int i, int j, int Arr2[][Rows], N5110 & lcd) {
    //printf("drawing at x= %d, y= %d \n",x,y);
    if ( Arr2[i][j-1] > 0) {
        //printf("spawn detected at x = %d, y= %d \n",i,j-1);
        lineBreak = 1;
        Arr2[i][j-1] = Arr2[i][j-1] - _laserDamage;
    } else if (Arr2[i-1][j-1] > 0){
        //printf("spawn detected at x = %d, y= %d \n",i-1,j-1);
        lineBreak = 1;
        Arr2[i-1][j-1] = Arr2[i-1][j-1] - _laserDamage;
    } else if (Arr2[i+1][j-1] > 0) {
        //printf("spawn detected at x = %d, y= %d \n",i+1,j-1);
        lineBreak = 1;
        Arr2[i+1][j-1] = Arr2[i+1][j-1] - _laserDamage;
    } else if (Arr2[i+1][j] > 0) {
        lineBreak = 1;
        Arr2[i+1][j] = Arr2[i+1][j] - _laserDamage;
    } else if (Arr2[i-1][j] > 0) {
        lineBreak = 1;
        Arr2[i-1][j] = Arr2[i-1][j] - _laserDamage;
    }
}    
void Weapon::laser_detectSpawnC(int i, int j, int Arr2[][Rows], char cArr2[][Rows], N5110 &lcd) {
    //printf("either L or R is  detected \n");
    if (cArr2[i+1][j-1] == 'l'){
        //printf("cArr2[%d][%d] = %c \n",i+1,j-1,cArr2[i+1][j-1]);
        lineBreak = 1;
        Arr2[i+2][j] = Arr2[i+2][j] - _laserDamage; 
        //printf("L found \n");
    } else if (cArr2[i-1][j-1] == 'r') {
        //printf("cArr2[%d][%d] = %c \n",i-1,j-1,cArr2[i-1][j-1]);
        lineBreak = 1;
        Arr2[i-2][j] = Arr2[i-2][j] - _laserDamage;
        //printf("R found \n");
    } 
}
void Weapon::bomb_main(int Arr2[][Rows], Gamepad &pad, N5110 &lcd) {
    if (_bomb < _bombCooldown) {
        //printf("bomb not ready yet \n");
        _bomb += 1;
        int cd = 3 + ((30* _bomb) / _bombCooldown); 
        for (int x = 3; x < cd; x++) { //draw a line 
            lcd.setPixel(x,47);
        }    
    } else { //allow bomb when cooldown is done.
        //printf("bomb is ready to detonate \n");
        for (int x = 3; x < 34; x++) { //draw a line 
            lcd.setPixel(x,47);
        }
        checkBombTarget(pad);
        if (bombTarget_flag == 1) {
            drawBombTarget(pad, lcd);
            if (pad.check_event(Gamepad::X_PRESSED)) {
                spawnDamageByBomb(Arr2, lcd);
            }
        }
    }
}
void Weapon::checkBombTarget(Gamepad &pad) {
    if (pad.check_event(Gamepad::L_PRESSED)) { //press L button to toggle flag
        if (bombTarget_flag == 1) {
            //printf("button L pressed and flag toggled \n");
            bombTarget_flag = 0;
        } else if(bombTarget_flag == 0) {
            bombTarget_flag = 1;
        }
    }
}
Target Weapon::targetCoord(Gamepad &pad) {
    Vector2D coord = pad.get_coord();
    //coord is used instead of mappedcoord because the bomb has to be able to go to the screen corner
    int yy = 24 - coord.y * 24;
    int xx = 42 + coord.x * 42;
    
    Target _coord = {xx,yy};
    return _coord;
}
void Weapon::drawBombTarget(Gamepad &pad, N5110 &lcd) {
    Target _coord = targetCoord(pad); //get the coordinate on the screen.
    _y = _coord.yy;
    _x = _coord.xx;
    //draw a "+" on the screen using the coordinate for the target
    lcd.setPixel(_x,_y);
    lcd.setPixel(_x+1,_y);
    lcd.setPixel(_x-1,_y);
    lcd.setPixel(_x,_y+1);
    lcd.setPixel(_x,_y-1);    
}
void Weapon::spawnDamageByBomb(int Arr2[][Rows], N5110 &lcd){ //draw the bombed area and deal damage to the area when X is pressed.
    _bomb = 0; 
    bombTarget_flag = 0; //clear flag
    //printf("why u not working now?? omg \n");
    //printf("x = %d, y = %d, bombRange = %d \n",a,b,r);
    printf("bombRange = %d \n",_bombRange);
    _bombRange = 10 + bomb.range ;
    int a = _x; //a and b is the origin of the circle, 
    int b = _y;
    int r = _bombRange; //r is radius of circle
    int c2 = r * r; 
    int x2 = a + r +1;
    int y2 = b + r +1;
    
    drawCircle(a, b, r, c2, x2, y2, Arr2, lcd);
    //printf("bomb detonated \n");
}
void Weapon::drawCircle(int a, int b, int r, int c2, int x2, int y2, int Arr2[][Rows], N5110 &lcd) { 
    //had to use this instead of lcd.drawcircle because it has to be able to manipulate the array.
    //find all the coordinate in a square depending on the radius of circle.
    for (int x1 = a - r; x1 < x2; x1 ++){
        for (int y1 = b - r; y1 < y2; y1 ++) {
            //this code because when y1 get negative. The game crash.
            int x3 = x1; int y3 = y1;
            if (y3 < 0) {
                y3 = 40;
            } if (x3 < 0) {
                x3 = 40;
            }
            int a2 = (x3 - a) * (x3 - a);
            int b2 = (y3 - b) * (y3 - b);
            if (a2 + b2 <= c2 +1) { //if the coordinate is within the circle ( c2 = a2 + b2 )
                //draw circle and deal damage to it .
                lcd.setPixel(x3,y3);
                Arr2[x3][y3] = Arr2[x3][y3] - _bombDamage;
            }
        }
    }        
}
void Weapon::shield_main(int Arr2[][Rows], char cArr2[][Rows], Gamepad &pad, N5110 &lcd) {
    if (pad.buttonhold_B == 1) { //if B pressed, generate shield. Shield doesnt have to be fully charged to be activated
        if (_shield > 0) { //shield will only activate if the shield has not depleted.
            shield_Rule(Arr2, cArr2, lcd);
        } else { //or else, deactivate the shield and recharge the shield.
            pad.buttonhold_B = 0;
        }    
    } 
    if (pad.buttonhold_B == 0) { // recharge shield 
        if (_shield < _shieldCapacity ) {
            _shield = _shield + _shieldRegenRate;
            //printf("current shield = %d \n",weap._shield); 
            //printf("shield regen rate = %d \n",weap._shieldRegenRate);
        } else { //when the shield is fully charged. It will automatically activate the shield.
                pad.buttonhold_B = 1;
        }
    }
    shieldMeter(lcd);
}
void Weapon::shield_Rule(int Arr2[][Rows], char cArr2[][Rows], N5110 &lcd) {
    drawEnergyShield(lcd);
    for (int x = 0; x < Cols; x++) { //from x = 0 to x = 83
        if (cArr2[x][45] == 'b') { //scan for spawn B
            Arr2[x][45] = 0;
            cArr2[x][45] = '\0';
            _shield -= 20;
        } else if ( cArr2[x][45] == 'd' || cArr2[x][45] == 'e' ) { //scan for spawn D&E
            Arr2[x][45] = 0;
            cArr2[x][45] = '\0';
            _shield -= 30;
        }
    }  
}
//draw a simple barrier at y = 45
void Weapon::drawEnergyShield(N5110 &lcd) {
    for (int x = 0; x < Cols; x++) {
        lcd.setPixel(x,45);    
    }
    for (int x = 0; x < Cols; x += 3) {
        lcd.setPixel(x,44);
    }    
}
void Weapon::shieldMeter(N5110 &lcd) {
    int cd = 50 + ((30 * _shield) / _shieldCapacity); 
    lcd.drawLine(50,47,cd,47,1);    
}
void Weapon::drone_main(int Arr2[][Rows], char cArr2[][Rows], N5110 &lcd) {
    lcd.setPixel(d_x,d_y);
    //prioritize spawn D&E
    droneScanForDE(Arr2, cArr2, lcd);
    if (d_foundDE == 0) {
        droneScanForAB(Arr2, cArr2, lcd);    
    }
    d_foundDE = 0;
}
void Weapon::droneScanForAB(int Arr2[][Rows], char cArr2[][Rows], N5110 &lcd) {
    for (int y = d_y; y > d_y - _droneRange; y--) { //scan through the given drone range from left to right
        for (int x = d_side; x < d_scan; x++) {
            if (cArr2[x][y] == 'a' || cArr2[x][y] == 'c') { //if detect something
                //printf("drone detected spawn A/C at x = %d, y = %d \n",x ,y);
                droneLaser(x, y, Arr2, cArr2, lcd);
                Arr2[x][y] = Arr2[x][y] - _droneDamage;
                breakout = 1;
                break; //break out of the first for loop.  
            } 
        }
        if (breakout == 1){
            breakout = 0;
            break; //break out of the second for loop.
        }
    }
}
void Weapon::droneScanForDE(int Arr2[][Rows], char cArr2[][Rows], N5110 &lcd) { //drone prioritize in killing spawnDE
    for (int y = d_y; y > d_y - _droneRange; y--) { //scan through the given drone range from left to right
        for (int x = d_side; x < d_scan; x++) {
            if (cArr2[x][y] == 'd' || cArr2[x][y] == 'e') { //if detect something
                //printf("drone detected spawn D&E at x = %d, y = %d \n",x ,y);
                droneLaser(x, y, Arr2, cArr2, lcd);
                Arr2[x][y] = Arr2[x][y] - _droneDamage;
                breakout = 1;
                d_foundDE = 1;
                break; //break out of the first for loop.  
            } 
        }
        if (breakout == 1){
            breakout = 0;
            break; //break out of the second for loop.
        }
    }
}
void Weapon::droneLaser(int x, int y, int Arr2[][Rows], char cArr2[][Rows], N5110 &lcd) { //this is used to draw line (laser) for the drone
    float m;
    if ( x != d_x) { //to prevent m (gradient) from going to infinity.
        m = (((float)y) - d_y) / (((float)x) - d_x); //to get the gradient of the line. y = mx + c
    } else {
        m = 50; //50 is more than enough since screen height is only 48 pixel.
    }
    int c = d_y - m * d_x; // y-intercept of the line
    //printf("y intercept = %d and gradient = %f \n",c,m);
    /*int lala = x - d_x;
    if ( lala == 0 ) { 
        printf("m = %d at x = %d \n",m,x);
    }*/
    for (int j = d_y ; j > y ; j--) { 
        int i = (j - c) / m;
        lcd.setPixel(i,j);
    }          
}
void Weapon::cannon_main(int Arr2[][Rows], char cArr2[][Rows], N5110 &lcd) { //dividing the screen into 4 parts like the laser 
    //printf("cannonFiring_flag = %d, cannon_y = %d, cannon_x = %d \n",cannonFiring_flag,cannon_y,cannon_x);
    if ( cannonFiring_flag == 0) { //save the current gradient and also the y-intercept
        cannonDirection = m;
        cannon_c = c;
        cannon_y = 46; //initial pos of cannon
        cannon_x = 43;
        cannonFiring_flag = 1;
        cannon_Damage =  _cannonDamage;
        _cannon = _cannon - 320; //each cannon clip costs 320.
        //printf("firing a new cannon \n");
    }
    //dividing the screen into 4 parts like the laser
    if ( cannonFiring_flag == 1) { //cannon fired   
        if ( cannonDirection > 1) {  
            cannon1and4(Arr2, cArr2, lcd); 
        }
        else if ( cannonDirection > 0){
            cannon2(Arr2, cArr2, lcd); 
        }
        else if ( cannonDirection > -1 ){
            cannon3(Arr2, cArr2, lcd);
        } 
        else if ( cannonDirection < -1){
            cannon1and4(Arr2, cArr2, lcd); 
        }   
    }
}
void Weapon::cannon1and4(int Arr2[][Rows], char cArr2[][Rows], N5110 &lcd) {
    if ( cannon_y > 0 ) {
        cannon_y --;
        //printf("printing cannonball at (%d,%d) \n",x,cannon_y);
        int x = -(cannon_y - cannon_c) / cannonDirection;
        draw_CannonBall(x, cannon_y, lcd);
        //search for spawn A, B and C
        cannon_HitBox(x, cannon_y, Arr2, cArr2);    
    } else {
        cannonFiring_flag = 0;
        //printf("cannon1and4 is done \n");    
    }
}
void Weapon::cannon2(int Arr2[][Rows], char cArr2[][Rows], N5110 &lcd) {
    if ( cannon_x < 83 ) {
        cannon_x ++;
        int y = - cannonDirection * cannon_x + cannon_c;
        //printf("printing cannonball at (%d,%d) \n",cannon_x,y);
        draw_CannonBall(cannon_x, y, lcd);
        //search for spawn A, B and C.
        cannon_HitBox(cannon_x, y, Arr2, cArr2);  
    } else {
         cannonFiring_flag = 0;
        //printf("cannon2 is done \n");    
    }
}
void Weapon::cannon3(int Arr2[][Rows], char cArr2[][Rows], N5110 &lcd) {
    if ( cannon_x > 0 ) {
        cannon_x --;
        int y = - cannonDirection * cannon_x + cannon_c;  
        //printf("printing cannonball at (%d,%d) \n",cannon_x,y);
        draw_CannonBall(cannon_x, y, lcd); 
        //search for spawn A, B and C.
        cannon_HitBox(cannon_x, y, Arr2, cArr2);    
    } else {
        cannonFiring_flag = 0;
        //printf("cannon3 is done \n");    
    }
}
void Weapon::cannon_HitBox(int i, int j, int Arr2[][Rows], char cArr2[][Rows]) {
    for (int x = i - 4; x < i + 5; x ++) {
        for (int y = j - 4; y < j + 5; y ++) {
            if (cannon_Damage > 0 ) { //if cannon can still deal damage, continue search for spawn
                if (cArr2[x][y] == 'a') {
                    cannon_Damage = cannon_Damage - 2; 
                    Arr2[x][y] = 0;
                    cArr2[x][y] = '\0';   
                }
                if (cArr2[x][y] == 'b') {
                    cannon_Damage = cannon_Damage - 5;
                    Arr2[x][y] = 0;
                    cArr2[x][y] = '\0';
                }
                if (cArr2[x][y] == 'c') {
                    cannon_Damage = cannon_Damage - 5;
                    Arr2[x][y] = 0;
                    cArr2[x][y] = '\0';
                }
            } else { //if the cannon cant deal any more damage, terminate search and clear flag
                cannonFiring_flag = 0; 
                break;   
            }
        }
    }
}
void Weapon::cannon_recharge() {
    if ( _cannon < _cannonCapacity ) {
        _cannon = _cannon + _cannonRegenRate;
    }    
    //printf("_cannon = %d \n",_cannon);
} 
void Weapon::cannon_Meter(N5110 &lcd) {
    float zz = 83 * ( ((float)_cannon) / _cannonCapacity) ; 
    //printf(" zz = %f \n",zz);
    for ( int x = 0 ; x < zz; x ++) {
        lcd.setPixel(x,0);
    }
}
void Weapon::draw_CannonBall(int x, int y, N5110 &lcd) {
    //draw a diamond shape 
    lcd.setPixel(x-1,y-1); lcd.setPixel(x,y-1); lcd.setPixel(x+1,y+1);
    lcd.setPixel(x-1,y);   lcd.setPixel(x,y);   lcd.setPixel(x+1,y);
    lcd.setPixel(x-1,y+1); lcd.setPixel(x,y+1); lcd.setPixel(x+1,y-1);
    lcd.setPixel(x-2,y);   lcd.setPixel(x+2,y); 
    lcd.setPixel(x,y+2);   lcd.setPixel(x,y-2);
}
void Weapon::setVar(int up, int up1) {
    //printf("HI, ME FROM WEAP. up = %d, up1 = %d \n",up,up1); 
    if (up == 0){  //if laser picked 
        laser.damage ++;
    } else if (up == 1) { //if bomb picked
        if (up1 == 0) {
            bomb.damage ++;
        } else if (up1 == 1) {
            bomb.range ++;
        } else {
            bomb.cooldown++;
        }
    } else if (up == 2) { //if drone picked
        if (up1 == 0) {
            drone.damage++;
        } else {
            drone.range++;
        }
    } else if (up == 3) { //if shield picked 
        if (up1 == 0) {
            shield.capacity ++;
        } else {
            shield.regenRate ++;
        }
    } else if (up == 4) { //if cannon picked
        if (up1 == 0) {
            cannon.damage ++;
        } else if (up1 == 1) {
            cannon.capacity ++;
        } else if (up1 == 2) {
            cannon.regenRate ++;
        }
    }
} 
void Weapon::reset_WeaponVariables() { 
    laser.damage = 0;
    bomb.damage = 0;
    bomb.range = 0;
    bomb.cooldown = 0;
    drone.damage = 0;
    drone.range = 0;
    shield.capacity = 0;
    shield.regenRate = 0;
    bomb.damage = 0;
    bomb.capacity = 0;
    bomb.regenRate = 0;
    _cannon = 0;
    _shield = 0;
    _bomb = 0;
}