吃透Scratch 3.0操作逻辑:从积木到接物小游戏实战

很多人第一次打开 Scratch 3.0 的时候,会觉得这玩意儿太简单了——一堆彩色积木拖来拖去,能做出什么正经东西?我带过几批零基础的学员,也帮同事改过他们给孩子做的课件项目,最初的判断几乎都是这样,结果做到第三个项目就卡住了:角色乱飞、克隆体越攒越多、切个场景就全乱套。问题从来不在积木本身,而在于没把这款图形化编程工具的软件操作逻辑吃透。Scratch 3.0 的操作分成两层,表层是拖积木、改造型、录声音这些动手动作,底层是舞台坐标系、角色职责划分、变量作用域、事件驱动这一整套组织方式。只会前一层,做的是会动的小猫;两层都明白,能做出带关卡、带计分、带音效的完整小游戏。这篇内容面向三类人:完全没碰过的新手、做过几个小 Demo 但总卡壳的进阶者,以及要拿它给孩子或学生做课堂演示的家长和老师。我把自己在实际操作中踩过的坑、调过的参数、反复验证过的操作顺序整理成一套完整流程,照着做基本能绕开八成的常见问题。

1. 把界面和操作逻辑先摸清楚

1.1 三块区域各自的职责,别混着用

Scratch 3.0 的编辑器界面看着元素很多,实际上就三个功能区在配合:左上那个白色方块是舞台,右上那条是角色列表,下面是积木区和代码区。刚上手最常见的问题是把舞台当画板用——直接在舞台上拖角色位置,然后发现脚本一跑全乱了。舞台只是显示结果的地方,角色的位置、大小、方向这些属性,正确做法是在代码区用积木控制,或者至少在角色列表里选中角色后再去调它的初始状态。

角色列表这块要特别注意"当前选中"的概念。所有积木区展示的积木、代码区展示的脚本,都属于当前选中的那个角色或舞台。你写了一段脚本,切到另一个角色发现脚本没了,不是软件出问题,是脚本本来就挂在原来那个角色身上。我在给学员改项目时,最常干的动作就是挨个点角色,看它的脚本是不是写错了对象。养成习惯:写脚本前先确认角色列表里高亮的是谁,这个动作能省掉大量排查时间。

积木区的分类颜色是固定的,运动是深蓝、外观是紫色、声音是粉红、事件是黄色、控制是橙色、侦测是浅蓝、运算和变量是绿色、自制积木是红色。颜色不只是好看,它会在你拼接时提示形状是否合法。比如运行类积木顶部是凸的、底部是凹的,必须首尾相连;布尔类积木是六边形尖角,只能塞进六边形的槽里。刚开始会觉得别扭,用熟了之后,形状本身就是最直接的语法检查器。

1.2 积木的四种形状决定了它能塞进哪里

Scratch 的积木按形状分成四类,这个知识点看起来基础,但它是理解整个操作体系的关键。堆叠积木(如"移动10步")上下有凹凸口,能串成脚本;帽子积木(如"当绿旗被点击")顶部是圆弧,只能放在脚本最上面;C形积木(如"重复执行"、"如果…那么")中间有开口,能把别的积木包进去;报告积木是圆头或六边形,本身不产生动作,只输出一个值,必须塞进槽里才有意义。

实际操作用得最多的是C形积木。这里有个新手极易忽略的点:C形积木的开口宽度有限,超过三层的嵌套在视觉上会挤成一团,很难看清楚谁包着谁。我的处理办法是控制嵌套深度不超过三层,超过就把内层逻辑抽成自制积木。这个习惯听起来是洁癖,实际上是给后续改代码省命——两周后回头看自己写的五层嵌套,大脑是真的会宕机。

注意:把报告积木直接拖到代码区的空白处,它会显示当前值,像是临时探针。这个用法非常好用,调参数的时候可以把"鼠标x坐标""计时器""某变量"拖出来盯着看,比反复点绿旗试错高效得多。

1.3 舞台坐标系和尺寸,所有位置运算的地基

