从 Canvas 到 Vibe Coding:HTML5 游戏开发入门与 AI 飞机大战实战
- 前言
- [一、HTML5 与 Canvas](#一、HTML5 与 Canvas)
-
- [什么是 Canvas?](#什么是 Canvas?)
- [Canvas 的降级机制](#Canvas 的降级机制)
- 二、获取绘图上下文
- [三、Canvas 基础绘图](#三、Canvas 基础绘图)
-
- [fillStyle 与 fillRect](#fillStyle 与 fillRect)
- [Canvas 坐标系](#Canvas 坐标系)
- [strokeRect 绘制边框矩形](#strokeRect 绘制边框矩形)
- [clearRect 的作用](#clearRect 的作用)
- [四、Canvas 动画原理](#四、Canvas 动画原理)
- [五、requestAnimationFrame 详解](#五、requestAnimationFrame 详解)
-
- [为什么不用 setInterval?](#为什么不用 setInterval?)
- [六、使用 AI 开发飞机大战小游戏](#六、使用 AI 开发飞机大战小游戏)
-
- 为什么这样设计提示词
- [MVP 思想](#MVP 思想)
- [Vibe Coding 的意义](#Vibe Coding 的意义)
- 总结
前言
提起网页游戏,很多人的第一印象可能是曾经风靡一时的 4399 Flash 小游戏。
在 Flash 时代,大量网页游戏依赖 Adobe Flash Player 运行。但随着浏览器标准的发展以及 Flash 在性能、安全性等方面问题的逐渐暴露,HTML5 逐渐成为新的技术方案。
如今我们看到的许多网页小游戏、在线绘图工具、数据可视化大屏甚至 3D 场景展示,背后都离不开 HTML5 提供的图形能力。其中最重要的技术之一便是 Canvas 画布。
通过 Canvas,开发者可以直接使用 JavaScript 操作像素,在浏览器中绘制图形,实现动画效果,甚至开发完整的网页游戏。
本文将从 Canvas 基础绘图 开始,逐步理解浏览器动画机制,并结合当前流行的 Vibe Coding 开发模式,借助 AI 实现一个简单的飞机大战小游戏。
一、HTML5 与 Canvas
什么是 Canvas?
Canvas 是 HTML5 提供的一个绘图容器,它允许开发者通过 JavaScript 直接进行图形绘制。
与普通 HTML 元素不同,Canvas 本身并不会自动显示内容,它更像是一张空白画布。开发者需要通过 JavaScript 提供的 API 在这块画布上绘制各种图形。
创建一个 Canvas 元素十分简单:
html
<canvas id="myCanvas" width="600" height="400"
style="border: 1px solid #333;">
</canvas>
运行后浏览器会显示一个宽度为 600px、高度为 400px 的绘图区域。
需要特别注意的是:
html
width="600"
height="400"
这里指定的是 Canvas 的 实际绘图分辨率。
很多初学者会习惯这样写:
css
canvas{
width:600px;
height:400px;
}
虽然视觉上尺寸发生了变化,但 Canvas 内部坐标系并不会同步改变,因此实际开发过程中应优先使用标签属性指定尺寸。
Canvas 的降级机制
html
<canvas id="myCanvas" width="600" height="400"
style="border: 1px solid #333;">
你的浏览器不支持Canvas(旧IE会显示这段文字)
</canvas>
对于现代浏览器来说,这段提示文字不会显示。
但如果浏览器无法识别 canvas 标签,那么标签内部的内容就会被正常渲染出来。
这就是 Canvas 的兼容性降级机制。
二、获取绘图上下文
Canvas 本身只是一个容器。
真正负责绘图的是 Canvas 提供的 绘图上下文(Context)。
代码如下:
js
const canvas = document.querySelector('#myCanvas');
const ctx = canvas.getContext('2d');
首先通过:
js
const canvas = document.querySelector('#myCanvas');
获取 Canvas 元素。
随后通过:
js
canvas.getContext('2d');
获取二维绘图环境。
这里返回的实际上是一个:
text
CanvasRenderingContext2D
对象。
后续所有绘图操作,例如:
js
fillRect()
strokeRect()
clearRect()
arc()
lineTo()
都需要通过这个对象完成。
因此:
js
ctx
可以理解为开发者手中的一支画笔。
如果传入的是:
js
canvas.getContext('webgl');
则会获取 WebGL 上下文,从而调用 GPU 能力进行三维图形渲染。
近年来 AI 游戏、数字孪生、3D 可视化等方向快速发展,也让 Three.js 等框架越来越受欢迎。
三、Canvas 基础绘图
下面来看第一个案例。
js
const canvas=document.querySelector('#myCanvas');
const ctx=canvas.getContext('2d');
ctx.fillStyle='#4299e1';
ctx.fillRect(20,20,100,80);
ctx.strokeStyle='#f565656';
ctx.lineWidth=4;
ctx.strokeRect(150,20,100,80);
ctx.clearRect(50,50,40,30);

虽然代码不长,但已经涵盖了 Canvas 最常用的几个 API。
fillStyle 与 fillRect
首先设置填充颜色:
js
ctx.fillStyle='#4299e1';
fillStyle 用于指定图形内部填充颜色。
随后绘制矩形:
js
ctx.fillRect(20,20,100,80);
参数格式如下:
js
fillRect(x,y,width,height)
对应含义:
| 参数 | 作用 |
|---|---|
| x | 横坐标 |
| y | 纵坐标 |
| width | 宽度 |
| height | 高度 |
因此:
js
ctx.fillRect(20,20,100,80);
表示从 (20,20) 开始绘制一个宽度为 100px、高度为 80px 的矩形。
Canvas 坐标系
这里需要理解一个重要概念。
Canvas 的坐标系与数学坐标系不同。
Canvas 的原点位于:
text
左上角 (0,0)
坐标增长方向如下:
text
→ x轴增大
↓ y轴增大
因此:
js
fillRect(20,20,100,80);
实际上表示:
text
向右偏移20像素
向下偏移20像素
的位置开始绘制图形。
这一点在后续游戏开发中十分重要。
strokeRect 绘制边框矩形
除了实心矩形之外,还可以绘制边框矩形。
首先设置边框颜色:
js
ctx.strokeStyle='#f565656';
设置边框宽度:
js
ctx.lineWidth=4;
随后绘制边框矩形:
js
ctx.strokeRect(150,20,100,80);
与:
js
fillRect()
不同:
text
fillRect() 绘制实心矩形
strokeRect() 绘制空心矩形
两者分别用于不同的绘图场景。
clearRect 的作用
最后执行:
js
ctx.clearRect(50,50,40,30);
用于清除指定区域。
参数格式:
js
clearRect(x,y,width,height)
需要特别强调的是:
clearRect()并不是简单地将区域涂成白色。
而是直接删除对应区域中的像素内容,使其恢复透明状态。
这个 API 在动画开发中极其重要。
因为后续所有游戏动画都离不开它。
四、Canvas 动画原理
静态图形只是 Canvas 最基础的能力。
真正让网页游戏动起来的是动画机制。
案例代码如下:
js
let x=20;
const y=20;
const width=100;
const height=80;
const speed=3;
function animate(){
ctx.clearRect(
0,
0,
canvas.width,
canvas.height
);
ctx.fillStyle='#4299e1';
ctx.fillRect(
x,
y,
width,
height
);
x += speed;
if(x > canvas.width){
x = -width;
}
requestAnimationFrame(animate);
}
animate();


游戏对象的状态
这里新增了几个变量:
js
let x=20;
const speed=3;
矩形的位置并不是固定的。
而是由变量控制。
每执行一次:
js
x += speed;
矩形就会向右移动。
实际上在游戏开发中,所有对象都拥有自己的状态。
例如:
js
飞机
{
x,
y,
speed
}
js
敌机
{
x,
y,
hp
}
js
子弹
{
x,
y,
damage
}
游戏运行的本质,就是不断更新这些状态。
为什么必须清空画布
动画开始时首先执行:
js
ctx.clearRect(
0,
0,
canvas.width,
canvas.height
);
如果省略这一句。
第一次绘制:
text
x=20
第二次:
text
x=23
第三次:
text
x=26
浏览器会保留之前所有图像。
最终形成长长的拖影。
因此动画开发遵循固定流程:
text
清空画布
↓
更新状态
↓
重新绘制
边界检测
代码中还有这样一段逻辑:
js
if(x > canvas.width){
x = -width;
}
当矩形完全离开画布右侧时:
text
x > canvas.width
成立。
此时:
js
x = -width;
会将矩形放置到画布左侧之外。
随后重新进入屏幕。
形成循环移动效果。
五、requestAnimationFrame 详解
动画最核心的一行代码是:
js
requestAnimationFrame(animate);
这是浏览器提供的高性能动画调度函数。
它会在下一次屏幕刷新时自动执行指定函数。
从而形成:
text
animate
↓
requestAnimationFrame
↓
animate
↓
requestAnimationFrame
不断循环。
这就是游戏开发中的 Game Loop(游戏循环)。
为什么不用 setInterval?
很多初学者可能会想到:
js
setInterval(animate,16);
理论上:
text
1000 ÷ 60 ≈ 16.67ms
似乎能够达到 60FPS。
但实际上存在很多问题。
- 时间不准确
浏览器任务繁忙时:
text
16ms
↓
20ms
↓
30ms
都有可能出现。
- 无法同步显示器刷新率
现代显示器可能是:
text
60Hz
120Hz
144Hz
而 setInterval() 无法自动适配。
- 后台资源浪费
用户切换标签页后。
setInterval() 仍然可能继续执行。
持续消耗系统资源。
而 requestAnimationFrame() 会:
text
同步显示器刷新率
自动优化性能
后台自动降频
提高动画流畅度
因此成为现代前端动画开发的标准方案。
六、使用 AI 开发飞机大战小游戏
掌握 Canvas 绘图和动画原理之后,我们便可以尝试开发一个完整的小游戏。
为了将更多精力放在需求设计与功能验证上,本项目采用当前流行的 Vibe Coding 模式,通过 Claude 辅助完成开发。
使用的提示词如下:
text
1.我使用vite生成一个原生js项目。
2.用原生HTML Canvas写一个打飞机小游戏:
1、底部玩家飞机,方向键上下左右移动,边界限制
2、空格键发射子弹,子弹向上飞行
3、顶部随机生成敌机向下移动
4、子弹击中敌机销毁并加分,敌机碰到玩家游戏结束
5、用requestAnimationFrame做游戏循环,全部绘制在canvas里,不要引入第三方游戏引擎

为什么这样设计提示词
可以发现。
我们并没有直接要求 AI:
text
写一个飞机大战
而是明确规定了:
- 技术栈
- 功能需求
- 实现方式
- 限制条件
例如:
text
Vite
原生JavaScript
Canvas
requestAnimationFrame
这些约束能够帮助 AI 输出更加符合预期的代码结构。
如果需求描述过于模糊,AI 很可能会引入额外框架,甚至采用完全不同的技术方案。
MVP 思想
飞机大战之所以成为经典练手项目。
是因为它能够覆盖游戏开发中的多个核心知识点:
- Canvas绘制
- 键盘事件
- 对象状态管理
- 随机生成
- 碰撞检测
- 积分系统
- 游戏循环
同时项目规模又足够简单。
这符合软件开发中的:
MVP(Minimum Viable Product)
即:
最小可行产品。
先完成能玩的版本。
再考虑技能系统、排行榜、商店系统等高级功能。
Vibe Coding 的意义
传统开发模式:
text
查资料
设计架构
编写代码
调试实现
Vibe Coding 模式:
text
定义需求
设计提示词
AI生成代码
测试与迭代优化
开发者逐渐从代码编写者转变为需求设计者和系统验证者。
AI 不会取代开发者。
但会成为开发过程中的重要生产力工具。
总结
Canvas 是 HTML5 提供的重要图形能力,它让浏览器具备了绘制图形、制作动画甚至开发游戏的能力。
通过本文的学习,我们依次了解了:
- Canvas 的基本概念
- 绘图上下文的获取方式
- fillRect、strokeRect、clearRect 等基础 API
- 浏览器动画的实现原理
- requestAnimationFrame 的工作机制
- Game Loop 游戏循环思想
- 基于 AI 的飞机大战项目开发流程
从静态图形到动态动画,再到完整的小游戏开发,我们能够发现:
游戏本质上只是"状态更新 + 画面重绘"的不断循环。
而在 AI 时代,借助 Vibe Coding,我们可以将更多精力放在需求设计和创意实现上,从而更加高效地完成项目开发。