1.效果图
2.代码实现
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>太空射击游戏</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background: linear-gradient(to bottom, #000046, #1d1d1d);
color: #fff;
font-family: Arial, sans-serif;
}
canvas {
border: 2px solid #fff;
background: url('https://www.transparenttextures.com/patterns/dark-matter.png');
background-size: cover;
}
#score {
position: absolute;
top: 20px;
left: 20px;
font-size: 24px;
}
#lives {
position: absolute;
top: 20px;
right: 20px;
font-size: 24px;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="800" height="600"></canvas>
<div id="score">得分: 0</div>
<div id="lives">生命: 3</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// 玩家设置
const playerWidth = 50;
const playerHeight = 30;
const playerSpeed = 5;
let playerX = (canvas.width - playerWidth) / 2;
let rightPressed = false;
let leftPressed = false;
// 子弹设置
const bulletWidth = 5;
const bulletHeight = 20;
const bulletSpeed = 4;
let bullets = [];
// 敌人设置
const enemyWidth = 50;
const enemyHeight = 30;
const enemyRowCount = 3;
const enemyColumnCount = 5;
const enemyPadding = 10;
const enemyOffsetTop = 30;
const enemyOffsetLeft = 30;
let enemies = [];
for (let c = 0; c < enemyColumnCount; c++) {
enemies[c] = [];
for (let r = 0; r < enemyRowCount; r++) {
enemies[c][r] = {
x: c * (enemyWidth + enemyPadding) + enemyOffsetLeft,
y: r * (enemyHeight + enemyPadding) + enemyOffsetTop,
status: 1
};
}
}
// 游戏状态
let score = 0;
let lives = 3;
let enemySpeed = 1;
let enemyDirection = 1; // 1 = 右, -1 = 左
// 事件监听
document.addEventListener('keydown', keyDownHandler);
document.addEventListener('keyup', keyUpHandler);
document.addEventListener('keydown', shootBullet);
function keyDownHandler(e) {
if (e.key === 'Right' || e.key === 'ArrowRight') {
rightPressed = true;
} else if (e.key === 'Left' || e.key === 'ArrowLeft') {
leftPressed = true;
}
}
function keyUpHandler(e) {
if (e.key === 'Right' || e.key === 'ArrowRight') {
rightPressed = false;
} else if (e.key === 'Left' || e.key === 'ArrowLeft') {
leftPressed = false;
}
}
function shootBullet(e) {
if (e.key === ' ' || e.key === 'Enter') {
bullets.push({ x: playerX + playerWidth / 2, y: canvas.height - playerHeight });
}
}
function drawPlayer() {
ctx.beginPath();
ctx.rect(playerX, canvas.height - playerHeight, playerWidth, playerHeight);
ctx.fillStyle = '#00f';
ctx.fill();
ctx.closePath();
}
function drawBullet() {
ctx.beginPath();
bullets.forEach(bullet => {
ctx.rect(bullet.x, bullet.y, bulletWidth, bulletHeight);
ctx.fillStyle = '#f00';
ctx.fill();
});
ctx.closePath();
}
function drawEnemies() {
for (let c = 0; c < enemyColumnCount; c++) {
for (let r = 0; r < enemyRowCount; r++) {
if (enemies[c][r].status === 1) {
const enemyX = enemies[c][r].x;
const enemyY = enemies[c][r].y;
ctx.beginPath();
ctx.rect(enemyX, enemyY, enemyWidth, enemyHeight);
ctx.fillStyle = '#0f0';
ctx.fill();
ctx.closePath();
}
}
}
}
function collisionDetection() {
bullets.forEach((bullet, index) => {
for (let c = 0; c < enemyColumnCount; c++) {
for (let r = 0; r < enemyRowCount; r++) {
const enemy = enemies[c][r];
if (enemy.status === 1) {
if (bullet.x > enemy.x && bullet.x < enemy.x + enemyWidth &&
bullet.y > enemy.y && bullet.y < enemy.y + enemyHeight) {
enemy.status = 0;
bullets.splice(index, 1);
score += 10;
}
}
}
}
});
enemies.forEach((column) => {
column.forEach((enemy) => {
if (enemy.status === 1 && enemy.y + enemyHeight >= canvas.height - playerHeight) {
lives -= 1;
enemy.status = 0;
if (lives <= 0) {
alert('游戏结束');
document.location.reload();
}
}
});
});
}
function updateBulletPosition() {
bullets.forEach(bullet => {
bullet.y -= bulletSpeed;
});
bullets = bullets.filter(bullet => bullet.y > -bulletHeight);
}
function drawScore() {
document.getElementById('score').innerText = `得分: ${score}`;
}
function drawLives() {
document.getElementById('lives').innerText = `生命: ${lives}`;
}
function moveEnemies() {
let moveDown = false;
enemies.forEach((column) => {
column.forEach((enemy) => {
if (enemy.status === 1) {
enemy.x += enemySpeed * enemyDirection;
if (enemy.x + enemyWidth > canvas.width || enemy.x < 0) {
moveDown = true;
}
}
});
});
if (moveDown) {
enemyDirection *= -1;
enemies.forEach((column) => {
column.forEach((enemy) => {
if (enemy.status === 1) {
enemy.y += enemyHeight / 2;
}
});
});
}
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawPlayer();
drawBullet();
drawEnemies();
collisionDetection();
updateBulletPosition();
moveEnemies();
drawScore();
drawLives();
if (rightPressed && playerX < canvas.width - playerWidth) {
playerX += playerSpeed;
} else if (leftPressed && playerX > 0) {
playerX -= playerSpeed;
}
requestAnimationFrame(draw);
}
draw();
</script>
</body>
</html>