TurboWarp拓展开发教程

TurboWarp拓展开发教程

前言

TurboWarp是一个基于Scratch的现代化编程环境,它不仅提供了更快的执行速度,还支持自定义拓展功能。通过JavaScript开发拓展,我们可以为TurboWarp添加新的积木块、功能模块和交互方式。本文将详细介绍如何开发TurboWarp拓展。

什么是TurboWarp拓展

TurboWarp拓展是用JavaScript编写的插件,可以为TurboWarp编辑器添加新的功能。拓展可以包含:

  • 自定义积木块(blocks)
  • 新的变量和列表操作
  • 外部API集成
  • 硬件控制功能
  • 游戏增强功能

开发环境准备

基础要求

  1. 熟悉JavaScript编程
  2. 了解TurboWarp/Scratch的基本概念
  3. 文本编辑器(推荐VS Code)
  4. 现代浏览器(用于测试)

项目结构

1
2
3
4
turbowarp-extension/
├── extension.js # 拓展主文件
├── package.json # 项目配置文件
└── README.md # 说明文档

基础拓展开发

创建拓展文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
(function(Scratch) {
'use strict';

class ExampleExtension {
getInfo() {
return {
// 拓展ID,必须唯一
id: 'exampleExtension',

// 拓展显示名称
name: '示例拓展',

// 拓展颜色(可选)
color1: '#FF6680',
color2: '#FF4D6A',
color3: '#FF3355',

// 拓展菜单项
menuIconURI: '', // 菜单图标URL

// 拓展描述
blocks: [
{
opcode: 'exampleBlock',
blockType: Scratch.BlockType.COMMAND,
text: '执行示例操作',
arguments: {}
},
{
opcode: 'getValue',
blockType: Scratch.BlockType.REPORTER,
text: '获取示例值',
arguments: {}
}
]
};
}

// 实现积木块功能
exampleBlock(args, util) {
// 这里实现具体功能
console.log('示例积木被执行');
}

getValue(args, util) {
// 返回一个值
return 'Hello TurboWarp!';
}
}

// 注册拓展
Scratch.extensions.register(new ExampleExtension());
})(Scratch);

项目配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"name": "turbowarp-example-extension",
"version": "1.0.0",
"description": "TurboWarp示例拓展",
"main": "extension.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"turbowarp",
"extension",
"scratch"
],
"author": "Your Name",
"license": "MIT"
}

高级拓展功能

