Scratch是积木式的语言(Blockly),依靠积木的可连接性来组成代码,防止简单语法错误的发生。Scratch分为十种积木,其中形象部分四种:动作、外观、声音、画笔。抽象部分六种:事件、侦测、运算、数据、控制、更多积木。本章将分别介绍所有积木的使用方式和一些易错细节,最后会展开描述所有积木的潜在使用场景。

注意:本章建议在看完全书之后再次阅读,或已经学习过Scratch一段时间的读者阅读。你将获得对Scratch更加系统和深化的理解。

动作

动作积木总览

Scratch的动作积木可以实现的功能归根结底只有两类:

  1. 移动
  2. 转向

其中移动类又分为了

  1. 直接移动和滑动
  2. 增量移动
  3. 移动到某角色或者鼠标指针
  4. 向面向方向移动

转向类分为了

  1. 直接转向
  2. 增量转向
  3. 面向某角色或鼠标指针

直接移动或者转向的模式

相当于指挥角色。直接安排角色到达某个地方面向某个角度。

增量的移动转向或者向面向方向移动,相当于编写角色的内部逻辑。例如设定某小车遇到红色左转30°遇到蓝色右转30°。

外观

外观积木总览

外观控制包括了

  1. 角色身上造型切换
  2. 外观特效
  3. 角色大小设定
  4. 说话思考
  5. 层叠关系设定
  6. 显示隐藏

造型切换

其中造型切换可以传入变量控制,其中变量可以是两种形式:

  1. 数字123456...对应了造型的编号
  2. 字符串,例如:“造型1”,对应了造型的名称

Scratch都可以自动的识别并找到对应的造型。如果好事者非要把编号为2的造型名称写成1,想看看究竟造型编号和造型名称哪个优先级更高。那么答案是造型名称更高,在“将造型切换为”积木中传入变量1时,名字为“1”的2号造型会显示出来。

外观特效

角色外观的特效分为了好多种类:颜色、鱼眼、旋转、像素化、马赛克、亮度、虚像

其中最有用的是颜色特效,他会在HSB的色轮上,把造型现有的所有颜色都增加固定的数值。例如造型现在是红色,增加颜色特效120会把角色变成蓝色。造型身上如果还有绿色,则会被转换为红色。

我们如果不想制造更多的造型,而想制造一些新鲜感的话,可以对角色的颜色特效进行设定,用一个红色的角色做基础款造型。这样方便我们知道增加颜色特效之后,造型大致会变成什么颜色。

但是这里有个警告:对于不了解Scratch性能的初学者,请减少颜色特效的使用,这几乎是最能拖慢Scratch运行速度的语句。这相当于给正常走路的人背了一大桶水,又要走路又要负重。

第二有用的特效是亮度和虚像,亮度的正值可以增加亮度直到100会变成纯白,负数值直到-100会变成纯黑,虚像特效从0到100分别对应了实体和绝对看不到。

  1. 虚像设为100时,角色完全不可见,但是仍旧可以识别碰撞
  2. 如果也不想角色识别碰撞,可以直接将角色隐藏

这两种用法会在不同场景派上用场

其他的外观特效使用较少,请读者自行尝试功能,但是要注意的是在使用过外观特效之后一定要使用清楚全部特效,否则很可能会因为设置了虚像而找不到角色。

大小设定

Scratch的舞台大小是480*360,导入计算机图片作为造型时可以传入不同大小的图片,如果大于Scratch的舞台,软件会自动帮我们把图片缩放到合适尺寸。但是这样可能会造成清晰图片的锯齿化。所以,请合理选择图片的大小。

角色身上的第一个脚本,我们要养成习惯对角色的大小进行设定。而增量大小设定积木可以配合循环模块来动态变化角色的外观。例如可以将角色做成心跳的闪动效果。

心跳效果实现和变种

说话思考

对于高端玩家来说,说话思考积木,大多数情况下应该只用在调试过程中。可以将变量或者积木块放入说话和思考框之中,让程序在运行过程之中显示中间结果,方便我们调试程序。相当于文本语言中的print,请收好你们说的hello world的冲动。

层叠关系设定

Scratch的层叠关系设定十分迷惑。

