Your browser does not support the canvas tag.

previous        Show / Hide Source        Download        next
//                                        Wutong Yang                                        \\
//                                       Tank Shooting                                       \\
//                                       "W" "A "S "D                                         \\
//                                     Move Four Direction                                     \\
//                                            "J"                                               \\
//                                            FIRE                                               \\
//                                  Surive As Long As You can                                     \\
//                                        Enjoy The game                                           \\

// declare globals
int numberOfMonster=10;         
Monster[] Monsters=new Monster[numberOfMonster];
Tank tank;
Cannon[] cannonList = new Cannon[10000]; // Allocate enough space for large amount of cannons, to avoid seg fault.
float scale=1;   // Used to directly change the size of the tank and cannons.
int validCannon =0;  // Used to organize cannons on the screen.
// keyboard controls
boolean upPressed;
boolean downPressed;
boolean leftPressed;
boolean rightPressed;
boolean firePressed;
boolean theFirstCannon=true;  // Used to make sure shooting only one cannon for each press.
int death;
int score;
void setup() {
  // set up window size ,frame rate
  size(800, 600);
  frameRate(60);

  // instantiate game objects
  tank=new Tank();
  createMonsters();
  for (int i=0; i<10000; i++) {
    cannonList[i]=new Cannon();
  }
}


void createMonsters() {
  for (int i=0; i<Monsters.length; i++) {
    Monsters[i]=new Monster();
  }
}


void draw() {


  if (firePressed&&theFirstCannon) // make sure one cannon for each "j" pressed.
  {
    validCannon++;
    cannonList[validCannon-1].update1(); // load it as an active cannon
    theFirstCannon = false;
  }
  for (int i=0; i<validCannon; i++) { 
    cannonList[i].update2(); // move the cannons on the screen
  }


  for (int i=0; i<Monsters.length; i++) {
    Monsters[i].update();
  }
  tank.update();

  // clear background
  background(40, 206, 52);
  for (int i=0; i<Monsters.length; i++) {
    Monsters[i].display();
  }
  for (int i=0; i<validCannon; i++) {
    cannonList[i].display();
  }
  tank.display();
  textSize(32);
  fill(score, 102, 153);
  text("score:", 10, 30); // score display 
  text(score,120,30);
  fill(255, 0, 0);
  text("death", 10, 60);  // death display
  text(death,120,60);
}



void keyPressed() {
  // detect if player is pressing up, down, left, or right
  switch(key) {
  case 'w': 
    upPressed=true;
    break;
  case 's': 
    downPressed=true;
    break;
  case 'a': 
    leftPressed=true;
    break;
  case 'd': 
    rightPressed=true;
    break;
  case 'j': 
    firePressed=true;  // press to fire
    break;
  }
}


void keyReleased() {
  // detect if player has released up, down, left or right  
  switch(key) {
  case 'w': 
    upPressed=false;
    break;
  case 's': 
    downPressed=false;
    break;
  case 'a': 
    leftPressed=false;
    break;
  case 'd': 
    rightPressed=false;
    break;
  case 'j': 
    { 
      firePressed=false;
      theFirstCannon=true;  // make sure one cannon for one press
    }
    break;
  }
}
class Cannon {


  PVector position = new PVector();
  PVector velocity = new PVector();
  Cannon() {
    position.set(1000, 1000); // make sure the cannons do not appear on the screen being fired out
  }

  void update1() {// used to fire
                  // update positions and velocity of the cannons being fired out based on the current direction of the tank 
                  // 0, 1, 2, 3 for up down left and right
    if (tank.direction==0)
    {
      position.set(tank.position.x, tank.position.y-10*scale);
      velocity.set(0, -5);
    }
    if (tank.direction==1)
    {
      velocity.set(0, 5);
      position.set(tank.position.x, tank.position.y+10*scale);
    }
    if (tank.direction==2)
    {
      velocity.set(-5, 0);
      position.set(tank.position.x-20*scale, tank.position.y);
    }
    if (tank.direction==3)
    {
      velocity.set(5, 0);
      position.set(tank.position.x+20*scale, tank.position.y);
    }
  }

  void update2() {// used to move
    position.add(velocity);
    if (!((position.x<800)&&(position.x>0)&&(position.y<600)&&(position.y>0)))  // if the cannon moves out of the screen, cancel it to make sure it does not hit monsters who are not on the visible screen and change the score
    {
      position.set(1000, 1000);
      velocity.set(0, 0);
    }
  }

