序:为什么从零写一个 2D 运行时
如果只从「能不能做出游戏」这个角度看,2026 年学 2D 游戏开发,几乎没有任何理由从零写引擎。Cocos Creator、Unity、Godot 都已经足够成熟:拖一个节点、挂一个组件、点一下运行,屏幕上就有了画面。Cocos Creator 3.8 还能一键把游戏发布到 H5、微信小游戏和原生平台,你真正要操心的只是把玩法写出来。
这本书却选了一条看起来最绕的路:先用 TypeScript 从零手写一个能跑、能测、能截图的 2D 运行时 mini2d,再用 Cocos Creator 3.8 把同一款游戏做一遍。
为什么?这篇序想认真回答这个问题。它不打算说服所有人,只想把这条路的动机、代价和取舍讲清楚,让你在翻开第 1 章 1.1 之前,就知道自己要付出什么、又能换回什么。
引擎替你做的,恰恰是你最该理解的事
先把一个现象摆出来。你在 Cocos 里拖一个 Sprite 节点,它会出现在屏幕上。看起来只发生了一件事,实际上背后至少发生了七八件:
| 你以为发生的事 | 引擎实际替你做的事 |
|---|---|
| 图片显示出来了 | 纹理被上传到 GPU,并归入了某个批次 |
| 节点在正确的位置 | 父节点的世界变换被逐级乘进了局部坐标 |
| 它在其他东西前面 | 渲染队列按层级与材质排了序 |
| 点它能响应 | 命中测试把屏幕坐标换算成了节点本地坐标 |
| 动画很顺 | 一个基于 deltaTime 的更新循环在每帧推进它 |
| 帧率稳定 | 逻辑更新与渲染被固定步长解耦 |
| 切场景没卡顿 | 资源按依赖图异步加载,并做了引用计数 |
这些事引擎都做得很好,而且比你第一次写的版本好得多。问题在于:它们被封装进了你从未打开过的源码里。 你调用 node.setPosition(x, y) 的时候,并不需要知道世界坐标是怎么算出来的;你也不会知道,当场景里节点数量涨到几千个时,哪一步会先成为瓶颈。
封装本身不是坏事——正是封装让「做一个游戏」从几个月缩短到几天。但如果你的目标是判断力,而不只是产出,封装就成了障碍:你无法对一个看不见的东西做出判断。
判断力只能靠亲手实现来获得
「判断力」这个词有点抽象,不如换成三个具体的问题:
- 当游戏在低端机上掉帧时,你知道该去查渲染、逻辑还是资源加载吗?
- 当某个 API 用起来「手感不对」时,你能说出它为什么会这样设计吗?
- 当两个方案摆在面前时,你能判断哪个更适合当前规模,而不是凭喜好选吗?
这三个问题的答案,都不会写在引擎文档里。文档告诉你怎么用,不会告诉你为什么这么用、什么时候会失效。而这些东西,只有在你自己实现过一遍、踩过一遍坑之后,才会变成直觉。
亲手写一遍的价值,不在于你写的引擎能打败 Cocos——它当然不能。价值在于:当你在 Cocos 里再次遇到「一帧是怎么开始的」「坐标是怎么换算的」「纹理是怎么合批的」这些问题时,你脑子里有一个自己搭过的模型可以对上号。 你不再是在调一个黑箱,而是在操作一个你能解释的东西。
为什么是现在:引擎越成熟,判断力越值钱
你可能会说:这些道理十年前也成立,为什么现在专门写一本书来讲?
因为行业的重心变了。十年前,「能不能做出来」本身就是门槛——你会不会写引擎、会不会用引擎,决定了你能不能被录用。今天,做出一个能跑的原型已经变得非常便宜:引擎足够成熟,模板足够多,连代码本身都可以由 AI 助手生成一大半。
当「生成」变便宜的时候,稀缺的东西就换成了判断:判断这段生成的代码是不是真的对、判断掉帧的原因到底在哪、判断这个方案能不能撑到上线。判断力没法被生成,它只能来自理解。而理解,最可靠的来源就是亲手实现过一遍。
这个逻辑和本书的姊妹书稿是一致的:工具让「写出能跑的代码」变便宜了,但没有让「判断它可不可靠」变便宜。 你越懂引擎内部是怎么转的,工具就越有用。
从零实现意味着什么:mini2d 会长成什么样
说了这么多「从零写」,具体写成什么样?先给一个轮廓,好让你心里有底。
mini2d 是一个纯 TypeScript、零 cc 依赖的 2D 运行时,渲染直接落在浏览器原生的 Canvas2D 上,不引入任何现成的游戏库。它按模块组织:时间与循环、渲染与坐标变换、场景图、输入、物理与碰撞、动画、音频、资源、UI、状态与存档、测试工具。每一章新增一个模块,代码是累积的——第 18 章的 mini2d 里,还留着第 1 章写下的那个主循环,只是它长大了。
它不会长成一个通用引擎。没有编辑器、没有可视化场景、没有跨平台打包、性能也谈不上顶尖。它只有两个目标:能被读懂,能被跑通。 前者靠克制——每个模块都短到能一口气读完;后者靠测试——每一节新增的逻辑都有对应的单测或截图断言。
到卷一结束时,mini2d 上跑着的《方块冲刺》已经是一个能打包、能多端发布、带测试的完整小游戏。它不大,但它是你自己的——从主循环到存档格式,每一行你都能解释。
本卷的写法:从零实现,但每章都对照 Cocos
需要先强调:这不是一本「自研引擎教程」,也不是一本「Cocos 用法手册」。它是两者的一种结合。
每一章都分两条腿走路。 前两节用 mini2d 从零实现某个机制,末节做「Cocos 对照」——把「你刚写的这段代码」和「Cocos 3.8 里的哪个模块、哪个 API」一一对上号。到第 18 章,你会把同一款游戏《方块冲刺》的两套实现——mini2d 版和 Cocos 版——并排放在一起看,并整理出一份迁移清单。
这样安排的好处是,你既拿到了原理,又拿到了工具:
| 只读 Cocos 文档 | 只写自研引擎 | 本卷的写法 |
|---|---|---|
| 知道 API 怎么调 | 知道机制怎么实现 | 既懂实现,又懂引擎怎么封装它 |
| 遇到瓶颈无从下手 | 不知道工业级怎么解决 | 能对照两者的取舍 |
| 上手快,天花板低 | 理解深,落地难 | 理解与落地兼顾 |
那一刻,前面十七章的对照会全部收拢成一句话:引擎不是魔法,是一堆你也能写出来、只是写得更好的决定。
18 章会带你走多远
也许你会好奇:这 18 章具体会经历什么?给一张路线图,你就知道每一步在解决什么问题。
| 阶段 | 章节 | 你会做出什么 |
|---|---|---|
| 地基 | 第 1–3 章 | 一个能跑的主循环,和能画出方块的渲染器 |
| 时间、输入与对象 | 第 4–6 章 | 帧率无关的运动、跟手的输入、可组合的组件 |
| 表现 | 第 7–11 章 | 碰撞、动画、声音、资源加载、UI 布局 |
| 系统与玩法 | 第 12–14 章 | 状态机、存档、AI、数值与掉落 |
| 质量与交付 | 第 15–18 章 | 调试工具、测试体系、打包发布、两套实现对照 |
这条路线不是随便排的。没有主循环,输入就无处安放;没有坐标系,碰撞就无从谈起;没有资源管理,UI 就加载不出图。每一章都在为下一章铺路,这也是为什么跳章会比想象中更容易卡住。
到第 18 章,你会做两件事:把 mini2d 版的《方块冲刺》和 Cocos 版的并排放在一起看,然后整理一份「从 mini2d 迁移到 Cocos Creator」的清单。那份清单,其实就是整卷内容的收束——它把「你亲手写过的机制」和「引擎替你封装的模块」一条条对上号。
为什么是《方块冲刺》
贯穿全书的项目叫《方块冲刺》——一款 2D 横版跑酷小游戏:玩家操控一个方块向右冲刺,跳过障碍、吃金币、捡道具,跑得越远分越高。
选它,是因为它体量小到能从零写完,又覆盖了 2D 游戏的全部关键面:
| 玩法要素 | 牵出的技术点 | 对应章节 |
|---|---|---|
| 方块跑跳 | 帧循环、固定步长、输入手感 | 1、4、5 |
| 障碍与金币 | 碰撞检测、宽相、触发器 | 7 |
| 关卡随距离推进 | 数据驱动、程序化生成 | 6、13 |
| 金币与道具 | 数值、掉落、经济 | 14 |
| 得分与结算 | 结算管线、UI 与存档 | 11、12、14 |
| 多端发布 | 构建、分包、平台适配 | 17 |
如果换一个更复杂的项目——比如一个带战斗的 RPG——你会在前几章就陷入玩法细节,反而看不清引擎机制。跑酷的好处是:它足够简单,简单到你全部的注意力都能放在「一帧是怎么转的」这件事上。
三层可运行性:把「不能跑」也如实写出来
写这类书最大的诚实问题在于:Cocos Creator 是一个 GUI 编辑器,它的运行时不在 npm 上,命令行里装不了、也跑不起来。
这意味着本书里必然有一部分内容,读者无法像跑一段 Node 脚本那样一键复现。很多教程的做法是把这部分含糊过去,让人误以为「照着敲就能跑」。本卷不这么做,而是把可运行性明确分成三层,写进目录页 ,也写在每一节里:
| 层 | 内容 | 能否真跑 | 怎么验证 |
|---|---|---|---|
| L1 | mini2d 从零实现(纯 TypeScript,零 cc 依赖) | 能真跑 | Node + vitest 单测、Playwright 无头截图 |
| L2 | Cocos 组件脚本(import { X } from 'cc') | 能真做类型检查 | tsc --noEmit 对 @cocos/creator-types@3.8.8 |
| L3 | Cocos 工程文件(.scene / .prefab / .meta) | 不能命令行复现 | 结构校验;正文显式标注「需编辑器」 |
这份表格对应三条写作铁律:
- 运行验证全部落在 L1。 你看到的每一段
mini2d代码,都是在 Node 里跑过、在浏览器里画过、被单测断言过的。 - L2 的每个
cc符号都必须真实存在。 写每一个 API 之前都先查引擎的cc.d.ts,绝不凭记忆写。 - L3 的「不能跑」本身也是内容。 正文会告诉你「在编辑器里打开会看到什么」,而不是假装它能命令行复现。
你可能会觉得「三层」这种说法有点啰嗦。但它解决的是一个真实痛点:读者花时间敲了一段代码,跑不起来,然后开始怀疑是书错了还是自己错了。把边界提前划清楚,你就不会把时间浪费在「为什么跑不了」上。
三个常见误解
到这一步,大概有三个问题会冒出来。它们都很合理,值得正面回答。
误解一:学 Cocos,为什么要写引擎?
这是最直接的疑问:我的目标是会用 Cocos,为什么要先去写一个看起来用不上的东西?
答案在前两节已经铺垫过:因为「会用」的天花板,取决于你理解多深。 一个只会调 API 的人,遇到引擎没提供现成方案的需求时就会卡住;而一个理解循环、坐标、合批、资源生命周期的人,能把引擎当成一堆可以组合的积木。
更重要的是,Cocos 的组件体系本身就有不少「约定」——为什么组件的生命周期有固定顺序、为什么 update 和 lateUpdate 要分开、为什么资源要手动释放。这些约定在从零实现里都能找到原型。写过一遍,你就不需要靠死记硬背来遵守它们,因为你亲眼见过它们解决了什么问题。
误解二:这是不是在造轮子?
「造轮子」通常指:明明有成熟方案,却偏要自己重造一遍,浪费精力。如果这本书是让你用一个自研引擎去发布商业游戏,那确实是造轮子。
但它不是。mini2d 是一个教具:它的作用是把引擎的机制摊开给你看,让你在最短的代码里看懂一件事是怎么运作的。教具不需要性能顶尖、不需要功能齐全,只需要透明——每一处实现都能被你读懂、被你改坏、再被你修好。
真正的产出,仍然是 Cocos 版的那款游戏。mini2d 负责让你理解,Cocos 负责让你交付。分工明确,就不算造轮子。
误解三:能不能跳过 mini2d,直接学 Cocos?
可以,而且这是本卷明确提供的路径。
目录页
给了三条读法:路径 A 完整走完 18 章、亲手敲 mini2d;路径 B 只读每章末节的 Cocos 对照、把 mini2d 当注解;路径 C 按问题随手查。如果你时间紧、只想尽快上手引擎,路径 B 就够了——但代价是牺牲一部分「知其所以然」,而且越往后越明显。
我的建议是:即使走路径 B,也至少完整读第 4 章 (时间与更新)和第 7 章 (物理与碰撞)。这两处最容易在引擎里「用错了也不知道」——角色移动速度随帧率变化、物理偶尔穿墙,都是只看文档很难意识到的坑。
这份取舍的代价
一份诚实的动机说明,也应该讲清代价。选这条路,你会失去三样东西:
| 代价 | 具体表现 | 我的看法 |
|---|---|---|
| 时间 | 同样学「怎么让角色动起来」,你多花了一倍时间写引擎 | 多花的时间换的是可迁移的理解,值得 |
| 直观 | mini2d 没有可视化编辑器,改参数要改代码、重跑 | 恰恰因此你会更清楚每个参数在做什么 |
| 完成度 | 前十七章你手里没有一个「像样」的游戏,只有一堆模块 | 第十八章会把它们收拢成完整作品 |
如果你只想要一个能立刻发布的小游戏,这条路的性价比确实不高——直接用 Cocos 跟着官方教程走更快。这本书服务的是另一种目标:你想要的不是这一个游戏,而是做下一个游戏时的底气。
与站内既有专题的分工
本站的游戏开发主题已经积累了一千多篇文章,覆盖客户端、服务端、发行与行业等方向,另有若干套围绕自研引擎与图形学的书稿。它们质量不低,但有一个共同的特点:每一篇都假设你已经理解某个机制是什么,然后带你在一个点上钻深。
这恰恰是它们对初学者不够友好的地方。一个连「一帧为什么是固定步长」都还没想清的人,去读一篇讲渲染管线优化的文章,收获会很有限——不是因为文章写得不好,而是因为缺了前置的那一层。这些文章串起来,像是一排深井,每口井都很深,但井与井之间没有路。
这本书要补的就是这条路:一条从零到能交付的递进路径。它从「一帧怎么开始」讲起,经过渲染、输入、组件、碰撞、动画、资源、UI,一路走到状态、存档、测试与打包,最后用一个完整项目收尾。读完它,你再去读那些专题文章,才能真正读出味道来。两者是互补关系:本书负责按顺序搭起一台引擎,专题负责就一个问题钻到底。
为什么不直接教你用引擎
有人会问:既然最终要交付的是 Cocos 版,为什么不干脆从 Cocos 讲起,把 mini2d 省掉?
因为**「先会用」和「先理解」是两种不同的学习曲线**。从 Cocos 讲起,你确实能更快看到画面,但你会先记住一堆「要这么做」的规则,却不知道它们为什么成立。当规则之间发生冲突,或者引擎没有提供现成方案时,你会失去方向。
从 mini2d 讲起,是先建立一套自己的模型,再用它去理解引擎的规则。这样一来,每一条规则在你眼里都不是「规定」,而是「某个问题的一种解」。你会知道它解决了什么、代价是什么、什么情况下会失效。
代价当然存在:前几章你看到的画面会比直接学 Cocos 简陋得多。但请记住,这本书卖的不是「快速出画面」,而是「长久能判断」。如果你追求的是前者,官方教程是更好的选择;如果你要的是后者,那么这段「简陋期」是必须付出的学费。
关于「读懂」与「会写」
在序的末尾,还有一件事必须提醒:这本书默认你会动手,而不只是阅读。
游戏开发和很多技术领域一样,特别容易制造「我明白了」的错觉。你看别人写的一段主循环,每一步都合理,读起来毫不费力;但合上书,让你从空白文件开始写一个能跑的循环,你可能连第一行都犹豫。这种「读得懂、写不出」的状态,是入门阶段最常见的陷阱。
所以本卷的每一节,都请你把代码敲一遍,而不是复制粘贴、更不是只读一遍。敲的过程会让你遇到那些「看起来对、其实差一点」的地方——少了一个 deltaTime、坐标少转了一次、资源忘了释放。这些细节,只有在键盘上才会暴露出来。
如果你时间实在紧,至少要保证一件事:每一章的末节(Cocos 对照)要自己走一遍,并且动手改一处参数、看一处变化。 只是读,你得到的是知识;动手改,你得到的才是手感。
一份最小的心智模型
如果要在开始前,用几句话概括 2D 游戏引擎的世界观,可以是这样:
- 一切从一帧开始:游戏本质上是「读输入、更新状态、画出来」的循环,把这三步拆清楚,剩下的都是它的延伸。
- 时间是第一公民:所有运动都要乘上
deltaTime,物理要跑在固定步长上,暂停与慢动作本质是缩放时间。 - 坐标系要统一:屏幕、世界、节点本地三套坐标之间要能自由换算,否则输入与渲染永远对不上。
- 绘制有代价:每个 Draw Call 都要花钱,合批的条件是「同样的材质、连续的顺序」,理解了才知道该怎么排。
- 资源有生命周期:加载了就要能释放,引用计数是避免「切场景后内存一直涨」的关键。
这五条会在全书反复出现。你不需要现在就完全理解它们,但记住这几句话,读后面的章节时会更有方向感。
给不同起点的读者
不同背景的人读这本书,路径应该是不一样的。
如果你有编程基础但没写过游戏,这本书就是为你写的。请按顺序读,不要跳章。第 1 章先让你理解「一帧」这件事,第 2、3 章把画面画出来、把场景组织起来,第 4 章之后才进入时间、输入与对象。每一节的示例都请亲手敲一遍——对第一次写游戏的人来说,「跑通」比「读懂」重要得多。
如果你用过 Unity 或 Godot,你可以读得很快,但要特别留意三处引擎之间差异最大的地方:坐标系与 y 轴方向(第 1、2 章)、组件生命周期的顺序(第 6 章)、资源的引用计数(第 10 章)。这三处想通了,你就能把旧经验平滑地迁移到 Cocos;想不通,则会一直觉得「Cocos 的手感和别的引擎不太一样」。
如果你是前端开发者,你的优势在 TypeScript 与 Canvas,短板在游戏工程经验。请重点关注第 4 章(时间与更新)、第 5 章(输入手感)与第 12 章(状态与存档)——这三块是 Web 开发里几乎不会遇到、却决定游戏好不好玩的部分。
如果你关注的是引擎内部原理,第 3 章(场景图与批处理)、第 7 章(碰撞与宽相)、第 10 章(资源与引用计数)信息密度最高。但请先读完第 1、2 章把坐标系立稳——后面所有的机制都建立在那一套坐标约定之上。
一个反复出现的提醒:能跑不等于对
在正式进入正题之前,有一个观念必须提前建立:画面看起来对,不等于逻辑真的对。
看一个具体现象:一个角色在 60 帧的机器上移动速度正常,换到 30 帧的设备上却慢了一半。画面看起来「还是在动」,不会报错,也不会崩溃——但它错了。这类问题不会在启动时暴露,只会安静地在某些设备上给出错误的结果,直到玩家投诉才被发现。
正确的定位应该是:「能动」只是最低门槛,正确性要靠确定性测试(第 16 章)、固定步长(第 4 章)与显式的坐标约定(第 1、2 章)共同保证。 带着这个定位去读后面的章节,你会更容易理解为什么本书既要讲「怎么把画面画出来」,也要讲「怎么把它测出来、看住它」。
读完这一卷,你手里会有什么
读完卷一,你应该拿到三样东西:
- 一个能跑的运行时。
mini2d不是零散片段,而是一个有模块划分、有测试、能打包的完整 2D 运行时。 - 一款完整的游戏。 《方块冲刺》在它上面跑起来,能存档、能结算、能发布到多个平台。
- 一套可迁移的判断力。 你理解了 2D 游戏的底层机制,这让你在用任何引擎时都更有底气。
这三样东西里,第三样最难量化,也最重要。前两样可能会随版本过时,第三样不会。
这本书不适合谁
一份诚实的取舍,也应该说清它不服务谁。如果你属于下面几类,这本书可能不是最合适的选择:
- 想找一本 Cocos Creator 的速查手册:本书从零讲机制,不按 API 分类组织。你需要的是官方文档,不是这本书。
- 想两周内上线一款商业游戏:卷一的目标是打地基,不是快速交付。想立刻发布的人,会觉得它「绕远」。
- 只想读、不想写:全书默认你动手敲代码。只读不写,引擎的知识很难真正落进手里。
- 只想学编辑器操作:本卷前十七章几乎不碰编辑器,编辑器实操集中在卷二。
如果你读完上面几条反而更想继续,那说明这本书正是为你准备的。
这本书想让你带走什么
说了这么多动机和取舍,最后收束成一句:这本书的目标,是让你在离开引擎文档之后,依然能对引擎做出判断。
判断它为什么这样设计、判断它什么时候会成为瓶颈、判断两个方案哪个更适合你的项目。这些判断不会因为 Cocos 换了版本而失效,也不会因为你转去用别的引擎而作废——因为它们讲的是 2D 游戏的底层机制,而不是某一个 API 的用法。
mini2d 只是通往这份判断力的一座桥。桥本身不重要,走过去之后你手里的东西才重要。
准备好之后,就翻开第 1 章 1.1 环境与仓库骨架 开始动手吧。如果你还想先确认这本书适不适合自己,可以回到目录页 看那三条路径,或者继续读前言 。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。