设想我们有多个角色,每一个人身上都有一段“当绿旗被点击”“置于最上层”的积木脚本。点击绿旗之后会发生什么情况呢?

大多数人会说不知道,求是的说,Scratch会把你创建顺序在先的“当绿旗被点击”之下的脚本先执行。这是由于这个“当绿旗被点击”积木在Scratch内部被首先注册出来,所以就会首先运行。这种多个脚本同时执行,说穿了只是计算机运行速度很快的假象。在Scratch内核,程序执行还是有顺序的而并非真的并发。

再来设想我们的多个角色身上“当绿旗被点击”的积木下有的跟着“置于最上层”积木,有的跟着“下移1层”,有的跟着“下移2层”....当我们点击绿旗让程序运行,会发生什么?

答案是,虽然我们知道了先拿出来的“当绿旗被点击”积木首先运行,但是由于层级关系太复杂,还是很混乱无法预测。这就是Scratch层叠关系设置欠合理的地方。

所以我们在使用层叠关系时候应该坚持一些原则:

  1. 例如尽量不使用多于3层的层叠关系
  2. 如果一定要使用多层次关系,那么在设定层级关系时请使用微小的等待时间差距来自己控制层级顺序
  3. 对于一直要处在最上层或者最底层的角色,请使用重复执行移到最上层或下移10层的脚本控制角色
  4. 更好的层级控制方法是在舞台上使用发送消息并等待积木,实现多角色之间的顺序设置层级
    层级关系设置原则

显示隐藏

在角色的属性盘之中,我们也可以设定角色是否显示。且Scratch的显示隐藏还有各类特效和画笔都是记忆状态,换句话说如果某次运行我们让角色隐藏了,那么下次再运行程序,角色还是被隐藏的。这次画的画,如果没有在下次开始时清空就会存留下去。

所以我们如果要使用隐藏积木,请一定记住让显示积木跟在“当绿旗被点击”积木后面。成对使用积木的规律我们要遵守以下三条:

  1. 隐藏和显示
  2. 外观特效和清除特效
  3. 画笔图章和清空

事实上更加广义的来说,这是一个将程序初始化的过程。任何的程序都需要妥善的初始化,你需要做两件事情:

  1. 将所有的状态都清空或者设为初始值
  2. 将所有定义的变量都赋予一个初始的数值

把所有角色都置于你已知的控制范围内,这是防止程序逐渐庞大后出现奇怪问题的预防针。

声音

Scratch声音控制分为两类

  1. 角色携带的音轨播放
  2. Scratch合成音符播放
    声音积木

播放声音

我们可以把角色携带的声音用积木块播放出来,这主要作用是播放音效,例如吃到金币的音效,被打击的音效等等。我们还可以选择

  1. “播放声音”:打开声音就让脚本继续向下执行
  2. “播放声音并等待”:打开声音不放完就不往下执行脚本

一般情况下要使用第一种,这样让角色播放音效的时候相当于打开了音乐就继续去做别的事情,不耽误后面的程序运行。但是要注意的是,如果要播放游戏结束音效,我们打开声音后面跟着一个“结束全部”积木,那么声音就听不到了,因为播放声音了之后马上结束了所有脚本的运行。

但是我们又不想播放声音并等待,因为那样会造成角色阵亡了还可以乱动,直到结束音乐播放完毕才可以停下来脚本。这种问题我们有两种解决方案可以参考

  1. 使用“播放声音”+“消息”+“结束角色身上其他脚本”积木,消息通知舞台上所有其他人停止。
  2. 使用“播放声音并等待”+“消息”+“结束全部”,通知本角色身上关于运动的脚本停止。

播放音符

Scratch的播放音符可以实现打击乐器和乐音乐器两种效果,通过数字编号0到200对应了十二平均律的各种音高。这样我们就可以用变量来控制音符的播放了,这样可以播放我们自己的乐谱。然而Scratch的音符是通过正弦波频率来合成的,低于40编号的音符听上去很奇怪,而且无法实现连续音符的过渡,所有的音符都是单独的,并不能实现什么优美得音乐效果。所以如果想播放音乐,还是使用外部导入音乐来的方便。

画笔

