Jenni Lee — Final Project

sketch

/* Jenni Lee
Section E
jennife5@andrew.cmu.edu
Final Project
*/

var tapirImage = [];
var cloudImage = [];
var clouds = [];
var plantImage = [];
var plants = [];

var numMovingFrame = 2;

function preload() {

  var filenames = [];
  // image location for tapir
  filenames[0] = "https://i.imgur.com/DW5kRkh.png";
  filenames[1] = "https://i.imgur.com/4KccJ7e.png";

  // image location for plants
  filenames[2] = "https://i.imgur.com/CICxu5P.png";
  filenames[3] = "https://i.imgur.com/KObxJ71.png";
  filenames[4] = "https://i.imgur.com/IYuCsVt.png";

  // image location for clouds
  filenames[5] = "https://i.imgur.com/w9ND0YA.png";
  filenames[6] = "https://i.imgur.com/6Ovkd5e.png";
  filenames[7] = "https://i.imgur.com/JH0DqMf.png";


  // PUT CODE HERE TO LOAD THE IMAGES INTO THE frames ARRAY,
  // USING THE FILENAMES STORED IN THE filenames ARRAY.

  for (var i = 0; i < numMovingFrame; i++) {
    tapirImage[i] = loadImage(filenames[i]);
  }

  for (i = 0; i < 3; i++) {
    plantImage[i] = loadImage(filenames[i + 2]);
  }

  for (i = 0; i < 3; i++) {
    cloudImage[i] = loadImage(filenames[i + 5]);
  } 
}

var ibuffer = 120; // buffer space (minimum distance) between two plants for jumping
function setup() {
  createCanvas(1000, 300);
  initiate();
  frameRate(30);
  textFont('Helvetica');
}

var currentTapirImageIndex = 0; // rotating tapir images to simulate tapir movement
var tapirLocationX = 80;
var tapirLocationY = 80;
var upperYJump = 200,
  lowerYJump = 80;
var speed = 3; // jump speed per frame
var jumpSpeed = 3;
var tapirMinHeight = 120;
var jumpStatus = false; // use this to tell if tapir is jumping or not
var tapirInPlantRangeCurr = []; // to record if tapir is in the plant range or not, the current state
var tapirInPlantRangePrev = []; // to record if tapir is in the plant range or not, the previous state
var numPlantsJumped = 0; // count total # of plants tapir jumps over
var isGameOver = false;

function initiate() {

  // create an initial collection of clouds
  for (var i = 0; i < 10; i++) {
    var rx = random(width); // randomly generate clouds at random locations to start with
    clouds[i] = makeCloud(rx);
  }
  // create an initial collection of plants
  for (i = 0; i < 6; i++) { // fixed location for plants, for jumping practice
    plants[i] = makePlant(230 + i * 180);
  }

  tapirLocationY = lowerYJump; // back to original position
  jumpSpeed = 3; // for tapir's jump speed
  jumpStatus = false; // to keep track if tapir is in jumping state or not
  isGameOver = false;
  numPlantsJumped = 0;
  currentTapirImageIndex = 0;
  for (i = 0; i < 10; i++) {
    tapirInPlantRangePrev[i] = false;
    tapirInPlantRangeCurr[i] = false;
  }
}

function draw() {
  background(229, 233, 137);

  noStroke();
  fill(70, 83, 130);
  rect(0, 0, width - 1, height - 51);

  // handling cloud display, the bottom layer of objects
  updateAndDisplayClouds();
  removeCloudsThatHaveSlippedOutOfView();
  addNewCloudsWithSomeRandomProbability();

  // draw terrain, next layer of object
  drawTerrain();

  // handling plants display, next layer of objects
  updateAndDisplayPlants();
  removePlantsThatHaveSlippedOutOfView();
  addNewPlantsWithSomeRandomProbability();

  // check the jumping status and display tapir
  updateTapirStatus();
  checkTapirOverPlant();
  
  // display the status such as # of total plants jumped, score
  displayStatusString();
}

function checkTapirOverPlant() {
  // check if tapir is inside any plant range
  for (var i = 0; i < plants.length; i++) {
    if (plants[i].x <= tapirLocationX + tapirImage[0].width) {
      if (plants[i].x + plantImage[plants[i].nPlantType].width >= tapirLocationX + tapirImage[currentTapirImageIndex].width) {
        tapirInPlantRangePrev[i] = tapirInPlantRangeCurr[i];
        tapirInPlantRangeCurr[i] = true;
        if (tapirLocationY < tapirMinHeight) {
          noStroke();
          fill(0, 0, 0);
          textSize(20);
          text("Game Over. Touch screen, click mouse, or press 'r' to restart.", width / 2 - 230, height / 2);
          isGameOver = true;
          noLoop();
        }
      } else {
        tapirInPlantRangePrev[i] = tapirInPlantRangeCurr[i];
        tapirInPlantRangeCurr[i] = false;
      }
    }
    if (tapirInPlantRangePrev[i] == true & tapirInPlantRangeCurr[i] == false) {
      numPlantsJumped++;
    }
  }
}