带参数的积木块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
(function(Scratch) {
'use strict';

class AdvancedExtension {
getInfo() {
return {
id: 'advancedExtension',
name: '高级拓展',
color1: '#4CAF50',
color2: '#45a049',
color3: '#3d8b40',

blocks: [
// 带输入参数的命令积木
{
opcode: 'sayHello',
blockType: Scratch.BlockType.COMMAND,
text: '向 [NAME] 打招呼',
arguments: {
NAME: {
type: Scratch.ArgumentType.STRING,
defaultValue: '世界'
}
}
},

// 带多个参数的积木
{
opcode: 'calculate',
blockType: Scratch.BlockType.REPORTER,
text: '[A] 加 [B] 等于',
arguments: {
A: {
type: Scratch.ArgumentType.NUMBER,
defaultValue: 10
},
B: {
type: Scratch.ArgumentType.NUMBER,
defaultValue: 5
}
}
},

// 布尔值积木
{
opcode: 'isEven',
blockType: Scratch.BlockType.BOOLEAN,
text: '[NUMBER] 是偶数?',
arguments: {
NUMBER: {
type: Scratch.ArgumentType.NUMBER,
defaultValue: 4
}
}
},

// 下拉菜单积木
{
opcode: 'getDay',
blockType: Scratch.BlockType.REPORTER,
text: '获取 [DAY] 的信息',
arguments: {
DAY: {
type: Scratch.ArgumentType.STRING,
menu: 'days',
defaultValue: 'monday'
}
}
}
],

// 下拉菜单定义
menus: {
days: {
items: [
{
text: '星期一',
value: 'monday'
},
{
text: '星期二',
value: 'tuesday'
},
{
text: '星期三',
value: 'wednesday'
}
]
}
}
};
}

// 实现积木功能
sayHello(args, util) {
const name = args.NAME;
// 在TurboWarp中显示消息
if (util.runtime.renderer) {
// 可以在这里添加更多逻辑
console.log(`Hello, ${name}!`);
}
}

calculate(args, util) {
const a = Number(args.A);
const b = Number(args.B);
return a + b;
}

isEven(args, util) {
const number = Number(args.NUMBER);
return number % 2 === 0;
}

getDay(args, util) {
const day = args.DAY;
const dayMap = {
'monday': '星期一',
'tuesday': '星期二',
'wednesday': '星期三'
};
return dayMap[day] || '未知';
}
}

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

实用拓展示例

数学计算拓展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
(function(Scratch) {
'use strict';

class MathExtension {
getInfo() {
return {
id: 'mathExtension',
name: '数学拓展',
color1: '#2196F3',
color2: '#1976D2',
color3: '#0D47A1',

blocks: [
// 阶乘计算
{
opcode: 'factorial',
blockType: Scratch.BlockType.REPORTER,
text: '[NUMBER] 的阶乘',
arguments: {
NUMBER: {
type: Scratch.ArgumentType.NUMBER,
defaultValue: 5
}
}
},

// 随机数生成
{
opcode: 'randomRange',
blockType: Scratch.BlockType.REPORTER,
text: '在 [MIN] 到 [MAX] 之间的随机数',
arguments: {
MIN: {
type: Scratch.ArgumentType.NUMBER,
defaultValue: 1
},
MAX: {
type: Scratch.ArgumentType.NUMBER,
defaultValue: 100
}
}
},

// 质数判断
{
opcode: 'isPrime',
blockType: Scratch.BlockType.BOOLEAN,
text: '[NUMBER] 是质数?',
arguments: {
NUMBER: {
type: Scratch.ArgumentType.NUMBER,
defaultValue: 7
}
}
},

// 最大公约数
{
opcode: 'gcd',
blockType: Scratch.BlockType.REPORTER,
text: '[A] 和 [B] 的最大公约数',
arguments: {
A: {
type: Scratch.ArgumentType.NUMBER,
defaultValue: 12
},
B: {
type: Scratch.ArgumentType.NUMBER,
defaultValue: 18
}
}
}
]
};
}

factorial(args, util) {
const n = Math.floor(Number(args.NUMBER));
if (n < 0) return 0;
if (n === 0 || n === 1) return 1;

let result = 1;
for (let i = 2; i <= n; i++) {
result *= i;
}
return result;
}

randomRange(args, util) {
const min = Number(args.MIN);
const max = Number(args.MAX);
return Math.floor(Math.random() * (max - min + 1)) + min;
}

isPrime(args, util) {
const n = Math.floor(Number(args.NUMBER));
if (n < 2) return false;
if (n === 2) return true;
if (n % 2 === 0) return false;

for (let i = 3; i <= Math.sqrt(n); i += 2) {
if (n % i === 0) return false;
}
return true;
}

gcd(args, util) {
let a = Math.floor(Math.abs(Number(args.A)));
let b = Math.floor(Math.abs(Number(args.B)));

while (b !== 0) {
let temp = b;
b = a % b;
a = temp;
}
return a;
}
}

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

网络请求拓展

API集成拓展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
(function(Scratch) {
'use strict';

class NetworkExtension {
getInfo() {
return {
id: 'networkExtension',
name: '网络拓展',
color1: '#9C27B0',
color2: '#7B1FA2',
color3: '#4A148C',

blocks: [
// 获取网页内容
{
opcode: 'fetchUrl',
blockType: Scratch.BlockType.REPORTER,
text: '获取网址 [URL] 的内容',
arguments: {
URL: {
type: Scratch.ArgumentType.STRING,
defaultValue: 'https://api.github.com'
}
}
},

// JSON数据解析
{
opcode: 'parseJSON',
blockType: Scratch.BlockType.REPORTER,
text: '从 [JSON] 中获取 [KEY] 的值',
arguments: {
JSON: {
type: Scratch.ArgumentType.STRING,
defaultValue: '{"name":"TurboWarp","version":"1.0"}'
},
KEY: {
type: Scratch.ArgumentType.STRING,
defaultValue: 'name'
}
}
},

// 天气查询
{
opcode: 'getWeather',
blockType: Scratch.BlockType.REPORTER,
text: '获取城市 [CITY] 的天气',
arguments: {
CITY: {
type: Scratch.ArgumentType.STRING,
defaultValue: '北京'
}
}
}
]
};
}

async fetchUrl(args, util) {
try {
const response = await fetch(args.URL);
const text = await response.text();
return text;
} catch (error) {
console.error('网络请求失败:', error);
return '请求失败';
}
}

parseJSON(args, util) {
try {
const json = JSON.parse(args.JSON);
return json[args.KEY] || '';
} catch (error) {
console.error('JSON解析失败:', error);
return '';
}
}

async getWeather(args, util) {
try {
// 这里使用一个免费的天气API示例
const response = await fetch(`https://wttr.in/${args.CITY}?format=3`);
const weather = await response.text();
return weather.trim();
} catch (error) {
console.error('天气查询失败:', error);
return '查询失败';
}
}
}

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

拓展测试和调试

本地测试方法

  1. 将拓展文件保存为.js文件
  2. 在TurboWarp编辑器中打开”添加拓展”
  3. 选择”从文件添加”或使用开发者模式
  4. 加载你的拓展文件进行测试

调试技巧

1
2
3
4
5
6
7
8
9
10
11
12
// 在拓展中添加调试信息
console.log('拓展已加载');
console.log('参数:', args);
console.log('工具对象:', util);

// 使用try-catch处理错误
try {
// 你的代码逻辑
} catch (error) {
console.error('错误信息:', error);
return '错误';
}

发布和分享

托管拓展文件

  1. 将拓展文件上传到GitHub Gist
  2. 使用GitHub Pages托管
  3. 使用专门的拓展托管服务

分享给社区

  1. 在TurboWarp社区论坛发布
  2. 在Scratch社区分享
  3. 在GitHub上创建仓库

最佳实践建议

代码规范

  1. 使用清晰的变量和函数命名
  2. 添加详细的注释说明
  3. 遵循JavaScript编码规范
  4. 处理各种异常情况

性能优化

  1. 避免阻塞主线程的操作
  2. 合理使用异步编程
  3. 优化算法复杂度
  4. 减少不必要的计算

用户体验

  1. 提供清晰的积木文本说明
  2. 设置合理的默认值
  3. 添加错误提示信息
  4. 考虑不同用户的需求

常见问题解决

拓展无法加载

  • 检查JavaScript语法错误
  • 确认文件编码为UTF-8
  • 验证拓展格式是否正确

积木不工作

  • 检查opcode是否匹配
  • 验证参数定义是否正确
  • 确认函数实现是否完整

网络请求失败

  • 检查CORS设置
  • 验证API访问权限
  • 处理网络异常情况

通过本教程,您应该能够掌握TurboWarp拓展开发的基本技能。从简单的积木块创建到复杂的网络API集成,拓展开发为TurboWarp提供了无限的可能性。建议从基础示例开始,逐步尝试更复杂的功能实现。