Scratch的画笔是角色坐标和外观的延伸。

  1. 落笔抬笔指的是在角色中心,也即是角色坐标位置落笔
  2. 图章指的是将角色现在的造型印在背景上

    画笔积木

    需要说明的是:

  3. 画笔和图章都直接画在了舞台背景之上,如果有其他角色,将会覆盖画笔的内容。因为舞台在Scratch之中是默认最底层的,不可能有比舞台还底层的东西。

  4. 画笔图章和角色隐藏与否无关,隐藏的角色依旧可以画笔和使用图章。
  5. 画笔和图章之间是可以互相覆盖的,后画的覆盖先画的。

对于画笔来说,Scratch 3.0之中可以完整的设置色相、饱和度和明度,也即是HSB颜色空间。在Scratch 2.0中我们只能设置画笔颜色为0到200为红橙黄绿青蓝紫的色相,饱和度是固定的。

作为代替,我们可以使用取色器设定画笔颜色积木块来设置其他颜色。不过麻烦在于我们没有办法取Scratch软件外的颜色,除非我们把色卡做成一个角色造型,导入到Scratch之中,然后使用取色器取用颜色。

其实Scratch留有一个RGB的后门的,取色器设定画笔颜色积木块可以放入一个变量。我们可以用这样的方式来控制RGB和透明度Alpha。

取色器的RGB后门

应用上,画笔大多是和运动控制结合使用的。然而我们总是局限于运动物体速度过慢的情况,这种情况下我们要使用自定义模块的运行不刷新屏幕模式来实现快速画笔。该模式将在自定义模块部分详细介绍。另:截止到写作时间为止,未发布的Scratch 3.0项目之中,使用自定义模块是默认不刷新屏幕的。

事件

Scratch之中圆顶的积木称之为脚本入口,也即是当他们等待的条件满足时,就开始下面连接的脚本。Scratch有六大脚本入口

  1. 绿旗入口
  2. 切换背景入口
  3. 角色点击入口
  4. 按键入口
  5. 声控入口
  6. 消息入口
    事件积木
    其中前五个入口是可以由人为发起的,最后一个是角色之间互发消息发起的。这里面最常见的绿旗入口我们几乎每天都要用到,但是我们真的了解绿旗入口么?

绿旗入口

我们究竟需要几个绿旗入口?前面在讲解层叠关系时说到了绿旗入口的Scratch内核注册顺序问题。虽然说计算机内部都是顺序执行的,但是我们还是在编写并发程序,也即是说许多绿旗入口在你一次点击之下会集体开始执行。在这种可怕的无法预测的情况下,我们需要做到的是防止两个绿旗入口下的脚本互相干扰。例如一段代码把一个变量改变了一个数值,另一段代码又改回去,一段说要停止程序,另一段却又开始等等。合理的拆分程序到不同的绿旗入口之下是一种必要的程序逻辑训练,如果有条件和耐心,不断地重新编写一个程序,以求更加的清晰和优化,这会极大地有助于编程思维能力的提升。

笔者的计算机课程老师经常教育笔者:如果发现程序错了,全部重新写一次,那将比你试图修改要快的多。而且你将有机会重新审视自己这段程序的逻辑,是最好的训练之一。

我们要坚持的原则是:

  1. 把互相无关的东西放在不同的绿旗入口之下。
  2. 检查程序流向是否会互相交叉干扰,同一个消息只有一个发送者,同一个变量同时只有一个更改者。

好事者又要提问了,如果同时一定有好多角色可以操作到某个变量,应该怎么办?

答案是,应该加锁,这个过程将在后续章节之中介绍。

切换背景入口

切换背景入口是为了不同关卡的场景切换而生,进入规定关卡则执行该入口下的内容。建议在设计复杂的多关卡游戏时,只在总控制部分放置切换背景更改状态的脚本。如果每个角色身上都带有此类脚本,而背景又经常切换的时候,逻辑将变得及其复杂,调试起来十分痛苦。

角色点击入口

角色的点击入口又要牵涉前文提到过的拖拽角色优先级最高。我们可以尝试简单的放下:当角色被点击则角色大小增加10。在编辑器状态下点击角色,角色将被拖拽起来而不会执行增加大小的积木。在播放器状态下,点击角色可以看到角色增加了大小。

