yhara.jp

Recent Posts
Edit

Opalでゲームを作るには(opal-phaser)

2016-12-21
Tech

この記事はOpal Advent Calendar 2016Ruby Game Developing Advent Calendar 2016の21日目の記事です。

OpalはRubyスクリプトをJavaScriptに変換してくれる処理系です。ということは、Opalを使えばRubyを使ってブラウザで動くゲームが作れるはずです。

opal-phaser

opal-phaserはPhaserというブラウザゲーム用ライブラリをOpalから使えるようにしたものです。今回はこれを触ってみたいと思います。

サンプルを動かしてみる

PhaserのサンプルをOpalに移植したものがあるみたいなので、とりあえず動かしてみましょう。READMEに書いてある通り、git cloneしてbundle installします。

$ git clone https://github.com/orbitalimpact/opal-phaser-examples
$ cd opal-phaser-examples
$ bundle install

そのあと、適当なサンプルのディレクトリに移動してbundle exec rackupし、http://localhost:9292/ を開きます。

$ cd examples/basics/click_on_image/
$ bundle exec rackup

実行結果です。自分が何をしようとしていたのか一瞬分からなくなりましたが、opal-phaserのサンプルを動かしていたのでした。画像をクリックするとクリックした回数が画面に表示されます。とりあえず動いているようで良かったです。

実行結果

他のサンプルも俄然、気になってきましたが、ここから先は自分の目で確かめてほしい。サブディレクトリがたくさんありますが、config.ruで検索すればサンプルだけ列挙できます。

% find . -name config.ru
./examples/animation/animation_events/config.ru
./examples/animation/change_frame/config.ru
./examples/animation/change_texture_on_click/config.ru
./examples/animation/destroy_animation/config.ru
./examples/animation/dynamic_animation/config.ru
./examples/animation/group_creation/config.ru
./examples/animation/load_texture/config.ru
./examples/animation/looped_animation/config.ru
./examples/animation/multiple_anims/config.ru
./examples/basics/click_on_an_image/config.ru
./examples/basics/image_follow_input/config.ru
./examples/basics/load_an_animation/config.ru
./examples/basics/load_an_image/config.ru
./examples/basics/move_an_image/config.ru
./examples/basics/render_text/config.ru
./examples/basics/tween_an_image/config.ru
./examples/bitmap_data/alpha_mask/config.ru
./examples/sprites/dynamic-crop/config.ru

また、phaser.js本体のExampleはもっとたくさんあるようです。

サンプルを読む

先ほどのbasics/click_on_image/のソースを見てみましょう。まず、index.htmlです。

<head>
    <title>Click On An Image</title>
    <script src="//cdn.jsdelivr.net/phaser/2.4.4/phaser.js"></script>
    <script src="/assets/main.js"></script>
</head>

phaser.jsをCDNから読み込んでいます。/assets/main.jsは、同ディレクトリのmain.rbがOpalによってコンパイルされるので、それを読み込んでいます。bodyタグの方も見てみましょう。

    <span id="title">click on an image</span>
    <script>
      Opal.load("main");
    </script>
    <div id="example"></div>

このscriptタグはOpalでコンパイルしたJSを実行開始する部分なので、消してはいけません。それ以外はclick on an imageというメッセージと、divタグが一つあるだけです。このdivタグは画像を表示するために使いそうですね。

main.rb

雰囲気が掴めたところでmain.rbを見てみましょう。これがOpalによってJSに変換されるRubyスクリプトで、このデモの中心部分です。

最初にImageというクラスがあります。こいつがクリックできるアインシュタイン(やっぱりアインシュタインだったのか…)のオブジェクトです。画像ファイルはこのディレクトリではなくて、少し上の階層のassetsというディレクトリにあります。そのあたりの設定はconfig.ruでやっているようです。

class Image
  def initialize(game)
    @sprite_key = "einstein"
    @sprite_url = "assets/pics/ra_einstein.png"
    @game       = game
  end

createメソッドに、クリックイベントを拾う処理が書いてあります。events.onでイベントハンドラを登録できるようですね。

  def create
    @counter = 0

    listener = proc do
      @counter   += 1
      @text.text = "You clicked #{@counter} times!"
    end 
...

    @text = @game.add.text(250, 16, '', { fill: '#ffffff' })

    @image.events.on(:down, self, &listener)
  end

@gameという変数は、以下のGameクラスのオブジェクトです。ファイルの最後がGame.newなので、ここがゲームプログラムのエントリポイントになるようですね。parent: "example"という指定は、index.htmlの<div id="example">を描画領域として使う、という指定でしょう。

class Game
  def initialize
    game  = Phaser::Game.new(width: 800, height: 600, renderer: Phaser::AUTO, parent: "example")
    state = MainState.new(game)
    game.state.add(:main, state, true)
  end
end

MainStateクラスはその下で定義されています。これとかを見ると、「タイトル画面」「プレイ中画面」みたいにシーンごとにStateを定義するみたいです。

class MainState < Phaser::State
  def initialize(game)
    @game = game
  end

  def preload
    @image = Image.new(@game)
    @image.preload
  end

  def create
    @image.create
  end
end

おわりに

今回はopal-phaserを紹介しました。プロジェクトとしては2年前からあるようで、今も開発が続けられています。

https://github.com/orbitalimpact/opal-phaser のGamesの項に、もう少しゲームらしいサンプルがあります。(tankgameはどうやって操作するのかよくわからない感じでしたが)

触ってみて良く分からないとかうまく動かないことがあれば、Twitter等で聞いてもらえればお手伝いできるかもしれません。


More posts