Discuss Scratch

ScratchUser139
Scratcher
100+ posts

Scratch 解决方法指南 VII


Scratch 变通指南 Ⅶ
༺༻

大家好,欢迎来到 Scratch 变通指南的第 7 篇左右!请使用下方目录跳转到您想了解变通方法的区块对应的论坛帖子。继续阅读目录后了解更多信息!
常见问题

“workaround”是什么意思?

如果您使用 Scratch 编程一段时间,很有可能您一直在寻找一个根本不存在的块——某种您在任何现有块中都找不到的操作或实用程序!Scratch 团队会尽量将块列表保持在最精简的状态,以免让 Scratch 新用户感到不知所措或困惑(还有其他一些原因)。这意味着我们必须利用现有的积木来实现与现有积木类似的新行为。这就是“变通方法”——利用现有资源创造出新颖实用的东西!

有人告诉我,我的建议有变通方法。这是否意味着我的想法有问题或不足?

不!实际上,这意味着其他 Scratch 用户也曾有过与你相同或类似的想法,而由于你们想到的积木在 Scratch 中并不存在,所以他们想出了一种方法,利用现有的积木来实现类似的功能。Scratch 团队不经常向 Scratch 添加新积木的原因有很多。其中两个主要原因是,他们不希望 Scratch 让年纪较小或缺乏经验的学生感到不知所措,以及他们希望鼓励 Scratch 用户自己提出解决方案,而不是使用那些能立即给出所有答案的积木。

当有人告诉你你的建议有解决方法时,这并不意味着你的想法有问题。这只是意味着你不必等待该块被添加(这可能永远不会发生,或者需要很长时间)——因为 Scratch 已有的块已经提供了实现你想要的功能的方法。如果你感兴趣,阅读这些解决方法并尝试学习它们的工作原理是很好的,因为这样做既是在练习解决问题,也是在学习其他人如何找到解决方法!

许多块都有解决方法,但这并不意味着它们永远不会被添加到 Scratch 中。Scratch 3.0 中添加的几个块,例如“苹果包含一个?”和“列表中项目编号”,在添加之前很久就已经有已知的解决方法,但 Scratch 团队最终认为它们值得添加到 Scratch 中。

我确信有一个块有解决方法,但我在这里找不到。我该怎么办?

本指南还很新,所以请随时回复此论坛帖子,我会尽力回复您所需块的解决方法,并在可能的情况下将其添加到指南中!我并非每天都活跃,但通常每周都会活跃几次,所以我会尽快回复您。其他人,如果他们能跟上新的回复,也可能会回复他们自己的解决方法!

我知道一个解决方法,但它不在本指南中!你能添加它吗?

可能吧!请在回复此论坛帖子时分享它。请记住,有些解决方法我不太想添加到指南中。它们是……
  1. 针对 Scratch 中确实存在的块的解决方法。即使方法非常有创意,本指南也只介绍 Scratch 中不存在的块。请查看Scratch Wiki,了解现有区块的变通方法——那里比这里更合适!

  2. 指南中已有区块的额外变通方法,除非它们采用截然不同的方法。我很乐意分享多种方法,但它们必须截然不同——例如,将“重复几秒钟”的代码改为使用“自2000年以来的天数”而不是“计时器”,就不是一个足够显著的改变。这在某种程度上是基于个人看法,o 如果您觉得某个更改比我想象的更重要,我深表歉意(但欢迎您在论坛帖子或回复中解释您的理由,我会尽力倾听并考虑您的意见!)。

  3. 针对行为极其特殊或复杂的块的变通方法。尽管“平台物理”、“简单的多层”和“云列表”都是使用 Scratch 块创建的好主意,但它们过于庞大且复杂,无法包含在一个简明扼要的变通指南中。稍后,我可能会添加教程链接(交互式 Scratch 项目或其他论坛帖子和工作室),以更详细地解释这些想法,但我还没有完全决定。(我想先给指南一些时间,让它先从简单的变通方法开始发展!)
如果您建议或分享一个变通方法,并告诉我您希望将其添加到主指南中,则表示您允许我进行调整,以使其与此处其他变通方法的外观和风格相符。我会始终在解决方法旁边注明来源并链接回您的原始帖子!

之前置顶的 Scratch 解决方法帖子在哪里?

有很多,我可能漏掉了一些……如果是这样,这个帖子的标题就不准确了,抱歉

不过,以下是我所知道的!
  1. (2016) 终极解决方法清单及更多内容 作者:MathlyCat
  2. (2017) 终极解决方法清单及更多内容 ②.⓪ 作者:openPoll
  3. (2019) 常见建议区块的解决方法 作者:Computer_Fizz
  4. (2020) 常见建议区块的解决方法积木 作者:BearSlothCoding
  5. (2020) 常用积木的实用解决方法! 作者:shradibop
  6. (2022) 常用积木的实用解决方法!(第 4 版) 作者:Nezon
  7. (2022) Scratch 解决方法指南 VII 作者:_nix(您在这里!)
ScratchUser139
Scratcher
100+ posts

Scratch 解决方法指南 VII

完整目录 (在这里找到解决方法!)
动作、外观和声音
  • 指向 x: y:
  • 围绕精灵旋转:
  • 围绕 x: y: 旋转:
  • 以每秒:步数的速度滑行至 x: y:
  • 以每秒:步数的速度滑行至精灵:
  • 围绕 x: y: 旋转:

  • 是否显示?/ 是否可见?
  • 色彩效果报告器、旋转、马赛克、音效报告器等
  • 隐藏所有精灵
  • 上一个服装
  • 最后一个服装
  • 服装名称列表
  • 服装数量
  • 随机服装
活动 &控制
  • 当(任何条件)为真时
  • 布尔值:“我收到了(消息)”
  • 等待直到我收到消息1
  • 重复直到我收到消息2
  • 仅向精灵1广播消息1

  • 重复2秒
  • 当(条件)时
  • 执行… 当(执行…)时直到)
  • 针对 5 到 10 之间的每个整数
  • 停止此精灵中的所有脚本
  • 停止另一个精灵中的脚本
  • 是克隆吗?
  • 删除所有克隆
  • 克隆数量
运算符与传感
  • true,false
  • x <= y,x >= y
  • x 异或 y(排他或)
  • x 到 y 的字母字符串
  • 十六进制转十进制
  • x 是偶数吗?x 是奇数吗?x 能被 y 整除吗?x 是 y 的倍数吗?
  • x 是整数吗?x 是小数吗?
  • x 的小数部分 / x 的小数部分
  • 四舍五入到最接近的 100,四舍五入到小数位
  • x 的 y 次方(幂运算,x^y)

  • 到 x 的距离: y:
  • 鼠标点击了此精灵?
  • 鼠标拖动了此精灵?
  • 已启用 Turbo 模式?
变量与列表
  • 列表的最后一项、倒数第二项,等等
  • 列表的随机项
  • 将列表的第 1 项改变 10
  • 删除列表的最后一项
  • 针对列表的每一项列表
其他
  • 内联代码注释
  • 返回/报告(来自自定义块)

  • 额外:演示 - 上下文“右键单击”/双击菜单 (作者:Hotwheels_Fan101)
ScratchUser139
Scratcher
100+ posts

Scratch 解决方法指南 VII

运动外观声音⬆︎ 目录

指向 x: y:

方法 1:专用“指向”精灵

此方法使用简单的运动块、两个变量和一个广播消息来指向一个精灵,该精灵会自行移动到您想要指向的位置。您需要为此创建一个新的精灵——它不需要任何服装,因为它不用于在舞台上显示任何东西!

// 在任何你想使用“指向”的精灵中……

将 [指向 x v] 设置为 [200] // 这些变量“适用于所有精灵”。
将 [指向 y v] 设置为 [120]
广播 [prepare point towards v] 并等待
指向 [指向精灵 v]

// 在专用的“指向精灵”中……