而且更重要的一点是,这个入口是一次性激发的,也即是我们如果在播放器状态下对角色点着鼠标不放,角色大小只会增加一次。要想执行第二次必须松开鼠标按键再次点击。这种防止被多次触发的机制也让该入口成为Scratch最安全的入口之一,当然前提是在播放器状态下。

按键入口

刚才我们讨论了角色被点击入口,大家可能还不能理解入口被多次触发带来的困扰。现在麻烦就要来了。

假设我们要写一段脚本,当向上键被按下时,角色的y坐标增加10。使用如下代码,当我们长按向上键时,可以观察到角色首先向上移动了一下,接着开始快速向上移动,中间发生了一个小的卡顿。好像向上窜了一下才往前移动,控制起来十分不流畅。

按键入口控制角色移动

为什么会发生这种奇怪的现象?

这是因为Scratch对于积木块执行速度的有特殊的控制。Scratch既想让按键可以单独的控制某个动作,不至于因为单独按键发生了连续执行的效果,又想让按键可以产生连续的控制这个动作。

这种矛盾的做法让按键入口很难作为角色移动的控制。一般来说我们要使用重复执行和侦测判断按键来实现稳定的角色移动控制。代码如下

重复执行加侦测判断控制角色移动

为什么重复执行价侦测判断的方案就可以稳定的控制角色移动呢?这要从游戏引擎说起了,任何一款用作游戏开发的引擎必然会自带一个执行速度固定的语句。

我们要实现角色以一个固定速度移动,我们只需要让他固定时间长度往前移动固定步数即可。设想这个语句的执行时间不固定,角色的速度也会不固定,这样就没法实现最简单的匀速运动。

熟悉游戏开发的朋友可能知道,在Unity编辑器之中有一个FixUpdate()语句,可是实现固定时间长度的运行。高级的物理引擎也都是基于这个语句实现的。在Scratch之中,为了不把这个问题展示给初学者引起不必要的迷惑,开发者们聪明的将重复执行积木变成了这个固定时间长度语句。也就是循环中间装入不是很多语句的时候,每次循环中间的语句执行完毕的时候还会等一小下,把一次循环的总时长补到大约是0.03s左右(测量并不准确)。

重复执行时间示意

因此,我们把“重复执行”积木之中放入一个“移动10步”积木,就可以实现角色的移动。究其根本是因为重复执行锁定了每一次执行的时间。

好事者又想问,如果我们往重复执行里面放入许多耗时极长的语句,会不会挤爆重复执行语句?

答案是不会,一旦重复执行之中包含的语句超过了重复执行锁定的时长,重复执行的时间就被撑长了,撑到执行完中间包含的所有语句。

声控入口

Scratch可以调用麦克风识别响度数值,如果响度大于某数值则该入口开启。声控入口和角色点击入口一样是一个单次入口,也即是开启之后必须等响度小于这个数值之后才能第二次开启。不会产生多次开启的情况,也是一个比较安全的入口。

消息入口

消息入口也称为消息接收器,是六个入口之中唯一一个不能靠人为开启,只能靠程序控制的入口。角色的消息既可以发给别的角色,也可以发给自己,还可以发给舞台上的脚本。这部分内容在后续内容将会详尽介绍。

侦测

Scratch的侦测积木分为以下几类:

  1. 距离和坐标侦测类
  2. 角色信息侦测类
  3. 视频响度侦测类
  4. 询问回答和计时器
  5. 碰撞侦测类
  6. 按键侦测类
    侦测类积木

侦测积木主要会产生两类结果。一类是数字,例如:坐标值、距离值、视频变动剧烈程度、响度、计时。另一类是布尔值,也就是真或者假,例如:是否按下了鼠标按键、是否按下了某键盘按键、是否碰撞某角色某颜色等。

距离和坐标侦测类

该类积木主要作用是获得和某角色或者鼠标指针的距离,获得鼠标指针的位置。可以方便的实现一些例如防御力场之类的效果,例如距离某角色50步就无法继续前进。也可以获得和鼠标之间的距离用来实现鼠标操纵。

角色信息侦测类

该积木可以实现在某角色身上的脚本中获知其他角色状态的功能。例如某boss想根据玩家角色的坐标值做出一些反应,就要依靠这块积木获得玩家角色的坐标值。