  void display() {
    if ((velocity.x!=0)||(velocity.y!=0))  // only draw when it is valid, save memory and time
    {
      rectMode(CENTER);
      fill(255, 0, 0);
      rect(position.x, position.y, 1*scale, 1*scale);
    }
    for (int i=0; i<10; i++) {
      if (dist(position.x, position.y, Monsters[i].position.x, Monsters[i].position.y)<20)  // check if the cannon hit one of the 20 monsters. destroy it 
      {
        score++;
        Monsters[i] = new Monster();
      }
    }
  }
}
class Monster {

  PVector position=new PVector(50, 50); // Initialization. Make it into the while loop.
  PVector velocity=new PVector();


  float monsterColor;

  Monster() {
    init();
  }

  void init() {
    // set initial Monster values

    while ((position.x<width)&&(position.x>0)&&(position.y>0)&&(position.y<height)) // this is the best way to randomize the monsters and make sure it does not appear on the screen at first  
    { 
      position.x=random(-200, width+200);
      position.y=random(-200, height+200);
    }

    velocity.x=(tank.position.x-position.x)/125;//Velocity updated off the current tank position.
    velocity.y=(tank.position.y-position.y)/125;//make sure the monsters was chasing the tank from the beginning.
    monsterColor=random(255);
  }


  void update() {
    // move monster towards the tank
    position.add(velocity);
    // if monster has moved off sponing areas, re-initialize it
    if ((position.x<-200)||(position.x>width+200)||(position.y<-200)||(position.y>height+200)) {
      init();
    }
  }


  void display() {

    
    stroke(monsterColor);
    strokeWeight(1);
    fill(monsterColor);
    
    // tentacles 
    line(position.x-10, position.y-10, position.x+10, position.y+10);
    line(position.x-10, position.y+10, position.x+10, position.y-10);
    // face
    ellipse (position.x, position.y, 10, 10);
    // eyes
    fill(255-monsterColor);
    ellipse (position.x+2, position.y-2, 2, 2);
    ellipse (position.x-2, position.y-2, 2, 2);

    if (dist(position.x, position.y, tank.position.x, tank.position.y)<20) // check if it hit the core of the tank. yes: restart the game, clear the score, increment the death 
    {
      death++;
      
      setup();
    }
  }
}
class Tank {

  PVector position = new PVector();
  int direction;  // decide display of the tank, and cannon direction
  Tank() {
    position.set(400, 300);  // spone at mid
    direction = 2; // start towards left
  }



  void update() {
//change the direction of the tank
    if (upPressed) {
      position.add(0, -2);
      direction = 0;
    }
    if (downPressed) {
      position.add(0, 2);
      direction = 1;
    }
    if (leftPressed) {
      position.add(-2, 0);
      direction = 2;
    }
    if (rightPressed) {
      position.add(2, 0);
      direction = 3;
    }
   if(position.x>800){
     position.x=0;
   }
   if(position.x<0){
     position.x=800;
   }
   if(position.y>600){
     position.y=0;
   }
   if (position.y<0){
     position.y=600;
   }
  }

  void display() {
    //the body first
    scale = 3;
    rectMode(CENTER);
    fill(0);
    rect(position.x, position.y, 10*scale, 10*scale);
    fill(255);
    // the core
    ellipse (position.x, position.y, 6*scale, 6*scale);
    fill(0);

    strokeWeight(1);
    stroke(0);
    // barrel position
    if (direction==2)// leftward
    {
      line(position.x-3*scale, position.y, position.x-6*scale, position.y);
      rectMode(CORNERS);
      rect(position.x-9*scale, position.y-1*scale, position.x-6*scale, position.y+1*scale);
    }
    if (direction==0)//upward
    {
      line(position.x, position.y-3*scale, position.x, position.y-6*scale);
      rectMode(CORNERS);
      rect(position.x-1*scale, position.y-9*scale, position.x+1*scale, position.y-6*scale);
    }
    if (direction==1)//downward
    {
      line(position.x, position.y+3*scale, position.x, position.y+6*scale);
      rectMode(CORNERS);
      rect(position.x-1*scale, position.y+6*scale, position.x+1*scale, position.y+9*scale);
    }
    if (direction==3)// rightward
    {
      line(position.x+3*scale, position.y, position.x+6*scale, position.y);
      rectMode(CORNERS);
      rect(position.x+9*scale, position.y+1*scale, position.x+6*scale, position.y-1*scale);
    }
  }//end of display
}