Spaces:
Running
Running
<html> | |
<head> | |
<title>Tank Battle</title> | |
<style> | |
body { | |
margin: 0; | |
overflow: hidden; | |
background: #333; | |
} | |
#gameCanvas { | |
background-repeat: repeat; | |
} | |
#instructions { | |
position: fixed; | |
top: 10px; | |
right: 10px; | |
color: white; | |
background: rgba(0,0,0,0.7); | |
padding: 10px; | |
border-radius: 5px; | |
font-family: Arial; | |
z-index: 1000; | |
} | |
.button { | |
position: fixed; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
padding: 20px 40px; | |
font-size: 24px; | |
background: #4CAF50; | |
color: white; | |
border: none; | |
border-radius: 5px; | |
cursor: pointer; | |
display: none; | |
z-index: 1000; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="instructions"> | |
Controls:<br> | |
WASD - Move tank<br> | |
Mouse - Aim turret<br> | |
Space - Fire | |
</div> | |
<button id="nextRound" class="button">Next Round</button> | |
<button id="restart" class="button">Restart Game</button> | |
<canvas id="gameCanvas"></canvas> | |
<script> | |
const canvas = document.getElementById('gameCanvas'); | |
const ctx = canvas.getContext('2d'); | |
const nextRoundBtn = document.getElementById('nextRound'); | |
const restartBtn = document.getElementById('restart'); | |
canvas.width = window.innerWidth; | |
canvas.height = window.innerHeight; | |
// Load images | |
const fieldImg = new Image(); | |
fieldImg.src = 'field.png'; | |
const bodyImg = new Image(); | |
bodyImg.src = 'body.png'; | |
const turretImg = new Image(); | |
turretImg.src = 'turret.png'; | |
const enemyImg = new Image(); | |
enemyImg.src = 'enemy.png'; | |
// Audio | |
const playerFireSound = new Audio('fire.mp3'); | |
const enemyFireSound = new Audio('fire2.mp3'); | |
// Game state | |
let currentRound = 1; | |
let gameOver = false; | |
let enemies = []; | |
let bullets = []; | |
let playerBullets = []; | |
let items = []; | |
// Tank properties | |
const player = { | |
x: canvas.width/2, | |
y: canvas.height/2, | |
speed: 5, | |
angle: 0, | |
turretAngle: 0, | |
width: 60, | |
height: 80, | |
health: 1000, | |
maxHealth: 1000 | |
}; | |
class Enemy { | |
constructor() { | |
this.x = Math.random() * canvas.width; | |
this.y = Math.random() * canvas.height; | |
this.health = 1000; | |
this.maxHealth = 1000; | |
this.speed = 2; | |
this.lastShot = 0; | |
this.shootInterval = 2000; | |
this.angle = 0; | |
} | |
update() { | |
this.angle = Math.atan2(player.y - this.y, player.x - this.x); | |
this.x += Math.cos(this.angle) * this.speed * 0.5; | |
this.y += Math.sin(this.angle) * this.speed * 0.5; | |
this.x = Math.max(0, Math.min(canvas.width, this.x)); | |
this.y = Math.max(0, Math.min(canvas.height, this.y)); | |
const now = Date.now(); | |
if (now - this.lastShot > this.shootInterval) { | |
this.shoot(); | |
this.lastShot = now; | |
} | |
} | |
shoot() { | |
enemyFireSound.currentTime = 0; | |
enemyFireSound.play(); | |
bullets.push({ | |
x: this.x, | |
y: this.y, | |
angle: this.angle, | |
speed: 5, | |
isEnemy: true | |
}); | |
} | |
} | |
// Draw background pattern | |
function drawBackground() { | |
const pattern = ctx.createPattern(fieldImg, 'repeat'); | |
ctx.fillStyle = pattern; | |
ctx.fillRect(0, 0, canvas.width, canvas.height); | |
} | |
// Game controls | |
const keys = {}; | |
let mouseX = 0; | |
let mouseY = 0; | |
let lastShot = 0; | |
const shootInterval = 1000; | |
document.addEventListener('keydown', (e) => { | |
keys[e.key] = true; | |
}); | |
document.addEventListener('keyup', (e) => { | |
keys[e.key] = false; | |
}); | |
canvas.addEventListener('mousemove', (e) => { | |
mouseX = e.clientX; | |
mouseY = e.clientY; | |
}); | |
function fireBullet() { | |
const now = Date.now(); | |
if (now - lastShot > shootInterval && keys[' ']) { | |
playerFireSound.currentTime = 0; | |
playerFireSound.play(); | |
playerBullets.push({ | |
x: player.x, | |
y: player.y, | |
angle: player.turretAngle, | |
speed: 10 | |
}); | |
lastShot = now; | |
} | |
} | |
function initRound() { | |
enemies = []; | |
for(let i = 0; i < 5 * currentRound; i++) { | |
enemies.push(new Enemy()); | |
} | |
player.health = player.maxHealth; | |
bullets = []; | |
playerBullets = []; | |
items = []; | |
} | |
function spawnHealthItem(x, y) { | |
items.push({ | |
x: x, | |
y: y, | |
width: 20, | |
height: 20 | |
}); | |
} | |
function updateGame() { | |
if(gameOver) return; | |
if(keys['w']) player.y = Math.max(player.y - player.speed, player.height/2); | |
if(keys['s']) player.y = Math.min(player.y + player.speed, canvas.height - player.height/2); | |
if(keys['a']) player.x = Math.max(player.x - player.speed, player.width/2); | |
if(keys['d']) player.x = Math.min(player.x + player.speed, canvas.width - player.width/2); | |
player.turretAngle = Math.atan2(mouseY - player.y, mouseX - player.x); | |
if(keys[' ']) fireBullet(); | |
enemies.forEach(enemy => enemy.update()); | |
// Update bullets and collision detection | |
playerBullets = playerBullets.filter(bullet => { | |
bullet.x += Math.cos(bullet.angle) * bullet.speed; | |
bullet.y += Math.sin(bullet.angle) * bullet.speed; | |
enemies = enemies.filter(enemy => { | |
const dist = Math.hypot(bullet.x - enemy.x, bullet.y - enemy.y); | |
if(dist < 30) { | |
enemy.health -= enemy.maxHealth / 2; | |
if(enemy.health <= 0) { | |
spawnHealthItem(enemy.x, enemy.y); | |
return false; | |
} | |
return true; | |
} | |
return true; | |
}); | |
return bullet.x >= 0 && bullet.x <= canvas.width && | |
bullet.y >= 0 && bullet.y <= canvas.height; | |
}); | |
bullets = bullets.filter(bullet => { | |
bullet.x += Math.cos(bullet.angle) * bullet.speed; | |
bullet.y += Math.sin(bullet.angle) * bullet.speed; | |
const dist = Math.hypot(bullet.x - player.x, bullet.y - player.y); | |
if(dist < 30) { | |
player.health -= 100; | |
if(player.health <= 0) { | |
gameOver = true; | |
restartBtn.style.display = 'block'; | |
} | |
return false; | |
} | |
return bullet.x >= 0 && bullet.x <= canvas.width && | |
bullet.y >= 0 && bullet.y <= canvas.height; | |
}); | |
items = items.filter(item => { | |
const dist = Math.hypot(item.x - player.x, item.y - player.y); | |
if(dist < 30) { | |
player.health = Math.min(player.health + 200, player.maxHealth); | |
return false; | |
} | |
return true; | |
}); | |
if(enemies.length === 0) { | |
if(currentRound < 10) { | |
nextRoundBtn.style.display = 'block'; | |
} else { | |
gameOver = true; | |
restartBtn.style.display = 'block'; | |
} | |
} | |
} | |
function drawHealthBar(x, y, health, maxHealth, width, height, color) { | |
const barX = x - width/2; | |
const barY = y - 50; | |
ctx.fillStyle = '#333'; | |
ctx.fillRect(barX, barY, width, height); | |
ctx.fillStyle = color; | |
ctx.fillRect(barX, barY, width * (health/maxHealth), height); | |
} | |
function drawGame() { | |
drawBackground(); | |
// Draw player | |
ctx.save(); | |
ctx.translate(player.x, player.y); | |
ctx.drawImage(bodyImg, -player.width/2, -player.height/2, player.width, player.height); | |
ctx.rotate(player.turretAngle); | |
ctx.drawImage(turretImg, -player.width/2, -player.height/2, player.width, player.height); | |
ctx.restore(); | |
// Draw player health bar | |
drawHealthBar(canvas.width/2, 30, player.health, player.maxHealth, 200, 20, 'green'); | |
// Draw enemies | |
enemies.forEach(enemy => { | |
ctx.save(); | |
ctx.translate(enemy.x, enemy.y); | |
ctx.rotate(enemy.angle); | |
ctx.drawImage(enemyImg, -30, -40, 60, 80); | |
ctx.restore(); | |
drawHealthBar(enemy.x, enemy.y, enemy.health, enemy.maxHealth, 60, 5, 'red'); | |
}); | |
// Draw bullets | |
ctx.fillStyle = 'yellow'; | |
[...playerBullets, ...bullets].forEach(bullet => { | |
ctx.beginPath(); | |
ctx.arc(bullet.x, bullet.y, 3, 0, Math.PI * 2); | |
ctx.fill(); | |
}); | |
// Draw items | |
ctx.fillStyle = 'green'; | |
items.forEach(item => { | |
ctx.beginPath(); | |
ctx.arc(item.x, item.y, 10, 0, Math.PI * 2); | |
ctx.fill(); | |
}); | |
// Draw round number | |
ctx.fillStyle = 'white'; | |
ctx.font = '24px Arial'; | |
ctx.fillText(`Round ${currentRound}/10`, 10, 30); | |
} | |
function gameLoop() { | |
updateGame(); | |
drawGame(); | |
requestAnimationFrame(gameLoop); | |
} | |
nextRoundBtn.addEventListener('click', () => { | |
currentRound++; | |
nextRoundBtn.style.display = 'none'; | |
initRound(); | |
}); | |
restartBtn.addEventListener('click', () => { | |
currentRound = 1; | |
gameOver = false; | |
restartBtn.style.display = 'none'; | |
initRound(); | |
}); | |
Promise.all([ | |
new Promise(resolve => fieldImg.onload = resolve), | |
new Promise(resolve => bodyImg.onload = resolve), | |
new Promise(resolve => turretImg.onload = resolve), | |
new Promise(resolve => enemyImg.onload = resolve) | |
]).then(() => { | |
initRound(); | |
gameLoop(); | |
}); | |
window.addEventListener('resize', () => { | |
canvas.width = window.innerWidth; | |
canvas.height = window.innerHeight; | |
}); | |
</script> | |
</body> | |
</html> |