今週の進み具合 #16 - 夏バテと Lua 5.3 ことはじめ

夏バテに困ってます。日記の更新が滞っておりました。まとめて 2 週間の進み具合を振り返っていきます。

進み具合 (2014年7月11日 - 7月27日)

実装したことは次の通りです。

  • JSON で記述したアニメーションステートの読み込み
  • Lua 5.3 (work 3) の組み込み
  • tolua の導入
  • Selene の導入
  • RapidJSON のアップデート
  • レンダリングキューとレンダリングコマンドの実装
  • エンティティコンポーネントシステムのリファクタリング

ゲーム作りについてはあまり進んでいません…(汗)
それぞれについて見ていきます。

JSON で記述したアニメーションステートの読み込み

アニメーションステートを外部ファイルから読み込もうと思い、JSON で記述することにしました。前回の日記で Lua を使ってみようと目論んでいましたが、JSON で事足りました。

ステートを指定してアニメーションツリーを再生することができるようになりました。アニメーションステートの遷移と、ステート間でのクロスフェードはまだ実装していません。ここ数ヶ月やってきたスケルタルアニメーションについて、ひとまず一段落したと思います。

Lua 5.3 (work 3) の組み込み

開発が進むにつれ、ネイティブの C++ コードだとコンパイルとリンクにかかる時間がプロジェクトの足かせになってきます。そこでスクリプティングの登場です。ランタイムの実行速度とメモリリソースを少しだけ犠牲にする代わりに、ゲームコードを書き換えても再コンパイルをする必要がなくなります。

今回は Lua 5.3 を利用することにしました。理由としては、組み込みやすく言語に癖がないことと、Lua 自体がミニマルであることが挙げられます。他の候補としては、Mono, V8, mruby が挙がりました。特にこだわりがなかったので、バイナリが小さい Lua を使うことにしました。

tolua の導入

Lua を使うとなると、ネイティブの C++ と Lua をつなぐバインディング部分を記述することになります。このバインディングを書くのがとても大変で、手作業でやるのは後々大変になるため、出来る限り自動化するのが重要になってきます。バインディング部分を示すコードをグルーコード (glue code) と言います。グルーコードを生成してくれるツールはいくつかあります。今回は tolua を使ってみました。もう 1 つ tolua++ という tolua を拡張したツールがありますが、こちらは Lua 5.1 にしか対応してなかったため、使用を見送りました。tolua のほうは Lua 5.2 対応でビルドも上手く通ったので利用することにしました。

Selene の導入

Lua は C で記述されたライブラリのため、そのまま C++ で扱うには少々面倒です。特に Lua ステートやスタックの管理が大変です。そこでそういった Lua のバインディングを楽にしてくれるライブラリがあります。 バインディングライブラリはグルーコード生成ツールに比べて種類が豊富で、多機能なものから最小限のものまで様々です。アプリケーションに適したものを使うことになるでしょう。 今回は C++11 に友好的でヘッダーオンリーな Lua バインディング Selene を使ってみました。他にも C++11 でヘッダーオンリーなライブラリとして SolLuaGlue などがあります。

RapidJSON のアップデート

更新の途絶えていた RapidJSON が、最近になって頻繁にコミットされるようになりました。それに伴い以前の googlecode から GitHub にリポジトリを移行しました。これまで溜まっていた pull request をどんどんマージしているようです。 JSON のパーサに RapidJSON を利用しているので嬉しい限りです。早速プロジェクトで使っている RapidJSON をアップデートしました。

サードパーティのライブラリについて現在はコピーして使っていますが、今後 Git サブツリーマージで代用していくべきか少し悩んでいます。

レンダリングキューとレンダリングコマンドの実装

レンダリングキューとレンダリングコマンドを実装しました。実装やフレームワークによって、このキューやコマンドが具体的に何を意味するのか変わってきますが、作成したのは 2D ゲーム用のレンダリングシステムです。ゲームワールド内のレンダリング可能なオブジェクトをすべて列挙して、それぞれに対してコマンドを発行し、キューに挿入します。コマンドを描画順(drawing-order または z-order)に並び替えて、キューに挿入されたすべてのコマンドを実行します。こういった描画の流れを行うようにしました。2D ゲームでは描画順が重要になります。こういったレンダリングキューを挟むことで、ゲームワールド内のシーングラフやオブジェクトのデータ構造(ヒエラルキーツリーなど)と描画順が分離できるようになりました。

エンティティコンポーネントシステムのリファクタリング

スクリプティングを利用するにあたって、ゲームワールドやレベル、ゲームオブジェクトの記述を考え直す必要がありました。そこで実装しているエンティティコンポーネントシステムを大幅にリファクタリングしました。エンティティコンポーネントシステムについてはいずれまとまったお話をしたいところです。

今週の予定

  • 1 度読み込んだアセットのキャッシュ

新しくゲームオブジェクトをロードするたびに、ファイルを開いて、png フォーマットで読み込んで、OpenGL でテクスチャを作成して、ということをやっています。そのためオブジェクトを作る瞬間にフレームレートががくんと落ちてしまいます。

(図 1) おばけをスポーンしているときにフレームレートが落ちる
(図 1) おばけをスポーンしているときにフレームレートが落ちる

そこで、1 度読み込んだアセットはキャッシュしておき、2 回目以降はキャッシュからアセットを取得し、共有するような形にしたいと思います。特にテクスチャのコピーを作るのは、メモリを無駄に食いますし、バッチレンダリングもできません。迅速なコンテントキャッシュの実装が今求められています。

(はたして次週、"今週の進み具合 #17" があるのでしょうか…。お楽しみに。)

参考文献

Leave a Reply