目录
日常生产生活中常用的按键开关有自锁按键和自复位按键。自锁按键,就像我们平时家中墙壁上安装的面板开关,其特点就是按一次后会自动锁定在开或者关的状态,如果要想切换开关状态,需要再按一次。

而自复位开关,就像一个弹簧,当按下去的时候是关闭状态,手一松,开关会自动弹起来,恢复成打开状态。这种开关一般用于点动控制,按一次会触发一次动作,长按则会一直触发动作。比如汽车的油门和刹车,鼠标和键盘的按键,遥控器的方向按键,还有一些设备的脚踏开关等。

那么在scratch中怎么实现这两种按键开关的功能呢?下边做一个简单介绍。因为这两种按键开关都有开和关的两种状态,为了让操作者能看清按键有按下和弹起的动态感觉,在scratch中需要给按键这个角色设计两种造型。

如图3所示,这个软件系统自带的按键,就有两种不同颜色的造型,我们把蓝色的看做是弹起的状态,橙色的看做是按下的状态,两种颜色也可以反过来代表开关状态,完全根据个人习惯而设定。
(一)自锁按键
下面用一个按键控制灯开关的小例子来说明一下,如何编写程序实现自锁按键功能。
例1:自锁按键控制亮灭
在这个例子中,用一个按键代表灯的开关,软件自带的彩色的球代表一个灯。

这个彩色的球一共有5种造型,我们只保留蓝色和橙色,蓝色代表灭,橙色代表亮,其他的造型删掉,如图1-5所示。

下边介绍一下可以实现这个自锁按键的功能的两种方法。
1、用“下一个造型”实现
当角色被点击时,就切换到下一个造型,因为角色只有两个造型,当处于第1个造型时,点击一下,切换到第2个,再点击一次又切换回第1个。下图是最简单的一种自锁按键开关程序。
按键角色程序、灯角色程序分别如图1-6所示、图1-7所示。


程序中,开关和灯的通信是依靠广播来完成的。这个广播是一种控制信号,可以在不同角色间传递信息。在本例中就像是开关和灯之间的电源线。
在按键这个角色端,如果当前是蓝色造型,当角色被点击时,切换下一个造型,也就是橙色造型,代表开关按下,此时广播信息“打开”;如果当前是橙色造型,当角色被点击时,切换下一个造型,也就是蓝色造型,代表开关关闭,此时广播信息“关闭”。
在灯这个角色端,当收到“打开”信息时,灯切换到编号为1的造型,也就是橙色造型,代表灯亮;当收到“关闭”信息时,灯切换到编号为2的造型,也就是蓝色造型,代表灯灭。
2、用“换成具体编号造型”来实现
当角色被点击时,如果造型是第1个,那么就切换到第2个,否则造型是第2个,那么就切换到第1个。按键开关角色程序如图1-8所示。

灯的程序依然不变,还是如图1-7所示。
理论上,这两种方法都可以实现自锁按键的功能,但本人推荐使用第2种方法,因为此种方案中,切换造型和广播这两句代码是紧挨着的,换完造型马上进行广播,时间差相对短,信息传递受到干扰而误触发的可能性较小。而第1种方案,在切换造型和广播之间,还有一句判断开关状态的语句,判断完再进行广播,更换造型和广播之间时间差相对较长,信息传递受到干扰而误触发的可能性要比第2种方案大一些。
(二)自复位按键
下边再看下自复位按键控制灯亮灭的例子。
例2:自锁按键控制亮灭
自复位按键,需要用到“碰到鼠标指针”和“按下鼠标”两个模块来实现。程序如图9所示。实现这个功能的关键点有两个:第一,必须碰到鼠标指针和按下鼠标两个条件同时具备,才表示手在按下按键,鼠标一旦移开,或者抬起,就表示松开了按键,按键就处于断开状态了。第二,开关是否按下要持续进行检测,一旦出现变化就立刻响应,所以开关是否按下的检测要放到重复执行模块之中。

(三)自锁按键的拓展实例
例3:单选按钮
在多个项目中,选择其中一个项目,进行后续的操作。最常见的情形,就是单选选择题,答案只有一个,要求做题者只能选则一个答案进行提交。单选按钮的特点是,只能选择一个按键按下,如果改变选择,又按下了另外一个按键,原来被按下的那个按键会自动弹起来。
(1)角色设计
从角色库里选则字母A、B、C、D四个字母。

字母角色只有一个造型,为了显示出被按下的状态,需要给这四个字母增加一个不用颜色的造型。操作方法是在造型编辑选项内,复制一个造型,然后把复制的这个造型的前景色填充为不同颜色即可。四个字母都需要进行同样的操作。

