ScratchX の Extension をローカルで開発する環境を整える の続きです。
今回は ScratchX で非同期のコマンドブロックを作ってみたいと思います。
非同期のコマンドブロックっていきなり言われても分からないと思うのでざっくり説明します。
ScratchX の Extension では以下の5種類のブロックを作ることができます。
- 同期コマンドブロック(Synchronous command)
- これは
X歩動かす
ブロックのように一瞬で処理が終わるブロックのことです - 形状的には四角いブロックです
- 非同期コマンドブロック(Asynchronous command)
- これは
N秒でx座標をX、y座標をYにする
のように一瞬で処理が終わらないブロックのことです
- 同期レポーターブロック(Synchronous reporter)
- レポーターブロックとは値のブロックのことです
- 同期コマンドブロックとは一瞬で値が取得できる
x座標
などブロックです - 形状的には楕円形のブロックです
- 非同期レポーターブロック(Asynchronous reporter)
- 非同期レポーターブロックは値を取得するのに時間がかかるブロックのことです
- Scratch に元からあるブロックに該当するものがあるのか分かりませんが Web API を叩いて値を取得するときなどに使用します
- ハットブロック(Hat block)
- ハットブロックとは
イベント
のところにあるキーが押された時
などのブロックのことです
長くなりましたが Extension ではこれらのブロックを定義することができます。
実は前回の ScratchX の Extension をローカルで開発する環境を整える で作ったブロックは 1の 同期コマンドブロック
です。
そして今回は 2 の 非同期コマンドブロック
を作ってみます。
作るもの
完成のイメージです。
今回は指定した秒数待ってからログ(ダイアログ)を表示するブロックを作ります。
wait 2 sec and log ろぐだよん
というやつです。
前回は即座にログを表示しましたが、今回は N秒待ってから表示するという動作になります。
こういう感じの動作を非同期な動作と呼びます。
事前準備
前回の ScratchX の Extension をローカルで開発する環境を整える で作った環境をベースにして作業をしていきます。
環境が無い方は是非記事を参考にして整えてみてください。
Extension を作る
前回作った log_extension.js
を以下のコードに変更します。
主に
- wait_log 関数を追加
- descriptor のところを修正
をやっているだけです。 書くのが面倒だったらまるごとコピペしちゃってください。
重要なのは wait_log
という関数の最後の callback
という引数です。
同期処理の場合、 ScratchX は関数の最後の行が実行されれば処理が終わったと判断できます。
しかし非同期処理の場合は最後の行が実行されても処理が終わったかどうかは分かりません。
そこで callback
という関数をを実行することで処理が終わったことを ScratchX に伝えてあげます。
今回の場合 alert
を実行した後に callback
を実行しているのでダイアログが閉じた後に callback
が実行されて次のブロックに処理が進みます。
(function(ext) {
// コメントは補足の説明なので書かなくてもいいです
// Extension が終了するときに呼ばれる
// 今は特に何もしない
ext._shutdown = function() {};
// Extension の状態を返す
// デバイスが繋がっていないときにはエラーを返したりする
// ---
// 返す値, 表示される色, 意味
// 0, red, error
// 1, yellow, not ready
// 2, green, ready
// ---
// 今回はデバイスなどは使用しないので常に準備完了
// ということで 2 を返します。
ext._getStatus = function() {
return {status: 2, msg: 'Ready'};
};
// wait 秒待ってから str を表示するブロック
ext.wait_log = function(wait, str, callback) {
setTimeout(function() {
alert(str);
callback();
}, wait * 1000);
};
// この関数がブロック処理になります。
ext.log = function(str) {
// ログを出力するだけ
alert(str);
};
// ブロックをどういう風に表示するかを書きます
// ここの書き方は結構難しいので今は説明しません
var descriptor = {
blocks: [
[' ', 'log %s', 'log', 'sample log'],
['w', 'wait %s secs and log %s', 'wait_log', 1, 'sample log']
]
};
// Scratch に作ったブロックを登録します
ScratchExtensions.register('Log Extension', descriptor, ext);
})({});
diff はこんな感じ。
diff --git a/src/log_extension.js b/src/log_extension.js
index b5b6251..349ac6e 100644
--- a/src/log_extension.js
+++ b/src/log_extension.js
@@ -20,6 +20,14 @@
return {status: 2, msg: 'Ready'};
};
+ // wait 秒待ってから str を表示するブロック
+ ext.wait_log = function(wait, str, callback) {
+ setTimeout(function() {
+ alert(str);
+ callback();
+ }, wait * 1000);
+ };
+
// この関数がブロック処理になります。
ext.log = function(str) {
// ログを出力するだけ
@@ -30,7 +38,8 @@
// ここの書き方は結構難しいので今は説明しません
var descriptor = {
blocks: [
- [' ', 'log %s', 'log', 'sample log']
+ [' ', 'log %s', 'log', 'sample log'],
+ ['w', 'wait %s secs and log %s', 'wait_log', 1, 'sample log']
]
};
保存したら実際に ScratchX に読み込ませて使ってみます。
ScratchX で使ってみる
まずはローカルサーバーを起動します。
前回と同じ手順です。
terminal でpackage.json
のあるディレクトリに移動して npm start
を実行します。
そしたら http://scratchx.org/?url=http://localhost:8080/log_extension.js
をブラウザで開いて I understand, continue
という緑色のボタンを押します。
すると以下の画像のように wait 1 secs and log sample log
というブロックが追加されていると思います。
早速以下のようにプロックを組んでみましょう。
そんでもって実行すると2秒後にダイアログが表示されます。
この2秒待ってから何か処理をする(今回はダイアログの表示)という動作が非同期な動作です。
まとめ
- 非同期な動作を行うブロックを作りました
- ブロックの関数内で
callback
を呼ぶことによって非同期処理の終了を ScratchX に伝えます
今回作ったブロックは特に有用なものではありませんが、非同期ブロックは
- ロボットが指定した位置に移動するまで待つ
- 通信が終わるまで待つ
などのように何か待つときに色々使えると思います。
次はレポーターブロックについて書きたいと思います。