最近、プログラミング教育が大きな注目を集めています。 日本でも小学校でのプログラミング教育必修化が検討されており、Ruby界隈でも『Hello Ruby』の翻訳本である『ルビィのぼうけん』が今年5月に出版されるといった話題もありますね。

プログラミング教育の盛り上がりは、松江でも例外ではありません。 筆者は、NPO法人Rubyプログラミング少年団の活動を通じて、小中学生にプログラミングを教えています。 そこでは、スモウルビー(Smalruby)というソフトウェアを使っています。

この記事では、いちユーザの立場からスモウルビーを紹介します。 想定読者は、ある程度プログラミングの経験があって、小中学生にプログラミングを教えたいと思っている方々です。 また、スモウルビーでゲームを作る際のノウハウはあまりウェブ上に無いため、それらについてもいくつか紹介したいと思います。

本記事では、それぞれ下記のバージョンを対象としています。

  • smalruby: 0.1.10
  • smalruby-editor: 0.4.0

スモウルビーについて

スモウルビーは命令を表すブロック(Rubyのブロックと区別するために、「命令ブロック」と呼ぶことにします)をマウスで操作してプログラミングをすることができるソフトウェアです。1

画面例

スモウルビーの作者である高尾氏の2014年のRubyKaigiの講演内容から、スモウルビー開発の経緯を簡単に紹介したいと思います。

小中学生にRubyを教える際、テキストプログラミングを用いる方法だと、大きく3つの点でつまずくことになります。

  • タイピングが難しい
  • Rubyの文法がわからない
  • 英語がわからない

プログラミングで何を作りたいかを考える以前に、プログラミングが出来るようになるまでの道のりが長く、 そのために、ワークショップで楽しんでも、その日限りの体験にとどまり、その後も継続してプログラミングを行うということにはなりにくかったそうです。 このような問題を解決するために、スモウルビーは開発されました。

スモウルビーのような言語はビジュアルプログラミング言語2と呼ばれ、スモウルビー以外にも多くの言語があります。 その中で、スモウルビーの特徴は、命令ブロックとRubyコードの相互変換が可能であることだと筆者は考えています。 命令ブロックから特定の言語のテキストを出力する機能をそなえたものは多くありますが、テキストから命令ブロックへの変換が可能な言語はあまりありません。3

下記の様に、入門としての命令ブロックの世界と本格的なRubyプログラミングの世界が地続きで繋がっているのが、スモウルビーの大きな魅力と言えるでしょう。

  • 命令ブロックとRubyコードの世界を行き来でき、段階的に移行する事ができる
  • スモウルビー自体がRuby製なので、Rubyを学べば自分でスモウルビーを改造することも可能になる

スモウルビーとScratch

スモウルビーの命令ブロックはScratchとの完全互換を目指して開発されています。

Scratchは世界中のプログラミング教育の現場で最も利用されているビジュアルプログラミング言語で、5月19日現在で登録ユーザ数は1187万人を超えています。 スモウルビーと比較すると、単純に機能がより充実しているということもありますが、それ以上に、GitHubのようなエコシステムがあるのが魅力的だと思います。

また、ゲームやアニメーションの作成だけでなく、フィジカルプログラミングに活用することもできます。 フィジカルプログラミングについては、スモウルビーでもsmalrubotを使ってArduino互換のボードを制御する事ができ、松江市内の市立中学校の技術・家庭科の授業でも活用されています

ここでは、Scratchの紹介はこのくらいにしたいと思います。より詳しく知りたい人は下記の情報をご参照ください。

スモウルビーのインストール

Windowsの場合は、公式で公開されている手順に従い用意されているZipファイルを展開するだけで簡単にセットアップできます。 USBメモリにファイルを展開してそこから起動することもできます。

LinuxやMacの場合、dxruby_sdlを使用するため、Rubyをインストールする前にSDL関連のパッケージをインストールする必要があることに注意してください。 dxruby_sdlのREADMEに従って必要なパッケージをインストールした上で、Rubyをインストールし、smalruby-editorのgemをインストールしてください。

スモウルビーでのゲーム開発ノウハウ

続いて、スモウルビーでゲームを開発する上でのはまりどころや、知っておくと便利なことについていくつか紹介したいと思います。

レシーバの指定方法

