xxxxxxxxxx
620
let SCREEN_WIDTH = 600;
let SCREEN_HEIGHT = 600;
//class for all objects that will be created in the game
class Character {
constructor(r, x, y) {
this.radius = r;
this.x = x;
this.y = y;
this.vx = 0;
this.vy = 0;
this.health = 0;
}
update() {
//updates position of characters on screen
this.y += this.vy;
this.x += this.vx;
}
//method to handle display of the object
display() {
this.update();
// fill(255, 0, 0);
// noStroke();
// ellipse(this.x, this.y, this.radius * 2, this.radius * 2);
}
//method to control health of the object
hit(amount) {
this.health = this.health - amount;
}
//generates ozone powerups randomly
gen_ozone(num) {
let prob = round(random(0, num));
if (prob == 1) {
game.ozone.push(new OzonePowerUp(this.x, this.y));
}
}
}
// class for main player inheriting from mainclass
class Tree extends Character {
constructor(r, x, y) {
super(r, x, y);
this.img = tree;
this.health = 100;
this.lives = 3;
this.projSpeed = 7;
this.img2 = apple;
this.shoot_sound = shoot;
//adjusts movement speed
this.move_speed = 10;
//initiates boolean values for input keys for movement
this.key_handler = { a: false, d: false, w: false, s: false };
//controls how fast the player shoots
this.projFrequency = 45;
}
update() {
//updates position of main player on screen
this.y += this.vy;
this.x += this.vx;
//control logic based on inout from user for movement
if (this.key_handler.a) {
this.vx = -this.move_speed;
} else if (this.key_handler.d) {
this.vx = this.move_speed;
} else {
this.vx = 0;
}
if (this.key_handler.w) {
this.vy = -this.move_speed;
} else if (this.key_handler.s) {
this.vy = this.move_speed;
} else {
this.vy = 0;
}
//limit movement to screen boundaries
if (this.x - this.radius < 0) {
this.x = this.radius;
} else if (this.x + this.radius > SCREEN_WIDTH) {
this.x = SCREEN_WIDTH - this.radius;
} else if (this.y - this.radius < 0) {
this.y = this.radius;
} else if (this.y + this.radius > SCREEN_HEIGHT) {
this.y = SCREEN_HEIGHT - this.radius;
}
//shoots projectiles from main player
if (frameCount % this.projFrequency == 0) {
this.shoot();
this.shoot_sound.play();
}
}
//method to handle display of the object
display() {
this.update();
image(this.img, this.x - 80, this.y - 50, 150, 150);
// fill(255, 0, 0);
// noStroke();
// ellipse(this.x, this.y, this.radius * 2, this.radius * 2);
}
//method that instantiates the projectiles
shoot() {
game.playerProjectiles.push(new Projectile(7,game.player.x - 2,game.player.y - 10,12,this.projSpeed,this.img2));
}
//method handling damage taken by main player
hit(amount) {
this.health = this.health - amount;
//logic for updating player health, lives and gameover state
if (this.health <= 0 && this.lives > 0) {
this.lives -= 1;
this.health = 100;
} else if (this.health <= 0 && this.lives == 0) {
game.gameOver = true;
}
}
}
//class for enemy objects
class Enemy extends Character {
constructor(r, x, y) {
super(r, x, y);
this.health = 10;
this.vy = 0.5;
this.projSpeed = 3;
this.img = random(imgArray);
this.img2 = wood;
}
update() {
//updates position of enemies on screen
this.y += this.vy;
//increases velocity of enemy when it reaches half screen
if (this.y > 300) {
this.vy = 1;
}
//logic controlling frequency of shooting by enemies
if (frameCount % 60 == 0) {
let prob = round(random(0, 3));
if (prob == 1) {
this.shoot();
}
}
}
//method instantiating projectiles from enemies
shoot() {
game.enemyProjectiles.push(
new Projectile(7, this.x, this.y + 25, 6, this.projSpeed, this.img)
);
}
display() {
this.update();
image(this.img2, this.x - 60, this.y -50, 100, 100);
// fill(255, 0, 0);
// noStroke();
// ellipse(this.x, this.y, this.radius * 2, this.radius * 2);
//logic for incrementing score and generating ozone powerup when enemy dies
if (this.health <= 0) {
game.score += 10;
this.gen_ozone(9);
}
}
}
//PROJECTILE class
class Projectile {
constructor(r, x, y, dir, s, img) {
this.radius = r;
this.x = x;
this.y = y;
this.speed = s;
this.vx = 0;
this.vy = 0;
this.img = img;
//variable controlling direction of projectiles, 6 is down, 12 is up
this.dir = dir;
//variable keeps track when projectile has collided with something
this.used = false;
}
update() {
//logic controlling the direction of projectiles based on number passed
if (this.dir == 12) {
this.vx = 0;
this.vy = -this.speed;
} else if (this.dir == 6) {
this.vx = 0;
this.vy = this.speed;
}
this.x += this.vx;
this.y += this.vy;
}
display() {
// logic for displaying projectiles, only displays if not collided
if (this.used == false) {
this.update();
image(this.img, this.x - 20, this.y - 20, 40, 40);
// fill(0, 255, 126);
// noStroke();
// ellipse(this.x, this.y, this.radius * 2, this.radius * 2);
}
}
//method for collision detection among bodies
collision(target) {
var distance = ((this.x - target.x) ** 2 + (this.y - target.y) ** 2) ** 0.5;
if (distance <= this.radius + target.radius) {
//if collision is detected, changes state of projectile to used
this.used = true;
return true;
} else {
return false;
}
}
}
//class for ozone powerups
class OzonePowerUp {
constructor(x, y) {
this.x = x;
this.y = y;
this.radius = 30;
this.healAmount = 20;
this.used = false;
this.img = ozone;
}
//method controlling amount of health given to player upon collection of powerup
give_health() {
game.player.health += this.healAmount;
if (game.player.health > 100) {
game.player.health = 100;
}
}
//method for collision detection with powerup
collision(target) {
var distance = ((this.x - target.x) ** 2 + (this.y - target.y) ** 2) ** 0.5;
if (distance <= this.radius + target.radius) {
//if collision is detected, changes state of powerup to used
this.used = true;
return true;
} else {
return false;
}
}
display() {
image(this.img, this.x - 25, this.y - 30, 50, 50);
// fill(0, 255, 0);
// noStroke();
// ellipse(this.x, this.y, this.radius, this.radius);
}
}
//instantiates all other classes and keeps them together
class Game {
constructor() {
//instantiates mainplayer at given coordinates
this.player = new Tree(40, 550, 500);
this.enemyProjectiles = [];
this.playerProjectiles = [];
this.ozone = [];
this.enemies = [];
this.timer = 0;
this.score = 0;
this.bg_img = forest;
bgsound.play();
//variables controlling game state
this.gameStarted = false;
this.gameOver = false;
this.gameWon = false;
//boolean variables tracking game levels
this.level1 = false;
this.level2 = false;
this.level3 = false;
this.level4 = false;
this.level5 = false;
this.level6 = false;
this.level7 = false;
this.level8 = false;
this.level9 = false;
}
//method handling display of everything throughout the game
display_game() {
//condition for displaying actual gameplay when game has started
if (this.gameStarted && this.gameOver == false && this.gameWon == false) {
image(this.bg_img, 0, 0, 600, 600);
this.player.display();
//loop for displaying all enemies in enemy array
for (let i = 0; i < this.enemies.length; i++) {
this.enemies[i].display();
}
//loop for displaying all projectiles in enemyprojectiles array
for (let i = 0; i < this.enemyProjectiles.length; i++) {
this.enemyProjectiles[i].display();
//logic for player and enemyprojectile collision detection, player then takes damage
if (this.enemyProjectiles[i].used == false && this.enemyProjectiles[i].collision(this.player)) {
this.player.hit(10);
}
}
//loops through enemyprojectiles array and pops any projectiles which have already collided
for (let i = 0; i < this.enemyProjectiles.length; i++) {
if (this.enemyProjectiles[i].used == true) {
this.enemyProjectiles.splice(i, 1);
break;
}
}
//loops through enemy array and pops any enemies with health less than zero
for (let i = 0; i < this.enemies.length; i++) {
if (this.enemies[i].health <= 0) {
this.enemies.splice(i, 1);
break;
//logic for score reduction if enemy reaches beyond screen height, and pops enemy from array
} else if (this.enemies[i].y > 650) {
this.enemies.splice(i, 1);
this.score -= 10;
break;
}
}
//loops through playerprojectiles array and displays them
for (let i = 0; i < this.playerProjectiles.length; i++) {
this.playerProjectiles[i].display();
//detects collision btn playerprojectiles and enemies, then enemy takes damage
for (let j = 0; j < this.enemies.length; j++) {
//Check if the projectile collides with any enemy
if (
this.playerProjectiles[i].used == false &&
this.playerProjectiles[i].collision(this.enemies[j])
) {
this.enemies[j].hit(10);
}
}
}
//loops through ozone powerups array, displays them, and detects collision with player
for (let i = 0; i < this.ozone.length; i++) {
this.ozone[i].display();
if (
this.ozone[i].used == false &&
this.ozone[i].collision(this.player)
) {
this.ozone[i].give_health();
}
}
//pops ozone powerup from array once collected by player
for (let i = 0; i < this.ozone.length; i++) {
if (this.ozone[i].used == true) {
this.ozone.splice(i, 1);
break;
}
}
this.show_score();
//logic controlling time in the game
if (frameCount % 60 == 0) {
this.timer += 1;
}
//logic for level control and enemy generation
if (this.timer == 1 && this.level1 == false) {
for (let i = 0; i < 5; i++) {
this.enemies[i] = new Enemy(25, 200 + 70 * i, 100);
}
this.enemies.push(new Enemy(25, 100 + 70 * 0, 10));
this.enemies.push(new Enemy(25, 100 + 70 * 1, 20));
this.enemies.push(new Enemy(25, 100 + 70 * 2, 30));
this.enemies.push(new Enemy(25, 100 + 70 * 3, 40));
this.level1 = true;
} else if (this.timer == 11 && this.level2 == false) {
this.enemies.push(new Enemy(25, 100 + 70 * 0, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 1, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 2, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 3, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 4, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 5, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 6, 0));
this.level2 = true;
} else if (this.timer == 20 && this.level3 == false) {
this.enemies.push(new Enemy(25, 100 + 70 * 0, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 1, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 2, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 3, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 4, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 5, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 6, 0));
this.level3 = true;
} else if (this.timer == 28 && this.level4 == false) {
this.enemies.push(new Enemy(25, 100 + 70 * 0, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 1, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 2, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 3, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 4, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 5, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 6, 0));
this.level4 = true;
} else if (this.timer == 36 && this.level5 == false) {
this.enemies.push(new Enemy(25, 100 + 70 * 0, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 1, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 2, 10));
this.enemies.push(new Enemy(25, 100 + 70 * 3, 30));
this.enemies.push(new Enemy(25, 100 + 70 * 4, 50));
this.enemies.push(new Enemy(25, 100 + 70 * 5, 70));
this.enemies.push(new Enemy(25, 100 + 70 * 6, 90));
this.level5 = true;
} else if (this.timer == 44 && this.level6 == false) {
this.enemies.push(new Enemy(25, 100 + 70 * 0, 200));
this.enemies.push(new Enemy(25, 100 + 70 * 1, 250));
this.enemies.push(new Enemy(25, 100 + 70 * 2, 100));
this.enemies.push(new Enemy(25, 100 + 70 * 3, 300));
this.enemies.push(new Enemy(25, 100 + 70 * 4, 200));
this.enemies.push(new Enemy(25, 100 + 70 * 5, 150));
this.enemies.push(new Enemy(25, 100 + 70 * 6, 300));
this.level6 = true;
} else if (this.timer == 51 && this.level7 == false) {
this.enemies.push(new Enemy(25, 100 + 70 * 0, 250));
this.enemies.push(new Enemy(25, 100 + 70 * 1, 100));
this.enemies.push(new Enemy(25, 100 + 70 * 2, 0));
this.enemies.push(new Enemy(25, 100 + 70 * 3, 300));
this.enemies.push(new Enemy(25, 100 + 70 * 4, 200));
this.enemies.push(new Enemy(25, 100 + 70 * 5, 225));
this.enemies.push(new Enemy(25, 100 + 70 * 6, 150));
this.level7 = true;
this.player.projFrequency = 30;
} else if (this.timer == 59 && this.level8 == false) {
this.enemies.push(new Enemy(25, 100 + 70 * 0, 300));
this.enemies.push(new Enemy(25, 100 + 70 * 1, 200));
this.enemies.push(new Enemy(25, 100 + 70 * 2, 100));
this.enemies.push(new Enemy(25, 100 + 70 * 3, 250));
this.enemies.push(new Enemy(25, 100 + 70 * 4, 230));
this.enemies.push(new Enemy(25, 100 + 70 * 5, 280));
this.enemies.push(new Enemy(25, 100 + 70 * 6, 300));
this.level8 = true;
} else if (this.timer == 66 && this.level9 == false) {
this.enemies.push(new Enemy(25, 100 + 70 * 0, 300));
this.enemies.push(new Enemy(25, 100 + 70 * 1, 250));
this.enemies.push(new Enemy(25, 100 + 70 * 2, 150));
this.enemies.push(new Enemy(25, 100 + 70 * 3, 300));
this.enemies.push(new Enemy(25, 100 + 70 * 4, 280));
this.enemies.push(new Enemy(25, 100 + 70 * 5, 290));
this.enemies.push(new Enemy(25, 100 + 70 * 6, 300));
this.level9 = true;
}
//logic for changing game state based on timer, score, and lives
else if (this.timer >= 73 && this.score < 0) {
game.gameOver = true;
} else if (this.timer >= 73 && this.player.lives >= 0) {
game.gameWon = true;
}
print(this.timer);
}
//displays gameover page when player loses game
else if (this.gameOver){
image(this.bg_img, 0, 0, 600, 600);
noStroke();
fill(76, 28, 4, 200)
//fill(6,57,112,150)
rect(130, 260, 320,130, 40)
fill(255)
textSize(35);
textFont(font);
text("Game Over", 200, 300);
textSize(25);
text("Score: " + str(this.score), 230, 330);
text("Press RETURN to begin " , 150, 360);
bgsound.stop();
}
//displays gamewon page when player wins game
else if (this.gameWon){
image(this.bg_img, 0, 0, 600, 600);
noStroke();
fill(6,57,112,200)
rect(140, 240, 350,150, 40)
fill(255)
textSize(25);
textFont(font);
text("You Have Saved The Earth!", 160, 300);
textSize(20);
text("Score: " + str(this.score), 260, 330);
text("Press RETURN to begin " , 200, 360);
bgsound.stop();
}
//displays main instructions page
else if (this.gameStarted == false && this.gameOver == false && this.gameWon == false) {
image(this.bg_img, 0, 0, 600, 600);
noStroke();
//fill(6,57,112,150)
fill(76, 61, 4, 200)
rect(105, 210, 430,200, 150)
textSize(45);
fill(255)
//fill(6,57,112);
textFont(font);
text("MAN VS TREE ", 170, 300);
textSize(20);
//textFont('Georgia');
text("Use WASD keys to move " , 200, 350);
text("Press RETURN to begin " , 205, 380);
}
}
//controls display of score, lives and ozone
show_score() {
noStroke();
fill(76, 61, 4, 150)
//fill(6,57,112,150)
rect(475, 13, 110,80, 30)
fill(255);
textSize(15);
//textFont('Helvetica');
textFont(font);
text("Score: " + str(this.score), 490, 40);
text("Ozone: " + str(this.player.health), 490, 60);
text("Lives: " + str(this.player.lives), 490, 80);
}
}
//preloads sounds and images used in the game
function preload() {
bgsound = loadSound("bgsound.mp3");
shoot = loadSound("apple.mp3");
font = loadFont('font3.ttf');
tree = loadImage("tree.png");
apple = loadImage("apple.png");
dynamite = loadImage("dynamite.png");
axe = loadImage("axe.webp");
ozone = loadImage("ozone.png");
wood = loadImage("wood.png");
forest = loadImage("forest.jpeg");
imgArray = [dynamite, axe];
}
function setup() {
createCanvas(SCREEN_WIDTH, SCREEN_HEIGHT);
//instantiates game class
game = new Game();
}
function draw() {
background(0);
//calls the display method of game object
game.display_game();
}
//controls movements of main character based on keypressed
function keyPressed() {
if (key == "a") {
game.player.key_handler.a = true;
} else if (key == "d") {
game.player.key_handler.d = true;
} else if (key == "s") {
game.player.key_handler.s = true;
} else if (key == "w") {
game.player.key_handler.w = true;
}
//changes state of game to started when return is pressed
if (game.gameStarted == false && keyCode == RETURN){
game.gameStarted = true
}
//instantiates game object again after game won or lost
if (game.gameOver == true && keyCode == RETURN || game.gameWon == true && keyCode == RETURN){
game = new Game()
}
}
function keyReleased() {
if (key == "a") {
game.player.key_handler.a = false;
} else if (key == "d") {
game.player.key_handler.d = false;
} else if (key == "s") {
game.player.key_handler.s = false;
} else if (key == "w") {
game.player.key_handler.w = false;
}
}