Your browser does not support the canvas tag.

previous        Show / Hide Source        Download        next
/*////////////////////////////////////////////////////////////////
 ** Fire The Cannons by Paul Williams
 ** Interactive Toy Assignement
 ** Shoot your Ships cannon to destroy boats and those pesky birds
 ** Aim the cannon with UP and Down arrow keys and click to fire
/*////////////////////////////////////////////////////////////////

//Counting variable used to move the waves.
float moveWaves = 0;

//Variables for the boats movement.
float boatPositionX = 0;
float boatPositionY = 0;
float boatBob= 0.3;

//Variables for the ducks movement.
float birdPositionX = 100;
float birdPositionY = 0;
float birdBob = 0.5; 

//Variables for Effects
boolean boatExplode = false;
boolean birdExplode = false;
boolean waterSplash1 = false;
boolean waterSplash2 = false;
float effectLength = 0;

//Variables for the cannon's fuse
boolean fuseLit = false;
float fuseHeight = 290;
float fuseBurned = 0;

//Variables for Cannon
float cannonBack = 360;
float cannonAngle = 70;
float cannonAngleValue = 1;
float cannonEnd = 50;

//Variables for Cannonballs.
boolean cannonballFired = false;
float defaultCannonballSize = 50;
float cannonballSize;
float defaultCannonballPosition = 350;
float cannonballPosition;
float shotSpeed=10;
float shotGravity=0;

//Setup the Scene
void setup() {
  frameRate(60);
  size(400, 400);
  smooth();
  rectMode(CORNERS);
}

//Repeat these actions.
void draw() {

  ////////////////////////////////////
  // DRAW
  ////////////////////////////////////

  // clear background
  background(175, 226, 239);

  drawWave(moveWaves, 1);
  drawBoat();
  drawWave(moveWaves, 2);
  drawWave(moveWaves, 3);
  drawBird();

  //Draw an effect if it's triggered
  if (boatExplode) {
    drawBoatExplode();
  }
  if (birdExplode) {
    drawBirdExplode();
  }
  if (waterSplash1) {
    drawWaterSplash1();
  }
  if (waterSplash2) {
    drawWaterSplash2();
  }

  drawPirateShip();
  drawCannonBalls();
  drawCannon();  

  // update wave position
  updateWavePosition();
}

////////////////////////////////////
// WAVE FUNCTIONS
////////////////////////////////////

// Creates a moving wave using colours, speeds, and lengths decided by the layer you input 
void drawWave(float moveWaves, float layer) {
  float waveDrawingPositionX = -100 * layer;
  // selecting colour based on layer input
  if (layer == 1) {
    stroke(10, 20, 150);
  }
  if (layer == 2) {
    stroke(0, 25, 200);
  }
  if (layer == 3) {
    stroke(63, 75, 239);
  }
  // Creating the waves using many rectangles and the sin fuction. Moves with the moveWaves variable multiplied by the layer to increase its speed
  while (waveDrawingPositionX < width) {
    rect(waveDrawingPositionX + moveWaves * layer, height/1.4, waveDrawingPositionX + 5 + moveWaves * layer, height/1.5-sin(waveDrawingPositionX/(10*layer))*(6 + 3*layer)-(100 - (20 * layer)));
    waveDrawingPositionX += 1;
  }
}

// Updates the waves current positions.
void updateWavePosition() {
  moveWaves += 1;
  if (moveWaves > 62) {
    moveWaves = 0;
  }
}

////////////////////////////////////
// TARGET FUNCTIONS
////////////////////////////////////

// Drawing the boat
void drawBoat() {
  stroke(0);
  fill(150, 20, 20);
  rect(boatPositionX + 10, height/2.1 + boatPositionY, boatPositionX + 60, height/2.4 + boatPositionY);
  fill (150);
  rect(boatPositionX + 20, height/2.4 + boatPositionY, boatPositionX + 35, height/2.8 + boatPositionY);
  quad(boatPositionX - 10, height/1.8 + boatPositionY, boatPositionX- 10, height/2.1 + boatPositionY, boatPositionX + 100, height/2.1 + boatPositionY, boatPositionX + 80, height/1.8 + boatPositionY);

  // Updating the boats X position
  boatPositionX += 1.2;
  if (boatPositionX > width + 200) {
    boatPositionX = -100;
  }
  // Updating the boats Y position
  boatPositionY += boatBob;
  if (boatPositionY > 5 || boatPositionY< -5) {
    boatBob *= -1;
  }
}

