简单地编写一个Scratch扩展

随着图形化编程的兴起,比如 Scratch编程猫和 Mind+ 等等变得越来越受欢迎。同时,像 Scratch 原有的内容已经不足以给各位提供足够的函数了。像 TurboWarpGandi IDE、Scratch Lab、Scratch X 等就提供了丰富的非原版函数库(即扩展,mod)。比如,你可以访问 TurboWarp扩展库 来查看 TurboWarp 为 Scratchers 提供的扩展。扩展和其他编程语言的“库函数”相似,都是添加原来没有的函数内容。如果你认为这些内容还不够你用,那你就得自己写了。怎么写呢?接下来就听我娓娓道来!

准备工作

很显然,你需要一个好用的文本编辑器(比如 VSCode、Notepad++等,当然,你直接用记事本也可以)、一个可以加载自定义扩展的 Scratch Mod (比如 TurboWarpGandi IDE 扩展模式等)、以及一些 JavaScript 基础。

如果你自恃拥有强大的编程能力和足够的英语基础,你可以前往 TurboWarp 扩展文档 查看更官方更权威的扩展教程。

基本格式

首先,我将为你展示 Scratch 扩展文件的基本结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(function (Scratch) {
"use strict";

Scratch.translate.setup({...});

class ExtName {
getInfo() {
return {
id: ...
name: ...
...
};
}

Function(arg) {...}
}

Scratch.extensions.register(new ExtName());
})(Scratch);

如上,这就是最基本的 Scratch 扩展格式。其中,Scratch.translate.setup()为你的扩展提供了 l10n (本地化)支持,可以提供这个函数来设置多语言。之后就是定义一个类了,这个类当中包含了你的扩展的信息(getInfo)和函数定义。最后,通过Scratch.extensions.register()函数来注册这个扩展。

接下来,让我们慢慢讲具体的内容~

Scratch.translate.setup() l10n 支持

在 Scratch 扩展中,Scratch.translate.setup()的语法如下:

1
2
3
4
5
6
7
8
9
10
Scratch.translate.setup({
"en": {
"_key": "translation",
...
},
"zh-cn": {
"_key": "翻译",
...
}
})

给这个函数提供一个 JSON 参数,在之后重新调用Scratch.translate()函数就可以将key字符串自动转换为对应的值(也就是翻译内容)。比如,我在上面设置了"_key"对应的值是"翻译",那么,当我的编辑器语言为简体中文(zh-cn)的时候,Scratch.translate("key")就会返回"翻译"

这是由 Scratch 本身提供的翻译功能,善用它会取得不错的成效。

getInfo() 给你的扩展编写信息

getInfo()函数中,你应该为其定义编写一堆内容,包括了扩展ID扩展名扩展积木颜色扩展积木等等。接下来我会给出一个简单的 getInfo() 示例,它可以创建一个 COMMAND 块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
getInfo() {
return {
id: "SampleExt",
name: "示例扩展",
color1: "#66ccff",
blocks: [
{
opcode: "SampleBlock",
blockType: Scratch.BlockType.COMMAND,
text: "示例积木"
}
]
}
}

如上,在getInfo()的定义中,你会看到一些键值对,比如idnamecolor1等等。其中,block后面对应的 Array 中,就是对扩展积木的定义。在这里,我定义了一个 COMMAND 块,上面显示的内容是“示例积木”,它的操作码(opcode)是”SampleBlock”。

操作码是最重要的一个键,因为它对应了后面对这个块相应的函数的定义。假如我要为这个块编写代码,我就应该在后面定义一个SampleBlock()函数,Scratch 在尝试将这些代码块释放到 Scratch 虚拟机 中的时候,会找到对应操作码的函数,绑定在块上,以便在编辑器中执行。

在定义一个块的时候,你可以使用一下内容:

类型 介绍
opcode string 该块运行时应该运行的函数的名称。例如,如果这是“Sample”,那么将运行类的“Sample”方法。每个扩展中的每个操作码必须是唯一的,因此多个扩展可以每个都有一个操作码为“Sample”的块
blockType Scratch.BlockType.* 用来决定块的形状,具体见下面一节
text string 将出现在块编辑器中的文本。当然,这里可能会出现一些特殊的语法,这将在后面讨论
arguments object 块中可输入的内容。是可选内容,同样在后面讨论

BlockType 块的类型

玩多了 Scratch ,你应该知道,在 Scratch 中,有很多种不同的块,有像拼图一样的,有圆圆的,有六边形的,也有帽子形状的,还有像个嘴巴一样的 C 的形状的。这就是不同的积木类型,在定义它们的时候,需要根据需求设置它们的类型,接下来我将介绍三个最常见的块类型:

COMMAND 块

你应该注意到了,在上一个小节中,我说的是创建一个 COMMAND 块,那什么是 COMMAND 块呢?COMMAND 的意思是指令,命令,也就是说,这个块将执行一个函数,但是不返回内容。所以它在 Scratch 中,就是那种拼图形状的块了。

REPORTER 块

我们在使用一些获取值的块的时候,它们通常是圆圆的,比如变量块。这就是 REPORTER 块,它们可以返回函数在运行之后返回的值给 Scratch 编辑器。

BOOLEN 块

当然,我们也会遇到一些判断相关的块,它们返回一个布尔值,要么真要么假。这就是 BOOLEN 块,它和 REPORTER 块很像,都可以返回函数的返回值。虽然口头上说的是返回布尔值,但是它们实际上是可以返回其他类型的值的。

帽子块和C型块将在后面介绍。

编写函数

现在,我为你提供一个最简单的扩展示例,这是在 TurboWarp 扩展文档上抄来的,它会返回一个随机数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class random {
getInfo() {
return {
id: 'random',
name: '我去 随机数!',
blocks: [
{
opcode: 'random',
blockType: Scratch.BlockType.REPORTER,
text: '随机数'
}
]
};
}

random() {
return Math.random();
}
}

Scratch.extensions.register(new random());

在这里,我定义了一个操作码为 randomREPORTER 块,上面显示的文本为 随机数 ,之后,根据操作码 random 我在后面定义了一个 random() 函数,并返回一个随机数。这个随机数将会返回到你的 Scratch 编辑器中,你可以在 TurboWarp 加载这个扩展试试。


简单地编写一个Scratch扩展
http://lanwywritexu.github.io/2025/03/09/How-to-write-a-Scratch-extension/
作者
Cyberexplorer
发布于
2025年3月9日
许可协议