function updateTapirStatus() {
  if (jumpStatus == true) {
    tapirLocationY += jumpSpeed;
    if (tapirLocationY >= upperYJump) { // tapir hit top jupming point, change direction
      tapirLocationY = upperYJump;
      jumpSpeed = -1 * speed;
    } else if (tapirLocationY < lowerYJump) {
      tapirLocationY = lowerYJump;
      jumpSpeed = speed;
      jumpStatus = false;
    }
  }
  image(tapirImage[currentTapirImageIndex], tapirLocationX, height - tapirLocationY);

  if (jumpStatus == false) {
    currentTapirImageIndex++;
  }
  currentTapirImageIndex = currentTapirImageIndex % numMovingFrame; // rotating tapir images

}

function keyTyped() {
  if (key == "a") {
    jumpStatus = true;
  } else {
    jumpStatus = false;
  }
  if (key == "r") {
    if (isGameOver == true) {
      initiate();
      loop();
    }
  }
}

function touchStarted() {
  if (isGameOver == true) {
    initiate();
    loop();
  }
  else {
    jumpStatus = true;
  }
}

// define object for plant
function makePlant(birthLocationX) {
  var plant = {
    x: birthLocationX,
    y: height - 40,
    speed: -2.1,
    nPlantType: round(random(0, 2)),
    move: plantMove,
    display: plantDisplay
  }
  return plant;
}

function plantMove() {
  this.x += this.speed;
}

function plantDisplay() {
  imageMode(CORNERS);
  image(plantImage[this.nPlantType], this.x, this.y,
    this.x + plantImage[this.nPlantType].width, this.y - plantImage[this.nPlantType].height);
  imageMode(CORNER);

}

function updateAndDisplayPlants() {
  // Update the building's positions, and display them.
  for (var i = 0; i < plants.length; i++) {
    plants[i].move();
    plants[i].display();
  }
}

function removePlantsThatHaveSlippedOutOfView() {
  var plantsToKeep = [];
  for (var i = 0; i < plants.length; i++) {
    if (plants[i].x + plantImage[plants[i].nPlantType].width > 0) {
      plantsToKeep.push(plants[i]);
    }
  }
  plants = plantsToKeep; // remember the surviving plants
}

function addNewPlantsWithSomeRandomProbability() {
  var newPlantLikelihood = 0.05;
  var toAddPlant = true;
  if (random(0, 1) < newPlantLikelihood) {
    var i = plants.length - 1;
    // make sure there is at least ibuffer distance from previous plant before adding a new one from right
    if (plants[i].x + plantImage[plants[i].nPlantType].width + ibuffer < width) {
      plants.push(makePlant(width));
    }
  }
}

// define object for cloud
function makeCloud(birthLocationX) {
  var cld = {
    x: birthLocationX,
    y: round(random(25, 50)),
    speed: -0.6,
    nCloudType: round(random(0, 2)),
    move: cloudMove,
    display: cloudDisplay
  }
  return cld;
}

function cloudMove() {
  this.x += this.speed;
}

function cloudDisplay() {
  image(cloudImage[this.nCloudType], this.x, this.y);
}

function updateAndDisplayClouds() {
  // Update the cloud's positions, and display them.
  for (var i = 0; i < clouds.length; i++) {
    clouds[i].move();
    clouds[i].display();
  }
}


function removeCloudsThatHaveSlippedOutOfView() {
  var cloudsToKeep = [];
  for (var i = 0; i < clouds.length; i++) {
    if (clouds[i].x + cloudImage[clouds[i].nCloudType].width > 0) {
      cloudsToKeep.push(clouds[i]);
    }
  }
  clouds = cloudsToKeep; // remember the surviving clouds
}

function addNewCloudsWithSomeRandomProbability() {
  var newCloudLikelihood = 0.004;
  if (random(0, 1) < newCloudLikelihood) {
    clouds.push(makeCloud(width)); // push the new cloud to the clouds array (to the end)
  }
}


function displayStatusString() {
  noStroke();
  fill(0, 200, 0);
  textSize(14);
  text("Touch screen, click mouse, or press 'a' to jump", 5, 20);
  textSize(40);
//  var statusString = "# Plants jumped over = " + numPlantsJumped;
  var statusString = numPlantsJumped;
  text(statusString, width/2, height/2 - 25);
}

function drawTerrain() {
  noFill();
  beginShape();
  var terrainSpeed = 0.00012;
  var terrainDetail = 0.005;

  for (var x = 0; x < width; x++) {
    var t = (x * terrainDetail) + (millis() * terrainSpeed);
    var y = map(noise(t), 0, 1, 0, height - 40);
    stroke(216, 158, 172);
    line(x, y, x, height - 50);
  }
  endShape();
}

For this project, I wanted to create a game of a tapir that jumps over flowers. Tapirs are my favorite animal, so I wanted to use that. I drew all pictures, clouds, tapir, and plants, on Adobe Illustrator to load them at preLoad time for various effects, and use image() function to display them all at specified locations when they are inside canvas range. I drew 3 types of clouds, and design/define a cloud object to record and keep track of the cloud type/shape (randomly selected), location (x and y), and movement speed. Mountain/terrain: I used noise() function to draw vertical line from a variable y location to the ground to simulate mountain. I drew two frames of tapir to simulate its running. When loading different frames at consecutive frames, it would seem tapir is running. Overall, this project was really fun.

Leave a Reply