如果不想使用这块积木,我们仍旧有替代方案。那就是把玩家角色的坐标值赋值给一个全局变量,然后所有人都可以看到这个变量。但是,这难道不是多此一举么?为什么要绕一个弯做这样的事情?

其实这种做法是有使用场景限制的,如果某个数值有许多人都要读取,那么最好把它做成一个全局变量。这样当我们要改写程序的时候,只需要改变这个全局变量就好,只需要动这一个地方。假如我们在每一个用到这个数值的地方都用侦测角色信息的积木这样使用,那么我们如果要改动就要改动好多地方,这时候疏漏和麻烦就找上门了。

不要一味地使用角色信息侦测积木,合理的使用变量可以方便我们做出易于更改维护的程序

视频响度侦测类

这是一个帮助文档也稀里糊涂解释的东西,它包含两个内容:

  1. 视频动作(motion)对于角色
  2. 视频方向(direction)对于角色

视频动作其实是角色对应视频区域之中,画面活动频繁程度的一个数值。角色对应区域画面如果没有任何移动,那么该数值将会很低,甚至接近零。为什么不会真的变成零呢?这是因为摄像头和环境都有微小的抖动,肉眼判断不出的运动计算机可以感知到。如果该区域画面之中活动剧烈,这个数值将会激增。Scratch官方以此为根据做了一个切水果的游戏,就是检测落下水果对应视频区域画面活动剧烈程度,判断是否被人手在视频中切中。

好事者又来提问了,假如我们让一个苹果从舞台上方逐渐掉落,那么苹果背后的视频和苹果发生相对运动,在苹果的眼中视频动作应该很高才对,是这样的么?

答案是不会的,我们可以简单地实现一下这个场景,就会发现这个数值根本就在0左右没有动。原因是Scratch的运行和拍电影一样是一帧一帧执行的,只是速度很快的时候我们肉眼无法分辨觉得它在运动。每一次视频动作检测都在角色移动了微小一步之后发生,这时角色已经停下,下次微小移动还没发生,当然不会和视频有相对运动。

角色移动中的视频动作检测

视频方向这个概念就更加迷惑了,这个数值好像一直就在狂跳从没稳定过。其实这个视频方向指的是角色对应视频区域里面视频运动方向。如果不理解的话,我们来做个试验。

视频方向检测实验
  1. 首先画一个占据舞台的大圆球作为角色1,如果没有完全占据则调整外观角色大小。首先将圆球设置外观特效为虚像80,打开摄像头,然后把视频方向对于角色1的赋值给变量dir。
  2. 画一个指向默认方向90°的方框,中心设置见上图。让该方框的方向重复执行始终指向dir。
  3. 运行观察,在大圆盘内挥手观察角色2指向的方向。

我们可以见到,手臂在视频中朝向哪里挥动,角色2就像指针一样指向了哪里。但是值得注意的一点是,这个方向十分不稳定,跳动还是有些剧烈,不适宜直接使用。本书将在后续章节滤波器之中讲述如何让该数值稳定下来以便使用。

此外关于视频处理要补充的一点是:无论我们将视频透明度设置成多少,哪怕设置成100完全看不到视频图像,动作和方向检测依然不受影响的生效。

相对检测相对于视频检测就容易理解的多,无非是麦克风输入的声音大小会变成一个响度数值。在之前的响度入口之中也可以直接使用。在此不做详述。

询问回答和计时器

熟悉文本语言的读者应该一眼就瞧出来询问回答就是C语言中的scan,为了输入变量而生。一般的用法是:

  1. 向询问框之中放入字符串变量,例如列表中存储许多问题,抽出一条放入询问框
  2. 询问之后程序会等待用户作答,按Enter键之后,这个答案就被存储进了回答变量之中
  3. 将回答变量用在别的地方,例如判断是否答案正确

计时器变量大家十分熟悉,但是却并不一定知道如何把他玩出花活。这里就举两个例子帮助大家打开思路,例子实现在后续章节介绍

  1. 使用计时器和自定义的变量配合实现蓄力攻击的效果
  2. 使用计时器实现连击效果,要知道连击的触发只在一段时间内有效