// Drawing the bird
void drawBird() {
  noStroke();
  fill(200, 200, 0);
  triangle(birdPositionX - 26, height/8 + birdPositionY+  4, birdPositionX - 16, height/8 + birdPositionY + 4, birdPositionX - 16, height/8 + birdPositionY - 3);
  fill(255, 128, 0);
  rect(birdPositionX + 6, height/8 + birdPositionY - 1, birdPositionX + 16, height/8 + birdPositionY + 4);
  fill (255);
  ellipse(birdPositionX, height/8 + birdPositionY, 22, 15);
  fill(50, 200, 20);
  ellipse(birdPositionX - 14, height/8 + birdPositionY, 10, 10);
  fill(100, 50, 0);
  quad(birdPositionX-5, height/8 +  birdPositionY, birdPositionX + 5, height/8 + birdPositionY, birdPositionX + 5, height/8 - birdPositionY *2, birdPositionX -5, height/8 - birdPositionY *2);

  // Updating the birds X position
  birdPositionX -= 2;
  if (birdPositionX < -100) {
    birdPositionX = width + 100;
  }
  // Updating the birds Y position
  birdPositionY += birdBob;
  if (birdPositionY > 5 || birdPositionY< -5) {
    birdBob *= -1;
  }
}


////////////////////////////////////
// EFFECT FUNCTIONS
////////////////////////////////////

// Draws the effect that plays when the Boat gets hit.
void drawBoatExplode() {
  fill(255, 0, 0);
  rect(width/2 - effectLength*2 + 5, height/2 - effectLength*2 + 5, width/2 + effectLength*2 - 5, height/2 + effectLength*2 - 5);
  fill(255, 255, 0);
  quad(width/2 - effectLength*2, height/2, width/2, height/2 - effectLength*2, width/2 + effectLength*2, height/2, width/2, height/2 + effectLength*2);

  updateEffect();
}

// Draws the effect that plays when the bird gets hit.
void drawBirdExplode() {
  fill(255, 0, 0);
  rect(width/2 - effectLength + 5, height/8 - effectLength + 5, width/2 + effectLength - 5, height/8 + effectLength - 5);
  fill(255, 255, 0);
  quad(width/2 - effectLength, height/8, width/2, height/8 - effectLength, width/2 + effectLength, height/8, width/2, height/8 + effectLength);

  updateEffect();
}

// Draws the effect that plays when you shoot the cannon with the cannon aimed at position 1.
void drawWaterSplash1() {

  fill(70, 85, 255);
  ellipse(width/2, height/1.8, effectLength + 10, effectLength + 10);
  fill(180, 180, 255);
  ellipse(width/2, height/1.8, random(15), random(15));

  updateEffect();
}

// Draws the effect that plays when you shoot the cannon with the cannon aimed at position 2 and miss the boat.
void drawWaterSplash2() {
  fill(70, 75, 255);
  ellipse(width/2, height/2, effectLength + 5, effectLength + 5);
  fill(180, 180, 255);
  ellipse(width/2, height/2, random(10), random(10));

  updateEffect();
}

// Updates the effects and stops them after 20 frames.
void updateEffect() {
  effectLength++;
  if (effectLength >= 20) {
    effectLength = 0;
    boatExplode = false;
    birdExplode = false;
    waterSplash1 = false;
    waterSplash2 = false;
  }
}

////////////////////////////////////
// PLAYER'S SHIP FUNCTIONS
////////////////////////////////////

// draws the ship which the cannon is placed on
void drawPirateShip() {
  stroke(0);
  fill(100, 50, 0);
  rect(0, height/1.6, width/2 -40, height/1.2);
  rect(width, height/1.6, width/2 +40, height/1.2);
  rect(width/2-40, height/1.4, width/2+40, height);
  rect(0, height/1.2, width, height/1.1);
  rect(0, height/1.1, width, height);
  fill(63, 75, 239);

  rect(-15, height/1.5, 5, height/1.2);
  rect(30, height/1.5, 50, height/1.2);
  rect(75, height/1.5, 95, height/1.2);
  rect(120, height/1.5, 140, height/1.2);

  rect(395, height/1.5, 410, height/1.2);
  rect(350, height/1.5, 370, height/1.2);
  rect(305, height/1.5, 325, height/1.2);
  rect(260, height/1.5, 280, height/1.2);
  noStroke();
}



