さて、今回もグダグダ考えていることを
記事にしようと思う。
線マップエディタもサウンド系ソースの自動生成ツールもできたので
そろそろマップを増やしたい。
というか、前回の公開からこれだけ期間が空いているので
マップを増やしてから公開したい、って気持ちはある。
あるんだけど、
マップが増えてから着手すると手戻りが多くなりそうなところを
先にやっつけた方が、結果的に作業が進めやすくなる。
ただ、この作業、実は相当前から構想は練っていたものの
面倒くさくて、ずぅーっと放置していたことだったりする。
やろうとしているのは、「依存性の注入」みたいなこと。
Wikipediaから引用すると
依存性の注入(いそんせいのちゅうにゅう、英: Dependency injection)とは、コンポーネント間の依存関係をプログラムのソースコードから排除し、外部の設定ファイルなどで注入できるようにするソフトウェアパターンである。英語の頭文字からDIと略される。
言葉で書くと難しそうだけど、
要するに依存関係のあるコードを、プログラムから減らして
「外部から与える情報(注入するもの)」で動作を変えるということ。
初音ミク冒険記で例を示すと
マップが切り替わった際に
敵やブレイクオブジェクトを配置するという処理で
この考え方を適用できそうってこと。
現在、VC++のマップ毎のソースにある初期処理には
敵やブレイクオブジェクトを配置する処理がある。
つまり、「マップ毎の初期処理」と
「敵やブレイクオブジェクトを配置する処理」には依存関係がある。
敵やブレイクオブジェクトの配置を変更するには
VC++のソースの変更が必要で
ソースを変更するってことは、動作確認のためにビルドが必要ということ。
これを敵やブレイクオブジェクトの配置を外部から与えるようにすることで
VC++のソースを修正しないで、プログラムの動きを変えちゃおう、って考え。
初音ミク冒険記だと、ミクとマップの当たり判定で使う線は、
mapフォルダのmapXX_YY.datというファイルに外出しされていて
このファイルを作るツールが、前に作ってた線マップエディタ。
敵の座標とかブレイクオブジェクトの座標は、
マップの難易度を上げるために敵を増やしたり、
逆に難易度を下げるために敵を減らす、
マップが単調になるのを防ぐためにブレイクオブジェクトを配置するなど
最終的には、いろいろと調整が必要になると思っている。
調整のたびにVC++でビルドするのは、面倒なので
外部のファイルから配置するようにしたい。
この仕組みができると、Astlibraの敵配置ツールみたいに
敵の配置をマップエディタから行えるようになる。
なので、マップ毎に
敵やブレイクオブジェクトを配置するデータを作る必要がある。
実は、VC++のマップ毎のソースには、別の依存関係もある。
それがLuaスクリプトで
VC++のマップソース1つにつき、必ず対応するLuaスクリプトが存在する。
現時点でも初音ミク冒険記の宝箱の配置は、
Luaからできるようになっていて
map00_1.luaには、以下の記述がある。
local iRet = openTakaraBako(460, 200, 0, DIRECTION_RIGHT, "クッション・ブーツ", 2, 3);
460, 200, 0というのがそれぞれX座標、Y座標、Z座標となっている。
(初音ミク冒険記は2Dゲームだけど、
ゲーム内のオブジェクトは内部的には3D座標で管理している)
試しにクッションブーツの宝箱の近くでセーブして
map00_1.luaの上記の箇所の200の値を250とか150とかにしてから
セーブしたデータをロードすると、宝箱の位置が変わることを確認できるし
DIRECTION_RIGHTをDIRECTION_LEFTにすると宝箱の向きが変わる。
”クッション・ブーツ”の文字を変えると宝箱を開けた時に
”○○を手に入れた”の○○の部分の文字が変わる。
最後の2は、宝箱を開けたことを示すイベントフラグで、
3は、宝箱を開けた後に続けて行う次のイベントフラグの番号だったりする。
(イベントフラグの番号の意味は、公開しているExcelのドキュメントで確認できる)
Luaスクリプトは、当たり判定で使う線マップと同じく
マップを切り替える、もしくは、
セーブデータをロードすると再読込するので
ビルドの作業もいらず、初音ミク冒険記を起動したまま
調整ができるので、お手軽なのだ。
敵やブレイクオブジェクトも、宝箱に合わせて
Luaから配置できるようにした方が
無駄にファイルも増えずに済むだろう。
さらに、各マップの切り替わりとか、
マップ切り替わり直後のBGMの切り替えもVC++でやっているので
本当は、これらの変更時もLuaから行った方が、
VC++のビルド回数を減らすことができるって寸法だ。
ここで、現時点のマップ数を確認してみよう。
・プロローグ:2マップ
・試練の洞窟:9マップ
・ボカロタウン(第2章):7マップ
・ウータウの森(公開しているもの):2マップ
ということで、4つのステージで既に20マップある。
実際にはウータウの森で未公開のマップも既にいくつかあるので
もう少し多いんだけどね。
ここで線マップエディタができたから、
ってことで、ガンガンとマップを増やしていき
その後、VC++からLuaに外出しすると
単純に作業の物量が増えてしまう・・・
つまり、20+α程度の数のうちにやってしまった方が
将来的には楽ができるってこと。
これから作るマップだけでイイじゃん!
と思うかもしれないけど、マップごとに作りが異なると
何かメンテナンスする時にも
複数パターン分の作業をすることになるので
できれば同じ作りにして1パターンだけ考えれば済むようにしておきたい。
じゃあ、なんで宝箱の配置はLuaで、
敵やブレイクオブジェクトはVC++なんだという話もある。
もともとは、宝箱の配置もC側だった。
それが、宝箱の位置、向き、イベントフラグの調整とかやってて
イベントフラグは、シナリオ進行に関わるからシナリオじゃん!
となり、ここだけ先にLuaに行ってしまったという経緯がある。
今考えると敵はともかく、ブレイクオブジェクトについては
最初からLuaに持って行っても良かったかもしれない。
現状のソースの行数は、トータルで78,595行
内訳が
VC++(ヘッダファイル含む):58,770行
Luaスクリプト:19,825行
なので、既に25%くらいがLuaになっている計算だ。
といってもトータルの行数の内、8500行近くは、何も書いていない空行で
コメントだけの行も27,000行くらいあるんで
実際に動く行数は、43,000行くらいになる。
C#のツールは、ステップカウンタを導入していないから分からないけど
トータルすると、結構な行数を書いているのかもしれない。
話がそれた。
元に戻そう。
将来的には、敵のAI部分もLuaに持って行く構想もあるんで、
早めに手を打っておきたい。
つーことで、この3連休で
VC++ロジックをLuaに持っていくことを具体的に考えて
試しにいくつかのマップに導入しようと思う。
そして今月中にこの辺りをやっつける方針としよう。
多分、この作業に専念すれば、今回の3連休でこなせるレベル。
ただ、閃の軌跡Ⅱに向けて引き継ぎデータを用意するって
ミッションがあるんで、これだけに専念もできないので
一応、必達目標で今月いっぱいとしておこうって話です。