diff options
author | elioat <elioat@tilde.institute> | 2024-07-03 07:14:37 -0400 |
---|---|---|
committer | elioat <elioat@tilde.institute> | 2024-07-03 07:14:37 -0400 |
commit | 729b918b593618bc0e74b5e98ef6273eb0e52f8c (patch) | |
tree | c8cc0a913fef7e70556e08c6608a7ca40b3f6e02 /js/mountain/game.js | |
parent | 822824c79ec0da595001c4448ae98d89ea8a4745 (diff) | |
download | tour-729b918b593618bc0e74b5e98ef6273eb0e52f8c.tar.gz |
*
Diffstat (limited to 'js/mountain/game.js')
-rw-r--r-- | js/mountain/game.js | 235 |
1 files changed, 233 insertions, 2 deletions
diff --git a/js/mountain/game.js b/js/mountain/game.js index 3c96005..5601d94 100644 --- a/js/mountain/game.js +++ b/js/mountain/game.js @@ -1,3 +1,234 @@ -// a 2d platformer game, where the character can jump, double jump, move left and right. -// That character can avoid spikes and obstacles. +// TODO: if there are no more levels show a "game win" message +// Game constants +const canvas = document.getElementById('gameCanvas'); +const ctx = canvas.getContext('2d'); +canvas.width = 800; +canvas.height = 600; + +const GRAVITY = 0.5; +const JUMP_STRENGTH = -12; +const MOVE_SPEED = 5; + +let keys = { left: false, right: false, up: false, down: false, space: false }; + +let levels = [ + [ + [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + ], + [ + // Next level example + [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + ] + // Add more levels as needed +]; + +let currentLevel = 0; + +class Player { + constructor(x, y) { + this.x = x; + this.y = y; + this.width = 30; + this.height = 30; + this.velocityX = 0; + this.velocityY = 0; + this.jumping = false; + this.doubleJumping = false; + } + + update() { + if (keys.left) this.velocityX = -MOVE_SPEED; + if (keys.right) this.velocityX = MOVE_SPEED; + if (!keys.left && !keys.right) this.velocityX = 0; + + this.velocityY += GRAVITY; + this.x += this.velocityX; + this.y += this.velocityY; + + // Collision detection + this.checkCollision(); + + // Limit falling speed + if (this.velocityY > 10) this.velocityY = 10; + } + + jump() { + if (!this.jumping) { + this.velocityY = JUMP_STRENGTH; + this.jumping = true; + } else if (!this.doubleJumping) { + this.velocityY = JUMP_STRENGTH; + this.doubleJumping = true; + } + } + + checkCollision() { + let row, col, belowRow, aboveRow, leftCol, rightCol; + + // Check collision with ground from below + row = Math.floor(this.y / 30); + col = Math.floor(this.x / 30); + belowRow = Math.floor((this.y + this.height) / 30); + + if (levels[currentLevel][belowRow] && levels[currentLevel][belowRow][col] === 1) { + if (this.velocityY > 0) { + this.y = belowRow * 30 - this.height; + this.velocityY = 0; + this.jumping = false; + this.doubleJumping = false; + } + } + + // Check collision with ground from above + aboveRow = Math.floor((this.y - 1) / 30); + if (levels[currentLevel][aboveRow] && levels[currentLevel][aboveRow][col] === 1) { + if (this.velocityY < 0) { + this.y = (aboveRow + 1) * 30; + this.velocityY = 0; + } + } + + // Check collision with ground from the left + leftCol = Math.floor(this.x / 30); + if (levels[currentLevel][row] && levels[currentLevel][row][leftCol] === 1) { + if (this.velocityX < 0) { + this.x = (leftCol + 1) * 30; + this.velocityX = 0; + } + } + + // Check collision with ground from the right + rightCol = Math.floor((this.x + this.width) / 30); + if (levels[currentLevel][row] && levels[currentLevel][row][rightCol] === 1) { + if (this.velocityX > 0) { + this.x = rightCol * 30 - this.width; + this.velocityX = 0; + } + } + + // Collision with lava + if (levels[currentLevel][row] && levels[currentLevel][row][col] === 2) { + this.reset(); + } + + // Collision with save point + if (levels[currentLevel][row] && levels[currentLevel][row][col] === 3) { + localStorage.setItem('savePoint', JSON.stringify({ x: this.x, y: this.y, level: currentLevel })); + } + + // Collision with goal + if (levels[currentLevel][row] && levels[currentLevel][row][col] === 5) { + alert('Level Complete!'); + loadNextLevel(); + } + } + + reset() { + let savePoint = JSON.parse(localStorage.getItem('savePoint')) || { x: 30, y: 30, level: 0 }; + this.x = savePoint.x; + this.y = savePoint.y; + currentLevel = savePoint.level; + this.velocityY = 0; + } + + render() { + ctx.fillStyle = 'blue'; + ctx.fillRect(this.x, this.y, this.width, this.height); + } +} + +function findPlayerStartPosition(level) { + for (let row = 0; row < levels[level].length; row++) { + for (let col = 0; col < levels[level][row].length; col++) { + if (levels[level][row][col] === 4) { + return { x: col * 30, y: row * 30 }; + } + } + } + // Default position if no start point found + return { x: 30, y: 570 }; +} + +function renderLevel() { + for (let row = 0; row < levels[currentLevel].length; row++) { + for (let col = 0; col < levels[currentLevel][row].length; col++) { + if (levels[currentLevel][row][col] === 1) { + ctx.fillStyle = 'brown'; + ctx.fillRect(col * 30, row * 30, 30, 30); + } else if (levels[currentLevel][row][col] === 2) { + ctx.fillStyle = 'red'; + ctx.fillRect(col * 30, row * 30, 30, 30); + } else if (levels[currentLevel][row][col] === 3) { + ctx.fillStyle = 'green'; + ctx.fillRect(col * 30, row * 30, 30, 30); + } else if (levels[currentLevel][row][col] === 5) { + ctx.fillStyle = 'gold'; + ctx.fillRect(col * 30, row * 30, 30, 30); + } + } + } +} + +function loadNextLevel() { + currentLevel++; + if (currentLevel >= levels.length) { + alert("You've completed all levels!"); + currentLevel = 0; + } + let startPosition = findPlayerStartPosition(currentLevel); + player.x = startPosition.x; + player.y = startPosition.y; + player.velocityY = 0; + localStorage.setItem('savePoint', JSON.stringify({ x: player.x, y: player.y, level: currentLevel })); +} + +let startPosition = findPlayerStartPosition(currentLevel); +let player = new Player(startPosition.x, startPosition.y); + +function gameLoop() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + + renderLevel(); + player.update(); + player.render(); + + requestAnimationFrame(gameLoop); +} + +document.addEventListener('keydown', (e) => { + if (e.code === 'ArrowLeft') keys.left = true; + if (e.code === 'ArrowRight') keys.right = true; + if (e.code === 'ArrowUp') keys.up = true; + if (e.code === 'ArrowDown') keys.down = true; + if (e.code === 'Space') player.jump(); +}); + +document.addEventListener('keyup', (e) => { + if (e.code === 'ArrowLeft') keys.left = false; + if (e.code === 'ArrowRight') keys.right = false; + if (e.code === 'ArrowUp') keys.up = false; + if (e.code === 'ArrowDown') keys.down = false; +}); + +gameLoop(); |