自制积木与屏幕刷新

在上篇文章的最后我给你留下了一个问题,有没有什么方法可以让重复执行积木不执行刷新?

答案是,使用自制积木,并且必须选中“运行时不刷新屏幕”选项。

下面我们就一起来看看运行时不刷新屏幕选项具体在做些什么。

当你运行下面的指令串时,每重复执行一次,Scratch就会对舞台刷新一次。你将看见小猫从(x:-100,y:0)位置,移动10次后来到(x:0,y:0)位置。

现在你可以制作一个新的积木“移动小猫”,勾选上“运行时不刷新屏幕”选项。

接着,将让小猫移动的指令串放入定义移动小猫积木中,变成下图的样子。

现在重新测试程序,你不会再看见小猫移动的过程,只能看见它停留在(x:-100,y:0)位置。

使用自制积木与不使用自制积木,程序的执行过程有什么改变?

当你制作一个自制积木,并勾选上“运行时不刷新屏幕”选项后,自制积木中的暂停点就会全部被忽略,Scratch会将自制积木中的所有指令作为一个整体来执行。

刚刚执行的自制积木相当于变成了下图这样。

为了验证自制积木中每次重复后不会暂停,你还可以进行下面的测试。

执行的过程如下:

  1. 事件一开始执行,执行移动小猫积木,执行过程不会暂停,角色重复3次移动10步和加入“事件一”。此时舞台不刷新。
  2. 事件一继续执行,将“事件一终止”加入列表,程序结束。此时舞台不刷新。
  3. 事件二开始执行,执行第1次重复,将“事件二”加入列表,达到暂停点,程序暂停。

此时执行队列中的所有事件到达暂停点,程序完成一轮操作,Scratch对舞台进行第一次刷新(角色向前移动30步)。

  1. 事件二开始执行第2次和第3次重复,将“事件二”加入列表。
  2. 事件二继续执行,将“事件二终止”加入列表,程序结束。

最终列表中的数据为下图这样。

接着,将两个当绿旗被点击积木下面的指令串交换一下位置,重新测试。

执行的过程如下:

  1. 左边指令开始执行,执行第1次重复,将“事件二”加入列表,到达暂停点,程序暂停。
  2. 右边指令开始执行,执行移动小猫积木,执行过程不会暂停,角色重复3次移动10步和加入“事件一”。此时舞台不刷新。
  3. 右边指令继续执行,将“事件一终止”加入列表,程序结束。

此时执行队列中的所有事件到达暂停点,程序完成一轮操作,Scratch对舞台进行第一次刷新(角色向前移动30步)。

  1. 事件二开始执行第2次和第3次重复,将“事件二”加入列表。
  2. 事件二继续执行,将“事件二终止”加入列表,程序结束。

最终列表中的数据会是下图这样。

看完上面的执行规则,现在你的脑子里会不会出现一个新问题。

假如你在自制积木中放入了一个不会停止的重复执行积木,Scratch会怎么办?

你可以将之前的重复执行(10)次积木换成不会停止的重复执行积木进行测试。

如果按照上面的规则运行,Scratch执行到移动小猫时,会一直停留在该自制积木中运行,说话积木永远无法执行。如果此时执行队列中还有其他指令串,它们也永远无法执行。舞台会停止刷新,你所看见的效果就是程序卡死,什么操作都不能执行。

为了避免上面所说的情况发生,Scratch会对上图的指令串进行一个特殊处理,强制每隔0.5秒就将自制积木中的指令暂停,并对舞台进行一次刷新。

你可以利用下图中的指令串进行测试。

执行的过程大致为:

  1. 左边的指令串开始执行,右转30度,计算器增加1后,到达暂停点,程序停止运行。此时不刷新舞台。
  2. 右边的指令串开始执行,进入移动小猫后快速执行不会停止。
  3. 等待0.5秒,Scratch强制暂停自制积木,此时执行队列中的所有事件到达暂停点,程序完成一轮操作,Scratch对舞台进行一次刷新(角色右转30度,计数器2变量增加1,角色移动一次,计数器变量增加几万,代表了在这0.5秒内重复执行的次数)。
  4. 重复1~3步,说话积木永远无法执行。

你还可以在自制积木中放入一个滑行积木测试,将滑行时间设置为1.3秒。因为滑行时间超过了0.5秒的强制刷新时间,所以你会看见小猫在舞台上移动了3次。分别是角色滑行到0.5秒、1秒和1.3秒时的位置。

现在你已经知道了自制积木勾选上“运行时不刷新屏幕”选项后的执行规则,以后当你再定义一个自制积木时,就要避免在它下面拼接拥有暂停点的积木(重复执行(10)次积木除外),因为它们的执行时间都可能会超过0.5秒,造成Scratch强制刷新,在舞台上出现你预料之外的效果。

最后还有一个与屏幕刷新相关的积木值得你注意,就是我们在实验中一直使用的计时器积木。

从它的样子你就可以知道,计时器积木只是一个变量,用来记录程序的运行时间。你有没有想过,它的变量值是如何更新呢?

你可以利用下面三个不同的指令串,分别来测试一下计时器时间的增长规律。

测试一,在重复执行中使用一个“刷新积木”。此时每重复执行一次,舞台将会刷新。

测试结果,每重复执行一次,计时器约增长0.033秒。

测试二,删除测试一中的“刷新积木”。此时重复执行一次后,舞台不会刷新。

测试结果,重复执行1万5千次左右,计时器约增长0.033秒。

第三个测试,将测试一中的重复执行积木放入自制积木中,并勾选上“运行时不刷新屏幕选项”。此时每间隔0.5秒,Scratch将强制执行一次刷新。

测试结果,重复执行30万次左右,计时器约增长0.5秒。

从以上的测试结果,你可以分析出什么结论?

计时器的时间并不是随时在增长,而是当Scratch执行刷新时,进行一次更新。通常情况下,每次刷新计时器增长0.033秒。当自制积木导致强制刷新时,计时器增长0.5秒。

为了验证上面的结论正不正确,你还可以自己增加其他角色和指令串进行测试。

平时你在使用并行事件完成一些功能时,经常会出现一些莫名其妙的BUG。例如我在《执行队列的运行规则》中留下的小练习。从逻辑上来看,程序似乎并没有什么问题。实际执行时,运行结果却总会与自己的预期不一致。

在Scratch没有按照你所预想的顺序执行时,就请你想一想每个执行时如何执行的,以便你能在实际开发中更快的解决问题。

Last Updated:
Contributors: lanheixingkong