从 Canvas 到 Vibe Coding:HTML5 游戏开发入门与 AI 飞机大战实战

从 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 开发飞机大战小游戏)
  • 总结

前言

提起网页游戏,很多人的第一印象可能是曾经风靡一时的 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。

但实际上存在很多问题。

  1. 时间不准确

浏览器任务繁忙时:

text 复制代码
16ms
↓
20ms
↓
30ms

都有可能出现。


  1. 无法同步显示器刷新率

现代显示器可能是:

text 复制代码
60Hz
120Hz
144Hz

setInterval() 无法自动适配。


  1. 后台资源浪费

用户切换标签页后。

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,我们可以将更多精力放在需求设计和创意实现上,从而更加高效地完成项目开发。

相关推荐
lichenyang4531 小时前
鸿蒙 Web 容器(一):怎么把一个 H5 页面嵌进鸿蒙页面?
前端
把你拉进白名单1 小时前
7.OpenClaw源码解析——可靠消息投递
人工智能·llm·agent
劈星斩月2 小时前
机器学习之 定义与三大范式
人工智能·机器学习·监督学习·强化学习·无监督学习
触底反弹2 小时前
🎨 通义万相实战:用 Qwen 多模态 API 实现 AI 换装换姿势,10 行代码搞定!
vue.js·人工智能
属鼠哥2 小时前
一场正在发生的范式转变:Loop Engineering(循环工程)
人工智能·aiops
码农小旋风2 小时前
Claude Code 基础用法大全:对话、分析、修改、测试、Git 和工作流
人工智能·git·chatgpt·claude
Solis程序员2 小时前
MCP (Model Context Protocol):AI应用连接外部世界的标准协议
人工智能·microsoft·agent·skill·mcp
贵慜_Derek2 小时前
《从零实现 Agent 系统》连载 29|多 Agent 研究 Harness:Lead、Worker 与 Spawn
人工智能·架构·agent
枫子有风2 小时前
AI编程-Vibe coding(大厂常问问题)
人工智能·ai编程