スモウルビーでは、「どのキャラクタ」が「どういう時」に「何をするか」を命令ブロックを使って表現します。 この記事では、「どのキャラクタ」を表す水色の命令ブロックを「キャラクタブロック」、「どういう時」を表すオレンジ色の命令ブロックを「イベントブロック」と呼ぶことにします。

キャラクタブロックはレシーバを意味し、その内側に実行する命令ブロックを配置します。

イベントブロックは、キャラクタブロックの内側にはめる必要があります。ありがちなミスとして、キャラクタブロックの下にイベントブロックを配置することがありますが、その場合、そのイベントブロックはレシーバが指定されていないことになり、単に無視されます。

キャラクタブロックは、トップレベルだけでなく、他の命令ブロックの内側にも配置することができます。

例えば、2つのキャラクタが衝突時に互いに消滅する場合に、下記の様に書くとタイミング依存で片方が消滅しない状態になることがあります。

サンプル1-1

require "smalruby"

cat1 = Character.new(costume: "costume1:cat1.png", x: 0, y: 172, angle: 305, rotation_style: :left_right)
cat2 = Character.new(costume: "costume1:cat3.png", x: 544, y: 172, angle: 95, rotation_style: :left_right)

cat1.on(:start) do
  loop do
    move(10)
    turn_if_reach_wall
    if hit?(cat2)
      vanish
    end
  end
end

cat2.on(:start) do
  loop do
    move(10)
    turn_if_reach_wall
    if hit?(cat1)
      vanish
    end
  end
end

ここで、一方の衝突判定の処理に消滅する処理をまとめると、必ず両方のキャラクタを消滅させることができます。

サンプル1-2

require "smalruby"

cat1 = Character.new(costume: "costume1:cat1.png", x: 0, y: 172, angle: 305, rotation_style: :left_right)
cat2 = Character.new(costume: "costume1:cat3.png", x: 544, y: 172, angle: 95, rotation_style: :left_right)

cat1.on(:start) do
  loop do
    move(10)
    turn_if_reach_wall
    if hit?(cat2)
      cat2.vanish
      vanish
    end
  end
end

cat2.on(:start) do
  loop do
    move(10)
    turn_if_reach_wall
  end
end

変数のスコープ

イベントの命令ブロックは、Rubyコードでブロックとなるため、トップレベルで変数を定義しておくと、グローバル変数的に使うことができます。

ただし、命令ブロックをコードに変換する際、縦方向で上にある命令ブロックから順番にシリアライズされるため、変数定義は一番上で行う必要があります。

例えば、あるキャラクタをタイマー代わりにすることで、時間経過によるギミックを組み込むことが可能になります。5

サンプル2

require "smalruby"

cat1 = Character.new(costume: "costume1:cat1.png", x: 12, y: 88, angle: 61, rotation_style: :left_right)
frog1 = Character.new(costume: "costume1:frog1.png", x: 544, y: 384, angle: 180, rotation_style: :left_right)
タイマー = 0

cat1.on(:start) do
  loop do
    move(10)
    turn_if_reach_wall
    if タイマー > 5
      say(message: "にゃあ")
      break
    end
  end
end

frog1.on(:start) do
  loop do
    say(message: タイマー)
    sleep(1)
    タイマー = タイマー + 1
  end
end

作者の高尾氏によると、将来的には、Scratchと同じように変数を定義した際に初期化しなければ0で初期化したグローバル変数に修正する予定だそうです。

イベントハンドラの扱い

イベントブロックを配置するとイベントハンドラとして登録されますが、上書きではなくて追加される形となります。イベント発生時には登録した全ての処理がマルチスレッドで実行されます。

現状では、イベントブロックは任意の場所にはめることができます。 アイテムを取ったときに動きを追加するといったことを簡潔に記述できますが、一方で、ループの中に入れたりすると意図せぬ挙動になってしまうこともあります。

例えば、下記の様に「ずっと[ ]を繰り返す」の中にキー入力のイベントブロックを配置してしまうと、イベントハンドラが際限なく登録されてしまい、一度キーを入力しただけでも複数回キーを入力したような挙動となってしまいます。

サンプル3

require "smalruby"

cat1 = Character.new(costume: "costume1:cat1.png", x: 0, y: 180, angle: 0, rotation_style: :left_right)

cat1.on(:start) do
  loop do
    on(:key_down, K_RIGHT) do
      move(10)
    end
  end