Scratch 3.0 的舞台固定是 480×360 像素,中心点是原点 (0,0)。横向 x 从 -240 到 240,纵向 y 从 -180 到 180,y 轴向上为正。这一点和大多数网页画布的坐标系相反,是从数学坐标系沿用过来的。如果你做过前端或者用过图像处理软件,第一次写"让角色往上飘"写成"y 增加"没问题,写成 y 减少就跑反了。

角色位置还有个"旋转中心"的概念,也就是造型编辑器里那个十字准星。角色移动、旋转都是围绕这个点进行的。做一个"车轮转动"的效果,如果造型中心点在轮子外面,转起来就是绕外面一点画圈,看起来像飞出去了。正确做法是在造型编辑器里把那根十字准星拖到轮子正中心。同理,做"左右移动脚步"效果的角色,中心点应该放在脚底,不然角色会像浮在半空。

坐标换算在项目里经常用到。比如做"角色跟随鼠标"的效果,可以直接用"移到鼠标指针";但做"角色沿鼠标方向移动一点点",就得算角度:用"面向鼠标指针"加上"移动 5 步"。这两个操作手感差别很大,前者是瞬移,后者是缓动追踪。我实测下来,缓动追踪的移动感更舒服,因为每一步都在重新计算角度,角色会自然地"追"过去。

2. 项目结构怎么搭:从想法到积木堆

2.1 角色划分的边界,决定了后期改动的痛苦程度

拿到一个需求,比如"做一个接苹果的小游戏",新手会直接开始堆积木,做到一半想加个"加速道具",发现整个脚本缠在一起没法改。我的流程是先在纸上(或者用注释角色)列出角色清单,每个角色只负责一件事:玩家角色负责接收键盘输入和碰撞判定,苹果角色负责下落和被接住,地面角色负责越界回收,背景负责显示分数和倒计时。

这种划分原则叫"一个角色一个职责"。判断标准很简单:如果两个角色的脚本里有大量一模一样的代码,说明它们该合并或者该抽公共积木;如果一个角色的脚本承担了三件不相关的事情(移动、计分、播音乐),说明该拆。拆角色在 Scratch 里几乎零成本,右键角色就能复制,复制出来的角色自带造型和脚本,改改就行。

需要提醒的是角色数量不是越多越好。每个角色在运行时都会占一点性能开销,几十个角色同时跑脚本,在老电脑上会明显掉帧。经验值是一个场景里活动角色控制在 10 个以内,超过的用克隆体代替。克隆体本质是同一个角色复制出多份实例,共用一套脚本,性能开销小得多。

2.2 用广播把模块之间解耦

广播是 Scratch 里最被低估的功能。新手往往把所有逻辑塞进"当绿旗被点击"下面的一个大脚本,几百块积木串成一条长蛇。这种写法的问题在于:想调整中间某个环节的执行时机,得把整条链拆开重组。

广播的用法是:一个脚本在关键时刻"广播并等待"或者"广播"某个消息,另一个脚本用"当接收到某消息"作为帽子积木开始执行。这样两段逻辑在代码区是分开的,互不干扰,改一段不会影响另一段。"广播并等待"会等接收方所有的"当接收到"脚本执行完毕再继续往下走,这个特性用来做关卡切换特别顺:玩家碰到终点 → 广播并等待"下一关" → 各角色收到消息后重置自己的状态 → 原来那个脚本才继续往下跑。

实操中要注意广播名一旦建立就不要随便改。改名之后其他角色里挂着的接收脚本会变成"当接收到 xxx"的孤儿状态,而且不会报错,只是永远不触发。我排查过好几个"游戏卡住不动"的问题,最后发现是广播名里多打了个空格。建议广播名统一用中文、简短明确,比如"开始游戏""游戏结束""角色重置",别用"消息1""消息2"这种没有语义的名字。

2.3 变量作用域:全局和私有搞混是最隐形的坑

Scratch 的变量分两种:适用于所有角色(全局)和仅适用于当前角色(私有)。界面上都长得一样,但作用域天差地别。全局变量所有角色共享同一份值,私有变量每个角色各有独立的一份。