(2)设计思路
单选按钮这种情况和例1的区别在于:例1是按键角色是命令发出者,灯角色是命令接收者,二者是单向的主从控制关系。而本例中,几个按钮地位是同等的,既是命令发出者,又是命令接收者,控制关系是双向的。所以这种情况下,广播的意义不是命令,而是告知。告知的内容是“自己被按下了”,当其他角色接收到告知后,无论是之前处于被按下的状态,还是弹起的状态,一律要变成弹起的状态。需要注意的是:广播是针对舞台内所有角色的,包括自己。那么问题来了,发出告知的角色也会接到自己发出的告知,同样会执行弹起的动作,这样就会导致自己刚被按下,然后又会弹起,这样就会出现无法选择任何角色的情况。
如何解决这个问题呢?那就需要所有角色在接收到告知后,能区分出是自己发出的,还是其他角色发出的。如果是其他角色发出的,那要执行弹起的动作;如果是自己发出的就不弹起。
那又怎么能区分这个告知的来源呢?最常见的做法就是要在告知的同时,要把自己的ID号也能通知到其他角色。告知以广播的形式创建,广播的消息名为“按下”。

按下按钮的ID号要用一个全局变量来进行存储,这个变量我们命名为“按下按钮ID”。
创建全局变量,需要在创建时选择“适用于所有角色”,如图所示。因为每个按钮被按下后,都要把自己ID号写入到“按下按钮ID”,并且其他角色也需要同步知道ID发生变化了,所以需要用全局变量。

我们还需要给每个角色创建一个局部变量来存储自己的ID号,方便后续的程序引用,也方便程序在不同角色之间进行移植。这个局部变量名为“我的ID”
创建局部变量,需要在创建时选择“仅适用于当前角色”,如图所示。因为角色自己的ID只是用来标注自己身份的,不能在设定自己ID的同时,把其他角色的ID也修改了,这个设定范围只限定在自己,所以要用局部变量。

其实全局变量就相当于一个变量,而局部变量是多个变量,局部变量只是表面看起来名字是一样的,其实这个变量还有一个前缀,就是角色名,而角色名都是唯一的,不能重复,所以“不同前缀+相同变量”这种模式就保证了每个角色ID的唯一性。
如何区分已创建变量是全局变量还是局部变量呢?三种方法:
第一,点选所有的角色看看它的所有变量,如果某个变量只在部分角色中有,其他角色没有,那者变量一定是局部变量。如果每个角色中都有这个变量名,那这个变量名有可能是全局变量,也可能是局部变量。所以,要靠另外一种方法。
第二,如果每个角色里都有相同的变量名,如果勾选或取消其中一个角色中的这个变量,其他角色中的这个变量勾选状态会跟着变化,那么这个变量就是全局变量,如果只有在进行勾选或取消这个角色中变化,其他角色里没变,那么这个变量就是局部变量。
第三,那么最直观的方法就是勾选角色中的变量,让这个变量在舞台中显示出来,看变量的命名方式,如果变量名前边有角色名前缀,就是局部变量,没有前缀的就是全局变量。


(3)代码
准备工作做完,就可以给每个角色编写代码了,角色A的代码如图所示。把A角色的代码复制到B、C、D,在相应的角色代码中,只需要修改“将我的ID设为”这一句代码,把这个模块的参数,分别修改为“B”、“C”、“D”即可,其他代码不动。

注意,那些变量不需要在舞台展示,把变量前边的“√”取消即可,如图1-16所示。

(四)自恢复按键的拓展实例
例4-1:自恢复按键点动控制小球移动
(1)舞台角色设计

为了控制小球向上移动,方向设置为0°,如图所示。scratch角色方向的规定为:向上0°为起点,顺时针旋转半圈为负数0°~180°,逆时针旋转半圈为负数,角度值只能给整数值,如果输入了正小数,会按照四舍五入的方法变化为正整数,如果输入了负小数,则按五舍六入的方法变化为负整数。1.4及以下变为1,1.5及以上变为2,-1.6及以下变为-2,-1.5及以上变为-1。

(2)点击按键一次小球移动一次
这个实例的原理相对简单,直接上代码,自复位按键代码如图所示。需要注意的是,本程序中只有控制小球移动的广播指令,没有停止的指令,因为小球的移动完设定步骤后,自动会停止,所以,只需要控制开始移动即可。

小球代码如图所示,注意,在“移动10步”,这句代码前一定要加一个等待时间,这个时间作用是为了去按键的抖动。这个抖动是因为人手在按下去鼠标的一瞬时,手按下的力不是很稳定,会有轻微的抖动,每一次抖动,都会被系统误认为是一次点击,为了防止误报,所以在小球端,加一个等待时间,把那段抖动的时间滤掉,只响应鼠标按下去比较稳定的那段时间,就不会有误报了。

(3)长按自复位按键小球一直移动
自复位按键代码如图所示,注意,此例中,定义了一个"移动"全局变量,在鼠标按下的时候,这个变量赋值为1,鼠标抬起时赋值为0。

小球程序如图所示。注意,这个程序中加入了重复执行的语句,这是因为鼠标按下一瞬间的控制指令,被小球的等待时间给滤掉了,为了能检测到后边的稳定按下时刻的指令,必须要不断重复检测。程序中还加入了判断“移动”变量是否为1的语句,是因为如果不加判断语句,那么按键按下一次后,因为有重复执行的语句,小球就会持续移动,不会停止。
改进后的程序可以实现长按小球持续移动功能,也可以实现点击一次小球移动一次的功能。

(未完待续)