很多人觉得做一个小游戏需要复杂的引擎,比如 Unity 或 Unreal Engine。
其实未必。
利用 HTML5 Canvas 和 JavaScript ,只需要 91 行代码,就能写出一个可运行的「打飞机小游戏」。
今天带大家一步一步拆解这个极简实现。
一、最终效果
功能非常简单:
- 方向键控制飞机移动
- 自动发射子弹
- 随机生成敌机
- 子弹击中敌机消失
游戏结构如下:
玩家飞机
↓
子弹系统
↓
敌机生成
↓
碰撞检测
↓
游戏循环
二、完整代码(约 91 行)
新建 index.html:
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Mini Plane Shooter</title>
<style>
canvas{background:#000;display:block;margin:auto}
</style>
</head>
<body>
<canvas id="game" width="400" height="600"></canvas>
<script>
const canvas = document.getElementById("game")
const ctx = canvas.getContext("2d")
let player = {x:180,y:520,w:40,h:40,speed:5}
let bullets=[]
let enemies=[]
let keys={}
document.addEventListener("keydown",e=>keys[e.key]=true)
document.addEventListener("keyup",e=>keys[e.key]=false)
function shoot(){
bullets.push({x:player.x+18,y:player.y,w:4,h:10})
}
setInterval(()=>enemies.push({
x:Math.random()*360,
y:-40,
w:40,
h:40,
speed:2+Math.random()*2
}),1000)
setInterval(shoot,300)
function movePlayer(){
if(keys["ArrowLeft"]) player.x-=player.speed
if(keys["ArrowRight"]) player.x+=player.speed
if(keys["ArrowUp"]) player.y-=player.speed
if(keys["ArrowDown"]) player.y+=player.speed
}
function updateBullets(){
bullets.forEach(b=>b.y-=8)
bullets=bullets.filter(b=>b.y>-20)
}
function updateEnemies(){
enemies.forEach(e=>e.y+=e.speed)
enemies=enemies.filter(e=>e.y<620)
}
function collide(a,b){
return a.x<b.x+b.w &&
a.x+a.w>b.x &&
a.y<b.y+b.h &&
a.y+a.h>b.y
}
function checkHits(){
bullets.forEach((b,bi)=>{
enemies.forEach((e,ei)=>{
if(collide(b,e)){
bullets.splice(bi,1)
enemies.splice(ei,1)
}
})
})
}
function drawRect(o,color){
ctx.fillStyle=color
ctx.fillRect(o.x,o.y,o.w,o.h)
}
function draw(){
ctx.clearRect(0,0,400,600)
drawRect(player,"cyan")
bullets.forEach(b=>drawRect(b,"yellow"))
enemies.forEach(e=>drawRect(e,"red"))
}
function gameLoop(){
movePlayer()
updateBullets()
updateEnemies()
checkHits()
draw()
requestAnimationFrame(gameLoop)
}
gameLoop()
</script>
</body>
</html>
打开浏览器即可运行。
三、核心原理拆解
整个游戏其实只有 5 个模块。
1 玩家飞机
javascript
let player = {x:180,y:520,w:40,h:40,speed:5}
控制移动:
javascript
if(keys["ArrowLeft"]) player.x-=player.speed
2 子弹系统
子弹是一个数组:
javascript
let bullets=[]
定时发射:
javascript
setInterval(shoot,300)
子弹每一帧向上移动:
javascript
bullets.forEach(b=>b.y-=8)
3 敌机系统
敌机会随机生成:
javascript
setInterval(()=>enemies.push({
x:Math.random()*360,
y:-40,
w:40,
h:40,
speed:2+Math.random()*2
}),1000)
4 碰撞检测
经典 AABB 碰撞检测:
javascript
a.x < b.x + b.w &&
a.x + a.w > b.x &&
a.y < b.y + b.h &&
a.y + a.h > b.y
只要矩形重叠就算碰撞。
5 游戏循环
核心循环使用:
javascript
requestAnimationFrame(gameLoop)
每一帧执行:
更新玩家
更新子弹
更新敌机
检测碰撞
重新渲染
四、为什么 91 行就能做游戏?
小游戏本质其实很简单:
| 模块 | 作用 |
|---|---|
| 输入系统 | 键盘控制 |
| 游戏对象 | 飞机 / 子弹 / 敌机 |
| 更新逻辑 | 每帧更新位置 |
| 碰撞检测 | 判断是否击中 |
| 渲染 | Canvas 绘制 |
早期很多 HTML5 Demo 游戏 甚至只有 100 行左右代码。
五、可以继续扩展什么?
如果继续扩展,可以增加:
- 分数系统
- 爆炸动画
- 多种敌机
- BOSS
- 游戏结束界面
- 音效
再多写 100 行,基本就能做出一个完整小游戏。
六、总结
只用 91 行代码,我们就实现了一个最简版「打飞机游戏」。
关键技术只有:
- HTML5 Canvas
- JavaScript
requestAnimationFrame- 碰撞检测
很多时候:
游戏并不复杂,复杂的是我们的想象。