这个区别在计分场景里最直观。分数用全局变量,所有角色读到的都是同一个分数;而如果给每个敌人角色建一个私有的"血量"变量,每个敌人各管各的,互不干扰。我见过一个典型翻车案例:做打地鼠游戏,作者建了个叫"随机位置"的变量本意是给每只地鼠各存一个目标位置,结果建成了全局变量,五只地鼠读到的是最后一次写入的值,于是五只地鼠齐刷刷跑到同一个洞里。改成私有变量,问题立刻消失。

判断方法很粗暴:这个数据是否需要被其他角色读取?需要就用全局,不需要就用私有。私有变量名在角色列表里会显示成"角色名:变量名"的形式,多少能看出来。另外,克隆体在继承私有变量时是复制一份,每个克隆体各自独立;但全局变量是共享的,一个克隆体改了值,所有克隆体看到的都变了。做"每个克隆体有独立速度"这种需求,必须用私有变量。

3. 核心操作细节与实操要点

3.1 事件与控制:脚本的启动和节奏由它们决定

"当绿旗被点击"是主入口,但一个项目里不应该只有它。常见的启动方式还有"当按下某键""当角色被点击""当接收到某消息""当响度大于某值"。多入口设计能让交互更丰富,但也带来状态管理问题:玩家按了空格开始游戏,脚本跑起来了,这时候又点了绿旗,所有状态需要重置。我的做法是保留一个专门的"初始化"脚本,挂在"当绿旗被点击"下面,把所有变量、角色位置、克隆体、计时器全部清回初始状态,其他入口的脚本都在开头广播"初始化"。

控制积木里,"重复执行"是每一帧执行一次循环体,Scratch 的运行帧率大约是每秒 30 帧,所以循环体里的"移动 1 步",一秒大约移动 30 步。这个换算关系对调速度很关键。想让角色每秒移动 100 像素,用"移动 3.33 步"左右。但 Scratch 的循环不是严格按帧计时,实际帧率会随电脑性能波动,所以做精确计时别用循环次数,用"计时器"变量。

"等待 0 秒"这个积木是给时间片让步用的,让其他脚本有机会执行。在密集循环里偶尔用一下能避免卡死。但很多人用它来"制造延迟",这是不靠谱的,因为 0 秒的等待时间不确定。"重复执行直到 xxx"比"重复执行 + 如果那么 + 停止这个脚本"的组合更清晰,能少写好几块积木,而且不容易漏掉退出条件。

注意:停止积木有三种模式——"停止全部脚本""停止这个脚本""停止该角色的其他脚本"。第三种模式看起来很冷门,实际上在做"同一角色同时有移动和开火两条独立逻辑"时非常有用,可以只终止其中一条而不影响另一条。

3.2 造型、声音与外观:视觉和听觉的细节都在这里

造型切换是动画的基础。连续的多张造型配合"下一个造型"加上短循环,就能做出奔跑、拍翅膀的效果。这里的关键是造型切换的节奏要和移动速度匹配。跑步动作一秒切 10 次造型,角色一秒移动 100 像素,那就是每移动 10 像素换一个姿势,视觉上很连贯。如果角色移动很快但造型切得慢,看起来就是在滑行。

造型编辑器里有几个必用的功能。一是翻转,左右移动的角色只需要画一个朝向的造型,用"将旋转方式设为左右翻转"就能自动镜像,省一半素材工作量。二是矢量模式与位图模式的切换,矢量模式画出来的图形放大不糊,适合几何形状和文字;位图模式适合导入的图片素材。混用会导致放大缩小后边缘模糊,尽量一个项目里统一用矢量重绘。

声音这块,Scratch 3.0 自带声音编辑器,能做裁剪、调整音量包络、加回声和机械音效果。实操中最常用的操作是"截取音效前段"——网上找到的素材往往前后有多余空白,用选中区域加删除,再把播放起点拖到正确位置。"播放声音直到结束"会阻塞脚本往下走,"播放声音"则不会,做背景音乐用后者,做打击音效用前者。

音量的坑在于:Scratch 的音量是 0 到 100 的百分比,不是分贝。设置成 100 就是最大音量,多个音效同时播放会叠加,容易炸音。遇到音效刺耳,先降低音量到 60 左右试试,比反复换素材有效得多。

