ScratchXを使って天気を取得するブロックを作成

Scratch には、独自のブロックを作る方法として代表的な方法の、1つは JSON Hack(英語) といって、”ブロックを作る” 機能を応用した方法があります。
2つ目の方法として、ブロックの中で Scratch の枠を超えた行動をとりたいとき、ScratchX を利用するという方法があります。

ScratchX は、Scratch をベースに派生したプロジェクトで、JavaScriptのコードを読み取らせることにより、Scratchに新しい動作を与えることができます。制約としては、「ブラウザーでできること」と、Scratchのブロックの仕組み内であればなんでもできます。

例えば、以下の様なText to Speech 拡張では、今時のブラウザで実装されている Web Speech API をScratchからコールすることにより、キャラクターに適当なことばを喋らせることができます。(環境には依存するようですが、Mac では日本語でも流暢に喋ってくれます。)
http://sayamindu.github.io/scratch-extensions/text-to-speech/#getting-started

新しいブロックを作る際に、手順としては

  • Webサーバ もしくは GitHubアカウントの用意
  • JavaScript のコードの用意、サーバにアップ
  • ScratchX から呼び出す

だけです。

1. Webサーバ もしくは GitHubアカウントの用意

Webサーバを用意する際に注意点としては、ルートディレクトリに以下の様な crossdomain.xml を公開する必要があるという点です。
これは、Scratchのアプリケーション(Flash)から、用意したスクリプトの読み込みをクロスドメインで許可するためのブツ。
CORSが出る前は、これをよく書きましたなぁ。(遠い目)

<cross-domain-policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.adobe.com/xml/schemas/PolicyFile.xsd">
  <site-control permitted-cross-domain-policies="master-only"/>
  <allow-access-from domain="scratchx.org"/>
  <allow-access-from domain="llk.github.io"/>
</cross-domain-policy>

GitHubアカウントには、リポジトリ内の情報をそのままWebに公開する機能があるのでアカウント名.github.ioというリポジトリを作成して、コンテンツを公開するという手もあります。
(残念ながら、私は別に使う目的があったので、自前のWebサーバを利用しました。)

2. JavaScriptのコードの用意

以下の様なJavaScriptコードを準備します。
これは、サンプルに従って、天気情報を取得するAPIをコールして、世界各地の気温を取ってくるものです。OpenWeatherMap APIは、華氏で気温を取得するため、日本で利用しているセ氏に変換する処理などを含んでいます。

https://gist.github.com/kawahara/d82734df5bb139871fac8cf4a5e31068

最低限必要なのは以下

// 終了処理
ext._shutdown = function() {};
// 準備処理。デバイスとの接続などのため、ステータス情報を
// 返す場合に必要
// status: 0 は準備失敗
// status: 1 は準備中
// status: 2 は準備完了
ext._getStatus = function() {
  return {status: 2, msg: 'Ready'};
};
var descriptor = {blocks: [...]};
// 利用する機能名、ブロックの情報、そしてブロックのロジックを含むオブジェクトを登録
ScratchExtensions.register('お天気拡張', descriptor, ext);

descriptor.blocks には、以下の様なブロック情報を配列で渡す。

var descriptor = {blocks: [
['R', '天気を取得', 'get_weather']
]};

配列中の1つ目は、識別符号のようなもので、以下のような種類があります。

  • ‘ ‘ (スペース): 同期コマンド (値を返さないもの、四角いブロック)
  • ‘w’: 非同期コマンド (値を返さないもの、四角いブロック)
  • ‘r’: 同期レポーター (値を返すもの、丸いブロック)
  • ‘R’: 非同期レポーター (値を返すもの、丸いブロック)
  • ‘h’: ハットブロック (冒頭に来るブロック)

2つ目は、ブロック名で、’%s の天気を取得’ のようにすることにより、利用者に入力してもらえるブロックになる。選択式にする方法もあるのですが、今回は説明しません。

3つ目は、呼び出す関数名となる。上の例の場合、

  ext.get_weather = function(callback) {
    $.ajax({
      url: 'http://api.openweathermap.org/data/2.5/weather?q=Kashiwa,%20JP&amp;units=imperial&amp;APPID=xxx',
      dataType: 'jsonp',
      success: function(data) {
        if (data.cod == 200) {
          console.log(data);
          var main = data.weather[0].main;
          if (main == undefined) {
            callback('');
          } else {
            callback(main);
          }
        } else {
          callback('');
        }
      }
    });
  };

の部分が呼び出されることになる。非同期系の場合、最終引数(%sなどが先に渡される)には、callback関数が渡されるので、それに対して、返したい値を渡せば処理が完了となる。(コマンドの場合、ただ呼び出すだけでよい。)
同期処理の場合、callback関数は使わず、愚直に return すればいいだけです。
1つだけ特殊な、ハットブロックは、指定した関数の返り値がtrueになった瞬間に、後に続くブロックが呼び出されるとのことです。(trueにしっぱなしにすると、ずっと呼び出されることになるので実装には注意が必要。)

3. 出来上がったコードをWebサーバにアップ、ScratchXから読み込み

出来上がったJavaScriptは、crossdomain.xml を配置してあるWebサーバ下のどこかに置きます。

最後に、ScratchX のトップから、Open Extension URL をクリックして、今回アップロードしたJavaScriptファイルのURLを設定してOpenします。

スクリーンショット 2016-07-05 23.58.03そうすると、その他に、追加したブロックたちが現れる。やったね!
スクリーンショット 2016-07-06 0.00.23

 

まとめ

今回、Scratch Day in Kashiwa のハッカソンブースに居座り、このような試みをしてみた。(Scratch Day in Kashiwa のみなさん!ありがとうございます!楽しかったです。)

このとこのWebは割と何でもできて、MIDI, 音声合成, 位置情報取得などなど夢は広がります。一方、ScratchX ではハードウェア連携も行うことができます。USB HIDとの通信や、シリアル通信もサポートしているので子どもと一緒にハードウェア開発をする際のお供になるかもしれません。

Leave a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です