Help us understand the problem. What is going on with this article?

ScratchX で非同期のコマンドブロック(Asynchronous command)を作る

More than 3 years have passed since last update.

ScratchX の Extension をローカルで開発する環境を整える の続きです。


今回は ScratchX で非同期のコマンドブロックを作ってみたいと思います。

非同期のコマンドブロックっていきなり言われても分からないと思うのでざっくり説明します。

ScratchX の Extension では以下の5種類のブロックを作ることができます。

  1. 同期コマンドブロック(Synchronous command)
    • これは X歩動かす ブロックのように一瞬で処理が終わるブロックのことです
    • 形状的には四角いブロックです
  2. 非同期コマンドブロック(Asynchronous command)
    • これは N秒でx座標をX、y座標をYにする のように一瞬で処理が終わらないブロックのことです
  3. 同期レポーターブロック(Synchronous reporter)
    • レポーターブロックとは値のブロックのことです
    • 同期コマンドブロックとは一瞬で値が取得できる x座標 などブロックです
    • 形状的には楕円形のブロックです
  4. 非同期レポーターブロック(Asynchronous reporter)
    • 非同期レポーターブロックは値を取得するのに時間がかかるブロックのことです
    • Scratch に元からあるブロックに該当するものがあるのか分かりませんが Web API を叩いて値を取得するときなどに使用します
  5. ハットブロック(Hat block)
    • ハットブロックとは イベント のところにある キーが押された時 などのブロックのことです

長くなりましたが Extension ではこれらのブロックを定義することができます。

実は前回の ScratchX の Extension をローカルで開発する環境を整える で作ったブロックは 1の 同期コマンドブロック です。

そして今回は 2 の 非同期コマンドブロック を作ってみます。

作るもの

完成のイメージです。

image

今回は指定した秒数待ってからログ(ダイアログ)を表示するブロックを作ります。

wait 2 sec and log ろぐだよん というやつです。

前回は即座にログを表示しましたが、今回は N秒待ってから表示するという動作になります。

こういう感じの動作を非同期な動作と呼びます。

事前準備

前回の ScratchX の Extension をローカルで開発する環境を整える で作った環境をベースにして作業をしていきます。

環境が無い方は是非記事を参考にして整えてみてください。

Extension を作る

前回作った log_extension.js を以下のコードに変更します。

主に

  1. wait_log 関数を追加
  2. descriptor のところを修正

をやっているだけです。 書くのが面倒だったらまるごとコピペしちゃってください。

重要なのは wait_log という関数の最後の callback という引数です。

同期処理の場合、 ScratchX は関数の最後の行が実行されれば処理が終わったと判断できます。

しかし非同期処理の場合は最後の行が実行されても処理が終わったかどうかは分かりません。

そこで callback という関数をを実行することで処理が終わったことを ScratchX に伝えてあげます。

今回の場合 alert を実行した後に callback を実行しているのでダイアログが閉じた後に callback が実行されて次のブロックに処理が進みます。

log_extension.js
(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 という緑色のボタンを押します。

image

すると以下の画像のように wait 1 secs and log sample log というブロックが追加されていると思います。

image

早速以下のようにプロックを組んでみましょう。

image

そんでもって実行すると2秒後にダイアログが表示されます。

この2秒待ってから何か処理をする(今回はダイアログの表示)という動作が非同期な動作です。

image

まとめ

  • 非同期な動作を行うブロックを作りました
  • ブロックの関数内で callback を呼ぶことによって非同期処理の終了を ScratchX に伝えます

今回作ったブロックは特に有用なものではありませんが、非同期ブロックは

  1. ロボットが指定した位置に移動するまで待つ
  2. 通信が終わるまで待つ

などのように何か待つときに色々使えると思います。

次はレポーターブロックについて書きたいと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away