3.3 克隆体:用得对是神器,用不对是灾难

克隆是 Scratch 3.0 里做"大量同类对象"的唯一正道——子弹、敌机、落叶、星星、粒子特效,全靠它。操作上就两条积木:**"当作为克隆体启动时"**作为帽子,"克隆自己"和"删除此克隆体"分别负责生和死。

问题几乎都出在"死"这一环。克隆体是有数量上限的,同一个角色最多同时存在 300 个克隆体,超过之后最早的会被强制删除。如果只克隆不删除,几百个克隆体同时在屏幕上跑脚本,帧率会断崖式下跌,表现为整画面卡成幻灯片。我在一个"雪花飘落"的 Demo 里就栽过:本来只想要 50 片雪花,写成了在"重复执行"里不断克隆,跑十秒之后卡得点不动。正确写法是克隆时立刻给克隆体一份"寿命"逻辑——飘出舞台边界或者存活超过若干秒就自我删除。

生命周期管理有个小技巧:在"当作为克隆体启动时"的最开头加一行"将变量[速度]设为在 1 到 3 之间取随机数",让每个克隆体的属性各自独立。前提是这个变量得是私有变量,全局变量做不到这一点。另外,克隆体会继承母体的造型、位置、大小、方向,但不继承脚本的执行进度。想要克隆体从指定位置出发,在克隆之前先"移到 x y",克隆完再把它移回去,或者直接在克隆体启动时重新定位。

体量控制上给个参考:单个角色同时存在 80 到 150 个克隆体,在中低端电脑上还能保持流畅;超过 200 个就要开始警惕了。真需要大量粒子效果,用"图章"配合画笔扩展,性能比克隆体好一个量级。

3.4 自制积木与"运行时不刷新屏幕"

自制积木相当于自定义函数,把重复的积木段打包成一个新积木。操作路径是在积木区最下面点"制作一个积木",输入名字,如果有参数就点"添加输入项"。做出来的积木会出现在积木区,颜色和帽子积木一样是红色。

这个功能最大的价值不是省积木数量,而是让脚本可读。一段三十块积木拼成的"跳跃物理",包成"执行跳跃"之后,主脚本里就剩一行,逻辑层次立刻清楚。参数还能让这个函数通用化,比如"绘制矩形 宽 高 颜色",一次定义,到处调用。

自制积木有个隐藏选项:勾选"运行时不刷新屏幕"。这个选项的作用是让这个积木内部的所有循环在一帧内跑完,而不是每帧跑一次。用画笔扩展画分形图形、画螺旋线、生成地图,不勾这个选项会看到图形一点一点"爬"出来,勾上之后瞬间成型。原理是 Scratch 默认每个循环会刷新一次画面,勾选后跳过刷新,等整个函数跑完再统一显示。这个选项只影响视觉,不影响计算结果。

画笔扩展需要手动添加,在左下角"添加扩展"里选"画笔"。扩展安装后会多出一组积木,用来落笔、抬笔、设置笔的颜色粗细、盖章。添加的扩展会跟着项目一起保存,换台电脑打开还在。常用扩展还有音乐(演奏音符)、视频侦测(摄像头动作捕捉)、文字朗读(TTS)、翻译。扩展不要装太多,每个都会增加加载时间,用不上的在项目结束时可以移除。

4. 完整实操:做一个可复现的接物小游戏

4.1 需求拆解与素材准备

目标定得具体一点:一个篮子左右移动接住从天上落下的水果,接到加分,漏掉扣命,三条命用完游戏结束。这个规模足够把前面讲的所有知识点串一遍,又不会大到失控。

素材准备阶段有几个实操建议。角色和背景不必自己画,Scratch 自带素材库里有大量现成的,点角色列表右下角的"选择一个角色"就能打开素材库。水果的造型可以直接用素材库里的,省时间。背景选一张深色渐变,能让水果和篮子更突出。需要注意的是角色大小要统一,导入后如果大小差异悬殊,选中角色后用"大小"属性统一调整到 60 到 80 之间,视觉上会协调很多。