另一件值得注意的事情是,Scratch的计时器和等待1秒积木,归根结底和其他语言之中的wait(),delay()差不多,并不是真实世界的时间。其实Scratch是留了最精确的时间取值点的,那就是一个不起眼的“自两千年至今的时间”积木。

  1. “等待1秒”积木的运行和Scratch的软件运行有关,软件卡顿则计时卡顿,所以最不准确。
  2. “计时器”积木的运行和CPU的运行有关,计算机卡顿则计时卡顿,所以第二不准确。
  3. “自两千年至今的时间*1000”(或者1000以上)所获得时间是获取网络时间,最为精确。

碰撞侦测类

这类积木可以说是最常用到的积木了,角色之间发生交互,被子弹击中等都要靠它们来实现。是否碰到某角色和鼠标大家凭直觉都会使用,就不在此赘述。这里要主要说的是碰到颜色的应用场景。

Scratch提供了两类颜色碰撞侦测,角色碰到某颜色,角色的某颜色碰到某颜色。这里依靠取色器规定颜色,当然也可以用我们之前介绍画笔取色器时说到的RGB后门来规定颜色。颜色碰撞有两类用法:

  1. 区分碰到一个物体上的不同部分。我们称之为一化为多
  2. 用许多角色共有的一种颜色碰撞检测语句,来代替多条碰撞角色检测语句,我们称之为多归为一

一化为多的举例:由于Scratch没有自带物理引擎,许多角色间碰撞和反弹实现起来总是比较尴尬,补充方法就是依靠颜色检测来实现。假如我们想知道是撞到了一个角色的侧面还是撞到了顶面。这时候就只能画上一些可以区别的颜色,通过颜色就可以判断是撞到了哪个部分。

多归为一的举例:假如舞台上有好几种敌人,玩家角色碰到敌人会阵亡。那么最好在设计的时候就把所有的敌人都标记上共同的一个颜色,只要在玩家角色上检测是否碰到该颜色,就知道是否碰到了敌人。否则我们就要写出碰撞所有敌人的语句十分麻烦。

此外,角色的某颜色碰到某颜色,适用于判断角色的某个部分是否碰到另外角色的某部分。

按键侦测类

该类积木的使用场景均在键盘和鼠标控制之中,后续章节会主要介绍。

运算

Scratch的运算分为三类

  1. 数字运算
  2. 字符串运算
  3. 布尔值运算

运算积木

数字运算

Scratch的数字运算没有括号,每一个积木就相当于一个积木,所以请大家关注一下运算的优先级关系。尤其是多层嵌套之后往往会看花眼。这时候的解决办法就是,多设置几个中间变量打散计算步骤,这样也可以检查计算中的数值出现的问题。

除了四则运算之外,Scratch提供了两个方便的运算积木,求余和四舍五入。在文本语言之中,求余可以方便我们获得数字的某一位或者某几位。然而在Scratch之中,数字和字符串是界限不明显的。我们可以把数字当成字符串,接着使用字符串运算的提取某一位字符来实现获得数字的某一位。

Scratch还给我们提供了包括乘方开方、上下取整、反三角函数和指数对数在内的一个较为强大的科学计算积木,在后续的数学章节之中我们会着重介绍这些工具。

字符串运算

Scratch之中的字符串工具可以使用在许多地方,包括使用字符串链接工具和变量组合来实现对于角色外观声音背景等的切换。读者可以自行尝试,所有可以从本地上传的例如音乐图片等均可以通过字符串变量来控制切换。

例如我们向一个角色上传了十段音乐,命名分别为:音乐1、音乐2、音乐3……我们可以使用如下的积木来实现批量播放音乐。

字符串连接批量播放音乐

布尔值运算

首先要说的是什么是布尔值,为什么要有布尔值。

布尔值只有两个,一个是True另一个是False。布尔值的产生是为了让计算机学会应对真实世界情况。小到游戏之中一个角色被子弹击中会扣血,大到火箭发射按钮,全部都是由布尔值操纵的。

设想一种情况,我们想让计算机在周围声音很大时作出一些反应,那么步骤应该是:

  1. 真实世界被传感器处理,例如我们可以获得一个响度数值,这个响度数值有时大有时小。
  2. 我们要设定一个值50,然后写一个布尔单元:如果大于50就为True,如果小于等于50就为False。
  3. 计算机就会在现实世界声音很大后作出一些反应。

