/* 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.