角色清单定四个:篮子(玩家控制)、水果(母体,负责生成克隆体)、背景(显示分数和生命值)、游戏结束提示(初始隐藏,结束时显示)。变量清单定三个:分数(全局)、生命(全局)、下落速度(私有,属于水果角色)。

4.2 篮子的脚本:输入处理和边界限制

篮子的核心是跟随鼠标横向移动,同时锁定 y 坐标不让它上下飘。

当绿旗被点击 将 x 设为 0 将 y 设为 -140 将大小设为 80 重复执行 将 x 设为 (鼠标的 x 坐标) 如果 <(x 坐标) > 200> 那么 将 x 设为 200 如果 <(x 坐标) < -200> 那么 将 x 设为 -200

这里"将 y 设为 -140"是锁定垂直位置,只让 x 跟着鼠标变。后面的两个判断是边界限制,防止篮子跑到舞台外面去。为什么边界设成 ±200 而不是 ±240?因为篮子本身有宽度,中心点跑到 ±240 时篮子有一半已经出界了。留出半个身位的余量是通用做法,具体数值取决于角色大小。

另一种控制方案是键盘方向键,用"当按下右移键"加"将 x 坐标增加 8",手感更接近传统游戏。两种方案可以都保留,鼠标控制适合触屏设备,键盘控制适合电脑。我实测下来,对新手项目,键盘方案的心智负担更低,不用管鼠标位置和角色的换算关系。

4.3 水果的生成与下落逻辑

水果角色本身不显示,只作为克隆体的"母版"。母体在开始时隐藏起来,然后不停克隆。

当绿旗被点击 隐藏 将 [下落速度] 设为 3 重复执行 等待 (在 0.4 到 1 之间取随机数) 秒 移到 (在 -200 到 200 之间取随机数) 200 克隆自己

注意"移到"是在克隆之前执行的,位置由母体决定,克隆体继承这个位置。等待的随机时间让水果不要整齐地一起落下,看起来更自然。下落的实现放在克隆体自己的脚本里:

当作为克隆体启动时 显示 将大小设为 (在 60 到 90 之间取随机数) 将造型设为 (在 1 到 [水果造型总数] 之间取随机数) 重复执行直到 <<(y 坐标) < -170> 或 <碰到 [篮子] ?>> 将 y 坐标增加 (0 - [下落速度]) 如果 <碰到 [篮子] ?> 那么 将 [分数] 增加 1 播放声音 [啵] 直到结束 如果 <(y 坐标) < -170> 那么 将 [生命] 减少 1 播放声音 [错误提示] 直到结束 删除此克隆体

"重复执行直到"的条件用了"或",两个条件任意一个成立就跳出循环:要么落到地面,要么被接住。循环外面统一做结果判定,再统一删除克隆体,逻辑比在循环里写"停止这个脚本"要干净。下落速度用数字 3 起步,随着分数上涨在背景角色的脚本里逐渐加大,游戏难度就有了自然的递进。

4.4 分数显示、难度递增和结束判定

背景角色负责所有的 UI 和全局判定。分数和生命要显示在舞台上,用"说"积木会跟着角色跑,位置不好控制,用变量监视器又太丑。正确做法是在背景上显示文字——Scratch 没有专门的文本显示积木,一般用两种方案:一是给背景加一个"分数面板"角色,里面有不同的数字造型,靠切换造型显示;二是用文字转造型的第三方方式。考虑到可复现性,我用最简单的方式:把分数变量拖到舞台左上角当监视器,够用且零成本。

难度递增和结束判定:

当绿旗被点击 将 [分数] 设为 0 将 [生命] 设为 3 将 [下落速度] 设为 3 重复执行 如果 <(分数) > 10> 那么 将 [下落速度] 设为 5 如果 <(分数) > 25> 那么 将 [下落速度] 设为 7 如果 <(生命) < 1> 那么 广播 [游戏结束] 停止全部脚本

这里用了两次独立判断而不是"如果…否则如果",因为分数是单调递增的,两个条件可能依次满足,用独立的"如果"能保证每次都重新设置。写的时候要注意,重复执行里每帧都在判断,写成"当分数 = 10"这种相等判断就永远触发不了,因为分数可能从 9 一次跳到 12。范围判断用大于小于,不要用等于,这是数值递增场景的铁律。