但是现实世界往往更为复杂,让计算机作出判断的条件也更多,甚至条件之间要互相影响。比如我们想让计算机在中午12点之后对于周围声音很大作出反应,那么步骤将被改写为:

  1. 真实世界被传感器处理,例如我们可以获得一个响度数值,这个响度数值有时大有时小。
  2. 另外有一个时钟传感器,可以获得时间。
  3. 设定“声音大于50”布尔单元,设定“过了12点”布尔单元
  4. 进行布尔运算得到:“声音大于50”并且“过了12点”
  5. 计算机将会对过了12点之后的声音很大作出反应

这样我们处理问题的完整流程应该是:

  1. 真实世界
  2. 传感器获得数值
  3. 设置布尔单元处理单个传感器
  4. 对于多个布尔单元进行布尔运算得到一个结果
  5. 让计算机对于计算结果布尔值进行反应
    布尔运算的意义

数据

Scratch自带两种数据结构,变量和列表。一共有以下几类积木:

  1. 变量赋值、变量增值
  2. 列表增删改查,列表长度信息
    数据积木

变量

变量在创建时会被询问作用域,也即是询问是对舞台上所有角色有效,还是只对当前角色有效。对所有角色有效的变量我们称之为全局变量,只对于角色自己有效的变量我们称之为私有变量。不同角色的私有变量可以重名,这就省去了我们命名的麻烦。

如果想给每一个克隆出来的角色加上一个血量值,那么我们必须用到私有变量。如果不小心设置了全局变量,那么一个角色死亡时,所有的克隆角色都将死亡,这显然是不合理的。

还应注意的是,在以往的scratch版本中,我们在导出角色到计算机,或者是复制角色的时候。角色身上的脚本使用的变量全部会被保存下来。我们再把这个角色导入另一个程序之中,运行的同时,角色身上原有的,所有当前程序没有的全局变量,统统会被Scratch自动创建出来。这是一件很危险的事情,在我们编写复杂程序的时候,很容易引起变量间的混乱。而在最新版的Scratch中,这个问题已得到解决,复制角色的时候,只有私有变量会保存下来。

不管怎样,我们要尽量的使用私有变量,可以私有的变量都设为私有,这样在复制或者导入导出角色时,会减少许多因为全局变量带来的麻烦。

列表

Scratch的列表的操作十分简单,无非是增删改查四类,再加上一个判断列表长度。值得注意的是,列表并不会在程序运行时自动更新,这种特性有些类似于数据库。如果要刷新列表,请使用删除全部列表数值积木。

列表创建之后,会在舞台上显示,这时在舞台上右键列表可以导入导出数据。列表支持txt格式,以换行符区别列表不同的项目。换句话说,我们创建一个txt,在里面写入数据,回车换行就可以把数据导入到Scratch的列表之中。

这种导入有什么用武之地呢?这里列举几个场景供大家参考:

  1. 用别的语言写好的曲线坐标方程,可以通过x、y两个列表导入Scratch绘制复杂图形
  2. 乐谱可以通过列表导入实现Scratch音乐播放
  3. 语言问答库可以通过列表导入之后制作问答机器人

控制

Scratch的控制积木分为四类

  1. 循环类
  2. 条件分支类
  3. 等待停止类
  4. 克隆相关类
    控制积木

循环

Scratch提供了三种循环积木,分别是

  1. 无限重复积木
  2. 计数循环积木
  3. 条件跳出循环积木

无限循环积木也称之为“死循环”,应用极其广泛。任何一个系统在启动的时候都进入了一个死循环,无条件的重复一些语句,例如监听某个按键是否按下,判断是否碰撞某个角色,一直重复某种运动等等。在前面按键入口的地方曾经叙述过Scratch死循环的运行最短时间固定特性,在此不重复讲述。

要注意的原则是:尽量少让消息入口下面使用死循环,可能会产生一些令人迷惑的结果。

计数循环积木,可以循环规定次数,然后继续后面的积木运行。这个积木值得注意的是,我们是否可以动态的更改循环次数?例如我们用一个变量i来规定循环次数,在该循环之中不停地改变i的数值,那么循环的次数会根据i来改变么?