end

作者の高尾氏によると、将来的には、キャラクタブロックの内側に直接はめるか、他のイベントブロックの真下にはめるかしかできなくする予定だそうです。

ログインとファイルの保存先について

スモウルビーにはログインという機能があります。ログインすると、ログインユーザ毎にファイルを別々に管理することができます。6

画面右上の「ログイン」ボタンを押してログインを行います。

ログイン前

ログイン後はログインユーザ名が表示されます。

ログイン後

未ログイン状態では、Windowsの場合は展開したフォルダのprogramsの中、LinuxやMacの場合は$HOMEの直下に作成したプログラムファイルが保存されます。 保存されるプログラムファイルについては「.rb」と「.rb.xml」の2種類がありますが、XMLファイルの方には命令ブロックの位置情報も含まれるため、別の環境でプログラムをロードしたい場合はXMLファイルをコピーするのがおすすめです。

ログインすると、Windowsであればprograms/[ログイン名]、LinuxやMacであれば $HOME/[ログイン名]にプログラムファイルが保存されるようになります。 ログイン状態であれば、キャラクタに使う画像を追加できるようになります。追加したキャラクタの画像データは、 Windowsであればprograms/[ログイン名]/__assets__、LinuxやMacであれば $HOME/[ログイン名]/__assets__に保存されます(便宜上、「アセットパス」と呼ぶことにします)。

画像追加

また、アセットパスにWAV形式やMIDI形式の音声ファイルを配置して、「[ ]の音を鳴らす」に音声ファイル名を指定すると、その音声ファイルを再生することができます。7

サンプル4

require "smalruby"

cat1 = Character.new(costume: "costume1:cat1.png", x: 94, y: 106, angle: 33, rotation_style: :left_right)
cat1.play(name: "bgm.mid")

DXRubyのAPIの呼び出し

スモウルビーはScratchライクにゲームを開発できるDXRubyのラッパーであるとも言えます。

DXRubyはRubyからDirectXを扱う為の拡張ライブラリで、Windows用の2Dゲームを作ることができます。 非常に簡潔な記述でゲームを開発できる、実行速度が速いといった特徴があり、島根県で毎年2回開催されているRuby合宿ではDXRubyを長年活用しています。8

動作環境がLinuxやMacの場合はDirectXが使えませんので、DXRubyではなくdxruby_sdl上で動作します。 dxruby_sdlはDXRuby互換の機能をSDLを使って実現しているもので、これもスモウルビーの作者である高尾氏によって開発されています。9

スモウルビーのプログラム上でDXRubyのWindowモジュールのメソッドを呼び出すことなども可能なので、初期化処理として、画面サイズの変更といった処理を追加することもできます。

サンプル5

require "smalruby"

cat1 = Character.new(costume: "costume1:cat1.png", x: 94, y: 106, angle: 33, rotation_style: :left_right)
Window.width = 800
Window.height = 640

cat1.on(:start) do
  loop do
    move(50)
    turn_if_reach_wall
  end
end

まとめ

本記事では、スモウルビーとその開発ノウハウについて紹介しました。 機会がありましたら、ぜひ使ってみてください。

最初のとっかかりとしては、Rubyプログラミング少年団のイベントでも使用している『はじめのいっぽ』(PDF)というテキストがおすすめです。

  1. 厳密に言うと、ScratchライクなUIでプログラムを作成できるエディタがsmalruby-editorで、その作成したプログラムの実行環境がsmalrubyですが、ひっくるめてスモウルビーと呼ぶことが多いです。 

  2. 最近はブロックプログラミング言語と呼ぶようになってきているそうですが、筆者はこのあたりの事情にそれほど明るくありません^^; 

  3. つい先月、テキストベースでScratchのプログラムを記述できるToshというソフトウェアがリリースされました 

  4. Scratchの現行バージョンは2.0ですが、この連載は1.4に関する内容となっていますので、その点はご留意ください。 

  5. 単純なウェイト処理であれば、もとから命令ブロックとして存在します。 

  6. DXRubyのSoundクラスを直接扱うこともできますが、こちらの方がパスの指定が楽です。 

  7. 外部サーバと通信したりはしません。 

  8. そういった縁もあり、松江Ruby会議05ではDXRuby作者のmirichi氏にご講演いただきました。 

  9. まだ完全互換ではありません。