游戏结束提示角色平时隐藏,"当接收到游戏结束"的时候显示,并说一句提示文字。想重新开始,点绿旗就行——所有初始化都写在"当绿旗被点击"里,状态自然复位。

5. 常见问题与排查实录

5.1 脚本不执行的六种原因

这是被问得最多的一类问题,按出现频率排了个序:

现象最可能原因排查动作
点绿旗毫无反应脚本没挂在"当绿旗被点击"下,或帽子积木是"当角色被点击"检查代码区第一个积木是哪个帽子
换了角色脚本不见了脚本属于另一个角色逐个点击角色列表查看
角色只在鼠标点击后动触发方式用了"当角色被点击",和预期不符换成绿旗或键盘触发
广播后没反应广播名不匹配,或多打空格对照发送端和接收端的名字
循环里只跑了第一行某块积木是阻塞式的,比如"等待 5 秒"检查是否有长等待或"播放声音直到结束"
脚本跑了一次就停用了"停止这个脚本",或"重复执行"被误拖到外面检查控制类积木的嵌套关系

排查顺序建议从外到内:先确认帽子积木对不对,再看触发条件能不能满足,最后看循环内部有没有早退。这个方法比一行行读代码快得多。

5.2 卡顿和帧率下降怎么定位

画面卡顿的原因基本就三个:克隆体没删干净、循环里套了太多耗时操作、角色数量过多。排查手段是开"舞台"右上角那个小绿旗旁边的显示帧率开关吗?Scratch 3.0 没有内置的帧率显示,我是用笨办法:让角色在循环里数数,用计时器算出一秒内循环了多少次,跑个十秒做平均,得到实际帧率。低于 20 基本就能确定有性能问题。

定位具体是哪个角色拖后腿,把角色一个接一个地"隐藏"或者临时停用它的脚本(在帽子积木上右键"删除积木"然后撤销),看帧率什么时候回升。这个方法很土,但百分百有效。最常见的罪魁祸首是忘了在"当作为克隆体启动时"里加删除逻辑,克隆体一直累积。第二个常见原因是"碰到颜色"这类像素级碰撞检测,在大面积角色上每帧检测一次开销很可观,能改成"碰到角色"就用角色检测。

5.3 那些文档里不写的实操坑

第一个坑是中文输入法和按键检测冲突。用"当按下 a 键"的时候,如果输入法处于中文状态,按键可能先被输入法吃掉,游戏收不到。解决办法是让使用者在玩之前切到英文输入法,或者改用鼠标交互。

第二个坑是造型中心点导致的位置偏移。换了造型之后角色"跳"了一下,多半是新造型的中心点和旧造型不一致。在造型编辑器里把两个造型的十字准星位置对齐,就能解决。

第三个坑是项目文件体积。在线版对单个项目的大小有上限,导入大量高清图片或者长音频很容易超。处理办法是把图片压到 480×360 以内,音频用 22kHz 单声道,能砍掉七八成体积。真想塞大素材,用桌面版保存成 .sb3 文件放在本地。

第四个坑是保存和版本。在线版每次改动都自动存,但如果网络中断,最近的改动可能丢。桌面版是手动保存,容易忘记。我的习惯是每完成一个功能模块就手动存一次,文件名带序号,这样改坏了还能退回去。

第五个坑是导出分享时的字体和素材。用了系统里特有的字体或者自己找的图片素材,换台电脑打开可能显示不出来。稳妥做法是只用 Scratch 自带的矢量字体,素材尽量用内置素材库里的。

我个人在实际操作中的体会是,Scratch 3.0 真正难的地方从来不是某一块积木怎么用,而是怎么把一个想法切成能落到具体角色和具体脚本上的小块。上面这套"角色划职责、广播做解耦、变量管作用域、克隆管生命周期"的做法,我用了很久,改动成本比一开始把所有东西堆在一个脚本里低了不止一个量级。刚开始照着做会觉得拆得太碎、太啰嗦,等你的项目做到第三版、第五版,就会庆幸当初拆开了。