// Draws every part of the cannon
void drawCannon() {
  // the barrel
  noStroke();
  fill(40);
  ellipse(width/2, height/1.2-cannonAngle, 60, cannonEnd);
  quad(width/2+50, height/1.2, width/2 + 30, height/1.2 - cannonAngle, width/2 - 30, height/1.2 - cannonAngle, width/2 - 50, height/1.2);
  ellipse(width/2, height/1.2, 100, 100);
  // The end piece  
  stroke(0);
  ellipse(width/2, cannonBack, 40, 40);
  // The hole for the fuse
  fill(0);
  ellipse(width/2, fuseHeight+30, 15, 15);
  // The wheels on the side
  fill(150, 80, 20);
  rect(width/2-50, height/1.03, width/2-70, height/1.45);
  rect(width/2+50, height/1.03, width/2+70, height/1.45);

  // The fuse
  noStroke();
  rect(width/2 + 5, fuseHeight + 30, width/2 - 5, fuseHeight + fuseBurned); 
  // Checks to see if the fuse is burning and if it is sets up the fire and shortens the length of the fuse
  if (fuseLit) {
    fuseBurned ++;
    if (fuseBurned < 30) {
      fill(255, 255, 0, 150);
      triangle(width/2 - 5, fuseHeight+fuseBurned, width/2 + 5, fuseHeight+fuseBurned, width/2 + random(-10, 10), fuseHeight + fuseBurned - 15);
      fill(255, 0, 0, 150);
      triangle(width/2 - 5, fuseHeight+fuseBurned, width/2 + 5, fuseHeight+fuseBurned, width/2 + random(-10, 10), fuseHeight + fuseBurned - 25);
      fill(255, 140, 0, 150);
      triangle(width/2 - 5, fuseHeight+fuseBurned, width/2 + 5, fuseHeight+fuseBurned, width/2 + random(-10, 10), fuseHeight + fuseBurned - 25);
    }
    // Constrains the fuse from going into negatives
    if (fuseBurned >=30) {
      fuseBurned = 30;
    }
  }
}

// draws the cannon balls beside the cannon and the cannon ball that fires
void drawCannonBalls() {
  stroke(0);
  fill(20);
  ellipse(325, 335, 42, 42);
  ellipse(300, 350, 45, 45);
  ellipse(340, 360, 46, 46);

  // if the fuse is fully burned the cannonball is now fired
  if (fuseBurned == 30) {
    cannonballFired = true;
  }

  // what happens when the cannonball is fired
  if (cannonballFired) {
    ellipse(width/2, cannonballPosition, cannonballSize, cannonballSize);
    // adjusting the height of and size of the cannonball as it flies
    cannonballPosition -= shotSpeed - shotGravity;
    shotGravity += 0.25;
    cannonballSize -= 0.7;
    // if the cannonball reaches 0 size the shot is complete. Check for collision and reset the fuse
    if (cannonballSize <= 0) {
      cannonballFired = false;
      fuseLit = false;
      fuseBurned = 0;
      collisionCheck();
    }
  }
}

////////////////////////////////////
// EVENT FUNCTIONS
////////////////////////////////////

// Checks if a cannonball has been fired. If not you may change the cannons angle with the assigned keys
void keyPressed() {
  if (!cannonballFired) {
    updateCannonAngle();
  }
}

// If you havn't already lit the fuse then clicking will light it and reset the defaults of the cannonball
void mouseClicked() {
  if (!fuseLit) {
    fuseLit = true;
    cannonballPosition = defaultCannonballPosition;
    shotGravity= 0;
    cannonballSize = defaultCannonballSize;
  }
}

// Updates all of the variables for the cannon to change its angle
void updateCannonAngle() {
  // Constraining cannons angle when trying to increase it
  if (cannonAngle < 120) {
    if (keyCode == UP) {
      cannonAngle += 20;
      cannonEnd -= 10;
      cannonAngleValue++;
      cannonBack +=10;
      shotSpeed += 1;
      fuseHeight +=10;
    }
  }
  // Constraining the cannons angle when trying to decrease it
  if (cannonAngle > 70) {
    if (keyCode == DOWN) {
      cannonAngle -= 20;
      cannonEnd += 10;
      cannonAngleValue--;
      cannonBack -= 10;
      shotSpeed -=1;
      fuseHeight -= 10;
    }
  }
}


// Checks if the cannonball hit anything by looking at locations of the boat and bird, and the angle values it's firing at
void collisionCheck() {
  // Checking if bird was hit if the cannon was at angle value 4
  if (cannonAngleValue == 4 && birdPositionX > width/2 - 20 && birdPositionX < width/2 + 20) {
    birdPositionX = 900;
    birdExplode = true;
  }
  // Checking if boat was hit if the cannon was at angle value 2
  if (cannonAngleValue == 2) {
    if (boatPositionX > width/2 - 90 && boatPositionX < width/2 + 10) {
      boatPositionX = -600;
      boatExplode = true;
    }
    // The boat was missed, playing the splash effect instead
    else {
      waterSplash2 = true;
    }
  }
  // Player the splash effect for aiming too low
  if (cannonAngleValue == 1) {
    waterSplash1 = true;
  }
}