diff --git a/game.js b/game.js deleted file mode 100644 index 80a56ff..0000000 --- a/game.js +++ /dev/null @@ -1,1195 +0,0 @@ -var translateration = 0; -var fps = 0; -var isDebug = false; -var draw_grid = false; -var plummetingSoundNotPlayedBefore = false; -var text_hor_unit; -var text_vert_unit; -var sfx = {}; -var mus = {}; -var skydecay = 0; -var fps_recent_values = []; -var random_values = []; // from 0 to 1 -for (i = 0; i < 500; i++) { - random_values[i] = Math.random(); -} -var memorized_platform; -var amounts = { - tree: 200, - cloud: 200, - mountain: 200, - canyon: 80, - collectable: 23, - enemies: 30, - platforms: 50, -}; -var env = { - skyColor: 0, //assigned at setup() - floorPos_y: ((512 + 256) * 3) / 4, - groundColor: "#7F562A", - end_x: 3000, - state: "INTRO", - isSoundEnabled: false, // never set it true. it causes premature playing of the game sfx and music before loading. - isMusicEnabled: false, -}; -class Entity { - constructor(x, y) { - (this.x = x), - (this.y = y), - (this.size = 1.5), - (this.speed = 8), - (this.score = 0), - (this.lives = 3), - (this.health = 100), - this.prejump_y, - (this.gravity = 1.5); - this.vert_speed = -1; // Is negative. - (this.state = { - isLeft: false, - isRight: false, - isFalling: false, - isJumping: false, - isPlummeting: false, - isDescending: false, - isAscending: false, - }), - (this.projectiles = []); - } - resetValues() { - this.size = 1.5; - this.speed = 7; - } -} -var gameChar; -var flagpole = { - x: env.end_x, - isReached: false, - size_vert: 4, - size_hor: 7, - cell_size: 20, - cell_size_v: 20, - cell_size_h: 20, -}; - -class Cloud { - constructor(x, y, size) { - this.x = x; - this.y = y; - this.size = size; - } -} -class Canyon { - constructor(x, width) { - this.x = x; - this.width = width; - } -} -class Collectable { - constructor(x, y, size, worth) { - this.x = x; - this.y = y; - this.size = size; - this.worth = worth; - } -} -class Enemy extends Entity { - constructor(x, y, damage, sin_x_speed, sin_y_speed) { - super(x, y); - this.damage = damage; - this.sin_x_speed = sin_x_speed; - this.sin_y_speed = sin_y_speed; - } - collidesWith(whoCollidesWith) { - let temp_x = this.x; - let temp_y = this.y; - this.x = this.x + 25 * Math.sin(frameCount / this.sin_x_speed) - 15; - this.y = this.y + 50 * Math.sin(frameCount / this.sin_y_speed) - 20; - if ( - Math.abs(whoCollidesWith.x - this.x) < 24 * this.size && - Math.abs(whoCollidesWith.y - this.y) < 24 * this.size - ) { - return true; - } - this.y = temp_y; - this.x = temp_x; - return false; - } - - drawEnemy() { - // lazy so its just a game character model, but with a black hat and no body. - let temp_y = this.y; - let temp_x = this.x; - this.x = this.x + 25 * Math.sin(frameCount / this.sin_x_speed); - this.y = this.y + 50 * Math.sin(frameCount / this.sin_y_speed); - drawGameChar(this.x, this.y, 1, this.size, false, color(this.damage, 100)); - this.y = temp_y; - this.x = temp_x; - } -} -class Platform { - constructor(left_x, right_x, y) { - this.left_x = left_x; - this.right_x = right_x; - this.y = y; - } - - isInXBorders(whoCollidesWith) { - return whoCollidesWith.x > this.left_x && whoCollidesWith.x < this.right_x; - } - isUnder(whoCollidesWith) { - return this.isInXBorders(whoCollidesWith) && whoCollidesWith.y < this.y; - } - isOver(whoCollidesWith) { - return this.isInXBorders(whoCollidesWith) && whoCollidesWith.y > this.y; - } - drawPlatform() { - push(); - rectMode(CORNERS); - fill(env.groundColor); - rect(this.left_x, this.y, this.right_x, this.y + 10); - pop(); - } -} - -var mountains_x = []; -var trees_x = []; -var enemies = []; -var clouds = []; -var canyons = []; -var collectables = []; -var platforms = []; -var cnv; -var win_img; -var gameover_img; - -function preload() { - soundFormats("mp3", "ogg"); - sfx.enemy = loadSound("../assets/sfx/enemy.ogg"); - sfx.falling = loadSound("../assets/sfx/falling.ogg"); - sfx.gameover = loadSound("../assets/sfx/gamover.ogg"); - sfx.jumping = loadSound("../assets/sfx/jumping.ogg"); - sfx.levelcomplete = loadSound("../assets/sfx/levelcomplete.ogg"); - sfx.plummeting = loadSound("../assets/sfx/plummeting.ogg"); - sfx.coin = loadSound("../assets/sfx/coin.mp3"); - /* "Midnight Tale", "Take a Chance" and "SCP-x5x" Kevin MacLeod (incompetech.com) - Licensed under Creative Commons: Attribution 4.0 License - http://creativecommons.org/licenses/by/4.0/ */ - mus.level = loadSound("../assets/Midnight Tale.mp3"); - mus.win = loadSound("../assets/Take A Chance.mp3"); - mus.gameover = loadSound("../assets/SCP-x5x.mp3"); - win_img = loadImage( - "https://static.wikia.nocookie.net/someordinarygamers/images/8/88/Bp_1401520973_youre_winner.png" - ); - gameover_img = loadImage("../assets/gameover.png"); -} -function drawFlagpole() { - push(); - strokeWeight(0); - fill(0); - translate(translateration, 0); - - if (flagpole.isReached && flagpole.cell_size_h > -flagpole.cell_size) flagpole.cell_size_h--; - // the flagpole pole - rect(flagpole.x, env.floorPos_y / 2, 2, env.floorPos_y / 2); - - // the flagpole flag - for (i = 0; i < flagpole.size_hor; i++) { - for (j = 0; j < flagpole.size_vert; j++) { - fill(((i + j) % 2) * 255); - rect( - flagpole.x + flagpole.cell_size_h * i, - env.floorPos_y / 2 + flagpole.cell_size_v * j, - flagpole.cell_size_h, - flagpole.cell_size_v - ); - } - } - pop(); -} -function drawGameChar(x, y, sprite, scale, has_body, hat_color, hand, width_mod, height_mod, jump_shift) { - // Note: - // The drawing starts at bottom-middlecenter! not at top-left! - // The aspect ratio is 5:8. - if (has_body == undefined) has_body = true; - if (hat_color == undefined) hat_color = "red"; - if (scale == undefined) { - scale = 1; - } - if (width_mod == undefined) { - width_mod = 1; - } - if (height_mod == undefined) { - height_mod = 1; - } - if (jump_shift == undefined) { - jump_shift = 12; - } - var ax_step = 5 * scale * width_mod; - var ay_step = 8 * scale * height_mod; - jump_shift = jump_shift * scale; - function _drawDefaultHat() { - strokeWeight(1); - stroke(0); - fill(hat_color); - ellipse(x, y - ay_step * 6, ax_step * 10, ay_step * 3); - ellipse(x, y - ay_step * 6, ax_step * 4, ay_step * 1); // x +0.5 * scale is a minor fix of misalignment. May become a bug. - strokeWeight(1); - beginShape(); - vertex(x - ax_step * 2, y - ay_step * 6); - vertex(x, y - ay_step * 10); - vertex(x + ax_step * 2, y - ay_step * 6); - endShape(); - } - function _drawDefaultBody(jumping) { - if (jumping) { - strokeWeight(1); - stroke(1); - fill("brown"); - triangle(x - ax_step * 2, y - ay_step * 1.5, x, y - ay_step * 4, x + ax_step * 2, y - ay_step * 1.5); - } else { - strokeWeight(1); - stroke(1); - fill("brown"); - triangle(x - ax_step * 2, y, x, y - ay_step * 4, x + ax_step * 2, y); - } - } - function _drawDefaultHand(direction) { - switch (direction) { - // to left - case 0: { - line(x, y - ay_step * 2.5, x + ax_step * 0.8, y - ay_step * 1); - break; - } - // relaxed - case 1: { - line(x, y - ax_step * 4, x, y - ay_step); - break; - } - // to right - case 2: { - line(x, y - ay_step * 2.5, x - ax_step * 0.8, y - ay_step * 1); - break; - } - // relaxed; doubled for easy animation cycling - case 3: { - line(x, y - ax_step * 4, x, y - ay_step); - break; - } - // relaxed - default: { - line(x, y - ax_step * 2.5, x, y - ay_step); - break; - } - } - } - switch (sprite) { - // Standing, facing frontwards - case 1: { - // Body - if (has_body) _drawDefaultBody(); - // Head - fill(0); - ellipse(x, y - ay_step * 5, ax_step * 6, ay_step * 4); - // Eyes - fill(255); - ellipse(x - ax_step * 1.2, y - ay_step * 4.2, ax_step / 1.5, ay_step / 2); - ellipse(x + ax_step * 1.2, y - ay_step * 4.2, ax_step / 1.5, ay_step / 2); - // Hat - _drawDefaultHat(); - break; - } - // Jumping, facing forwards - case 2: { - y -= jump_shift; - // Body - if (has_body) _drawDefaultBody(true); - // Hands. (Hands!) - line(x - ax_step * 1, y - ay_step * 2.5, x - ax_step * 3.2, y - ay_step * 3.2); - line(x + ax_step * 1, y - ay_step * 2.5, x + ax_step * 3.2, y - ay_step * 3.2); - // Head - fill(0); - ellipse(x, y - ay_step * 5, ax_step * 6, ay_step * 4); - // Eyes - fill(255); - ellipse(x - ax_step * 1, y - ay_step * 3.8, ax_step / 1.5, ay_step / 2); - ellipse(x + ax_step * 1, y - ay_step * 3.8, ax_step / 1.5, ay_step / 2); - - // Hat - _drawDefaultHat(); - break; - } - // Walking left - case 3: { - // Body - if (has_body) _drawDefaultBody(); - // Hand. (Hand!) - if (has_body) _drawDefaultHand(hand); - // Head - fill(0); - ellipse(x, y - ay_step * 5, ax_step * 6, ay_step * 4); - // Eyes - fill(255); - ellipse(x + ax_step * 1.2, y - ay_step * 4.2, ax_step / 1.5, ay_step / 2); - // Hat - _drawDefaultHat(); - break; - } - // Walking right - case 4: { - // Body - if (has_body) _drawDefaultBody(); - // Hand. (Hand!) - if (has_body) _drawDefaultHand(hand); - // Head - fill(0); - ellipse(x, y - ay_step * 5, ax_step * 6, ay_step * 4); - // Eyes - fill(255); - ellipse(x - ax_step * 1.2, y - ay_step * 4.2, ax_step / 1.5, ay_step / 2); - // Hat - _drawDefaultHat(); - break; - } - // Jumping left - case 5: { - y -= jump_shift; - // Body - if (has_body) _drawDefaultBody(true); - // Hands. (Hands!) - line(x - ax_step * 1, y - ay_step * 2.5, x - ax_step * 3.2, y - ay_step * 3.2); - line(x + ax_step * 1, y - ay_step * 2.5, x + ax_step * 3.2, y - ay_step * 3.2); - - // Head - fill(0); - ellipse(x, y - ay_step * 5, ax_step * 6, ay_step * 4); - // Eyes - fill(255); - ellipse(x - ax_step * 1, y - ay_step * 3.8, ax_step / 1.5, ay_step / 2); - - // Hat - _drawDefaultHat(); - break; - } - // Jumping right - case 6: { - y -= jump_shift; - // Body - if (has_body) _drawDefaultBody(true); - // Hands. (Hands!) - line(x - ax_step * 1, y - ay_step * 2.5, x - ax_step * 3.2, y - ay_step * 3.2); - line(x + ax_step * 1, y - ay_step * 2.5, x + ax_step * 3.2, y - ay_step * 3.2); - - // Head - fill(0); - ellipse(x, y - ay_step * 5, ax_step * 6, ay_step * 4); - // Eyes - fill(255); - ellipse(x + ax_step * 1, y - ay_step * 3.8, ax_step / 1.5, ay_step / 2); - - // Hat - _drawDefaultHat(); - break; - } - // Error - default: - fill("red"); - text("Character error - No or wrong sprite number provided", x, y); - break; - } -} -function drawTree(x, y, scale, type, hasLeaves) { - // x, y are the middle bottom of the tree. - noStroke(); - fill(255); - if (hasLeaves == undefined) { - hasLeaves = true; - } - if (scale == undefined) { - scale = 1; - } - if (type == 0) { - fill(110, 87, 20); - triangle(x - 15 * scale, y, x, y - 150 * scale, x + 15 * scale, y); - fill(63, 72, 52); - if (hasLeaves) triangle(x - 45 * scale, y - 45 * scale, x, y - 120 * scale, x + 45 * scale, y - 45 * scale); - if (hasLeaves) triangle(x - 45 * scale, y - 85 * scale, x, y - 180 * scale, x + 45 * scale, y - 85 * scale); - } else if (type == 1) { - fill(147, 105, 7); - triangle(x - 10 * scale, y, x, y - 120 * scale, x + 10 * scale, y); - fill(78, 61, 31); - if (hasLeaves) { - ellipse(x, y - 50 * scale, 80 * scale, 30 * scale); - ellipse(x, y - 70 * scale, 100 * scale, 30 * scale); - ellipse(x, y - 90 * scale, 80 * scale, 30 * scale); - ellipse(x, y - 110 * scale, 40 * scale, 30 * scale); - } - } -} -function drawCloud(cloud) { - if (cloud.size == undefined) { - scale = 1; - } - noStroke(); - - fill(200); - ellipse(cloud.x - 20, cloud.y - 10, 50 * cloud.size, 30 * cloud.size); - - fill(220); - ellipse(cloud.x + 20, cloud.y - 20, 70 * cloud.size, 50 * cloud.size); - - fill(255); - ellipse(cloud.x, cloud.y, 90 * cloud.size, 40 * cloud.size); - ellipse(cloud.x + 45, cloud.y - 10, 50 * cloud.size, 35 * cloud.size); -} -function drawMountain(x, m_width, m_height, skew) { - noStroke(); - fill(60); - triangle(x - m_width, env.floorPos_y, x + skew, m_height, x + m_width, env.floorPos_y); - fill(90); - triangle(x - m_width, env.floorPos_y, x + skew, m_height, x - m_width / 1.5, env.floorPos_y); - fill(170); - triangle( - (4 * x - m_width + 3 * skew) / 4, - (env.floorPos_y + 3 * m_height) / 4, - x + skew, - m_height, - (4 * x + m_width + 3 * skew) / 4, - (env.floorPos_y + 3 * m_height) / 4 - ); -} -function drawCanyon(canyon) { - noStroke(); - let x = canyon.x; - let c_width = canyon.width; - fill(90, 30, 0); - quad( - x - c_width / 2, - env.floorPos_y, - x + c_width / 2, - env.floorPos_y, - x + c_width / 2, - height, - x - c_width / 2, - height - ); - - fill("blue"); - quad( - x - c_width / 20, - env.floorPos_y, - x + c_width / 20, - env.floorPos_y, - x + c_width / 20, - height, - x - c_width / 20, - height - ); - - fill(30); - quad( - x - c_width / 2, - env.floorPos_y, - x + c_width / 2, - env.floorPos_y, - x + c_width / 10, - env.floorPos_y + env.floorPos_y / 40, - x - c_width / 10, - env.floorPos_y + env.floorPos_y / 40 - ); -} -function drawCollectable(collectable) { - let x = collectable.x; - let y = collectable.y; - let size = collectable.size; - let worth = collectable.worth; - strokeWeight(0.5); - fill(253, 195, 52); - ellipse(x, y, 3.5 * size, 3.5 * size); - fill(171); - ellipse(x, y, 3 * size, 3 * size); - fill(253, 195, 52); - ellipse(x, y, 2.5 * size, 2.5 * size); - fill(200, 150, 30); - textSize(size * 1.5); - textAlign(CENTER, CENTER); - fill(0); - text(worth, x, y); - - textSize(12); - textAlign(LEFT, TOP); -} -function drawSky() { - background(env.skyColor); -} -function drawAudioSymbol() { - push(); - fill(0); - strokeWeight(4); - triangle( - width - text_vert_unit * 5, - text_hor_unit * 7, - width - text_vert_unit * 4, - text_hor_unit * 5, - width - text_vert_unit * 4, - text_hor_unit * 9 - ); - if (env.isSoundEnabled) { - arc(width - text_vert_unit * 3, text_hor_unit * 7, text_hor_unit, text_vert_unit * 1.5, (3 * PI) / 2, PI / 2); - arc(width - text_vert_unit * 3.5, text_hor_unit * 7, text_hor_unit, text_vert_unit, (3 * PI) / 2, PI / 2); - } - textSize(text_vert_unit / 2); - strokeWeight(0); - pop(); -} -function drawMusicSymbol() { - push(); - fill(0); - strokeWeight(4); - rectMode(CORNERS); - if (env.isMusicEnabled) { - line(width - text_vert_unit * 4.5, text_hor_unit * 15, width - text_vert_unit * 4.5, text_hor_unit * 11); - line(width - text_vert_unit * 2.5, text_hor_unit * 14, width - text_vert_unit * 2.5, text_hor_unit * 10); - line(width - text_vert_unit * 4.5, text_hor_unit * 11, width - text_vert_unit * 2.5, text_hor_unit * 10); - } - ellipse(width - text_vert_unit * 4.5, text_hor_unit * 15, text_vert_unit / 2); - ellipse(width - text_vert_unit * 2.5, text_hor_unit * 14, text_vert_unit / 2); - pop(); -} -function playSound(sound, volume, isMusicEnabled) { - if (volume == undefined) volume = 1; - if (env.isSoundEnabled) { - sound.play(0, 1, volume); - } else { - sound.stop(); - } -} -function playMusic(sound, volume) { - if (volume == undefined) volume = 1; - if (env.isMusicEnabled) { - sound.play(0, 1, volume); - } else { - sound.stop(); - } -} - -function drawMountains() { - push(); - translate(translateration * 0.3, 0); - for (i = 0; i < mountains_x.length; i++) { - drawMountain( - mountains_x[i], - 100 + 200 * random_values[i + 121], - 400 - 50 * random_values[i + 211], - 50 * random_values[i + 8] - ); - } - pop(); -} -function drawClouds(areMoving) { - push(); - translate(translateration * 0.6, 0); - for (i = 0; i < clouds.length; i++) { - push(); - if (areMoving) translate(frameCount * random_values[i], 0); - drawCloud(clouds[i]); - pop(); - } - pop(); -} -function drawCanyons() { - push(); - translate(translateration, 0); - for (i = 0; i < canyons.length; i++) { - drawCanyon(canyons[i]); - fill(200, 150, 0); - } - pop(); -} -function drawTrees() { - push(); - translate(translateration, 0); - for (i = 0; i < trees_x.length; i++) { - drawTree(trees_x[i], env.floorPos_y, 0.5 + random_values[i], Math.round(trees_x[i]) % 2); - } - pop(); -} -function drawCollectables() { - push(); - translate(translateration, 0); - for (i = 0; i < collectables.length; i++) { - drawCollectable(collectables[i]); - } - pop(); -} -function drawPlatforms() { - push(); - translate(translateration, 0); - for (i = 0; i < platforms.length; i++) { - platforms[i].drawPlatform(); - } - pop(); -} -function manageEnemies() { - push(); - translate(0, 0); - for (i = 0; i < enemies.length; i++) { - enemies[i].drawEnemy(); - for (j = 0; j < gameChar.projectiles.length; j++) { - if (enemies[i].collidesWith(gameChar.projectiles[j])) { - enemies.splice(i, 1); - gameChar.projectiles.splice(j, 1); - i = 0; - j = 0; - playSound(sfx.enemy); - } - } - if (enemies[i].collidesWith(gameChar) && env.state == "LEVEL") { - background(255 * random(), 255 * random(), 255 * random()); - playSound(sfx.enemy, enemies[i].damage / 10); - gameChar.state.isPlummeting = true; - } - } - pop(); -} -function drawInterface() { - push(); - translate(-translateration, 0); - fill("black"); - rect(0, 0, width, text_vert_unit * 2); - - stroke("red"); - line(0, text_vert_unit * 2, width, text_vert_unit * 2); - fill("red"); - textFont("Courier New"); - textSize(text_vert_unit); - text("Score: " + gameChar.score, width - text_vert_unit * 7, text_hor_unit * 2); - text("Lives: " + gameChar.lives, width - text_vert_unit * 14, text_hor_unit * 2); - // Debug things - drawAudioSymbol(); - drawMusicSymbol(); - if (isDebug) debug(); - pop(); -} -function shootProjectile() { - playSound(sfx.coin, 0, 1, 0.5); - let projectile = { color: "red", x: gameChar.x, y: gameChar.y - 45, direction: 0 }; - if (gameChar.state.isLeft) { - projectile.direction = -15; - gameChar.projectiles.push(projectile); - } else { - projectile.direction = 15; - gameChar.projectiles.push(projectile); - } -} -function updateProjectiles() { - for (i = 0; i < gameChar.projectiles.length; i++) { - push(); - stroke(gameChar.projectiles[i].color); - strokeWeight(4); - line( - gameChar.projectiles[i].x, - gameChar.projectiles[i].y, - gameChar.projectiles[i].x - 30, - gameChar.projectiles[i].y - ); - pop(); - gameChar.projectiles[i].x += gameChar.projectiles[i].direction; - if (gameChar.projectiles[i].x > width - translateration || gameChar.projectiles[i].x < 0 - translateration) { - gameChar.projectiles.splice(i, 1); - } - } -} -function manageMovement() { - if (gameChar.state.isPlummeting) { - gameChar.y += gameChar.speed / 2; - gameChar.size *= 0.98; - gameChar.speed *= 0.96; - if (gameChar.size < 0.2) restart(1); - } else if (!(gameChar.state.isJumping || gameChar.state.isFalling)) { - // Checking if the character is beyond the platform, then making them fall. - if (memorized_platform != undefined && !memorized_platform.isInXBorders(gameChar)) { - gameChar.state.isFalling = true; - memorized_platform = undefined; - } else { - // Falling into canyons - if (isOverCanyon(gameChar) && memorized_platform == undefined) { - gameChar.state.isPlummeting = true; - if (!plummetingSoundNotPlayedBefore) { - playSound(sfx.plummeting); - plummetingSoundNotPlayedBefore = true; - } - } - if (gameChar.state.isAscending && gameChar.y > floorPos_y) { - gameChar_y -= gameChar.speed; - } - if (gameChar.state.isDescending && gameChar_y < height) { - gameChar_y += gameChar.speed; - } - if (gameChar.state.isLeft) { - gameChar.x -= gameChar.speed; - } - if (gameChar.state.isRight) { - gameChar.x += gameChar.speed; - } - } - } else if (gameChar.state.isJumping) { - // Forget the platform as it is irrelevant when we gain height. - memorized_platform = undefined; - gameChar.y += gameChar.vert_speed; - gameChar.vert_speed += gameChar.gravity; - if (gameChar.vert_speed > 0) { - gameChar.state.isJumping = false; - gameChar.state.isFalling = true; - playSound(sfx.falling); - } - if (gameChar.state.isLeft) { - gameChar.x -= gameChar.speed; - } - if (gameChar.state.isRight) { - gameChar.x += gameChar.speed; - } - } else if (gameChar.state.isFalling) { - // Checking is a platform under the player, and therefore, if it is, save it and check the next frame did the character - // go under the platform - if so, end them on the platform. - for (i = 0; i < platforms.length; i++) { - if (platforms[i].isUnder(gameChar)) memorized_platform = platforms[i]; - } - if (memorized_platform != undefined && memorized_platform.isOver(gameChar)) { - gameChar.y = memorized_platform.y; - gameChar.state.isJumping = false; - gameChar.state.isFalling = false; - } else { - gameChar.y += gameChar.vert_speed; - gameChar.vert_speed += gameChar.gravity; - if (gameChar.y >= env.floorPos_y + 50) { - gameChar.y = env.floorPos_y + 50; - gameChar.state.isJumping = false; - gameChar.state.isFalling = false; - } - if (gameChar.state.isLeft) { - gameChar.x -= gameChar.speed; - } - if (gameChar.state.isRight) { - gameChar.x += gameChar.speed; - } - } - } - // Borders of the world check - if (gameChar.x <= 50) { - gameChar.x = 50; - } -} - -// Fun fact - the following function is made using ChatGPT! -function drawIsogonalBrickWall(x, y, size, hSkew, vSkew) { - push(); - translate(translateration, 0); - // Set the fill color of the bricks to a redish - fill(150, 100, 110); - - // Calculate the width and height of each brick - let brickWidth = size / 5; - let brickHeight = size / 10; - - // Draw the bricks in a 5x10 grid, with a small gap between each brick - for (let i = 0; i < 5; i++) { - for (let j = 0; j < 10; j++) { - let xPos = x + i * (brickWidth + 1) + j * hSkew; - let yPos = y + j * (brickHeight + 1) + i * vSkew; - rect(xPos, yPos, brickWidth, brickHeight); - } - } - pop(); -} - -function checkCollectable(whoCollidesWith) { - for (i = 0; i < collectables.length; i++) { - if ( - Math.abs(whoCollidesWith.x - collectables[i].x) < collectables[i].size * 2 && - Math.abs(whoCollidesWith.y - collectables[i].y) < collectables[i].size * 2 - ) { - whoCollidesWith.score += collectables[i].worth; - collectables.splice(i, 1); - playSound(sfx.coin); - } - } -} -function isOverCanyon(who) { - for (i = 0; i < canyons.length; i++) { - if (Math.abs(who.x - canyons[i].x) < 43 + 25 * random_values[i + 124]) { - return true; - } - } - return false; -} -function scrolling(centerOnWho) { - if (centerOnWho.x > width - width / 2.5 - translateration) { - translateration -= centerOnWho.speed; - } else if (centerOnWho.x < width / 2.5 - translateration) { - translateration += centerOnWho.speed; - } -} -function checkFlagpole(withWho) { - if (withWho.x > env.end_x) { - flagpole.isReached = true; - env.state = "WIN"; - withWho.isWinner = true; - playSound(sfx.levelcomplete); - } -} -function restart(decreaseLives) { - if (env.state != "LEVEL") window.location.reload(); // Reloads the web page. - gameChar.state.isPlummeting = false; - gameChar.lives -= decreaseLives; - if (gameChar.lives < 1) { - env.state = "GAMEOVER"; - playSound(sfx.gameover); - return; - } - gameChar.x = width / 2; - gameChar.y = env.floorPos_y + 50; - gameChar.resetValues(); - translateration = -gameChar.x; - plummetingSoundNotPlayedBefore = false; -} - -function getSpriteNumber() { - if (gameChar.state.isJumping && gameChar.state.isLeft) return 5; - else if (gameChar.state.isJumping && gameChar.state.isRight) return 6; - else if (gameChar.state.isJumping) return 2; - else if (gameChar.state.isFalling && gameChar.state.isLeft) return 5; - else if (gameChar.state.isFalling && gameChar.state.isRight) return 6; - else if (gameChar.state.isFalling) return 2; - else if (gameChar.state.isPlummeting) return 2; - else if (gameChar.state.isLeft) return 4; - else if (gameChar.state.isRight) return 3; - else if (gameChar.state.isDescending) return 1; - else return 1; -} -function debug() { - function _drawGridLines() { - push(); - console.log("works"); - stroke(255); - strokeWeight(1); - for (i = text_vert_unit; i < width; i += text_vert_unit) { - line(0, i, width, i); - } - for (j = text_hor_unit; j < height * 2; j += text_hor_unit) { - line(j, 0, j, height); - } - pop(); - } - this.drawGrid = false; - - if (gameChar.state.isJumping) text("JUMPING", text_vert_unit * 6, text_hor_unit * 2); - if (gameChar.state.isFalling) text("FALLING", text_vert_unit * 6, text_hor_unit * 2); - if (gameChar.state.isPlummeting) text("PLUMMETING", text_vert_unit * 11, text_hor_unit * 2); - - if (frameCount % 2 == 0) { - fps = Math.round(frameRate() * 10) / 10; - if (fps_recent_values.length < 200) fps_recent_values.push(fps); - else fps_recent_values.splice(0, 1); - fps_recent_values.push(fps); - } - fill("red"); - text(fps, text_vert_unit, text_hor_unit * 2); - stroke("black"); - beginShape(LINES); - for (i = 1; i < fps_recent_values.length; i++) { - vertex((text_vert_unit + i) * 1.5, (text_hor_unit * 6 - fps_recent_values[i]) * 2); - } - endShape(); - text(gameChar.x, text_vert_unit * 18, text_hor_unit * 2); - if (draw_grid) drawGridLines(); -} - -function createEnemies() { - enemies[0] = new Enemy(1100, 600, random(10, 50), random(20, 50), random(10, 30)); - - for (let i = 1; i < amounts.enemies; i++) { - let elevation; - if (random_values[i] <= 1 / 3) elevation = 350; - else if (random_values[i] > 1 / 3 && random_values <= 2 / 3) elevation = 300; - else elevation = 400; - - enemies[i] = new Enemy( - enemies[i - 1].x + 200 + 250 * random(), - elevation, - random(10, 50), - random(20, 50), - random(10, 30) - ); - } -} -function createTrees() {} -function setup() { - cnv = createCanvas(1024 + 256, 512 + 256); - - env.skyColor = color(142, 152, 135); - gameChar = new Entity(); - gameChar.x = width / 2; - gameChar.y = env.floorPos_y + 50; - - platforms[0] = new Platform(500, 600, 350); - for (i = 1; i < amounts.platforms; i++) { - let left_x = platforms[i - 1].right_x + 100 + 300 * random(); - let right_x = left_x + 50 + 100 * random(); - if (left_x > env.end_x && right_x > env.end_x) break; - platforms[i] = new Platform(left_x, right_x, 300 + 100 * random()); - } - createEnemies(); - - trees_x = [50]; - for (i = 1; i <= amounts.tree; i++) { - trees_x[i] = trees_x[i - 1] + 20 + 50 * random_values[i]; - } - clouds[0] = new Cloud(-1000, 60, 1); - for (i = 1; i <= amounts.cloud; i++) { - clouds[i] = new Cloud( - clouds[i - 1].x + 20 + 50 * random_values[i], - (env.floorPos_y / 1.9) * random_values[i + 60], - 0.5 + random_values[i + 100] - ); - } - - mountains_x = [50]; - for (i = 1; i <= amounts.mountain; i++) { - mountains_x[i] = mountains_x[i - 1] + 20 + 400 * random_values[i + 100]; - } - - canyons[0] = new Canyon(gameChar.x + 200, 100 + 50 * random_values[124]); - for (i = 1; i <= amounts.canyon; i++) { - let x = canyons[i - 1].x + 200 + 600 * random_values[i + 100]; - if (x > flagpole.x - 250) break; - canyons[i] = new Canyon(x, 100 + 50 * random_values[i + 124]); - } - - collectables[0] = new Collectable(gameChar.x + 350, env.floorPos_y + 50, 20, 10); - for (i = 1; i <= amounts.collectable; i++) { - let worth; - if (random_values[i] <= 1 / 3) worth = 15; - else if (random_values[i] > 1 / 3 && random_values <= 2 / 3) worth = 20; - else worth = 25; - let x = collectables[i - 1].x + 70 + 400 * random_values[i + 213]; - if (x > flagpole.x) break; - collectables[i] = new Collectable(x, env.floorPos_y + 50, worth, worth); - } - - // Pruning over-canyon trees. Literally. - for (i = 0; i < trees_x.length; i++) { - for (j = 0; j < canyons.length; j++) { - if ( - trees_x[i] > canyons[j].x - (40 + 50 * random_values[j + 124]) && - trees_x[i] < canyons[j].x + (40 + 50 * random_values[j + 124]) - ) { - trees_x[i] = undefined; - } - } - } - // Doing the same with collectables, for honesty. - for (i = 0; i < collectables.length; i++) { - for (j = 0; j < canyons.length; j++) { - if ( - collectables[i].x > canyons[j].x - (40 + 50 * random_values[j + 124]) && - collectables[i].x < canyons[j].x + (40 + 50 * random_values[j + 124]) - ) { - collectables[i].x = NaN; - } - } - } -} -function draw() { - text_hor_unit = height / 40; - text_vert_unit = width / 40; - - drawSky(); //fill the sky - fill(env.groundColor); - rect(0, env.floorPos_y, width, height); - drawMountains(); - // Also updates clouds movement using translate(). May be disabled. - drawClouds(true); - drawTrees(); - drawCanyons(); - drawFlagpole(); - drawIsogonalBrickWall(-89, env.floorPos_y - 89, 200, 0, -30); - drawCollectables(); - drawPlatforms(); - - switch (env.state) { - case "INTRO": { - push(); - textAlign(CENTER); - textSize(text_vert_unit * 3); - strokeWeight(10); - textFont("Courier"); - textStyle(BOLD); - fill(0); - text("The Dead Magic Run", width / 2, height / 2); - textSize(text_vert_unit); - text("Press any button to attempt a run", width / 2, height / 2 + text_vert_unit * 2); - pop(); - break; - } - case "INSTRUCTIONS": { - push(); - textAlign(LEFT); - textSize(text_vert_unit); - strokeWeight(3); - textFont("Courier"); - rectMode(CORNERS); - fill(0, 100); - rect(text_hor_unit, text_vert_unit * 3, text_hor_unit * 55, text_vert_unit * 11); - fill(255); - text("The goal is to survive and reach the right end.", text_hor_unit, text_vert_unit * 4); - text("Press WASD to move, Space to jump", text_hor_unit, text_vert_unit * 5); - text("E or mouse click to shoot.", text_hor_unit, text_vert_unit * 6); - text("Press P to enable and disable sounds,", text_hor_unit, text_vert_unit * 7); - text("and O letter to enable and disable music.", text_hor_unit, text_vert_unit * 8); - text("Press Space to continue and begin the run. Good luck.", text_hor_unit, text_vert_unit * 10); - pop(); - break; - } - case "LEVEL": { - // Update scrolling based on the character movement - scrolling(gameChar); - translate(translateration, 0); // Translating everything else to prevent next elements from scrolling too. - // Collectables collision - checkCollectable(gameChar); - checkFlagpole(gameChar); - manageMovement(); - // the sprite state machine - var sprite = getSpriteNumber(); - drawGameChar( - gameChar.x, - gameChar.y, - sprite, - gameChar.size, - true, - "red", - (hand = Math.floor(frameCount / 12) % 4) - ); - manageEnemies(); - updateProjectiles(); - playMusic(mus.level); - break; - } - case "WIN": { - manageEnemies(); - push(); - image(win_img, width / 2 - win_img.width / 2 + 10, height / 2 - win_img.height / 2); - fill("yellow"); - textSize(text_vert_unit * 1.5); - textAlign(CENTER); - strokeWeight(2); - textFont("Courier"); - text("Level complete. Press R to replay.", width / 2, height / 2 - win_img.height / 2); - translate(translateration, frameCount); - pop(); - scrolling(flagpole); // fix the viewpoint on the flagpole - translate(translateration, 0); // Translating everything else to prevent next elements from scrolling too. - // Forcing to run right - gameChar.state.isRight = true; - gameChar.state.isLeft = false; - // the sprite state machine - var sprite = getSpriteNumber(); - manageMovement(); - drawGameChar(gameChar.x, gameChar.y, sprite, gameChar.size, true, "red", Math.floor(frameCount / 12) % 4); - playMusic(mus.win); - break; - } - case "GAMEOVER": { - manageEnemies(); - push(); - image(gameover_img, width / 2 - 256 / 2, height / 2 - 256 / 2); - fill("black"); - textSize(text_vert_unit * 1.5); - textAlign(CENTER); - strokeWeight(2); - textFont("Courier"); - text("Gamover. Press R to replay.", width / 2, height / 2 - 256 / 2); - pop(); - translate(translateration, 0); - playMusic(mus.gameover); - break; - } - default: { - push(); - textSize(50); - fill("red"); - text("Game state error!", width / 2, height / 2); - pop(); - break; - } - } - drawInterface(); -} - -function playMusic(requestedMelody) { - // spaghetti code. - if (requestedMelody != mus.level) mus.level.stop(); - if (requestedMelody != mus.win) mus.win.stop(); - if (requestedMelody != mus.gameover) mus.gameover.stop(); - if (!requestedMelody.isPlaying() && env.isMusicEnabled) { - requestedMelody.play(0, 1, 0.3); - } else if (!env.isMusicEnabled) requestedMelody.stop(); -} - -function mouseClicked() { - shootProjectile(); -} -function keyPressed() { - if (env.state == "INTRO") { - env.state = "INSTRUCTIONS"; - } else if (key == " " && env.state == "INSTRUCTIONS") { - env.state = "LEVEL"; - } - if (keyCode == 32 && !(gameChar.state.isJumping || gameChar.state.isFalling)) { - gameChar.state.isJumping = true; - gameChar.prejump_y = gameChar.y; - gameChar.vert_speed = -30; - playSound(sfx.jumping); - } - if (key == "E" && env.state == "LEVEL") { - shootProjectile(); - } - if (key == "A") { - gameChar.state.isLeft = true; - } - if (key == "D") { - gameChar.state.isRight = true; - } - if (key == "R" && (env.state == "WIN" || env.state == "GAMEOVER")) { - restart(); - } - if (key == "P" && !env.isSoundEnabled) { - env.isSoundEnabled = true; - } else if (key == "P" && env.isSoundEnabled) { - env.isSoundEnabled = false; - } - if (key == "O" && !env.isMusicEnabled) { - env.isMusicEnabled = true; - } else if (key == "O" && env.isMusicEnabled) { - env.isMusicEnabled = false; - } - if (key == "G" && isDebug) draw_grid = true; - - console.log("keyPressed: " + key); - console.log("keyPressed: " + keyCode); - return false; -} -function keyReleased() { - if (key == "M") { - if (isDebug) isDebug = false; - else isDebug = true; - } - if (key == "A") { - gameChar.state.isLeft = false; - } - if (key == "D") { - gameChar.state.isRight = false; - } - if (key == "G" && isDebug) draw_grid = false; - console.log("keyReleased: " + key); - console.log("keyReleased: " + keyCode); -}