当绿旗被点击时
隐藏 // 你不想让这个精灵可见!

当我收到 [prepare point towards v] 时
将 x 设置为 (指向 x)
将 y 设置为 (指向 y)

方法 2:三角函数“指向”

此方法使用三角函数“atan”通过数学计算你当前位置和目标之间的方向。

定义指向 x: (目标 x) y: (目标 y)
指向 ([atan v] 方向 (((目标 x) - (x 位置)) / ((目标 y) - (y 位置)))
如果 <(目标 y) < (y 位置)> 则
顺时针旋转 (180) 度
结束

围绕精灵旋转: (感谢 @hill_walker123!)

使用基本三角积木“sin”和“cos”来跟随圆围绕目标精灵的路径。(您可以通过拖出“操作符”底部的“abs of”积木并更改其下拉菜单来获取它们)菜单。)

定义围绕 (精灵) 旋转 (度) 度
将 [自定义方块运行前的方向 v] 设置为 (方向)
将 [距离 v] 设置为 (到 (精灵) 的距离)
指向 (精灵)
将 x 设置为 (((精灵) 的 [x 位置 v]) + ((距离 :: 变量) * (((方向) + (180)) + (度))) 的 [sin v]
将 y 设置为 (((精灵) 的 [y 位置 v]) + ((距离 :: 变量) * (((方向) + (180)) + (度))) 的 [cos v]
指向 (自定义方块运行前的方向)
顺时针旋转 (度) 度 // 这使得精灵看起来像是在沿着圆圈旋转。

此脚本使用几何概念来计算精灵的最终位置。它的工作原理是计算一个圆,其中心恰好位于目标精灵上,其中一个点就是正在奔跑的精灵的位置(因此,它的半径就是正在奔跑的精灵到目标精灵的距离)。它使用这个圆来计算如果精灵沿着圆周(指定度数)的圆弧运动,精灵将位于何处。

这里的许多块都与三角函数值之间的转换有关,并将它们转换回正确的值以显示在实际屏幕上。
  1. “cos”和“sin”块需要的方向范围是 0 到 360 度,而 Scratch 的“方向”块的范围是 -180 到 +180 度,所以我们加了 180 度。
  2. “cos”和“sin”实际上根本不处理距离,它们只是假设你讨论的是一个半径为 1 的圆,所以我们将结果乘以正在奔跑的精灵和目标精灵之间的距离,以缩放到正确的半径。
  3. “cos”和“sin”也不处理位置问题,它们假设你讨论的是一个以 (0, 0) 为中心的圆。因此,我们使用普通的加法块来平移(移动)该点,使其相对于目标精灵。
(请注意,如果你使用钢笔块绘图,由于它分两步移动,因此这种解决方法会产生锯齿状线条。你可以将“设置 x”和“设置 y”块替换为一个“转到 x: y:”块,效果相同。)

围绕 x: y: 旋转

方法 1:从当前位置沿圆周方向移动 (谢谢,@1080GBA!)

此方法结合了以下解决方法“指向 x: y:”(本文前面已提到)“到 x: y: 的距离”(请参阅此文! 并结合一些三角函数知识。如果你想让你的精灵围绕某个位置旋转,画一个包含精灵原有位置的圆,那么这样做就对了!

定义围绕 x: (x) y: (y) 旋转 (度) 度
将 [自定义方块运行前的方向 v] 设置为 (方向)
获取到 x: (x) y: (y) 的距离 :: custom // 查看解决方法!
指向 x: (x) y: (y) :: custom // 也来看看这个解决方法吧!
将 x 设置为 ((x) + ((到位置的距离) * ([sin v] of (((方向) + (180)) + (度)))))
将 x 设置为 ((x) + ((d距离到位置) * ([cos v] of (((direction) + (180)) + (degrees)))))
指向方向(自定义块运行前的方向)
顺时针旋转 (degrees) 度 // 这有助于精灵看起来像是在跟随圆圈旋转。

围绕精灵旋转:(就在这上面) 的解决方法一样,我们在 Scratch 的“direction”块中添加 +180,因为“cos”和“sin”的取值范围为 0 到 360,而“direction”的取值范围为 -180 到 180。我们仍然乘以距离,得到圆的半径——这次,我们使用另一种解决方法来计算距离!最后,我们使用普通的加法块来平移(移动)精灵,使其以该位置为中心。

(如果您使用钢笔绘图,这会生成锯齿状的线条。将“设置 x”和“设置 y”块合并成一个更大的“转到 x: y:”块,就可以绘制一个平滑的圆圈。)

方法 2:创建一个全新的圆圈
(此方法与 @Malicondi 的解决方法 略有不同,但它是基于此方法的——谢谢!)

此方法完全忽略精灵的当前位置,因此您可以自行指定圆圈的半径和当前角度。这种方法对于制作更复杂的动画非常有用!

定义围绕 x: (x) y: (y) 方向 (dir) 半径 (radius) 的圆
将 x 设置为 ((x) + ((radius) * ([sin v] of (dir))
将 y 设置为 ((y) + ((radius) * ([cos v] of (dir))

方向输入使用与 Scratch 的“指向方向”积木相同的规则:0 表示垂直向上,90 表示向右,180 表示垂直向下,以此类推。

(如果您使用钢笔绘图,这会生成锯齿状的线条。将“设置 x”和“设置 y”积木组合成一个大的“转到 x: y:”积木,它将绘制一个平滑的圆。)

以每秒:/ 步的速度滑行到 x: y: 到 x: y:

我们可以使用“glide: secs to x: y:”来执行实际移动。棘手的部分在于计算以指定速度移动需要多长时间!

首先,我们计算距离,也就是从精灵当前位置到我们想要滑动的位置可以画的直线的长度。然后将该距离除以指定的速度。这样我们就得到了以秒为单位的答案,也就是“glide: secs to x: y:”块所需的时间。

例如,一个精灵从 (0, 0) 滑动到 (100, 0) 总共移动了 100 步。以“每秒 25 步”的速度,总共需要 100 / 25 = 4 秒。以 10 的速度——慢得多!——总共需要 100 / 10 = 10 秒。

定义滑动(速度) 每秒步数到 x: (x) y: (y)
将 [x 轴差值的平方 v] 设置为 (((x) - (x 轴位置)) * ((x) - (x 轴位置)))
将 [y 轴差值的平方 v] 设置为 (((y) - (y 轴位置)) * ((y) - (y 轴位置)))
将 [到位置 v 的距离] 设置为 ((x 轴差值的平方) + (y 轴差值的平方) 的 [平方 v]
滑行 ((到位置的距离) / (速度)) 秒到 x: (x) y: (y)

数学看起来很复杂,但这仅仅是勾股定理。您可以将这些积木放入它们自己的自定义积木中,并在其他地方使用。这使得这个解决方法非常简单:

定义滑行 (速度) 每秒步数到 x: (x) y: (y)
获取距离到 x: (x) y: (y) :: 自定义
滑行 ((距离到位置) / (速度)) 秒到 x: (x) y: (y)

滑行到精灵:速度:/ 滑行:每秒步数到精灵:

Scratch 3.0 添加了“滑行:秒到:”块,这里完美契合。而且 Scratch 内置了“到精灵的距离”报告器,所以我们也可以使用它!否则,就和上面一样变通了。

定义滑行 (速度) 每秒步数到精灵:(精灵)
滑行 ((距离到精灵)) / (速度)) 秒到精灵 ::运动

是显示/可见吗?

方法 1:在隐藏/显示的同时设置变量

Scratch 不会直接告诉你精灵是否可见,但你可以使用变量来跟踪。

定义隐藏并记住
隐藏
将 [visible? v] 设置为 [false]

定义显示并记住
显示
将 [visible? v] 设置为 [true]

方法 2:先设置变量,然后再显示/隐藏

如果你的项目使用“更新”或“渲染”广播循环(就像许多 Scratch 游戏一样),你可以使用变量来表示精灵是否显示,并在广播结束时仅反映一次变化。

当我接收 [更新 v]
...
如果 <某些条件 :: 灰色> 则
将 [visible? v] 设置为 [true]
否则
将 [visible? v] 设置为 [false]
结束
...
如果 <(visible?) = [true]> 则
显示
否则
隐藏
结束

色彩效果报告器、旋转、马赛克、音效报告器等

您可以使用与“visible?”相同的方法,处理 Scratch 不允许的其他属性访问也是如此。

请记住,某些效果(例如颜色)会在某个点“循环” - 例如,100 表示完全相反的颜色,200 表示恢复正常,因此 50 和 250 会产生相同的结果。(note) 您可以使用“mod”运算符块将值保持在特定范围内,只要您知道它在哪个值处循环即可。

点击绿旗时
清除图形效果
将 [颜色效果 v] 设置为 [0]
永久生效
将 [颜色 v] 效果改变 (10) :: 外观
将 [颜色效果 v] 改变 (10)
如果 <((颜色效果) mod (200)) > [100]> 则
将 [马赛克 v] 效果设置为 [10]
否则
将 [马赛克 v] 效果设置为 [0]
结束
结束

注意:从技术上讲,即使颜色效果确实会在每个 200 的倍数上循环,但值 0 是“特殊的”,会完全禁用该效果。颜色为 100 时,白色和灰色会变蓝;颜色为 200 时,白色和灰色会变红。每 200 重复一次:颜色为 400 时,白色/灰色会变红;颜色为 300 时,白色/灰色会变蓝。例如,如果你想检查颜色效果是“偏红”还是“接近正常”,你可以执行 (color mod 200 < 40 或 color mod 200 > 160) and (not color = 0)。请参阅此帖子的讨论。

其他效果在超过一定值后不会有任何变化:亮度 -50 表示暗,-80 表示更暗,-100 表示完全黑色;任何更负的数值都不会使精灵比漆黑更暗。如果需要,可以使用如下脚本来限制变量:

当绿色旗帜被点击时
永远
如果 <(亮度效果) > [100]> 则
将 [亮度效果 v] 设置为 [100]
否则
如果 <(亮度效果) < [-100]> 则
将 [亮度效果 v] 设置为 [-100]
结束
结束
结束

隐藏所有精灵

使用广播:

广播 [隐藏所有精灵 v] 并等待

// 将其添加到每个精灵中:

当我收到 [隐藏所有精灵 v] 时
隐藏

您还可以使用类似“当背景切换到 (backdrop2) 时”的事件,并将其仅添加到特定精灵中,以更好地控制哪些精灵隐藏、显示以及何时显示。

上一个服装

方法 1:从服装编号中减去

使用服装编号积木并减 1:

切换服装为 ((服装 [编号 v] :: 外观) - (1))

您无需为背景使用变通方法——“切换背景为”积木块本身就包含“上一个背景”选项。

方法 2:在输入框中输入字符串“previous outfit” (谢谢,@musicROCKS013!)

Scratch 还支持在输入框中使用纯文本“previous outfit”。您无法直接在下拉菜单中输入,但可以使用“连接”块使其适应:

切换服装为 (join [previous c] [ostume])

您也可以“欺骗”Scratch,让其在输入框中输入文本“previous outfit”。查看此项目中的详细信息(或将块打包!)。

最后一套服装 / 最终一套服装

切换到编号为零的服装:

将服装切换为 ((0) + (0))

当你超过结尾或到达开头时,Scratch 会自动“回绕”当前服装编号。这是一个循环,因此“永远:下一套服装”可以正常工作。反之亦然:编号为零的服装在编号为一的服装之前,因此它会回绕到结尾。

服装名称列表

您可以自动创建一个服装名称列表,方法是从第一件服装开始,循环“下一件服装”,直到到达末尾再返回到第一件服装,每次都将当前服装名称添加到列表中:

删除所有 [服装名称 v] :: 列表
将服装切换为 ((0) + (1)) // 这样您就可以从第一件服装开始!
重复执行,直到 <<(服装 [编号 v] :: 造型) = [1]> 且 <([服装名称 v] 的长度) > [0]>>
将 (服装 [名称 v] :: 造型) 添加到 [服装名称 v]
下一件服装
结束

我们在循环中使用“且服装名称长度 > 0”,这样循环就不会在开始之前就停止。在第一次迭代中,列表始终为空。我们立即将一个项目添加到列表中,这样一旦回到造型 1,我们就可以停止。即使精灵只有一套造型,这种方法也能奏效!

最终,造型会始终切换回造型 1,因此,如果您需要在运行此代码后恢复原始造型,请将原始造型保存在一个变量中:

将 [原始造型 v] 设置为 (造型 [名称 v] :: 外观)
... // 上一个脚本中的所有代码
将造型切换为 (原始造型)

造型数量

方法 1:造型名称列表的长度

如果您已经ady 收集了精灵服装名称的列表(使用变通方法),你只需获取列表的长度即可。

将 [服装数量 v] 设置为 ([服装名称 v] 的长度)

方法 2:切换到最后一件服装,然后切换到服装编号

切换到最后一件服装,方法是先切换到服装编号 0,然后获取服装编号:

将服装切换到 ((0) + (0))
将 [服装数量 v] 设置为 (服装 [编号 v] :: 造型)

这显然会改变当前的服装,因此如果恢复原始服装很重要,请将其保存在一个变量中:

将 [原始服装 v] 设置为 (服装 [名称 v] :: 造型)
将服装切换到 ((0) + (0))
将 [服装数量 v] 设置为 (服装 [编号 v] :: 造型)
将服装切换到 (原始服装)

随机服装 (谢谢,@medians!)

方法 1:重用“服装数量”变量

如果您已经使用上述方法之一来获取精灵拥有的服装数量,则可以重用该变量:

将服装切换为 (随机选择 (1) 到 (服装数量 :: 变量))

方法 2:切换到最后一套服装,然后随机选择

此方法完全不需要变量:

将服装切换为 ((0) + (0)) // Scratch将数字 0 包裹起来,表示“最后一套服装”
切换服装至(随机 (1) 至 (服装 [编号 v] :: 造型))

实际上,您不需要使用这两种背景解决方法,因为“切换背景至”已经有一个“随机背景”选项!
ScratchUser139
Scratcher
100+ posts

Scratch 解决方法指南 VII

事件 & 控制⬆︎ 目录

当(任何条件)成立时 (感谢@INSERT-USER_NAME!)

Scratch 有一个方便的“when”积木,它带有一个菜单,可以在特定条件成立时激活某些功能,但选项只有“计时器”和“响度”,因此功能略有限制。不过,我们只需要一个“timer”选项,就可以让它适用于其他任何条件:

当 [timer v] > ((timer) - <(costume [name v] :: looked) = [costume4]>
说 [哇!我现在看起来像个墨西哥卷饼了!] 持续 (3) 秒 :: looked

只需将你想要的条件放在“减号”(-) 块中即可。这使用了一个技巧,将 true 条件(布尔值)视为 1,将 false 视为 0。所以,如果你使用的自定义条件是 false,Scratch 基本上就是这样做的……

当 [timer v] > ((timer) - (0))

计时器会检查它是否大于自身,而这永远不会为真——计时器就像任何普通数字一样,是相等的。到自身!

一旦条件为 ,Scratch 就会减 1,结果始终为真:计时器的值始终大于 比自身小一

请记住,Scratch 的“when”积木仅在其条件 变为真时激活一次。因此,请注意以下情况:

当 [timer v] > ((timer) - <<(x 位置) = [50]> 或 <(x 位置) = [100]>>)

如果精灵移动到 x = 50 或从任何其他 x 位置移动到 x = 100,则会激活此积木。如果它直接从 50 移动到 100,或从 100 移动到 50,则不会再次激活 :就 Scratch 而言,没有任何变化,因为整体条件(“x = 50 或 x = 100”)从真变为真。“何时”积木需要至少有一帧条件为假才能再次运行。

您可以使用“重复直到”和其他常规 Scratch 控制积木,在条件为真时继续执行某些操作(您只需将条件复制到“重复直到”积木中——使用“非”积木,这样就可以重复执行,直到条件为假)。

布尔值:“我收到(消息)”

此积木被拒绝,因为它的含义有点模糊。请查看下面的其他积木,了解您想要的具体行为!

等待直到我收到消息 1

使用变量来跟踪您是否已收到广播。(为此选择“ (创建时设置为“仅限精灵”。)重要的是,在开始等待时立即重置它——这样,只有在再次收到广播后才会停止等待,前提是你之前已经收到过!

将 [我收到消息 1 了吗?v] 设置为 [false]
等待直到 <(我收到消息 1 了吗?) = [true]>
说 [我收到了!] 持续 (1) 秒

当我收到 [消息 1 v] 时
将 [我收到消息 1 了吗?v] 设置为 [true]

重复执行直到我收到消息 2

使用与“等待直到我收到”基本相同的方法,但使用“重复执行直到”积木:

将 [我收到消息 2 了吗?v] 设置为 [false]
重复执行直到 <(我收到消息 2 了吗?) = [true]>
转动顺时针 (30) 度
结束
说 [我收到了!] 持续 (1) 秒

当我收到 [消息 2 v] 时

将 [我收到了消息 2 吗?v] 设置为 [true]

仅向精灵 1 广播消息 1

方法 1:向一个精灵广播 (谢谢,@yavuz61035!)

将要响应的精灵名称设置为一个变量。每个精灵都会收到广播,因此,在每次使用“当我收到”消息时,请检查变量是否与该精灵的名称匹配:

询问 [下一个跳舞的精灵是谁?] 并等待
将 [接收者跳一段酷炫的舞蹈 v] 设置为 (答案)
广播 [跳一段酷炫的舞蹈 v] 并等待
播放声音 [Hooray! v] 直到完成

当我在 Gobo 的代码中收到 [跳一段酷炫的舞蹈 v] 时
如果 <(接收者跳一段酷炫的舞蹈) = [Gobo]> 则
指向方向 (45 度 v)
重复 (4)
重复 (10)
移动 (10) 步
结束
顺时针旋转 (90) 度
结束
结束

当我在 Tera 的代码中收到 [跳一段酷炫的舞蹈 v] 时
如果 <(接收者跳一段酷炫的舞蹈) = [Tera]> 则
设置旋转方式 [左右 v]
重复 (5)
指向方向 (90 度 v)
滑动 (1) 秒到 x: (50) y: (100)
指向方向 (-90 度 v)
滑动 (1) 秒到 x: (50) y: (-50)
结束
结束

通常,最好为每个“目标”广播使用不同的变量。这样,如果您同时广播两条或多条不同的消息,就能确保每条消息都能到达目的地!

方法 2:同时向 2 个或以上特定精灵广播

同一 Scratch 帧内无法广播同一条消息两次——该消息只会被接收一次。因此,如果您想向两个特定的精灵广播,则必须使用列表:

删除所有 [who's receive sing along v] :: 列表
将 [Dee] 添加到 [who's receive sing along v]
将 [Devin] 添加到 [who's receive sing along v]
将 [Sam] 添加到 [who's receive sing along v]
将 [Scratch Cat] 添加到 [who's receive sing along v]
广播 [sing along v]

当我收到 [sing along v] 时
如果 <[who's receive sing along v] 包含 [Scratch Cat]> 则
将 [pitch v] 效果设置为 (0) :: sound
重复 (3)
播放 [Meow v] 声音直到完成
将 [pitch v] 效果更改为 (20) :: sound
结束
结束

方法 3:不停止/重启广播

请记住,如果您广播的内容中有一些精灵目前正在响应,Scratch 将中断并重新启动所有“当我收到”脚本,并发送相同的消息。如果您想确保已经启动的精灵在您再次广播消息(可能是发送给另一个精灵)后继续运行,您可以使用变量和“等待直到”或“永远……如果”块。

当我收到 [加入团队 v] 时
如果 <(谁正在加入团队) = [Pico]> 则
将 [团队成员 v] 设置为 [true] // 局部变量,“仅限此角色”
结束

当绿旗被点击时
将 [团队成员 v] 设置为 [false]
等待 <(团队成员) = [true]>
永远
... 跟随领导者 ... :: 灰色
结束

在上面的例子中,如果你 没有 使用额外的变量(仅限此角色),而只是将“永远”块放在 if 块中,那么每次只会有一个角色跟随领导者!

但请记住:如果你正在开发不同类型的项目,Scratch 中断广播的方式可能会很有用!例如,在一个音乐项目中,每次只有一个特殊乐器在独奏:使用新角色再次广播将停止当前独奏,然后开始新的独奏。如果你将“接收者”变量设置为一个不存在的精灵(或者仅仅是“nobody”),它会停止当前的独奏,而不会开始新的独奏!

重复 2 秒

方法 1:计时器变量和“重复至”循环

使用变量为当前计时器添加秒数。此变量表示重复循环应停止的时间。当计时器超过该值时,循环停止。

将 [何时停止 v] 设置为 ((timer) + (2))
重复至 <(timer) > (何时停止)>
顺时针旋转 (10) 度
将大小改变 (2)
结束

我们使用“>”块而不是“=”块,因为计时器实际上是一个相当精确的十进制值。例如,当我们将“何时停止”变量设置为 2.438 时,计时器可能为 0.438。最终,计时器会达到接近 2.438 的值,但它实际上可能会不断增大,但永远不会恰好等于 2.438,因为 Scratch 脚本每秒不会运行 1000 次,而只会运行 30 次!

方法 2:等待块并中断/取消广播

如果您在“重复几秒钟”块中使用了更多循环,或者您还有其他需要时间的块(例如“滑行”),您可以使用广播的特殊行为来“取消”循环内部并停止循环中正在运行的任何内容,即使它只是运行了一部分。

设置 [循环完成? v] 设置为 [false]
广播 [在循环 v 内] // 注意,这不是一个“广播并等待”的块
等待 (2) 秒
设置 [循环完成? v] 变为 [true]
广播 [循环内部 v]

当我收到 [循环内部 v] 时 // 确保每个循环使用不同的消息
如果 <(循环完成?) = [false]> 则
永远
... // 例如,循环内部:
指向 (90) 方向
滑动 (0.75) 秒到 x: (100) y: (0)
指向 (-90) 方向
滑动 (0.75) 秒到 x: (-100) y: (0)
结束
结束

while (条件)

方法 1:“重复直到不”循环

使用“重复直到”积木,并在条件周围放置一个“不”积木(来自“运算符”类别):

重复直到 <不<(x 位置) < [150]>>
将 x 的值改变 (10)
结束

“Repeat until” 循环执行,直到条件成立。“While”循环执行,直到条件不成立。由于它们互为逆操作,因此您可以使用“not”来反转条件,并获得与“while”相同的效果。

方法 2:破解“while”块

(!) 请注意,虽然像这样的破解块是 Scratch 语言的正常组成部分,但 Scratch 团队并未正式支持它们的使用。使用破解块的项目可能会被标记为 NFE,从而导致项目无法出现在首页或“探索”部分。]

Scratch 2.0 和 Scratch 3.0 中有一个隐藏的、“被黑”的块,叫做“while”。它和其他编程语言中典型的“while”循环完全一样:

while <(y 位置) < [120] :: 运算符> {
将 y 的值改变 (20)
} :: 控制循环
while <(y 位置) > [0] :: 运算符> {
将 y 的值改变 (-10)
} :: 控制循环

你可以将“while”块从其他 Scratch 项目(例如这个)拖到你的背包中获取。

do … while (do … until)

在其他编程语言中,即使条件一开始为假,循环内部也总是执行一次是很常见的。您可以通过将条件存储在变量中并使该变量的初始值为真来实现相同类型的行为:

将 [条件 v] 设置为 [true]
重复执行,直到 <(条件) = [false]>
转到 [随机位置 v]
将 [条件 v] 设置为 <触摸 [鼠标指针 v] ?>
结束

针对 5 到 10 之间的每个整数

方法 1:“重复”循环

计算起始值和结束值的差值,然后将变量递增该值:

将 [数字 v] 设置为 (起始值 :: 灰色)
重复 (((结束值 :: 灰色) - (起始值 :: 灰色)) + (1))
执行 (join [数字是:] (数字)) 执行 (1) 秒
将 [数字 v] 的值更改为(1)
结束

我们加 1,使循环包含起始值:如果起始值为 5,结束值为 10,则循环将计数 5、6、7、8、9、10。或者,如果起始值和结束值相同,脚本仍然会运行,但只运行一次,并且只使用一个值!

方法 2:“重复直到”循环

从初始位置开始,然后不断增加一个变量,直到到达结束:

将 [number v] 设置为 (start :: grey)
重复直到 <(number) > (end :: grey)>
例如 (join [The number is: ] (number)) 持续 (1) 秒
将 [number v] 的值更改为 (1)
结束

我们使用“大于”而不是“等于”来使循环包含起始值。它会根据起始值、结束值以及介于起始值和结束值之间的所有值运行脚本。

此方法还可以轻松地按 1 以外的数字递增计数,例如按 0.25 或 10 递增。

停止此精灵中的所有脚本

您可以组合两个“停止脚本”块,以同时停止精灵中的所有其他脚本和当前脚本:

...
if <some condition :: grey> then
stop [other scripts in sprite v]
stop [this script v]
end
do something :: grey

请注意,如果您打算将此块放在脚本末尾,则无需包含“stop this script”,因为该脚本在“stop other scripts in sprite”运行后不会执行任何操作。

停止另一个精灵的脚本

使用广播:

// 在精灵1中……

广播 [停止精灵2 v 中的脚本] 并等待

// 在精灵2中……

当我收到 [停止精灵2 v 中的脚本] 时
停止 [精灵 v 中的其他脚本]

如果您打算“关闭”精灵并将其从当前场景中移除,也可以在此处使用类似“隐藏”的块。

是克隆吗?

使用变量——并确保在创建变量时将其设置为“仅用于此精灵”!

当点击绿旗时 // 这将仅由原始精灵运行,克隆精灵不会运行
设置 [是克隆吗?将 [是克隆体吗?v] 设置为 [false]

当我以克隆体身份启动时 // 这只会由克隆体运行(当然!)
将 [是克隆体吗?v] 设置为 [true]

然后,你可以在响应广播时使用此变量——如果你希望只有原始精灵响应某个广播,而克隆体不响应,请将其设置为 false。

删除所有克隆体

当你发送广播时,所有精灵和克隆体都会响应。你可以使用连接到广播的“删除此克隆体”积木,使“当我接收”所在的精灵的所有克隆体在你发送该广播时都被删除。

广播 [删除所有克隆 v] 并等待

当我收到 [删除所有克隆 v] 时
删除此克隆

克隆数量

使用变量——创建变量时,请确保变量设置为“所有精灵”(默认)。每当创建一个克隆时,变量值增加(加 1);每当删除一个克隆时,变量值减少(减 1)。你可以创建一个自定义的“删除此克隆并保持跟踪”块来帮助记忆:

当点击绿旗时
将[克隆数量 v] 设置为 [0]

当我以克隆体形式启动时 // 在每个被克隆的精灵中
将[克隆数量 v] 的值更改为 (1)

定义删除此克隆并保持跟踪
将[克隆数量 v] 的值更改为 (-1)
删除此克隆
ScratchUser139
Scratcher
100+ posts

Scratch 解决方法指南 VII

运算符 & 感知⬆︎ 目录

true, false

大多数情况下,只使用字符串“true”或“false”即可:

将 [我是狗吗?v] 设置为 [true]
将 [蛇很粘吗?v] 设置为 [false]

有些 Scratchers 更喜欢使用 1 和 0,因为它们更容易拟合数学表达式,也更简洁。

如果您确实需要特定的布尔值,可以使用始终知道其值的条件语句。将这些值保存在全局变量(“用于所有精灵”)中非常方便,以便在整个项目中使用:

将 [true v] 设置为 <[5] < [10]>
将 [false v] 设置为 <[5] > [10]>

将 [true v] 设置为 <not <>> // 空输入被视为 false,not false = true
将 [false v] 设置为 <not <not <>>> // not not false = not true = false

您不能将变量或任何回合报告器直接放入布尔值槽中,但可以使用比较块:

如果 <<touching [snake v] ?> 并且 <(snakes are slimy?) = [true]>> 则
开始发出声音 [Scream1 v] :: sound
说 [Yikes!!!] for (2)秒
结束

x <= y, x >= y

方法 1:“非”积木

使用“非”积木来表示相反的条件:

<(答案) ≤ [20] :: 运算符> … 等同于… <非 <(答案) > [20]>> :: 灰色

<(y 位置) ≥ [100] :: 运算符> … 等同于… <非 <(y 位置) < [100]>> :: 灰色

对于两个数字 x 和 y,以下三项只能有一个为真:x 小于 y、x 等于 y 或 x 大于 y。当你询问其中两个条件时,实际上只是在排除第三个条件,因此我们使用“非”积木块和第三个条件来模拟检查另外两个条件。

方法 2:“或”积木块

或者,你也可以使用“或”积木块:

<<(答案) < [20]> 或 <(答案) = [20]>>
<<(y 位置) > [100]> 或 <(y 位置) = [100]>>

这种方法更直接,可能更容易理解,但缺点是你必须写出两次数字/积木块。

x XOR y(异或)

“异或”表示“一个条件为真,但不是两个条件都为真”(与普通的“或”不同,后者表示“一个条件为真,或两个条件都为真”)。

方法 1:仅使用基本布尔值块

您可以使用普通的“与”、“或”和“非”块组合构建相同的含义:

<<<x :: grey> 或 <y :: grey>> 和 <非 <<x :: grey> 和 <y :: grey>>>>

由于此方法需要写出两次条件,每次读写都比较麻烦,因此您可以使用带有布尔值参数的自定义块来简化操作:

定义互斥的 <x> 或 <y>
将 [xor v] 设置为 <<<x> 或 <y>> 和 <非 <<x> 和 <y>>>>

方法 2:等于块(比较布尔值)

理解“xor”的另一种方法是“这两个条件是否不同?”因为异或运算意味着只有 一个 值为真,另一个为假。你可以像其他任何积木一样,在“=”积木内使用布尔值积木,然后使用“not”来询问“它们不相同吗?”:

<not <<x :: grey> = <y :: grey>>

方法 3:加法积木(求和布尔值)(谢谢,@D-ScratchNinja!)

你也可以将布尔值视为数字。如果布尔值为真,则将其视为数字 1。如果布尔值为假,则将其视为 0(零)。正因如此,你可以巧妙地使用数学积木来处理布尔值:

<(<x :: grey> + <y :: grey>) = (1)>

x + y = 0 的唯一原因是 x 和 y 都为假 (x = 0, y = 0)。x + y = 2 的唯一原因是 x 和 y 都为真 (x = 1, y = 1)。

x + y = 1 有两种情况:x 为真且 y 为假 (x = 1, y = 0) 或 x 为假且 y 为真 (x = 0, y = 1)。这些就是我们想要的:只有当 x 和 y 不同时,x + y = 1,这就是“异或”的含义。

字符串中 x 到 y 个字母

您可以使用一个带有递增变量的循环,从第一个位置开始,一直循环到最后一个位置,每次都将当前字母附加到变量的末尾。

定义 获取字符串 (start) 到 (stop) 之间的字母
将 [子字符串 v] 设置为 [] // 空字符串
将 [解析 v] 设置为 (start)
重复执行,直到 <<(解析) > (stop)> 或 <(解析) > (字符串的长度)>
将 [子字符串 v] 设置为 (连接字符串 (子字符串) (解析字母)))
将 [解析 v] 的值更改为 [1]
结束

十六进制转十进制

Scratch 可以将十六进制数(如 FF)转换为十进制数(如 255),只需将十六进制数放入任意数学块即可。请确保在数字前添加两个特殊字符 0x(先零后 X)。无法在数字输入中输入此代码,但如果使用“询问并等待”等积木、变量或“连接”积木获取,则可以正常工作。

询问[十六进制数字是多少?]并等待
将[十六进制 v] 设置为 (join [0x] (答案))
将[十进制 v] 设置为 ((1) * (十六进制))
例如 (join (join (十六进制) [十进制为 ]) (十进制))

x 是偶数吗?x 是奇数吗?x 能被 y 整除吗? x 是 y 的倍数吗? (谢谢,@medians!)

方法 1:“x mod 2”和零比较

“mod”运算符是“modulo”的缩写(在其他编程语言中通常用 % 表示),它告诉你第二个数除以第一个数的余数。如果余数为零,则表示除数能整除被除数。 (10 mod 5 = 0,13 mod 5 = 3,13 mod 6 = 1。)

所有偶数都能被 2 整除,而所有奇数都不能,因此你可以将“mod 2”的结果与 0 进行比较,以判断一个数是否为偶数:

<((5) mod (2)) = [0]> // false
<((316) mod (2)) = [0]> // true

你可以使用“非”积木来判断它是否为奇数。但是,您可以通过与 1 而不是 0 进行比较来节省区块,因为 1 是 x ÷ 2 的唯一其他可能余数:

<((612) mod (2)) = [1]> // false
<((1025) mod (2)) = [1]> // true

请注意,对于“mod 2 = 1”,您只能获得整数的正确结果。如果您真正感兴趣的是“这个数能被 2 整除吗?”,请与 0 进行比较,这也适用于小数(2.25 mod 2 = 0.25,它不是零,而 2.25 不能被 2 整除)。

方法 2:“x mod y”和零比较

您也可以使用模运算符来检查其他数的可整除性:

询问 [我们需要多少个鸡蛋?] 并等待
如果 <((answer) mod (12)) = [0]> 则
说 (join [好的,我们将购买 ] (join ((answer) / (12)) [ 一打!]))
结束

您可以使用“not”或“if/else”积木来检查它是否不可整除。和 2 一样,你可以保存一个方块,但不同之处在于:除以 5 的余数可能是 0、1、2、3 或 4。因此,检查答案是否大于零,以判断它是否为除零以外的任何值(因为余数永远不会为负数):

询问 [有多少只虫子会守卫堡垒?] 并等待
如果 <(answer) > [100]> 则
如果 <((answer) mod (25)) > [0]> 则
说 [抱歉,如果您想要超过 100 个,请输入 25 的倍数]
结束
结束

x 是整数吗? x 是小数/分数吗?

方法 1:检查是否能被 1 整除

整数(和整数)都能被 1 整除:如果 3 除以 1,则没有余数;而 3.25 除以 1,则余数为 0.25。您可以使用“mod”积木检查除法的余数:

<((32) mod (1)) = [0]> // 0 = 0:真
<((13.37) mod (1)) = [0]> // 0.37 = 0:假

如果您要检查数字 不是整数,请将“等于”积木替换为“大于”积木。

方法 2:与四舍五入后的值进行比较 (谢谢,@1080GBA!)

将值与其自身进行比较——但要进行四舍五入——如果要检查它是否为小数,请使用“非”积木:

询问 [选择图形分辨率 1(块状)到 10(详细):] 并等待
如果 <非<(答案) = (四舍五入(答案))>> 则
说 [请仅使用整数分辨率] 等待 (3) 秒 :: 查看
停止 [此脚本 v]
结束
... 更多答案验证 ... :: 灰色

x 的小数部分 / 的小数部分x

方法 1:除以 1 的余数

对于正数,你可以使用“mod”积木将数字除以 1 并得出余数:

((8) mod (1)) // 0
((8.25) mod (1)) // 0.25
((8.50) mod (1)) // 0.5
((8.75) mod (1)) // 0.75
((9) mod (1)) // 0

处理负数时,“mod”积木会稍微复杂一些。 (它返回第一个数比第二个数的前一个最大倍数 的数,因此 -6 mod 3 = 0,-5 mod 3 = 1,-4 mod 3 = 2。)

如果您要检查的数字是(或可能是)负数,请使用“abs”将其变为正数,然后再进行“mod”:

(([abs v] of (-1.125)) mod (1)) // 0.125

方法 2:从整数中减去底数

如果您只处理正数(包括零到正一之间的小数),请使用“运算符”类别中的“of”积木从数字本身中减去“floor”(“floor”表示“向下取整”):

将 [whole part v] 设置为 ([floor v] of (timer))
将 [小数部分 v] 设置为 ((timer) - (整数部分))

// 或者直接

((variable) - ([floor v] of (variable))

如果值为(或可能为)负数,使用“abs”(绝对值)选项将其设为正数,效果相同:
(([abs v] of (variable)) - ([floor v] of ([abs v] of (variable))))

四舍五入到最接近的 100,四舍五入到小数位

方法 1:四舍五入到最接近的 5、25、100、2、0.25 等

如果您只想显示一定精度的值,可以按顺序使用除法、四舍五入和乘法来获得四舍五入的答案:

定义将 (number) 四舍五入到最接近的 (precision)
将 [rounded v] 设置为 ((round ((number) / (precision))) * (precision))

方法 2:仅去除小数

Scratch 使用的数学系统有时会给出与预期值相差 1 的微小分数(例如 0.1 + 0.2 = 0.30000000000000004)。如果您只想保留特定位数,可以按顺序使用乘法、舍入和除法的组合来获得舍入后的答案:

定义将 (number) 舍入为 (digits) 个小数
将 [rounded v] 设置为 ((round ((number) * ([10 ^ v] of (digits)))) / ([10 ^ v] of (digits))

请注意,此方法仅适用于舍入小数位——“round”块不会对已经是整数的值执行任何操作!

如果您想截断末尾的小数,而不关心小数位是否以 5 或更大开头,请将“round”替换为“floor”。(例如,如果您想将 0.2468 保留 3 位小数,使用“round”将得到 0.247,使用“floor” 会得到 0.246。)

x 的 y 次方(指数运算,x^y)

方法 1:重复乘法/除法(仅限整数指数)

此方法简单易懂。如果您不介意指数为负,可以跳过“else”部分。但请记住,这仅适用于整数指数,因为您不能重复循环 2.247 次,例如!

定义 raise: (base) 为 exponent: (exponent)(方法 1)
将 [power v] 设置为 [1]
如果 <<(exponent) = [0]> 或 <(exponent) > [-1]>> 则
重复 (exponent)
设置将 [power v] 设置为 ((power) * (base))
end
else
repeat (exponent)
将 [power v] 设置为 ((power) / (base))
end
end

方法 2:对数

此方法使用 Scratch 的对数块 10^/log 和 e^/ln 来计算幂。(示例中使用了 10^ 和 log,但你可以将它们替换为 e^ 和 ln;结果相同。)答案也可能不是完美的整数——如果答案必须是整数(例如,当你将它与另一个整数进行比较时),请确保在结果上使用“round”块。

define raise: (base) to exponent: (exponent)(方法 2)
将 [power v] 设置为 ((exponent) * ([log) 的 ([10 ^ v] v] of ([abs v] of (base)))))
if <(base) < [0]> then
将 [power v] 设置为 ((-1) * (power))
end

到 x 的距离: y:

您可以使用“sqrt”积木块(平方根)和乘法来在 Scratch 中执行勾股定理!其实比听起来简单:

define 获取到 x 的距离: (x) y: (y)
将 [x 差值的平方 v] 设置为 (((x) - (x 位置)) * ((x) - (x 位置))
将 [y 差值的平方 v] 设置为 (((y) - (y 位置)) * ((y) - (y 位置))
将 [到位置 v 的距离] 设置为 ([sqrt v] of ((square of x 差值) + (y 差值的平方)

如果更改“x 位置”和“y 位置”积木,此方法也适用于获取任意两点之间的距离。您不需要额外的变量,它们只是为了帮助您阅读:如果您愿意,可以将这些积木直接放入大型平方根方程中。

鼠标点击了此精灵?

方法 1:使用重置分隔变量

使用一个变量,并在开始等待或重复之前重置它:

当此精灵点击时
将 [鼠标点击?v] 设置为 [true]

说 [点击我继续。] :: 看起来
将 [鼠标点击?v] 设置为 [false]
等待直到 <(鼠标点击?) = [true]>
说 [] // 什么也不说
广播 [继续v]

(提示:您可以使用相同的方法等待或重复,直到收到广播!请查看事件与控制部分。)

方法 2:分离变量并等待 (谢谢,@Little_Mittle12345!)

如果您想单独使用一个简单的变量,可以在上面的“当此精灵被点击时”代码后放置一个“等待”块:

当此精灵被点击时
将 [鼠标点击?v] 设置为 [true]
等待直到<不是<鼠标按下?>>
将 [鼠标点击?v] 设置为 [false]

当绿旗被点击
将 [鼠标点击?v] 设置为 [false]

此变量几乎适用于任何环境,包括无限循环!

方法 3:鼠标触摸并按下 (谢谢,@1080GBA!)

如果您想获得类似“点击”的效果,但希望在一个持续运行的循环中运行(例如,将其他代码分组用于交互操作),可以使用“操作符”类别的“与”积木,其中包含两个“感应”积木:

当绿色旗帜被点击时
永远
... 其他游戏控件 ... :: 灰色
如果 <<触摸 [鼠标指针 v] ?> 并且 <鼠标按下?>> 则
将大小改变 (10) 度
顺时针旋转 (20) 度
结束
结束

请注意,如果您开始点击其他地方,然后将鼠标拖到精灵上,这仍然会运行代码,因此这与“当此精灵被点击时”积木略有不同。

鼠标拖动此精灵?

方法 1:等待直到鼠标未按下
请注意: 此方法 与“设置拖动模式:可拖动”块兼容。

如果您想要一个可以在任何地方使用的报告器,您可以使用一个脚本控制变量——在创建变量时选择“仅适用于此精灵”:

当此精灵被点击时
将 [鼠标拖动此精灵?v] 设置为 [true]
等待直到 <<鼠标未按下?>>
设置 [鼠标拖动此精灵? v] 设置为 [false]

当绿色旗帜被点击时
永远
如果 <(鼠标拖动此精灵?) = [true]> 则
将 [ghost v] 效果设置为 (50)
转到 [鼠标指针 v]
否则
将 [ghost v] 效果设置为 (0)
结束
结束

如果您不想使用新变量(也许您只需要了解精灵中某个部分的“拖动”),您可以将更直接的感知和控制块用作现有脚本的一部分:

当此精灵被点击时
将 [ghost v] 效果设置为 (50)
重复执行,直到 <<鼠标按下?>>
转到 [鼠标指针 v]
结束
将 [ghost v] 效果设置为 (0)

如果您使用“set drag mode: draggable”,则此方法无效。这是因为“拖动模式:可拖动”改变了“当此精灵被点击时”的工作方式,因此只有当你放开精灵(鼠标向上)并且根本没有开始拖动精灵时才会激活(因此你按下鼠标后只会将其保持在一个位置)。

方法 2:使用单独的永久循环来代替“当此精灵被点击时”

如果您想使用“设置拖动模式:可拖动”感应块,可以使用以下更复杂的方法:

当绿色旗帜被点击时
设置拖动模式 [可拖动 v] :: 感应
永久
如果 <<未按下鼠标?>> 且 <触摸 [鼠标指针 v] ?>> 则
等待直到 <<按下鼠标?> 或 <未触摸 [鼠标指针 v] ?>>
如果 <触摸 [鼠标指针 v] ?> 则
将 [幽灵 v] 效果设置为 (50)
等待直到 <未按下鼠标?>>
将 [幽灵 v] 效果设置为 (0)
结束
结束
结束

每帧都会检查鼠标是否位于精灵上方,但 被按下。 (这被称为“悬停”在精灵上方。)如果是,它会暂停并等待,直到鼠标按下或鼠标移开。如果鼠标没有移开,我们已经知道鼠标按下了,因为这是“等待直到”块结束的唯一其他方式。这意味着在该精灵上方开始了拖动。

如果您想在精灵被拖动时出现某种精美的动画,可以使用“重复直到(鼠标未按下)”而不是“等待直到(鼠标未按下)”。

涡轮模式已启用?

存在多种涡轮模式检测器,但这里有一个简单的:

当绿色旗帜被点击时
重复 (10)
等待 (0) 秒
结束
设置 [涡轮已启用? v] 到 <(timer) < (0.1)>

使用正确的比较块非常重要——拖出“<”,表示计时器小于 0.1。

这样做之所以有效,是因为 Turbo 模式会将通常需要 Scratch 等待一帧的块变为即时执行。(Turbo 模式会尝试在一帧内尽可能多地运行代码帧——这就是为什么大多数动画在启用 Turbo 模式后运行速度非常快的原因。)10 帧大约是 10 * 0.33 = 0.34 秒,但在 Turbo 模式下,它几乎可以立即运行,您可以通过计时器块检测到这一点。
ScratchUser139
Scratcher
100+ posts

Scratch 解决方法指南 VII

变量 & 列表⬆︎ 目录

列表的最后一项、倒数第二项等

方法 1:“列表长度”积木和减法

使用“列表长度”积木:

([我的列表 v] 的长度) 的 [我的列表 v])

你也可以使用减法积木来获取接近末尾但未相当熟练:

(item (([my list v] 的长度) - (1)) of [my list v])

方法 2:直接在条目输入框中输入单词“last”

您也可以直接复制单词“last”并将其粘贴到“item of”区块中。(请注意,您无法直接输入 - 您必须一次性粘贴整个单词。)

(item [last] of [my list v])

如果您觉得操作起来有困难,可以将其他 Scratch 项目(例如 这个)中的区块拖到您的背包中。

列表中的项(随机)

方法 1:“随机选取”积木

使用“随机选取”和“列表长度”积木:

(项 (随机选取 (1) 至 ([我的列表 v] 的长度)) 的 [我的列表 v])

方法 2:直接在项输入框中输入“随机”

您也可以直接复制“随机”一词并将其粘贴到“项”积木中。 (与“last”类似,你必须一次性粘贴所有单词。)

([my list v] 中的 [random] 项)

如果你觉得这个方法很难用,可以从其他 Scratch 项目(例如 这个)将积木拖到你的背包中。

将列表中的第 1 项增加 10

方法 1:就地操作

如果你只是执行一个简单的操作,例如增加一个值,这种方法就很有用。

将 [my list v] 中的第 (1) 项替换为 (([my list v] 中的第 (1) 项) + (10))

方法 2:将其存储在变量中,然后将变量放回列表

如果您要执行由多个块组成的更复杂的操作(例如其他与数学相关的自定义块),或者您需要在更改值后对其进行其他操作,则此方法非常有用。

将 [项目值 v] 设置为 ([我的列表 v] 中的项目 (1))
将 [项目值 v] 更改为 (10)
将 [我的列表 v] 中的项目 (1) 替换为 (项目值)

删除列表的最后一项

方法 1:“列表长度”积木

使用“列表长度”积木:

删除 [我的列表 v] 中的 ([我的列表 v] 的长度)

如果您想记住该值并将其用于其他用途(例如其他编程语言中的“弹出”函数),您可以在将其从列表中移除之前将其存储在变量中:

将 [弹出的值 v] 设置为 ([我的列表 v] 中的项目 ([我的列表 v] 的长度)) v])
删除 [我的列表 v] 中的 [我的列表 v] ([我的列表 v] 的长度)

方法 2:直接在项目输入中输入单词“last”

与“item of”积木一样,您也可以直接复制单词“last”并将其直接放入“delete”积木中。(与此技巧一样,您必须一次性粘贴所有单词。)

删除 [我的列表 v] 中的 [last]

如果您难以操作此操作,可以将该积木从其他 Scratch 项目(例如 这个)拖到您的背包中。

针对列表中的每个项目

方法 1:“项目 #”变量和“重复执行直到”循环

使用“项目 #”变量(通常也称为“解析”或“索引”)和一个循环:

将 [项目 # v] 设置为 [1]
重复执行直到 <(项目 #) > ([我的列表 v] 的长度)>
如果 <([我的列表 v] 中的项目 (项目 #)) = [something]> 则
执行某事 :: 灰色
结束
将 [项目 # v] 的值更改为 [1]
结束

请注意,如果您决定在循环中添加或删除列表中的项目,则必须小心谨慎。

插入一个项目会将插入位置之后的所有项目向后移动 1 位。因此,如果您在“项目 #”的位置插入一个项目,则意味着您还会在循环的下一次迭代中处理该项目。如果您想跳过新项目,请确保在插入时使用额外的“将项目 # 移动 1 位”。同样,如果您将其插入到“项目 #”之前,您最终会反复循环同一个项目,因为您之前所在的项目现在向后移动了 1 位(这与项目 # 变量的移动一致)。

删除一个项目有相反的注意事项:删除位置之后的每个项目都会向后移动 1 位。如果您删除当前项目 # 处的项目(导致其之后的所有内容左移),然后在继续之前增加项目 #,您最终会跳过一个项目!请确保在删除时“将项目 # 移动 -1 位”。在当前项目编号或之前添加一个项目,即可取消“将项目编号加 1”;或者,如果检测到需要移除的项目,则根本不运行“将项目编号加 1”的命令。

方法 2:破解“for each”块

(!) 请注意,虽然像这样的破解块是 Scratch 语言的正常组成部分,但 Scratch 团队并未正式支持使用它们。使用破解块的项目可能会被标记为 NFE,导致项目无法显示在首页或“探索”版块下。

Scratch 2.0 和 Scratch 3.0 中有一个隐藏的“破解”块,名为“for each”。它会从 1 计数到提供的数字。这通常非常适合计数列表中的项目:

for each [item # v] of (length of [my list v]) {
if <(item (item #) of [my list v]) = [something]> then
do something :: grey
end
} :: control loop

你可以将“for each”积木从其他 Scratch 项目(例如这个)拖到你的背包中获取。

方便的是,“for each”积木每次都会计算其 number 输入中的积木。这意味着它的工作原理类似于“重复执行,直到 (item # = 列表长度)”,而不仅仅是“重复 (列表长度)”。但要小心:如果您不断向列表中添加项目,循环将永远运行(Scratch 3.0 中列表中项目的最大数量为二十万)。
ScratchUser139
Scratcher
100+ posts

Scratch 解决方法指南 VII

杂项⬆︎ 目录

内联代码注释 (感谢@TheCreatorOfUnTV!)

您可以通过右键单击 Scratch 中的任何块并选择“添加注释”来添加注释,这样您就可以添加注释来解释脚本的功能。但这些注释会浮动在脚本的一侧,您可能希望将代码注释直接放在脚本内部!

这就像创建一个实际上不执行任何操作的自定义块一样简单!创建一个包含文本输入的自定义块,并将定义留空即可。

定义注释:(我的注释)

当绿旗被点击时
注释:[此脚本处理可自定义的键盘输入。]
永久
注释:[玩家角色控制]
将 [跳跃输入 v] 设置为 <是否按下 [键盘控制 v] 中的键 (第 (1) 项)?>
将 [左移动输入 v] 设置为 <是否按下 [键盘控制 v] 中的键 (第 (2) 项)?>
将 [右移动输入 v] 设置为 <是否按下 [键盘控制 v] 中的键 (第 (3) 项)?>
注释:[菜单控制]
将 [确认输入 v] 设置为 <是否按下 [键盘控制 v] 中的键 (第 (4) 项)?>
将 [菜单向上输入 v] 设置为 <是否按下 [键盘控制 v] 中的键 (第 (5) 项)?>
将 [菜单向下输入 v] 设置为 <是否按下 [键盘控制 v] 中的键 (第 (6) 项)?>
...
结束

您可以随意设置文本标签。例如,其他代码语言使用“//”或“#”。或者,您可以创建多个自定义块,每个块使用不同的描述性标签:例如“section:”、“note:”、“warning:”、“todo:”!

返回/报告(来自自定义块)

方法 1:“停止此脚本”

如果您主要想阻止自定义块继续运行任何块,可以使用“停止此脚本”块。它只会停止自定义块的代码,而不会停止调用自定义块的脚本。

点击绿旗时
永久
判断是否存活 :: 自定义
如果 <(alive?) = [true]> 则
玩家控制直到死亡
结束
结束

定义玩家控制直到死亡
永久
判断是否存活 :: 自定义
如果 <(alive?) = [false]> 则
停止 [此脚本 v]
结束
…玩家控制物品 … :: 灰色
结束

方法 2:变量

如果您正在创建一个用于计算某些内容的自定义块,则可以使用变量来跟踪结果,并从调用该自定义块的脚本中访问它。

定义 获取 (string) 的最后一个字母
将 [最后一个字母 v] 设置为 ((string) 的字母 (string) 的长度)

定义 获取一个有趣的单词
将 [有趣的单词 v] 设置为 ([有趣的单词 v] 的项 (随机选取 (1) 到 ([有趣的单词 v] 的长度)))

当绿旗被点击时
说 (加入 [你好 ] (用户名)) 持续 (2) 秒
说 [我们来给你起个代号吧!] 持续 (2) 秒
说 [你的代号是……] 持续 (2) 秒
获取 (用户名) 的最后一个字母
获取一个有趣的单词
说 (加入 (加入 (用户名) 的字母 (1)) (有趣的单词)) (最后一个字母))

方法 3:“返回”列表

如果您希望多次运行自定义块并跟踪所有为了方便查看结果,您可以使用“返回”列表保存多个结果。

定义:检查自定义控件(控件名称)是否被按下
将 [索引 v] 设置为([自定义控件名称 v] :: 列表中(控件名称)的项目编号)
如果 <key([自定义控件键 v] 中的项目(索引))是否被按下?> 则
将 [true] 添加到 [return v]
否则
将 [false] 添加到 [return v]
结束

永久
删除所有 [return v] :: 列表
检查自定义控件 [jump] 是否被按下
检查自定义控件 [defend] 是否被按下
如果 <([return v] 中的项目 (1)) = [true]> 则
如果 <([return v] 中的项目 (2)) = [false]> 则
jump :: 自定义
结束
结束
...
结束

额外:演示 - 上下文“右键单击”/双击菜单 by Hotwheels_Fan101

访问项目! 这是一个简单的上下文菜单示例,它使用变量和一个“当舞台被点击时”块(在舞台中)来检测短时间内的两次点击。请注意,舞台包含两个示例脚本,一个在特定背景下禁用上下文菜单,另一个则不禁用,因此您需要选择适合您项目的脚本,或者如果您想尝试,可以删除一个。
UserBlockedYou
Scratcher
47 posts

Scratch 解决方法指南 VII

oh great everything is undefined (i should do a hong kong version)
哦好正所有嘢都係未定義嘅(我應該做個香港版)

Last edited by UserBlockedYou (Aug. 9, 2025 08:01:57)

Powered by DjangoBB