Untitled
unknown
plain_text
a month ago
24 kB
3
Indexable
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Retro Arcade Shooter</title>
<style>
body {
margin: 0;
background-color: #111;
color: white;
font-family: sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
overflow: hidden;
}
canvas {
border: 4px solid #333;
background-color: #050510;
box-shadow: 0 0 20px rgba(0, 257, 257, 0.2);
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="800" height="600"></canvas>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// --- GAME STATE ---
let score = 0;
let gameOver = false;
// --- PLAYER OBJECT ---
const player = {
x: canvas.width / 2,
y: canvas.height - 60,
size: 30,
speed: 5,
color: '#00ffcc'
};
// --- ARRAYS ---
const bullets = [];
const enemies = [];
// --- CONTROLS TRACKING ---
const keys = {
ArrowLeft: false,
ArrowRight: false,
ArrowUp: false,
ArrowDown: false,
Space: false
};
// --- INPUT LISTENERS ---
window.addEventListener('keydown', (e) => {
if (e.code === 'ArrowLeft' || e.code === 'KeyA') keys.ArrowLeft = true;
if (e.code === 'ArrowRight' || e.code === 'KeyD') keys.ArrowRight = true;
if (e.code === 'ArrowUp' || e.code === 'KeyW') keys.ArrowUp = true;
if (e.code === 'ArrowDown' || e.code === 'KeyS') keys.ArrowDown = true;
if (e.code === 'Space') {
if (!keys.Space && !gameOver) {
shoot();
}
if (gameOver) {
resetGame();
}
keys.Space = true;
}
});
window.addEventListener('keyup', (e) => {
if (e.code === 'ArrowLeft' || e.code === 'KeyA') keys.ArrowLeft = false;
if (e.code === 'ArrowRight' || e.code === 'KeyD') keys.ArrowRight = false;
if (e.code === 'ArrowUp' || e.code === 'KeyW') keys.ArrowUp = false;
if (e.code === 'ArrowDown' || e.code === 'KeyS') keys.ArrowDown = false;
if (e.code === 'Space') keys.Space = false;
});
// --- GAME ACTIONS ---
function shoot() {
bullets.push({
x: player.x,
y: player.y - player.size,
radius: 4,
speed: 8,
color: '#ff0055'
});
}
function spawnEnemy() {
if (gameOver) return;
const size = Math.random() * (40 - 20) + 20;
enemies.push({
x: Math.random() * (canvas.width - size) + size/2,
y: -size,
size: size,
speed: Math.random() * (3 - 1) + 1,
color: '#ffcc00'
});
// Schedule next enemy spawn dynamically
setTimeout(spawnEnemy, Math.random() * (1500 - 600) + 600);
}
function resetGame() {
score = 0;
enemies.length = 0;
bullets.length = 0;
player.x = canvas.width / 2;
player.y = canvas.height - 60;
gameOver = false;
spawnEnemy();
gameLoop();
}
// --- COLLISION DETECTION ---
function checkCollision(rect1, rect2) {
// Simple bounding box collision
return rect1.x - rect1.size/2 < rect2.x + rect2.size/2 &&
rect1.x + rect1.size/2 > rect2.x - rect2.size/2 &&
rect1.y - rect1.size/2 < rect2.y + rect2.size/2 &&
rect1.y + rect1.size/2 > rect2.y - rect2.size/2;
}
// --- UPDATE LOGIC ---
function update() {
if (gameOver) return;
// Move Player & Keep In Bounds
if (keys.ArrowLeft && player.x - player.size/2 > 0) player.x -= player.speed;
if (keys.ArrowRight && player.x + player.size/2 < canvas.width) player.x += player.speed;
if (keys.ArrowUp && player.y - player.size/2 > 0) player.y -= player.speed;
if (keys.ArrowDown && player.y + player.size/2 < canvas.height) player.y += player.speed;
// Update Bullets
for (let i = bullets.length - 1; i >= 0; i--) {
bullets[i].y -= bullets[i].speed;
// Remove off-screen bullets
if (bullets[i].y < 0) {
bullets.splice(i, 1);
}
}
// Update Enemies
for (let i = enemies.length - 1; i >= 0; i--) {
enemies[i].y += enemies[i].speed;
// Check collision with player
if (checkCollision(player, enemies[i])) {
gameOver = true;
}
// Check collision with bullets
for (let j = bullets.length - 1; j >= 0; j--) {
// Treat bullet as a small box for simplicity
const bulletBox = { x: bullets[j].x, y: bullets[j].y, size: bullets[j].radius * 2 };
if (checkCollision(enemies[i], bulletBox)) {
enemies.splice(i, 1);
bullets.splice(j, 1);
score += 10;
break;
}
}
// Remove off-screen enemies
if (enemies[i] && enemies[i].y > canvas.height + enemies[i].size) {
enemies.splice(i, 1);
}
}
}
// --- RENDER LOGIC ---
function draw() {
// Clear screen
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw Player (Triangle Ship)
ctx.fillStyle = player.color;
ctx.beginPath();
ctx.moveTo(player.x, player.y - player.size);
ctx.lineTo(player.x - player.size, player.y + player.size);
ctx.lineTo(player.x + player.size, player.y + player.size);
ctx.closePath();
ctx.fill();
// Draw Bullets
ctx.fillStyle = '#ff0055';
bullets.forEach(bullet => {
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, bullet.radius, 0, Math.PI * 2);
ctx.fill();
});
// Draw Enemies (Squares)
enemies.forEach(enemy => {
ctx.fillStyle = enemy.color;
ctx.fillRect(enemy.x - enemy.size/2, enemy.y - enemy.size/2, enemy.size, enemy.size);
});
// Draw Score
ctx.fillStyle = '#fff';
ctx.font = '20px sans-serif';
ctx.fillText(`Score: ${score}`, 20, 40);
// Draw Game Over Screen
if (gameOver) {
ctx.fillStyle = 'rgba(0, 0, 0, 0.75)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#ff0055';
ctx.font = '50px sans-serif';
ctx.textAlign = 'center';
ctx.fillText('GAME OVER', canvas.width / 2, canvas.height / 2 - 20);
ctx.fillStyle = '#fff';
ctx.font = '20px sans-serif';
ctx.fillText('Press SPACE to Restart', canvas.width / 2, canvas.height / 2 + 30);
ctx.textAlign = 'start'; // reset text align
}
}
// --- MAIN ENGINE LOOP ---
function gameLoop() {
update();
draw();
if (!gameOver) {
requestAnimationFrame(gameLoop);
}
}
// Start the game loop initially
spawnEnemy();
gameLoop();
</script>
</body>
</html>
}
}
}
})
})
}
}
}
}
}
}
}
}
}
}
}
})
}
})
}
})
}
}
}
})
}
}
}
}Editor is loading...
Leave a Comment