经常有人问我,都2025年了,为什么还有人要把Scratch逼成游戏引擎?不瞒你说,我一度也回答不上来。但当我真正动手,把一款正经的空战射击游戏塞进这个“教小孩拖积木”的工具里,还稳定跑在接近60帧时,我才意识到:之前不是Scratch做不到,而是我们对这个东西的想象力,一直停在“课堂作业”那个层级。
三个月前,我们团队接了一个教育硬件相关的交互项目,目标平台是学校机房的老旧浏览器。要求非常苛刻:不能装插件、不能开外网、不能上重型框架,最后还必须开放给学生自己拖积木二次修改。我们盘了一圈方案,Unity WebGL太大,Godot导出到老机器上还是吃力,纯HTML5游戏倒是能跑,但学生根本没法改。兜兜转转,唯一剩下的候选者,居然是Scratch。
这篇文章不是Scratch教程,而是我们团队对这次项目的完整复盘。我会把三个月里的技术选型、架构设计、性能调优、真实踩坑,以及最后我们不得不承认的边界,全部摊开来写。如果你也在评估“用Scratch做作品到底能做到什么程度”,或者想驯服一个轻量级引擎,这篇文章应该能帮你省下至少一个月的试错时间。
1. 为什么非得跟Scratch较劲:一场被迫开始的疯狂改造
先说结论:这不是一个“我们觉得Scratch天下第一”的故事,而是一个“在约束条件下,所有体面方案全被否掉之后,只剩Scratch一个选项”的故事。
1.1 项目约束逼出来的选择
当时摆在桌面上的方案有这么几个:
- 纯Web游戏(Phaser / Cocos Creator HTML5):能跑,画质好,但学生拿不到源码入口,更别说动手改。
- Unity WebGL 导出的页面:功能强,但加载体积以MB起步,在学校机房那种性能环境下基本属于灾难。
- Godot Web导出:比Unity轻一些,但同样的二次修改问题。
- 桌面客户端:机房装软件是不可能的,学校IT管理员第一个不同意。
最后“能拖动积木、能改参数、浏览器直接打开、老电脑跑得动”这几项一叠加,Scratch几乎是唯一解。
但Scratch毕竟是Scratch。它默认是给小学生做动画、讲故事、写九九乘法表这类作品用的,跟“游戏引擎”四个字离了十万八千里。我们当时拿到手的,只是一个渲染舞台、一堆精灵角色、一个30帧左右的主循环,以及一个“碰到边缘就反弹”级别的物理系统。要在这个基础上搭出真正可玩的游戏,得先搞清楚:它能改的是什么,不能改的又是什么。
1.2 列一张“能/不能/可Hack”的摸底清单
开工之前,我们花了几天时间把Scratch 3.0的能力边界撸了一遍,大致是这样的:
| 引擎能力 | Scratch 现状 | 能不能Hack |
|---|---|---|
| 渲染 | 精灵+背景,基于Canvas/SVG | 可以,但需要改变绘制思路 |
| 帧循环 | 默认约30FPS主循环 | 能利用“运行时不刷新屏幕”做局部加速 |
| 碰撞 | 只有“碰到”相关积木,无物理引擎 | 需要自研AABB/圆形碰撞 |
| 场景切换 | “换成背景”积木 | 能搭,但要做状态管理 |
| 对象批量管理 | 克隆体,官方默认上限300 | 不够,必须列表+数据驱动 |
| 素材资源 | 逐个上传造型和声音 | 可批量,但要走脚本处理 |
| 代码组织 | 自制积木、广播消息 | 可以按模块约定,但没有私有函数 |
| 多人协作 | 官方不支持 | 必须自建资源/代码合并管线 |
这张表做出来之后,团队内部沉默了十分钟。因为几乎每一格都在说“不行”。但我们反过来想了一下:既然分解出来的问题都清清楚楚,那就意味着每个问题都有对应的拆解方案。三个月的时间,我们就是照着这张表一格一格去填的。
这个“摸底清单”的思路,后来成了整个项目最值钱的东西。因为在改Scratch的过程中,你很容易陷进“某个积木为什么这么卡”的细节里,忘记了全局。有了这张表,所有冒出来的问题都能归类到“渲染、循环、资源、逻辑”这四个桶里,定位效率完全不同。
2. 拆开sb3的壳:把“积木项目”变成可操控的代码资产
真正动手改造的第一步,不是打开Scratch编辑器拖积木,而是去拆它的文件格式。因为如果连素材和代码都没法程序化处理,后续的批量化工作根本不可能推进。
2.1 sb3文件本质上就是一个Zip压缩包
Scratch 3.0的项目文件后缀是.sb3。很多人以为它是一个专有格式,其实它就是一个标准ZIP压缩包,里面装着一个project.json加上若干素材文件。用命令行解压一下就能看到结构:
unzip my_game.sb3 -d my_game_project/ cd my_game_project ls -la你会看到类似这样的内容:
project.json cd73a1e2c3d420a01a9f9f3c0b8c2e5b.svg d41d8cd98f00b204e9800998ecf8427e.png ...其中project.json是整个项目的“大脑”,所有角色、造型、积木逻辑、舞台配置全都以JSON形式存在里面。也就是说,理论上我们可以在不打开Scratch编辑器的情况下,直接改JSON来批量修改整个项目。
2.2 用JSON直接改项目的批量操作姿势
project.json的结构并不复杂,核心是一个targets数组。每个target对应一个角色或舞台,里面包含name、blocks、costumes、sounds等字段。比如我们想给所有敌人角色统一改名,加一个“enemy_”前缀,用Python写个小脚本就够了:
import json, zipfile with zipfile.ZipFile('my_game.sb3', 'r') as z: data = json.loads(z.read('project.json')) for target in data['targets']: if target['isStage']: continue if target['name'].startswith('敌人'): target['name'] = 'enemy_' + target['name'] # 写回新的sb3 with zipfile.ZipFile('my_game_renamed.sb3', 'w') as z: # 重新打包素材文件加改后的project.json这一步的意义非常大。它意味着“批量重命名角色”“批量替换造型”“批量调整初始变量”这些在编辑器里得手动点几百下的操作,现在可以在一秒钟内完成。
我们后期甚至做了一个“换肤工具”:美术输出一套角色素材,脚本自动替换project.json里对应costumes的assetId和md5ext,几秒钟就生成一个换了主角形象的新版本。这其实就是在做Unity引擎里“人物模型替换”类似的事情——素材规范好之后,替换成本就只受限于文件命名的约定。
2.3 把素材规范成一条可复用的资源管线
从这一步开始,我们严格按引擎项目的惯例来管理素材:
- 角色命名:
spaceship_player_idle.png、spaceship_player_move.png - 动画帧后缀:
_0、_1、_2,按顺序播放。 - 背景命名:
bg_level_1、bg_boss。 - 所有素材统一PNG,透明背景。
这样做的好处是,整个项目从“美术画好图,然后一股脑拖进Scratch”变成了“美术按规格出图,脚本批量打包进sb3”。美术和程序可以并行,程序不需要等素材,美术也不需要迁就代码。这条管线,其实才是我们把Scratch当引擎用的第一块基石。
提示:如果你打算复刻这套流程,最该先做的是把
project.json里一个最简单的角色复制三份,对比JSON里哪些字段变了。搞清楚一次,你会少走很多弯路。
3. 轰出稳定帧率:渲染层和帧循环的极限压榨
拆完文件,最硬的骨头就来了:性能。Scratch默认的渲染方式,对“引擎”这个定位来说,简直是另一套生态系统里的东西。想让它在浏览器里稳定跑游戏,必须在渲染和帧循环两个方向上大改。
3.1 舞台画布480x360:先把游戏设计塞进这个分辨率
Scratch 3.0的舞台逻辑分辨率默认是480x360,这个数字没法随便改。有人会问,那做出来的游戏岂不是很小?其实不是,浏览器全屏播放时会自动拉伸缩放,关键是游戏内部所有的坐标、碰撞、UI布局都必须基于这个逻辑尺寸来设计。
我们一开始没当回事,美术给了一套1920x1080的精美UI图,放进Scratch后,界面被缩成一小坨。后来老实了,所有设计图统一按480x360出,玩家看到的实际视觉大小交给缩放解决。
这其实是“约束倒逼设计”的典型例子。习惯了Unity那种自由分辨率之后,你反而会觉得固定逻辑分辨率省了很多事——横版游戏、俯视角迷宫、空战,全都围绕这块画布设计,界面再也不会出现“四角对不齐”的毛病。
3.2 重要发现:画笔积木比精灵渲染快得多
在Scratch里,每一个精灵角色在舞台上都是一个独立的渲染单元。当同屏精灵数量一多,浏览器就得为每个精灵做独立的变换、裁剪、合成操作,性能直线下降。我们实测中,精灵数量超过100个时帧率就已经开始肉眼可见地波动了。
但这里藏着一个被很多人忽略的点:画笔积木(Pen)。它的绘制路径和精灵不是一套系统,走的是Canvas 2D的底层绘制接口。换句话说,用画笔绘制大量简单图元(圆形、矩形、线条)时,性能远高于几十个精灵在舞台上互相叠加。
于是我们做了一件事:把粒子、弹幕、光效、地面网格这些“非交互装饰元素”全部从精灵改成画笔绘制。一个由200个粒子组成的爆炸特效,用精灵做会卡到怀疑人生,用画笔做却非常轻松。屏幕上的画面内容没有变,但底层的绘制路径完全不同。
3.3 想稳定帧率,必须掌握“运行时不刷新屏幕”
Scratch的自制积木有一个非常关键的高级选项,中文叫“运行时不刷新屏幕”,英文叫run without screen refresh。勾上之后,这段自制积木里所有操作会在同一个帧内瞬间执行完,中间不会触发屏幕重绘。
这个概念怎么理解呢?你可以把它想象成游戏引擎里的“单个Update调用”——整段逻辑作为一次原子操作执行,只有全部跑完之后才把结果绘制到屏幕上。这样一来:
- 我们可以把物理计算、碰撞检测、对象状态更新全部放进一个勾了“不刷新”的自制积木里。
- 每次进入这个积木,游戏世界完成一次“逻辑推进”,然后统一渲染一帧。
- 彻底避免了Scratch默认那种“每移动一步就重绘一次”的性能浪费。
我们的主循环大概长这样(积木伪代码):
当绿旗被点击 重复执行 运行逻辑(自制积木,勾选运行时不刷新屏幕) 渲染画面(自制积木,负责更新精灵和画笔) 等待0秒这个架构看着简单,但它决定了整个游戏的内核是“帧循环驱动”,而不是“事件驱动”。没有这个东西,后面所有对象池、状态机、性能优化全都无从谈起。
3.4 三种渲染策略的实测数据
我们测试了三种做法,数据差距非常明显:
| 渲染方案 | 同屏对象上限 | 帧率表现 |
|---|---|---|
| 全部用精灵 | 50-80个 | 20-30FPS,偶发卡顿 |
| 精灵+画笔混合 | 200-300个 | 稳定40-50FPS |
| 精灵只做交互、画笔负责视觉元素 | 满足整局游戏需求 | 接近60FPS |
记住一个原则:交互对象(玩家、敌人、可拾取物)用精灵;数量大、无交互、纯视觉的元素(弹幕、粒子、背景动画)尽量走画笔。这是我们在这次项目中总结出的最实用的单条性能建议。
4. 没有魔法,只有状态机:用积木搭出引擎级代码结构
性能问题解决到一半,另一个更隐形的敌人浮现了:代码组织。Scratch的积木不是文件,不是行文,它是一块块堆在编辑区里的视觉代码。一旦逻辑复杂起来,整个画面会变成一张蜘蛛网,谁都看不懂,更别说维护。
我们这个项目是三个人同时开发的,不可能像单机作品那样一个人拖积木拖到爽。那就必须用接近真实引擎的思路来组织Scratch代码。
4.1 场景管理:用列表硬撸一套Scene Stack
Scratch切场景最常见的方法是“换成XX背景”,然后给每个角色发广播:“你切换到第X场景的状态吧”。问题是,一旦游戏有十几个角色、七八个场景,这样的广播满天飞,很容易出现场景A的精灵在场景B里闪一下的灵异事件。
我们的做法是模仿游戏引擎里的场景栈(Scene Stack)。用两个全局列表维护场景状态:
scene_stack:存当前所有场景ID,类似["title", "level1"]。scene_current:存当前有效场景ID。
切换场景时只做三件事:
- 往
scene_stack里推入新场景ID。 - 更新
背景造型为对应场景。 - 广播一条
scene_enter消息。
所有角色收到scene_enter后,先去查scene_current,如果这个场景和自己无关,就立刻隐藏自己;如果有关,才进入对应的初始化逻辑。
这套方案的好处在于,场景切换变成了可控的、可回溯的。再也不会出现“场景切过去了但角色忘了隐藏”这类问题。而且列表是全局的,任何一个精灵需要问“我现在在哪个场景”,直接读取即可,不需要再搞一堆私有变量。
4.2 对象池:用列表做数据层,克隆体只当渲染层
Scratch的克隆体上限是300个,而且克隆体越多性能越差。但一个像样的弹幕游戏,同屏子弹可能就有几百颗,更别提敌人身上还要挂特效。真要全用克隆体去堆,游戏还没开始就已经卡死了。
我们的破局思路是把“数据”和“表现”分开,做法如下:
- 维护一张全局列表
entities,每一行代表一个游戏对象,字段用“列号约定”来表示,比如第1列是x坐标、第2列是y坐标、第3列是速度、第4列是类型。 - 克隆体只负责“根据列表数据渲染自己”。每次循环,克隆体去读实体列表,找到自己对应的那行数据,把位置、造型、旋转等设置成数据里记录的值。
- 所有游戏逻辑(移动、碰撞、伤害计算)完全在列表上运行,不依赖任何精灵。
这样的结果是,逻辑对象的上限从300个克隆体一下子变成了列表能存的数据量——几千个都没问题。而真正放在舞台上的克隆体,只需要维持“画面里可见的那几十个”就够了,因为不可见对象根本不需要渲染。
提示:刚开始可能会觉得这套做法很绕,但你一旦跑起来就会发现,它才是Scratch空间里最接近真实游戏引擎架构的写法。数据层和渲染层分离,在任何引擎里都是值得遵循的原则,Scratch也不例外。
4.3 团队协作:一人一个模块,最后用JSON合并
三个人同时改一个Scratch项目,如果不做隔离,结果就是互相覆盖,文件冲突到怀疑人生。我们的方式是干脆把项目拆成三个“模块工程”:
- 我负责渲染层(画笔绘制、精灵舞台表现、特效)。
- 一个伙伴负责玩法逻辑(玩家控制、敌人AI、碰撞处理)。
- 另一个伙伴负责资源和数值(关卡配置、武器参数、声音资源)。
开发阶段,三个人各自维护一个独立的sb3文件,里面只放自己负责的那部分积木和测试角色。每天快到下班时统一同步一次,同步方式就是从Git上拉取最新的project.json,然后用Python脚本合并到一个总项目里。
这个流程在早期相当痛苦,因为合并JSON时经常出现变量ID冲突。但撑过第一周,把命名规范和合并脚本稳定下来后,效率反而比在Web端多人实时编辑高——因为每个人在自己模块里都拥有完全的控制权,不会互相干扰。
做一个形象的比喻:这就像代码仓库的分支管理。主分支永远是完成版本,开发者各自开功能分支,功能稳定后合并回主分支。用这套思路去管理Scratch项目,虽然土,但是真的稳。
5. 性能战场上的真实伤亡:三个月的调优手记
前面几章讲的都是方案和架构,属于“纸上的胜利”。真正让整个团队心态炸裂的,是开发过程中一个个具体的性能事故。这一章是我最想写的部分——因为所有看起来“很套路”的优化建议,背后其实都是血泪。
5.1 克隆体一多就卡到怀疑人生
第一次大规模掉帧出现在联调第一周。我们把三个模块合并之后,同屏有200多个克隆体在飞,当时只是在测试场景里随便跑了几下,笔记本风扇就开始狂转,浏览器标签页直接卡到“无响应”。
当时第一反应是骂美术“为什么做了这么多特效”。冷静下来之后,我们才意识到问题不在素材量,而在克隆体本身的渲染开销。Scratch一个克隆体就是一个精灵,200个精灵意味着每一帧浏览器都要做两百次精灵合成。无论你的电脑多么强,这个数量级都会出问题。
后来就是用第4章讲的对象池方案解决的——把逻辑数据搬到列表里,克隆体只留真正需要显示的那几十个。这里想特别点一句:如果你在Scratch里做项目,发现克隆体刚上百就有明显卡顿,不要等,直接切列表数据驱动,这是最省时间的选择。
5.2 广播风暴:事件系统成了新的瓶颈
对象池让克隆体数量下来了,但帧率并没有回到理想水平。继续排查,发现罪魁祸首变成了广播消息。
Scratch的“广播”——对应引擎里的“事件系统”——在收到消息后,会同步执行所有写了“当收到消息”的脚本。如果场景里有30个角色各自写了“当收到消息”的脚本,一条广播发出来,这30段脚本全部排队执行,非常吃帧。
更糟糕的是,我们最初的代码为了省事,在帧循环里每帧都广播一条“update”消息。每帧30条音频,每条音频唤醒几十个角色,累加起来直接把单帧时间拉爆。
我们的处理方式有一个原则:事件只当“信号”,不当“数据传输通道”。具体的状态和数据都放在列表里,角色自己每帧去读取,而不是等广播来“喂”。
把“每帧广播update”改成“只在状态变化时才发广播”之后,帧率立刻回升了接近20帧。后来我们甚至约定:除了一开始进场的那几条广播,游戏运行期间不再有连续广播,所有持续行为一律轮询列表。
5.3 亮度特效的隐形巨坑
这个坑特别想写出来,因为和视觉表现相关,很容易踩。
项目里需要做“敌人受击闪烁”的效果。美术同学直接在Scratch里写了“将亮度特效设为50”,试玩时发现,只要敌人一被击中,整个画面就瞬间爆卡,帧率掉到个位数。
原因很简单:Scratch的“亮度”“颜色”“鱼眼”这类滤镜特效,在渲染器里是重量级操作。它不是在贴图层面打一层遮罩,而是对每一帧的画面做额外的像素级处理。偶尔用一次还能忍受,但在实时战斗里高频次触发,性能直接崩盘——这就像一台普通电脑玩普通游戏没问题,一玩大型3D游戏就花屏闪退。
替代方案其实非常土:
- 用“造型切换”模拟闪烁:把受击瞬间切到一张同轮廓的白色造型,下一帧切回来。
- 完全不碰滤镜,用透明度变化(虚像/显示交替)来表达受击反馈。
这两个方案在视觉上不差,性能却差了一个数量级。我们在项目里最终定了条死规矩:所有渲染滤镜一律禁用,任何视觉特效必须用造型切换或画笔模拟。
这条规矩执行后,整个项目的帧率抖动问题几乎绝迹。
5.4 性能面板:Shift+点击绿旗,Scratch自带的调试秘技
说一个很多人不知道的Scratch调试功能:在Scratch 3.0编辑器页面,按住Shift键的同时点击绿旗,会在舞台角落显示一个性能调试面板,里面能看到实时的帧率(FPS)、渲染调用次数、舞台绘制耗时等数据。
这简直是给引擎调优准备的“神级外挂”。我们后期基本每改一次代码就打开面板跑一遍,看到帧率掉下来,就直接根据渲染次数判断是“精灵太多”还是“滤镜太重”。没有这个面板,我们可能要多花两周时间盲猜性能瓶颈。
我的建议是:如果你也打算认真用Scratch做游戏,不管做不做引擎化改造,都把这个调试面板的能力记住。它就像游戏引擎编辑器里那个FPS计数器和Draw Call统计器,是所有优化的起点。
6. 最终交付:跑得动《空战》,却跑不动《暗黑》
三个月的连续挣扎之后,我们最终交付了什么?这一章说说成果,也说说边界。
6.1 最后跑通的三个Demo
Starship:横版空战射击。玩家控制飞船躲避弹幕、击落敌人,Boss有简单两阶段AI。同屏最多出现过150颗子弹+30架敌机,稳定在50FPS以上。Jump King:平台跳跃。惯性手感、重力模拟、移动平台,核心物理全部基于列表数据和自制积木,不依赖Scratch自带物理。Pocket Dungeon:俯视角小迷宫。实现了基于格子的移动、视野遮挡、简单寻路,算是对“场景栈”和“状态机”的最终验证。
这三个Demo全部能在学校机房的旧浏览器上流畅运行,学生打开后还能直接进入编辑器拖积木改参数。从这个角度看,项目目标算是完成了。
6.2 我们承认的边界
但我也不想神话这套方案。它终究不是Unity,不是Godot,连“轻量引擎”都算不上,硬要给它定位,叫“Scratch上的一个游戏框架”更贴切。
做不动的场景主要有这些:
- 大地图无缝加载:Scratch没有流式加载机制,做大图必须靠场景分块切换,边缘会有明显过渡。
- 重度物理模拟:超过几十个刚体的实时碰撞,性能压力依然很大。
- 复杂AI:大量寻路、多个决策树同时运行,逻辑耗时会挤占渲染时间。
- 高清美术表现:毕竟逻辑分辨率只有480x360,精细美术的地面展示并不占优。
- 多路声音:声音同时播放太多也会造成丢帧,尤其在老电脑上。
把这些边界列出来,不是否定项目,而是为了给后来者一个合理预期——它适合做玩法有趣、画面够用、体量轻巧的游戏,而不是3A级别的宏达叙事。
6.3 重新认识Scratch的上限
经过这三个月,我们对Scratch的评价发生了本质变化。它并不是“能力小”,而是“思路完全不同”。它的积木编辑环境天然面向“每个角色独立跑脚本”的模型,而引擎要求你“全局管理所有对象”。要在Scratch里做引擎,本质不是学会某个积木,而是改变组织方式——用列表管理数据、用广播做状态信号、用画笔代替精灵渲染、用JSON脚本批量处理资源。
当我们把这一整套思路跑通之后,再回头看最初那张“能/不能/Hack”摸底清单,上面每一格几乎都填满了对应的解法。Scratch的上限,远比大多数人想象的高;但把它变高的过程,也远比大多数人有耐心。
7. 给也想“自虐”的人:工具链和避坑清单
最后这一章是给想复刻这条路的人的。如果你正在考虑用Scratch做一个认真严肃的游戏项目,下面这些工具、方法和坑,可以直接抄作业。
7.1 必备工具链清单
- Python脚本:解包、打包、修改sb3里的
project.json。这是所有批量操作的中枢。 - Git仓库:用来管理
project.json的版本。每次大改动前打个tag,出问题时回滚非常方便。 - 文本编辑器/IDE:直接打开
project.json查看结构、搜索替换关键词。 - 素材命名规范:从第一天就按“角色_用途_序列”来命名所有造型和声音,否则后面批量换UI、换角色会痛不欲生。
- Scratch性能调试面板:Shift+点击绿旗,随时观察帧率。
这套工具链里最容易被低估的是Git。手一抖删掉某个角色,Ctrl+Z都没法恢复的时候,你才会意识到版本管理有多重要。
7.2 我们踩过的坑,按“毒性”排序
| 坑 | 现象 | 原因 | 解法 |
|---|---|---|---|
| 克隆体爆量 | 200个以上明显掉帧 | 每个克隆体都是独立渲染单元 | 列表做数据层,克隆体只做渲染 |
| 滤镜特效 | 一用就卡到个位数帧率 | 渲染器会做像素级重处理 | 禁用滤镜,用造型切换模拟 |
| 广播风暴 | 广播一多整帧超时 | 每个角色都会同步响应 | 事件只作信号,数据放列表 |
| 多人协作冲突 | JSON合并崩溃 | 变量/积木ID冲突 | 模块化开发 + 脚本合并 |
| 素材命名混乱 | 批量替换找不到目标 | 没有统一命名规则 | 第一天就定规范 |
如果你只记住三条,记住这三条:克隆体省着用、滤镜别碰、事件别传数据。
7.3 关于心态的唯一建议
这三个月最深的体会是:做Scratch引擎,技术难点其实全是心理难点。每当你想放弃的时候,总会有某个优化方案像救命稻草一样冒出来,然后下一个问题又把你打趴下。你能做的只有一件事——把每个问题拆小,一次只做一个,用最小的可运行demo去验证它。
我们前两周浪费了大量时间在“完美素材”上,后来发现素材再好看,性能一崩全白搭。正确的顺序是:先把最小游戏循环跑通,再把角色数量加到性能极限,然后优化,最后才往里面填美术和音效。
最后分享一个我个人的小习惯:每次调优性能之前,先看Scratch调试面板的数字,再凭直觉猜瓶颈,不要直接动手改。猜错很正常,但猜对之后你会对这个系统的运作方式越来越有感觉。等到你一眼就能看出“这片卡顿是精灵太多还是逻辑太慢”的时候,说明你已经不只是会用Scratch了,而是真的开始用引擎思维来思考它了。
“from scratch”这个短语,特别适合用来总结这次项目:它既是“从零开始”,也意味着“把自己身上能刮下来的耐心,全部刮干净”。熬过三个月,你获得的不仅是一台“Scratch游戏引擎”,还有一套在任何游戏项目里都不吃亏的工程思维。