LoginSignup
5
3

More than 5 years have passed since last update.

Ruby 向けゲーム GUI フレームワーク "quincite" の紹介

Posted at

この記事はゲームエンジン・ライブラリ・ツールの開発 Advent Calendar 2016 の 6 日目の記事です。

quincite

クインサイトと読みます。ゲームで手軽に GUI を記述することを目的にしています。

quincite 自体は GUI コンポーネントのツリー構造を構築するだけで、描画とかはしません。実際に GUI のコンポーネントを画面に表示するためには、たとえば DXRubyGosu を使って、それぞれ描画処理を実装する必要があります。

DXRuby 用の実装には dxruby_sprite_ui があって、Gosu 用の実装には gestalt_ui というものが予定されています。Gosu 版のほうはまだ試作段階で gem 化できていませんが、ゆくゆくは gem にして bundler でインストールできるようになる予定です。

どうして Ruby ?

ぼくにとって書いてて楽しいのが Ruby だったというのが一番の理由です。

それはそれとして、ちょっと思いついたアイデアをすぐに動かして試せる環境がほしいと思ったことはありませんか。ぼくはあります。

紙の上にゲーム画面を書いて、この画面でこうやったら次はこうなって、みたいなの考えるのはとても楽しいです。

さて、このアイデアをもとにさくっとプロトタイプを作りたいと考えます。

Ruby だと思いついたことをすぐにコードに起こせます。思いつきドリブンでゲーム作るのにもってこいの言語だと思っています。

ゲームの GUI を作るのはめちゃ大変

ゲームの GUI というのは、思ってるよりかなり労力を要求されます。タイトル画面ひとつ作るだけでもけっこうな手間です。

そのへんよろしくやってくれるライブラリが、Ruby にはありません。そもそも Ruby でゲームを作るということがニッチなのでそれはしょうがない。

でも、さくっとゲーム書きたいのに、GUI ベースのゲーム作るのが大変なのでは困ります。

そういう自分の中での要請が背景にあって、quincite が作られました。

quincite の使い方

quincite の wiki から抜粋すると、

require 'quincite'
include Quincite

class Node
  include UI::Component
  def initialize(id)
    init_component
    self.id = id
  end
end

class Nodeset < Node
  include UI::Container
  def initialize
    super
    init_container
  end
end

ui = UI.build(UI::Nodeset) do
  Node {
    x 0
    y 0
  }
end
ui.layout

こういうコードで、シンプルなコンポーネントツリーを構築できます。

Quincite::UI::Component モジュールをインクルードしたらそれが quincite のコンポーネントになって、さらに Quincite::UI::Container モジュールをインクルードしたら子コンポーネントを持つことができるようになります(コンテナとコンポーネントを同時にインクルードすることを想定しています)。

UI.build メソッドに渡したブロックをビルダー DSL と呼んでいて、このブロックの中でコンポーネントツリーを宣言的に記述できるようになっています。例のコードでは Node(0, 0) に配置するだけになっています。

これはコンポーネントツリーを構築するだけしかしないので、実際にゲーム画面に出すには任意のライブラリを使った描画メソッドを実装する必要があります。

DXRuby で quincite を使う

Ruby でゲームを作るためのライブラリに DXRuby というものがあるのでこれを使って quincite の GUI を実際に画面に出すのをやってみます。

quincite 上に DXRuby 用のコンポーネント定義を書くサンプルでもよいのですが、DXRuby にはすでに dxruby_sprite_ui というライブラリがあるので、これを使います。

dxruby_sprite_ui

描画やクリック判定に DXRuby::Sprite を使っているので dxruby_sprite_uiという名前になっています。DXRuby モジュールの下に追加されるので DXRuby から使うときはそのまま SpriteUI と書けば使えます。

クリックすると内容が変わるボタンのデモです。

require 'dxruby'
require 'dxruby_sprite_ui'

SpriteUI.equip :MouseEventHandler

ui = SpriteUI::build {
  TextButton {
    text 'Hello, world!'
    hello = true
    onclick -> target {
      target.text = hello ? 'Goodbye, world...' : 'Hello again, world!'
      hello = !hello
      ui.layout
    }
  }
}
ui.layout

mouse_event_dispatcher = SpriteUI::MouseEventDispatcher.new(ui)

Window.loop do
  mouse_event_dispatcher.update
  mouse_event_dispatcher.dispatch
  ui.draw
end

こんな感じで、DSL でコンポーネントツリーを作って、イベントハンドラを書くだけで、クリックで何かする GUI が作れます。簡単。

quincite がやっていること

描画やクリック判定以外のことはだいたい quincite がやっています。

たとえばクリックイベントの発火は dxruby_sprite_ui で実装していますが、イベントの伝達とイベントハンドラの呼び出しは quincite 側で実装されています。

上の例にない機能だと自動レイアウトがあって、コンポーネントを絶対座標で指定しなくても他のコンポーネントとの位置関係からよろしく自動配置できるようになっています。

ちょっとサンプルのコードが大きいのでリンクだけ貼っておきます。

課題

  • リンク先のコードを見てもらえればわかりますが marginpadding を都度指定しないといけなくてぜんぜん DRY ではないので同じようなスタイルを使いまわせるようにしたいということを考えています。
  • リファレンスがないので使い方がぜんぜんわからないことに定評があります。
  • ビルダー DSL はでかくなりがちなので外部ファイルに吐き出せるようにしたい気持ちが大きい。
  • ビルダー DSL のエラーがわかりにくいのでなんとかしたい気持ちが大きい。
  • 動的にコンポーネントを生やす仕組みが弱いので同じような要素の繰り返しなどは力技でコードを書く必要があります。
  • キーイベント処理はいまのところ対応できていません。

まだまだ若いライブラリなのでこれからだと思っています。

dxruby_sprite_ui を使ったゲームのサンプル

「野メイド」という育成 SLG っぽいデモゲームを作ったのでそちらをご覧ください。

おわりに

Ruby でゲームを作るための GUI ライブラリを紹介させていただきました。いまのところ使っているのが自分だけしかいないという状況なんですが、今後リファレンスとサンプルコードを充実させていこうと思っているのでどんどん使ってみてほしいと思う次第です。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3