diff options
Diffstat (limited to 'html/mountain')
-rw-r--r-- | html/mountain/game.js | 71 |
1 files changed, 64 insertions, 7 deletions
diff --git a/html/mountain/game.js b/html/mountain/game.js index b4fcf3f..a05bdb9 100644 --- a/html/mountain/game.js +++ b/html/mountain/game.js @@ -13,7 +13,8 @@ const GAME_STATE = { const PLATFORM_TYPE = { NORMAL: 'normal', - DEADLY: 'deadly' + DEADLY: 'deadly', + FALLING: 'falling' }; const PLAYER_SIZE = 20; @@ -45,6 +46,14 @@ const DEATH_ANIMATION_DURATION = 55; const ENEMY_SPEED = 2; +const FALLING_PLATFORM_DELAY = 800; +const FALLING_PLATFORM_GRAVITY = 0.5; + +const PLATFORM_PARTICLE_COUNT = 30; +const PLATFORM_PARTICLE_SPEED = 8; +const PLATFORM_PARTICLE_SIZE = 4; +const PLATFORM_PARTICLE_LIFETIME = 40; + let gameState = GAME_STATE.PLAYING; let level = 1; let platforms = []; @@ -247,9 +256,15 @@ function generatePlatformsForPartition(partition) { ), width: platformWidth, height: PLATFORM_HEIGHT, - type: (level > 1 && Math.random() < 0.2) ? - PLATFORM_TYPE.DEADLY : - PLATFORM_TYPE.NORMAL + type: (() => { + if (level > 1 && Math.random() < 0.2) return PLATFORM_TYPE.DEADLY; + if (level > 1 && Math.random() < 0.3) { + return PLATFORM_TYPE.FALLING; + } + return PLATFORM_TYPE.NORMAL; + })(), + fallTimer: null, + velocityY: 0 }; let overlapping = false; @@ -424,6 +439,11 @@ function updatePlayer() { if (platform.type === PLATFORM_TYPE.DEADLY) { killPlayer(); } else { + if (platform.type === PLATFORM_TYPE.FALLING && !platform.fallTimer) { + platform.fallTimer = setTimeout(() => { + platform.isFalling = true; + }, FALLING_PLATFORM_DELAY); + } player.velocityY = 0; player.isJumping = false; player.jumpsLeft = 2; @@ -496,9 +516,9 @@ function draw(currentTime) { ); for (let platform of platforms) { - ctx.fillStyle = platform.type === PLATFORM_TYPE.DEADLY ? - 'tomato' : - '#1A1A1A'; + ctx.fillStyle = platform.type === PLATFORM_TYPE.DEADLY ? 'tomato' : + platform.type === PLATFORM_TYPE.FALLING ? 'rgba(26, 26, 26, 0.75)' : + '#1A1A1A'; ctx.fillRect(platform.x, platform.y, platform.width, platform.height); } @@ -576,6 +596,7 @@ function gameLoop(currentTime) { updateEnemies(); updateParticles(); updateDeathParticles(); + updatePlatforms(); accumulator -= FRAME_TIME; } @@ -583,6 +604,42 @@ function gameLoop(currentTime) { requestAnimationFrame(gameLoop); } +function createPlatformParticles(platform) { + for (let i = 0; i < PLATFORM_PARTICLE_COUNT; i++) { + const angle = (Math.PI * 2 * i) / PLATFORM_PARTICLE_COUNT; + particles.push({ + x: platform.x + platform.width / 2, + y: platform.y + platform.height / 2, + velocityX: Math.cos(angle) * PLATFORM_PARTICLE_SPEED * (0.5 + Math.random()), + velocityY: Math.sin(angle) * PLATFORM_PARTICLE_SPEED * (0.5 + Math.random()), + size: PLATFORM_PARTICLE_SIZE + Math.random() * 2, + life: PLATFORM_PARTICLE_LIFETIME, + initialOpacity: 0.6 + Math.random() * 0.4 + }); + } +} + +function updatePlatforms() { + platforms.forEach(platform => { + if (platform.type === PLATFORM_TYPE.FALLING && platform.isFalling) { + platform.velocityY += FALLING_PLATFORM_GRAVITY * player.gravityMultiplier; + platform.y += platform.velocityY; + + // Create particles when platform goes off screen + if ((player.gravityMultiplier > 0 && platform.y > canvas.height + 50) || + (player.gravityMultiplier < 0 && platform.y < -50)) { + createPlatformParticles(platform); + } + } + }); + + // Remove platforms that have fallen off screen in either direction + platforms = platforms.filter(platform => + platform.type !== PLATFORM_TYPE.FALLING || + (player.gravityMultiplier > 0 ? platform.y < canvas.height + 100 : platform.y > -100) + ); +} + document.body.style.margin = '0'; document.body.style.overflow = 'hidden'; resizeCanvas(); |