以下是完整的、可直接运行的最终版代码
<!DOCTYPE html>
<html>
<head>
<title>突击行动 - 终极完整版</title>
<style>
body {
margin: 0;
overflow: hidden;
background: #1a1a1a;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
#gameCanvas {
border: 2px solid #4CAF50;
border-radius: 5px;
box-shadow: 0 0 20px rgba(76, 175, 80, 0.3);
}
#hud {
position: absolute;
top: 20px;
left: 20px;
color: #fff;
font-family: Arial, sans-serif;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
}
#powerup {
position: absolute;
top: 60px;
left: 20px;
color: #FFD700;
font-family: Arial, sans-serif;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
}
.apple-text {
color: #FF4444;
}
#restart {
display: none;
position: absolute;
padding: 15px 30px;
font-size: 20px;
background: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
box-shadow: 0 0 15px rgba(76, 175, 80, 0.5);
}
</style>
</head>
<body>
<div id="hud">得分: <span id="score">0</span></div>
<div id="powerup"></div>
<canvas id="gameCanvas"></canvas>
<button id="restart">重新开始</button>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');
const powerupElement = document.getElementById('powerup');
const restartButton = document.getElementById('restart');
// 游戏配置
canvas.width = 800;
canvas.height = 600;
const config = {
playerSpeed: 5,
bulletSpeed: 8,
tripleShotDuration: 5000,
fullCircleDuration: 5000,
bulletCount: 12,
enemy: {
size: 25,
speed: 2,
baseSpawnRate: 60,
color: '#FF5252'
}
};
// 游戏对象
let player = {
x: canvas.width/2,
y: canvas.height/2,
size: 30,
color: '#4CAF50'
};
let bullets = [];
let enemies = [];
let powerups = [];
let score = 0;
let gameActive = true;
let tripleShot = false;
let fullCircleShot = false;
let powerupTimer = null;
let appleTimer = null;
let mouse = { x: 0, y: 0 };
// 事件监听
canvas.addEventListener('mousemove', updateMousePosition);
canvas.addEventListener('click', shoot);
restartButton.addEventListener('click', initGame);
window.addEventListener('keydown', handleKeyDown);
window.addEventListener('keyup', handleKeyUp);
function initGame() {
player.x = canvas.width/2;
player.y = canvas.height/2;
bullets = [];
enemies = [];
powerups = [];
score = 0;
tripleShot = false;
fullCircleShot = false;
gameActive = true;
restartButton.style.display = 'none';
powerupElement.innerHTML = '';
updateScore();
gameLoop();
}
function gameLoop() {
if (!gameActive) return;
ctx.fillStyle = '#1a1a1a';
ctx.fillRect(0, 0, canvas.width, canvas.height);
handleMovement();
updatePlayer();
updateBullets();
updateEnemies();
updatePowerups();
checkCollisions();
checkPowerupCollisions();
requestAnimationFrame(gameLoop);
}
function handleMovement() {
if (keys.w || keys.ArrowUp) player.y -= config.playerSpeed;
if (keys.s || keys.ArrowDown) player.y += config.playerSpeed;
if (keys.a || keys.ArrowLeft) player.x -= config.playerSpeed;
if (keys.d || keys.ArrowRight) player.x += config.playerSpeed;
player.x = Math.max(player.size, Math.min(canvas.width - player.size, player.x));
player.y = Math.max(player.size, Math.min(canvas.height - player.size, player.y));
}
function updatePlayer() {
let color = '#4CAF50';
if (tripleShot) color = '#FFD700';
if (fullCircleShot) color = '#FF4444';
ctx.beginPath();
ctx.arc(player.x, player.y, player.size, 0, Math.PI * 2);
ctx.fillStyle = color;
ctx.fill();
ctx.shadowColor = color;
ctx.shadowBlur = 20;
}
function updateBullets() {
bullets.forEach((bullet, index) => {
bullet.x += bullet.dx;
bullet.y += bullet.dy;
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, 4, 0, Math.PI * 2);
ctx.fillStyle = '#FFC107';
ctx.fill();
ctx.shadowColor = '#FFC107';
ctx.shadowBlur = 15;
if (bullet.x < -10 || bullet.x > canvas.width + 10 ||
bullet.y < -10 || bullet.y > canvas.height + 10) {
bullets.splice(index, 1);
}
});
}
function updateEnemies() {
const spawnRate = Math.max(30, config.enemy.baseSpawnRate - Math.floor(score/50));
if (Math.random() * spawnRate < 1) {
enemies.push({
x: Math.random() * canvas.width,
y: -config.enemy.size,
size: config.enemy.size,
color: config.enemy.color
});
}
enemies.forEach((enemy, index) => {
const angle = Math.atan2(player.y - enemy.y, player.x - enemy.x);
enemy.x += Math.cos(angle) * config.enemy.speed;
enemy.y += Math.sin(angle) * config.enemy.speed;
ctx.beginPath();
ctx.arc(enemy.x, enemy.y, enemy.size, 0, Math.PI * 2);
ctx.fillStyle = enemy.color;
ctx.fill();
ctx.shadowColor = enemy.color;
ctx.shadowBlur = 20;
if (enemy.y > canvas.height + enemy.size) {
enemies.splice(index, 1);
}
});
}
function updatePowerups() {
if (Math.random() < 0.002) {
const types = ['triple', 'apple'];
powerups.push({
x: Math.random() * (canvas.width - 30),
y: Math.random() * (canvas.height - 30),
type: types[Math.floor(Math.random() * types.length)],
size: 20,
spawnTime: Date.now()
});
}
powerups.forEach((powerup, index) => {
if (powerup.type === 'apple') {
drawApple(powerup.x, powerup.y, powerup.size);
} else {
ctx.save();
ctx.translate(powerup.x, powerup.y);
ctx.rotate((Date.now() - powerup.spawnTime)/500);
ctx.fillStyle = '#FFD700';
for (let i = 0; i < 5; i++) {
ctx.beginPath();
ctx.rotate(Math.PI * 2 / 5);
ctx.moveTo(0, 0);
ctx.lineTo(powerup.size/2, 0);
ctx.lineTo(powerup.size/1.5, -powerup.size/1.5);
ctx.closePath();
ctx.fill();
}
ctx.restore();
}
});
}
function drawApple(x, y, size) {
ctx.save();
ctx.translate(x, y);
ctx.beginPath();
ctx.arc(0, 0, size, 0, Math.PI * 2);
ctx.fillStyle = '#FF4444';
ctx.fill();
ctx.beginPath();
ctx.moveTo(-size/3, -size/2);
ctx.quadraticCurveTo(0, -size, size/3, -size/2);
ctx.fillStyle = '#4CAF50';
ctx.fill();
ctx.restore();
}
function checkCollisions() {
enemies.forEach((enemy, eIndex) => {
bullets.forEach((bullet, bIndex) => {
const dx = enemy.x - bullet.x;
const dy = enemy.y - bullet.y;
const distance = Math.sqrt(dx*dx + dy*dy);
if (distance < enemy.size) {
enemies.splice(eIndex, 1);
bullets.splice(bIndex, 1);
score += 10;
updateScore();
}
});
const pd = Math.sqrt((enemy.x - player.x)**2 + (enemy.y - player.y)**2);
if (pd < enemy.size + player.size) {
gameOver();
}
});
}
function checkPowerupCollisions() {
powerups.forEach((powerup, index) => {
const dx = player.x - powerup.x;
const dy = player.y - powerup.y;
const distance = Math.sqrt(dx*dx + dy*dy);
if (distance < player.size + powerup.size) {
if (powerup.type === 'triple') {
activateTripleShot();
} else if (powerup.type === 'apple') {
activateApplePowerup();
}
powerups.splice(index, 1);
}
});
}
function updateMousePosition(e) {
const rect = canvas.getBoundingClientRect();
mouse.x = e.clientX - rect.left;
mouse.y = e.clientY - rect.top;
}
function shoot() {
if (!gameActive) return;
if (fullCircleShot) {
for (let i = 0; i < config.bulletCount; i++) {
const angle = (Math.PI * 2 * i) / config.bulletCount;
bullets.push({
x: player.x,
y: player.y,
dx: Math.cos(angle) * config.bulletSpeed,
dy: Math.sin(angle) * config.bulletSpeed
});
}
} else {
const angle = Math.atan2(mouse.y - player.y, mouse.x - player.x);
const bulletCount = tripleShot ? 3 : 1;
for (let i = 0; i < bulletCount; i++) {
const spread = tripleShot ? (i - 1) * 0.2 : 0;
bullets.push({
x: player.x,
y: player.y,
dx: Math.cos(angle + spread) * config.bulletSpeed,
dy: Math.sin(angle + spread) * config.bulletSpeed
});
}
}
}
function activateTripleShot() {
tripleShot = true;
clearTimeout(powerupTimer);
powerupTimer = setTimeout(() => {
tripleShot = false;
powerupElement.innerHTML = '';
}, config.tripleShotDuration);
powerupElement.innerHTML = '三倍火力激活!剩余5秒';
}
function activateApplePowerup() {
fullCircleShot = true;
clearTimeout(appleTimer);
appleTimer = setTimeout(() => {
fullCircleShot = false;
powerupElement.innerHTML = '';
}, config.fullCircleDuration);
powerupElement.innerHTML = '<span class="apple-text">全屏射击激活!剩余5秒</span>';
}
function updateScore() {
scoreElement.textContent = score;
}
function gameOver() {
gameActive = false;
restartButton.style.display = 'block';
ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
const keys = {};
function handleKeyDown(e) {
keys[e.key.toLowerCase()] = true;
if (e.code === 'Space') shoot();
}
function handleKeyUp(e) {
keys[e.key.toLowerCase()] = false;
}
initGame();
</script>
</body>
</html>
主要功能说明:
- 使用WSAD或方向键移动玩家
- 鼠标瞄准,点击左键或空格键射击
- 两种强化道具:
- ★ 金色星星:三连发精准射击(5秒)
- 🍎 红色苹果:360度全屏弹幕(5秒)
- 敌人生成速度随分数增加
- 玩家颜色反馈当前状态:
- 绿色:普通状态
- 金色:三连发状态
- 红色:全屏射击状态
- 持续更新的计分系统
- 游戏结束可重新开始
直接复制全部代码保存为.html文件,用现代浏览器打开即可体验完整游戏。玩家需要灵活运用两种强化道具来应对不断增强的敌人攻势,挑战更高分数!