Spaces:
Running
Running
| <html> | |
| <head> | |
| <style> | |
| body { | |
| margin: 0; | |
| overflow: hidden; | |
| background: black; | |
| } | |
| #gameCanvas { | |
| background-image: url('stage 1.jpg'); | |
| background-size: cover; | |
| } | |
| #message { | |
| position: fixed; | |
| bottom: 550px; | |
| left: 0; | |
| width: 100%; | |
| color: white; | |
| text-align: center; | |
| font-size: 30px; | |
| font-family: Arial; | |
| } | |
| #stats { | |
| position: fixed; | |
| top: 20px; | |
| left: 20px; | |
| color: white; | |
| font-family: Arial; | |
| font-size: 28px; | |
| } | |
| #villainCount { | |
| position: fixed; | |
| top: 20px; | |
| right: 20px; | |
| color: white; | |
| font-family: Arial; | |
| font-size: 28px; | |
| } | |
| #healthBar { | |
| width: 300px; | |
| height: 30px; | |
| background: #333; | |
| margin-top: 5px; | |
| } | |
| #healthFill { | |
| width: 100%; | |
| height: 100%; | |
| background: red; | |
| transition: width 0.3s; | |
| } | |
| #bulletCount, #enemyCount { | |
| font-size: 28px; | |
| } | |
| #replayButton { | |
| position: fixed; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| padding: 15px 30px; | |
| font-size: 20px; | |
| font-family: Arial; | |
| background-color: white; | |
| color: black; | |
| border: none; | |
| border-radius: 5px; | |
| display: none; | |
| cursor: pointer; | |
| } | |
| #replayButton:hover { | |
| background-color: lightgray; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <canvas id="gameCanvas"></canvas> | |
| <div id="message"></div> | |
| <div id="stats"> | |
| Health:<div id="healthBar"><div id="healthFill"></div></div> | |
| Bullets: <span id="bulletCount">35</span> | |
| </div> | |
| <div id="villainCount">Villains: <span id="enemyCount">30</span></div> | |
| <button id="replayButton">Replay</button> | |
| <audio id="bgMusic" src="cinematic-time-lapse-115672.mp3" loop></audio> | |
| <audio id="playerShootSound" src="Maincharactergunsound.mp3"></audio> | |
| <audio id="enemyShootSound" src="Renovatorsgunshot.mp3"></audio> | |
| <audio id="playerHitSound" src="Maincharactershot.mp3"></audio> | |
| <audio id="enemyHitSound" src="Renovatorsgetshot.mp3"></audio> | |
| <script> | |
| const canvas = document.getElementById('gameCanvas'); | |
| const ctx = canvas.getContext('2d'); | |
| const message = document.getElementById('message'); | |
| const healthFill = document.getElementById('healthFill'); | |
| const bulletCount = document.getElementById('bulletCount'); | |
| const enemyCount = document.getElementById('enemyCount'); | |
| const bgMusic = document.getElementById('bgMusic'); | |
| const replayButton = document.getElementById('replayButton'); | |
| const playerShootSound = document.getElementById('playerShootSound'); | |
| const enemyShootSound = document.getElementById('enemyShootSound'); | |
| const playerHitSound = document.getElementById('playerHitSound'); | |
| const enemyHitSound = document.getElementById('enemyHitSound'); | |
| canvas.width = window.innerWidth; | |
| canvas.height = window.innerHeight; | |
| const player = { | |
| x: canvas.width / 2.3, | |
| y: canvas.height - 260, | |
| width: 250, | |
| height: 250, | |
| speed: 10, | |
| health: 10, | |
| bullets: 35, | |
| direction: 1, | |
| image: new Image(), | |
| imageLeft: 'Maincharacterdefaultleft.png', | |
| imageRight: 'Maincharacterdefaultright.png', | |
| imageShootLeft: 'gunshotleft.png', | |
| imageShootRight: 'gunshotright.png', | |
| imageHitLeft: 'ExplosionLeft.png', | |
| imageHitRight: 'ExplosionRight.png' | |
| }; | |
| player.image.src = player.imageRight; | |
| let enemies = []; | |
| let bullets = []; | |
| let enemyBullets = []; | |
| let enemiesRemaining = 30; | |
| let mouseX = 0; | |
| let gameStarted = false; | |
| let gameOver = false; | |
| function spawnEnemy() { | |
| if (!gameStarted || gameOver) { | |
| return; | |
| } | |
| if (enemies.length >= 10) { // 동시에 존재할 수 있는 적의 수 제한 | |
| return; | |
| } | |
| const side = Math.random() < 0.5 ? 0 : canvas.width; | |
| const enemy = { | |
| x: side, | |
| y: Math.random() * (canvas.height - 150), | |
| width: 250, | |
| height: 250, | |
| speed: side === 0 ? 1 : -1, | |
| image: new Image(), | |
| imageLeft: 'Renovators Default Right.png', | |
| imageRight: 'RenovatorsDefaultLeft.png', | |
| imageShootLeft: 'RenovatorsgunLeft.png', | |
| imageShootRight: 'RenovatorsGunRight.png', | |
| imageHitLeft: 'RenovatorsExplodeLeft.png', | |
| imageHitRight: 'RenovatorsExplodeRight.png', | |
| lastShootTime: Date.now() | |
| }; | |
| enemy.image.src = side === 0 ? enemy.imageLeft : enemy.imageRight; | |
| enemies.push(enemy); | |
| } | |
| function updateGame() { | |
| ctx.clearRect(0, 0, canvas.width, canvas.height); | |
| player.direction = mouseX > player.x ? 1 : -1; | |
| player.image.src = player.direction === 1 ? player.imageRight : player.imageLeft; | |
| ctx.drawImage(player.image, player.x, player.y, player.width, player.height); | |
| // 플레이어가 발사한 총알 처리 | |
| bullets.forEach((bullet, index) => { | |
| bullet.x += bullet.speed; | |
| ctx.fillStyle = 'yellow'; | |
| ctx.fillRect(bullet.x, bullet.y, 10, 5); | |
| }); | |
| // 적 처리 | |
| enemies.forEach((enemy, enemyIndex) => { | |
| enemy.x += enemy.speed; | |
| ctx.drawImage(enemy.image, enemy.x, enemy.y, enemy.width, enemy.height); | |
| // 플레이어와 적이 충돌했을 경우 처리 | |
| if (checkCollision(player, enemy)) { | |
| player.health--; | |
| healthFill.style.width = (player.health / 5 * 100) + '%'; | |
| player.image.src = player.direction === 1 ? player.imageHitRight : player.imageHitLeft; | |
| enemies.splice(enemyIndex, 1); // 적 제거 | |
| playerHitSound.play(); | |
| if (player.health <= 0) { | |
| endGame("Game Over! Go back to the past and change the current result!"); | |
| } | |
| } | |
| // 플레이어의 총알이 적을 맞췄을 경우 처리 | |
| bullets.forEach((bullet, bulletIndex) => { | |
| if (checkCollision(bullet, enemy)) { | |
| // 총알이 적을 맞췄을 때 처리 | |
| enemy.image.src = enemy.speed > 0 ? enemy.imageHitRight : enemy.imageHitLeft; | |
| setTimeout(() => { | |
| enemies.splice(enemyIndex, 1); // 적 제거 | |
| bullets.splice(bulletIndex, 1); // 총알 제거 | |
| enemiesRemaining--; | |
| enemyCount.textContent = enemiesRemaining; | |
| }, 100); | |
| enemyHitSound.play(); | |
| if (enemiesRemaining <= 0) { | |
| endGame("You have successfully protected New York. Return to the time machine."); | |
| } | |
| } | |
| }); | |
| // 적의 총알 발사 | |
| enemyShoot(enemy); | |
| }); | |
| if (enemiesRemaining <= 0 && enemies.length === 0) { | |
| endGame("You have successfully protected New York. Return to the time machine."); | |
| return; // 게임 종료 후 더 이상 업데이트하지 않음 | |
| } | |
| // 적의 총알 처리 | |
| enemyBullets.forEach((bullet, index) => { | |
| bullet.x += bullet.speed; | |
| ctx.fillStyle = 'orange'; | |
| ctx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height); | |
| // 총알이 플레이어와 충돌했을 경우 처리 | |
| if ( | |
| bullet.x < player.x + player.width - 30 && | |
| bullet.x + bullet.width > player.x + 30 && | |
| bullet.y < player.y + player.height - 30 && | |
| bullet.y + bullet.height > player.y + 30 | |
| ) { | |
| player.health--; | |
| healthFill.style.width = (player.health / 5 * 100) + '%'; | |
| player.image.src = player.direction === 1 ? player.imageHitRight : player.imageHitLeft; | |
| enemyBullets.splice(index, 1); // 총알 제거 | |
| playerHitSound.play(); | |
| if (player.health <= 0) { | |
| endGame("Game Over! Go back to the past and change the current result!"); | |
| } | |
| } | |
| }); | |
| // 화면 밖으로 나간 총알 제거 | |
| bullets = bullets.filter(bullet => | |
| bullet.x >= 0 && bullet.x <= canvas.width | |
| ); | |
| enemyBullets = enemyBullets.filter(bullet => | |
| bullet.x >= 0 && bullet.x <= canvas.width | |
| ); | |
| // 게임이 종료되지 않으면 계속 업데이트 | |
| if (!gameOver) { | |
| requestAnimationFrame(updateGame); | |
| } | |
| } | |
| setTimeout(() => { | |
| message.textContent = "Click on the character"; | |
| setTimeout(() => { | |
| message.textContent = "You can move your character using the arrow keys."; | |
| setTimeout(() => { | |
| message.textContent = "The character's direction follows the mouse cursor."; | |
| setTimeout(() => { | |
| message.textContent = "Press the space bar to shoot a bullet."; | |
| setTimeout(() => { | |
| message.textContent = "Your mission is to defeat the Renovators who have attacked New York. Defeat them all and save New York in 2030!"; | |
| setTimeout(() => { | |
| message.textContent = ""; | |
| gameStarted = true; | |
| }, 5000); | |
| }, 3000); | |
| }, 4000); | |
| }, 4000); | |
| }, 4000); | |
| }, 0); | |
| function endGame(messageText) { | |
| gameOver = true; | |
| message.textContent = messageText; | |
| replayButton.style.display = 'block'; | |
| } | |
| function checkCollision(rect1, rect2) { | |
| return ( | |
| rect1.x + rect1.width * 0.2 < rect2.x + rect2.width * 0.8 && | |
| rect1.x + rect1.width * 0.8 > rect2.x + rect2.width * 0.2 && | |
| rect1.y + rect1.height * 0.2 < rect2.y + rect2.height * 0.8 && | |
| rect1.y + rect1.height * 0.8 > rect2.y + rect2.height * 0.2 | |
| ); | |
| } | |
| function enemyShoot(enemy) { | |
| const now = Date.now(); | |
| if (now - enemy.lastShootTime >= 3000 && !gameOver) { | |
| enemy.image.src = enemy.speed > 0 ? enemy.imageShootRight : enemy.imageShootLeft; | |
| enemyBullets.push({ | |
| x: enemy.x + enemy.width / 2, | |
| y: enemy.y + enemy.height / 2.5, | |
| width: 10, | |
| height: 5, | |
| speed: enemy.speed > 0 ? 5 : -5 | |
| }); | |
| enemy.lastShootTime = now; // Update the last shoot time | |
| enemyShootSound.play(); | |
| } | |
| } | |
| window.addEventListener('keydown', (e) => { | |
| if (!gameOver) { | |
| switch (e.key) { | |
| case 'ArrowUp': | |
| if (player.y > 0) player.y -= player.speed; | |
| break; | |
| case 'ArrowDown': | |
| if (player.y < canvas.height - player.height) player.y += player.speed; | |
| break; | |
| case 'ArrowLeft': | |
| if (player.x > 0) player.x -= player.speed; | |
| break; | |
| case 'ArrowRight': | |
| if (player.x < canvas.width - player.width) player.x += player.speed; | |
| break; | |
| case ' ': | |
| if (player.bullets > 0) { | |
| player.image.src = player.direction === 1 ? player.imageShootRight : player.imageShootLeft; | |
| bullets.push({ | |
| x: player.x + player.width / 2, | |
| y: player.y + player.height / 2.5, | |
| width: 10, | |
| height: 5, | |
| speed: player.direction * 10 | |
| }); | |
| player.bullets--; | |
| bulletCount.textContent = player.bullets; | |
| playerShootSound.play(); | |
| } | |
| break; | |
| } | |
| } | |
| }); | |
| window.addEventListener('mousemove', (e) => { | |
| mouseX = e.clientX; | |
| }); | |
| replayButton.addEventListener('click', () => { | |
| location.reload(); | |
| }); | |
| setInterval(spawnEnemy, 2000); | |
| bgMusic.play(); | |
| updateGame(); | |
| </script> | |
| </body> | |
| </html> |