答案是不会,Scratch的计数循环只会记住第一次传入的i的数值,并严格执行这么多次循环然后跳出循环。这是为了防止儿童在编程时动态的改变循环次数产生错误。Scratch里面不可以在程序之中新建变量和列表,原因也是如此,这样可以防止儿童在使用时产生程序崩溃。

条件跳出循环积木每次执行前都会判断条件是否成立,如果条件不成立就不进入这一次循环。这个积木很好的补充了Scratch没有break语句的缺陷。

条件分支

条件分支积木十分简单,只有if和if else两块,不做赘述。

等待和停止类

等待?秒是Scratch最常用的控制运行节奏的语句,经常和重复执行动作配合使用。但是要注意的是,因为循环执行最短时间固定的特性,等待?秒如果设置的时间过于小,将变得毫无意义。因为Scratch还是会自动补全时间到循环的固定最短时长。

需要注意的是等待?秒积木也会自动补全时间差,该积木有一个最短运行时间大约是0.033s,和循环最短时间一致,具体应用细节请参考后续章节scratch疑难问题举例

在条件到达之前一直等待积木十分有用,可以方便的帮助我们消除某些二值条件的重复影响。

例如,当我们按下空格的时候要执行一个动作,不论我们是用按键入口方法实现,还是用重复执行+条件判断按键是否按下来实现。当我们长按空格的时候,动作会被病态的重复好多次。这时候我们就要依靠等待“空格键按下不成立”的来实现长按屏蔽。只有当空格键抬起,这条等待语句才可以继续向下执行循环。

防止空格长按的正确和错误写法

停止积木有三种:

  1. 停止全部,等同于绿旗边上的红灯,结束全部舞台上的程序
  2. 停止当前脚本,停止本段脚本
  3. 停止角色其他脚本,停止角色身上除了本段脚本之外的所有脚本

需要注意的是:停止全部有时候并不能真的停下我们全部的程序,原因可能是程序有绿旗入口之外的别的入口。虽然程序被停止了,但是入口又被按键声音等激发打开。妥善的停止程序运行是一个很细致的工作,有时候游戏角色阵亡,但是还有一系列特效和动作没有播放,这时候不能贸然停止全部。要用消息等待等方式确保所有舞台其他角色都停止运行,然后再停止全部。

克隆相关类

Scratch和一系列游戏编辑器一样,都需要克隆功能,来制造批量的敌人、子弹、背景等角色。克隆积木分为

  1. 克隆动作
  2. 克隆体入口
  3. 删除克隆体

克隆动作可以由本角色发出,克隆自己。也可以由别的角色发出克隆某角色。推荐的方法是,使用舞台作为克隆的总控制器。防止脚本理解和管理混乱。

克隆体入口是决定克隆体和母体区别的关键,母体并不会运行该入口下的脚本,只有成为了克隆体才会执行该入口以下的脚本。通常的做法是,将母体大小和造型等设置完毕后隐藏,在克隆体启动入口下将克隆角色移动到规定位置后显示。克隆之中的细节问题将在后续的克隆专题之中详尽描述。

更多积木

Scratch的更多积木之中涉及函数制作和硬件相关两种,本书不牵涉任何硬件的内容,单独介绍自定义模块(函数)制作。

自定义模块定义

自定义积木和文本语言的函数功能类似,只是没有返回值的存在。意义在于打包某功能之后重复使用。可以设置参数,这里包括了数字参数、字符串参数、布尔参数三类。分别对应Scratch的三种变量类型。

好事者又来提问,如果我们定义两个自定义积木,分别定义他们的参数。他们都包含一个叫做num的参数,那么这个从定义条上拖出来的参数可以互换着使用么?

答案是,可以的。Blockly的底层还是文本语言,重名的不同函数参数可以互相放置,不会产生问题。

自定义积木最关键的使用方法是运行时不刷新屏幕,一旦勾选了这个选项,入口下的所有循环都被取消了固定的最小运行时间,运行速度大约会提升1000倍,所有程序跑的飞一样快。但是一旦不小心往这里面放置了很多语句,电脑就会被卡住。这也是风险所在。

还需要注意的是Scratch自带的加速模式(编辑菜单下)并不建议使用,因为很可能会让计算机死机。

results matching ""

    No results matching ""