ブラウザ上でRubyっぽいプログラムを作成・実行する 〜スモウルビー3のRuby→命令ブロックの変換機能を使ってみる〜


筆者は[Scratch 3.0](https://beta.scratch.mit.edu)ベースの[スモウルビー3](https://smalruby.jp/smalruby3-gui/)というビジュアルプログラミングツール(参考情報:[Wikipedia:ビジュアルプログラミング言語](https://ja.wikipedia.org/wiki/%E3%83%93%E3%82%B8%E3%83%A5%E3%82%A2%E3%83%AB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E))を開発しています。この記事では[スモウルビー3](https://smalruby.jp/smalruby3-gui/)を使って、ブラウザ上でRubyっぽいプログラムを作成・実行してみようと思います。

## はじめてのスモウルビー3

早速ですが、 https://smalruby.jp/smalruby3-gui にアクセスし、「ルビー」タブをクリックしてテキストエディタを表示してください。そして、次のコードをコピペしたら、 ![緑色のフラッグ](https://qiita-image-store.s3.amazonaws.com/0/4197/072f724c-ae5a-33af-78d9-422908f1ab8d.png "icon--green-flag.png") ボタンをクリックして、コピペしたコードを実行してみてください。

```ruby
self.when(:flag_clicked) do
  loop do
    move(10)
    bounce_if_on_edge
    wait
  end
end
```

みなさんの画面でも次のスクリーンキャプチャのように、ネコが左右に往復しているはずです。

![Rubyのコードをコピペして緑色のフラッグをクリックするとねこが左右に動き続ける](https://qiita-image-store.s3.amazonaws.com/0/4197/e56b913d-dcf2-ed81-8f11-9b41dbf80903.gif "画面録画-2018-12-18-時刻-23.28.02.gif")

このプログラムで使っている各メソッドの機能を次の表にまとめました。

| メソッド名 | 機能 |
|-----|--- |
| `self.when(:flag_clicked) do 〜 end` | ![緑色のフラッグ](https://qiita-image-store.s3.amazonaws.com/0/4197/072f724c-ae5a-33af-78d9-422908f1ab8d.png "icon--green-flag.png") ボタンがクリックされたときに指定したブロックを実行する |
| move(10) | 指定したドット数分、向いている方向にキャラクターを動かす |
| bounce_if_on_edge | キャラクターが端に着いたら、 **いい感じに** 跳ね返る |
| wait | キャラクターが再描画されるまで、ほんの少し待つ |

このように スモウルビー3を使えば、ブラウザ上でRubyのプログラムを作成・実行することができます。しかも、キャラクターを動かしたり、音を鳴らしたり、背景を自由に設定したりと、2次元のゲームを作りたい人にとってはうれしいメソッドが用意されています。

## 手を叩くことに反応する

もう少しだけスモウルビー3の実力をみてもらいたいと思います。
プログラムを改良して、手を叩くたびにネコが動くスピードが速くなるようにしてみます。

まずはネコのスピードの初期値を変数に代入するのですが、スモウルビー3では基本的にローカル変数は使えません[^1]。次のようにローカル変数のかわりにインスタンス変数を使います。

```ruby
@speed = 10
```

これはとても違和感を感じると思いますが、スモウルビー3の「ルビー」タブに入力したコードは、選択中のキャラクター(ネコ)に対するものとなっており、各メソッド呼び出しのレシーバはキャラクターを表現したオブジェクトになります。インスタンス変数であれば「ルビー」タブのコードのどこからでも参照できるので、とても都合が良いのです。このため、スモウルビー3ではインスタンス変数を使うことにしました。

次に、手を叩いたことを検出できるようにします。

スモウルビー3には、手を叩く、つまり大きな音がしたときに指定したブロックを実行するメソッド `self.when(:greater_than, "loudness", 10) do 〜 end` が用意されています。

これらを使って、手を叩くたびにネコのスピードが速くなるようにしたものが次のプログラムです。

```ruby
self.when(:flag_clicked) do
  @speed = 10
  forever do
    move(@speed)
    bounce_if_on_edge
  end
end

self.when(:greater_than, "loudness", 10) do
  @speed += 1
end
```

さらに、一定以上のスピード(31)になったら「ゴール！」ということにします。

`say` メソッドを使えば、キャラクターから吹き出しが出て、そこにメッセージを表示できます。

```ruby
self.when(:flag_clicked) do
  @speed = 10
  forever do
    move(@speed)
    bounce_if_on_edge
  end
end

self.when(:greater_than, "loudness", 10) do
  @speed += 1
  if @speed > 30
    say("ゴール！")
  end
end
```

![スピードが30より上になったらネコがゴールと言う](https://qiita-image-store.s3.amazonaws.com/0/4197/06e5823d-22f5-5ad7-1227-4863b155ca93.png "スクリーンショット 2018-12-19 21.30.27.png")

これがスモウルビー3です。

ブラウザ上でRubyを動かして学べるサービスとしては、[TryRuby](https://ruby.github.io/TryRuby/)が有名ですが、スモウルビー3もそのようなサービスの一員として、Rubyコミュニティに受け入れてもらえるとうれしいです。

## スモウルビー3の仕組み

さて、ここからはスモウルビー3の仕組みについて触れていきたいと思います。

冒頭で触れたようにスモウルビー3は、[Scratch 3.0](https://beta.scratch.mit.edu/)をベースに開発しているビジュアルプログラミングツールです。

Scratchは全世界で利用されており、そのユーザー数は3000万人以上。対象年齢は少学生3年生(7歳)以上、日本国内ではプログラミング初心者や小中学生向けのプログラミング教室や小学校での利用実績が数多くあります。

Scratchは主にマウスで操作して、画面上のキャラクター(Scratchではスプライトと呼ぶ)や背景に対する命令を表現したブロック(命令ブロック)を組み合わせてプログラムを作成します。

このScratchをベースに開発しているスモウルビー3では、RubyのコードをScratchの命令ブロックに変換する機能を追加しています。
さきほどの「手を叩くとネコのスピードが速くなる」プログラムは、次の命令ブロックとして表現されます。これはスモウルビー3の「コード」タブに切り替えると確認できます。

![「手を叩くとネコのスピードが速くなる」プログラムに対応する命令ブロック](https://qiita-image-store.s3.amazonaws.com/0/4197/6641f46e-fdc3-a690-85e1-ea14f7afe1ca.png "スクリーンショット 2018-12-19 21.44.42.png")

さらに、スモウルビー3には命令ブロックからRubyのコードに変換する機能もあります。スモウルビー3を使い始めたばかりで命令ブロックに対応するRubyのメソッドがわからない場合は、「コード」タブを使って命令ブロックの組み合わせでプログラムを作成してから「Ruby」タブに切り替えることで、利用可能なメソッドの種類、機能、名前を把握することができます。

![画面録画-2018-12-19-時刻-21.57.57.gif](https://qiita-image-store.s3.amazonaws.com/0/4197/433605f1-52dc-d26a-5a34-3d54fbe7f815.gif "画面録画-2018-12-19-時刻-21.57.57.gif")

スモウルビー3は、ブラウザ上でプログラムを作成・実行でき、2次元のゲームを作成するのに便利な命令が用意されていることは魅力なのですが、その一方で、Scratch 3.0で実現できることしか「ルビー」タブのコードでも表現できません。

例えば、class、module、for、whileなど、Rubyの基本的な文法のいくつかも実現できません。
この記事のタイトルで「Rubyっぽい」としているのはそのような理由からです。

それでも、Rubyやプログラミングの初心者が、

 - 順次処理(変数の代入、四則演算、各種キャラクター操作の命令など)
 - 条件分岐(if 〜 else 〜 end)
 - 繰り返し(loop do 〜 end、until 〜 end)

といったプログラムの基本的な要素を、主にマウスの操作によって命令ブロックを組み合わせるだけで、各命令の機能を確認しながら、Rubyでの文法も学べるというのは、とても良いことなのではないかと考えています。

## RubyのコードをScratchの命令に変換する仕組み

最後に、スモウルビー3で、どのようにしてRubyのコードをScratchの命令ブロックに変換しているのかについて説明します。

スモウルビー3は、JavaScriptで実装しています。Rubyのコードを解析するためのライブラリは、JavaScriptでは実装されていません。しかしながら、Rubyで実装したものはたくさんあります(参考資料「[Qiita:Rubyのコードをパースするライブラリまとめ](https://qiita.com/vzvu3k6k/items/dd45ad293ae2d60c7a4e)」)。

特に、[parser gem](https://github.com/whitequark/parser)は、pure rubyで実装されて、使いやすく、ripper よりも認識率が高いと謳っています。これをJavaScriptから使えるといいですよね。そこで、Opalの出番です。

[Opal](https://github.com/opal/opal)は、RubyのコードをJavaScriptのコードに変換するためのコンパイラです。これを使えば、parser gemをJavaScriptに変換でき、スモウルビー3からも利用できます。

このように、Opalとparser gemのおかげで、スモウルビー3は、Rubyのコードを正確に解析してScratchの命令ブロックに変換できています。

![Opal + parser gemでブラウザ上でRubyコードを解析](https://qiita-image-store.s3.amazonaws.com/0/4197/56cd3cbd-b40c-a6f0-0e48-16ab03dac6fe.gif "画面録画-2018-12-19-時刻-22.28.39.gif")

## まとめ

スモウルビー3は、ブラウザ上でRubyっぽいプログラムを作成・実行できます。
ただし、制限もあってScratch 3.0で実現できることしか表現できません。
また、スモウルビー3は、Rubyのコードを解析するために、Opalを使ってparser gemをJavaScriptから利用しています。

スモウルビー3の開発はまだ始まったばかりです。少し触るとバグを発見するかもしれません。機能不足を感じるかもしれません。スモウルビー3はGitHubで公開しているオープンソースソフトウェア [GitHub: smalruby / smalruby3-gui](https://github.com/smalruby/smalruby3-gui/) ですので、そんなときは、ぜひみなさんもスモウルビー3の開発に参加していただければと思います。

私は、スモウルビー3が、3000万人以上のユーザーを持つScratchとRubyコミュニティの橋渡しとなることを願って開発を続けています。これからも [スモウルビー3](https://smalruby.jp/smalruby3-gui/) をよろしくお願いします。

![スモウルビーのイメージキャラクター「はっち」](https://smalruby.jp/images/hatti.png)

[^1]: スモウルビー3では、メソッドを定義したときのみ、その引数をローカル変数として使うことができます。