人机枪战小游戏
by SparkOwl95190 lines4.7 KB
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>人机枪战小游戏</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
canvas{background:#222;display:block;margin:0 auto;cursor:crosshair;}
body{background:#111}
</style>
</head>
<body>
<canvas id="gameCanvas"></canvas>
<script>
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
canvas.width = 900;
canvas.height = 600;
// ========== 输入控制 ==========
const keys = {};
let mouse = {x:0,y:0,down:false};
document.addEventListener("keydown",e=>keys[e.key.toLowerCase()]=true);
document.addEventListener("keyup",e=>keys[e.key.toLowerCase()]=false);
canvas.addEventListener("mousemove",e=>{
const rect=canvas.getBoundingClientRect();
mouse.x=e.clientX-rect.left;
mouse.y=e.clientY-rect.top;
});
canvas.addEventListener("mousedown",()=>mouse.down=true);
canvas.addEventListener("mouseup",()=>mouse.down=false);
// ========== 玩家 ==========
const player = {
x: canvas.width/2,
y: canvas.height/2,
r:18,
speed:4,
hp:100,
score:0
};
// 子弹数组
let bullets = [];
// 敌人AI数组
let enemies = [];
let lastShot = 0;
const shootCD = 180; //射击冷却ms
// 生成子弹
function spawnBullet(){
const now = Date.now();
if(now-lastShot < shootCD) return;
lastShot = now;
const angle = Math.atan2(mouse.y-player.y, mouse.x-player.x);
bullets.push({
x:player.x,
y:player.y,
vx:Math.cos(angle)*10,
vy:Math.sin(angle)*10,
r:5
})
}
// 生成敌人AI
function spawnEnemy(){
let x,y;
const side = Math.floor(Math.random()*4);
if(side===0){x=0;y=Math.random()*canvas.height}
else if(side===1){x=canvas.width;y=Math.random()*canvas.height}
else if(side===2){x=Math.random()*canvas.width;y=0}
else {x=Math.random()*canvas.width;y=canvas.height}
enemies.push({
x:x,
y:y,
r:16,
speed:1.6,
hp:1
})
}
// ========== 游戏循环 ==========
function loop(){
// 清画布
ctx.fillStyle="#222222";
ctx.fillRect(0,0,canvas.width,canvas.height);
// 玩家移动 WASD
if(keys["w"]) player.y -= player.speed;
if(keys["s"]) player.y += player.speed;
if(keys["a"]) player.x -= player.speed;
if(keys["d"]) player.x += player.speed;
// 边界限制
player.x = Math.max(player.r, Math.min(canvas.width-player.r, player.x));
player.y = Math.max(player.r, Math.min(canvas.height-player.r, player.y));
// 射击
if(mouse.down) spawnBullet();
// 更新子弹
for(let i=bullets.length-1;i>=0;i--){
const b=bullets[i];
b.x += b.vx;
b.y += b.vy;
// 超出屏幕删除子弹
if(b.x<0||b.x>canvas.width||b.y<0||b.y>canvas.height){
bullets.splice(i,1);continue;
}
//子弹碰敌人
for(let j=enemies.length-1;j>=0;j--){
const e=enemies[j];
const dx=b.x-e.x;
const dy=b.y-e.y;
const dist=Math.sqrt(dx*dx+dy*dy);
if(dist < b.r+e.r){
enemies.splice(j,1);
bullets.splice(i,1);
player.score +=10;
break;
}
}
}
// 更新敌人AI:追踪玩家
for(let i=enemies.length-1;i>=0;i--){
const e=enemies[i];
const dx=player.x - e.x;
const dy=player.y - e.y;
const angle=Math.atan2(dy,dx);
e.x += Math.cos(angle)*e.speed;
e.y += Math.sin(angle)*e.speed;
//敌人撞到玩家
const dist = Math.hypot(player.x-e.x, player.y-e.y);
if(dist < player.r + e.r){
player.hp -= 15;
enemies.splice(i,1);
}
}
// 绘制玩家
ctx.beginPath();
ctx.arc(player.x,player.y,player.r,0,Math.PI*2);
ctx.fillStyle="#42A5F5";
ctx.fill();
//绘制敌人
ctx.fillStyle="#ff4444";
enemies.forEach(e=>{
ctx.beginPath();
ctx.arc(e.x,e.y,e.r,0,Math.PI*2);
ctx.fill();
})
//绘制子弹
ctx.fillStyle="#ffee44";
bullets.forEach(b=>{
ctx.beginPath();
ctx.arc(b.x,b.y,b.r,0,Math.PI*2);
ctx.fill();
})
// UI文字 分数血量
ctx.fillStyle="#fff";
ctx.font="22px Arial";
ctx.fillText(`分数:${player.score}`,20,30);
ctx.fillText(`血量:${player.hp}`,20,60);
//游戏结束判断
if(player.hp <=0){
ctx.fillStyle="#ff3333";
ctx.font="48px Arial";
ctx.textAlign="center";
ctx.fillText("游戏结束!",canvas.width/2,canvas.height/2);
}
requestAnimationFrame(loop);
}
// 定时生成敌人
setInterval(spawnEnemy,1200);
loop();
</script>
</body>
</html>
Game Source: 人机枪战小游戏
Creator: SparkOwl95
Libraries: none
Complexity: moderate (190 lines, 4.7 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: game-sparkowl95" to link back to the original. Then publish at arcadelab.ai/publish.