DXRubyのポリシーなど

最近、mrubyのSDLライブラリや、Rubyでも他のゲームライブラリなどが出てきている。前からRuby用ゲームライブラリは比較的たくさんあったわけだが、他のものを眺めていて、ようやくいまごろDXRubyの特徴的な設計方針がわかったような気がした。
もともと作り始めたのはRubyを触り始めた頃で、オブジェクト指向もよくわかっておらず、Rubyの難しい機能もさっぱりという状態だった。ようするに自分という具体的な初心者をターゲットに置いて、DXRubyの開発はスタートしたのである。

一般的にゲームライブラリは「何ができるか」に注目する。ここではあえて、「何が無いか」を取り上げてみよう。DXRubyにはざっくりと以下のものが存在しない。
(a) includeして使うモジュールが存在しない。
(b) クラスを継承して使う必要がある抽象クラスが存在しない。
(c) ブロックを受け取り保存して後で呼び出すコールバック機能が存在しない。

これらはオブジェクト指向では普通に行われる、もしくはRubyの特徴的な機能だ。しかし、開発当初時代の俺には難しすぎたのである。自分で理解できない機能を実装できるわけがない。
長いことSpriteの実装をためらってきたのは、これを開発当時の自分が使えるのかというところに疑問を持っていたからなのだ。結局、Spriteは単体でSprite.newとかしてもそれなりに使えるように設計した。継承の概念が必須という状況にはしたくなかったからだ。いまでも簡単なコードを書くときはSprite.newってしている。例えばこのあいだのホーミングレーザーの自機と敵はSprite.newとして作られたSpriteオブジェクトだ。いちいちクラス定義を書くのは面倒である。

Ruby用ライブラリはそれぞれ独自のmoduleを作ってその中にクラスを定義するというお作法がある。ネームスペースとしてモジュールを使う手法で、DXRubyにも目立たないがDXRubyモジュールというものが存在していて、全てのクラス/モジュール/定数はその下に定義されている。最初はそれすらも無くて直接トップに定義していたが、途中でモジュールを追加した。DXRubyがincludeしなくても使えるのは、require時に勝手にincludeしているからである。これはひどい。でもぶっちゃけ、「おまじないでinclude DXRubyと書きます」なんて説明、俺にはできない。ちなみにrequire前にグローバル変数$dxruby_no_includeにtrueを設定しておくとincludeされないという極悪非道な仕様もある。あるにはあるが自分自身使ったのは1度しかないし、使ってる人を見たことも無い。たぶんいらない。

Windowモジュールはなぜクラスじゃないのか。ウィンドウを生成するのにオブジェクトを作らないという部分に批判的な意見を見たことがある。が、ウィンドウなんてたいがい1つしか作らないし、使わない複数ウィンドウ機能のために生成したWindowオブジェクトをローカル変数に格納したら、それを参照して描画メソッドを呼ぶときに面倒なことになる。グローバル変数に入れるか?このライブラリはグローバル変数が必須なのか?引数に入れて持ちまわすか?モジュールでいいやん?
似たような感じで、ゲームループのブロック引数でゲームオブジェクトが渡されてくるタイプもある。ブロック引数はローカル変数だからこれも同じ問題を抱える。そのオブジェクト、必要なの?と。

Shaderも悩んだ。Shader.new(hlsl)でクラスオブジェクトを返すという手も考えていた。しかしWindow.draw_shaderに渡すオブジェクトは1つでいい場合もあり、そしたらShader.new(hlsl).newという意味がわからない式が出てくることになる。クラスオブジェクトという存在は初心者には難しいのである。だからクラスを2つに分離する設計を選択した。無論、HLSLを初心者が書くのかという疑問はある。でもまあ、HLSLを書けるRuby初心者がいてもおかしくはない、かな。

そんな感じである。
ゲームのプログラムをオブジェクト指向的に綺麗に設計すればいい、とか、言われても困る。なぜなら想定ユーザはオブジェクト指向初心者だったのだから。Rubyの機能を活用したスマートなライブラリがいい、と言われても困る。なぜなら想定ユーザはRuby初心者だったのだから。
その代わり、原始的な機能しか提供していないから、ユーザが勉強して何かしらクラスを作ったりして拡張してくれればいいだろう。使う人のレベルに合わせて、使う人が拡張するのである。ちょっと面倒かもしれないけども。こんなんあったら便利じゃね?とか言いながら公開してドヤ顔するのは大変すばらしいことだ。俺もよくやってる(ドヤァ

最近ちょっと難しい機能を作ったりしてるが、わからない人は使わなくても問題ないというレベルにとどめてはあって、たぶん無意識のうちに当時の自分を思い出してるのではないか、とか、そんなことを思いつつ。
尻切れトンボ的にこの記事は終わるのである。