AIMS覚え書き
数年触ってようやくミニゲーム1本完成させられたので、現時点でわかった開発する上でのコツとか色々とまとめ。
AIMSのエンジンであるLunaを長らく使っていたので違いについても。現在一般公開されてるv1.50基準なので最新版では変わってる部分もあるかも。
角度の精度が低い事の注意点
AIMSの角度は0〜360と荒い。このため時々めんどくさい事態になる。
大問題なのは0度と180度が直線にならない事。真横に撃たれた後しばらくして上に軌道変更するショットは0度と180度で指定すると左右で画面上に消えるフレームが変わる。WAY毎に画面内に存在できる弾数を制限してる場合、左右で連射力が変わってしまう。
問題解決のためにはベクトルで指定するのが最も手っ取り早い。あるいは、角度とスピードを入れると0〜90度を反転させてベクトルを代入する関数を作るのもいい(つまり上下左右でそれぞれ線対称になる)。速度をマイナスにするのもありだがHeadingがめんどい。
ちなみにCAGESTGHDでは速度をマイナス、Headingを180度逆にする事で対処した。
なお整数でしか角度を指定できないわけではなく、小数でも可能。Lunaと同じ0〜65535なのか浮動小数点なのかは不明。
OnVanish()は2回以上呼ばれる事がある
現在何発のショットが画面内にあるかを自機クラスのVARで持ち、ショットアクターから増減させる場合、ショットのOnVanish()から減らすとショット数がマイナスになる。
おそらくこれはOnVanish()が2回以上呼ばれるためで、防ぐにはすでにOnVanish()が呼ばれたかどうかを保持するためにVARを使うなり、OnStep()でvanish()するときにカウントするなり対策する必要がある。
CAGESTGHDでは後者で対処した。
描画バグについて
高速描画のバグ
高速描画を使うとたまに画面がぐちゃぐちゃになったり表示されなかったりする。v1.50のみの現象で、以前のバージョンでは起こらない。
Yソートを使うと発生する可能性が高く、Zを使うとそれなりの確率で発生する。Zを全く使っていなくてもまれに発生する。
結構長い間これで躓いてた…。現状Zは封印してバージョンアップ待ち。
特殊描画のdrawTextureFont()が描画されない
drawTextureFont()関数はたまに普通のテキストアクターを作らないと表示されない。たまに表示される。
DiGLoGとCAGESTGHDで別々に発生したので再現性はあるが、厳密な条件はわからない。
ちなみにこの状態で普通のテキストアクターを点滅させるとdrawTextureFont()の方もつられて点滅する。
CAGESTGHDでは常に表示されている制限時間に普通のテキストアクターを使う事で対処。
三角関数とか
頻繁に使うSinやCosはcommon.luaに関数を作っておくと楽。Atanは大体の場合でaimPtoP()が代わりに使える。
何気にcommon.luaにはリファレンスに書いてない関数が多いので一度目を通しておくと吉。
テーブル
ゲーム内のデータを入れるテーブルはクラスっぽく使わず、配列っぽく使った方が管理が楽。
とするよりも
function UseLifePotion(target)
--回復処理
endITEM_LIFEPOTION = { name="LifePotion", itemNo=1, func=UseLifePotion }
ITEM_LIFEPOTION = { "LifePotion", 1, UseLifePotion }
ITEM_NAME = 1
ITEM_NO = 2
ITEM_USEFUNC = 3
ITEM_MAXID = 3
とした方が管理しやすい。
DiGLoGのコードがぐちゃぐちゃになって崩壊した最大の原因。Luaでクラス作るのは本当に難しい。
連続して鳴らしたくない効果音
毎フレーム鳴らしたくない効果音がある場合は、効果音それぞれにインターバルの値を設定してアクターのOnStep()から減らすのが手っ取り早い。サンプルのpadListenerのように実装する。
もちろん効果音を鳴らす関数を自作するひつようがあるし、インターバルの値を保持するためのテーブルも用意しないといけない。
現時点での疑問点
パッチ用のパックファイル読み込み優先順位の設定
パッチを出すときにはパッチ側のパックファイルを先に検索し、ファイルがなければ最初のバージョンのパックファイルを読みに行くようにしなければならない。Lunaではこの設定をする関数があったが、AIMSでは見当たらない。
帯描画の座標指定方法
drawGraphicList()の座標指定はdrawGraphic()のような相対指定ではなく、かといって絶対指定でもない。
効率の良い関数セーブ方法
例えばアイテムなどでセーブデータに関数が含まれる場合セーブされないので、何らかの方法で復元する必要がある。
現時点ではアイテム番号をIDに関数をテーブルにしておいて、ロード時に関数を代入するのを考えているが明らかに非効率的。
ITEMFUNCLIST = {}
ITEMFUNCLIST[ITME_LIFEPOTION[ITME_NO]]=ITME_LIFEPOTION[ITEM_USEFUNC]
ITEMFUNCLIST[ITME_MANAPOTION[ITME_NO]]=ITME_MANAPOTION[ITEM_USEFUNC]
ITEMFUNCLIST[ITME_SCROLLOFTOWNPORTAL[ITME_NO]]=ITME_SCROLLOFTOWNPORTAL[ITEM_USEFUNC]
--以下アイテムの数だけ
欠点
音関係が弱い
これはLunaもそうだが、再生位置を取得したり変更したりできる関数がないためスーパーマリオワールドのヨッシーに乗ったらドラムを追加するとか、HellSinker.の錆竜のクラムボン稼ぎ用音楽同期とか、Seg.5道中のSol/Luna移行時のBGM変更とかができない。
このため実はCAGESTGの新作はAIMSでは出せない。ゴーストの展開と音楽の同期が取れずドラムをプログラム側で効果音で鳴らす事もできない他、地味にエピローグの歌詞も同期できない。
プログラムができない人にとってはLuaが超むずい
C++はとりあえず何でもかんでもクラスにしておけばぐちゃぐちゃになっても動きはするのでプログラムがわからない人でも完成まで持って行く事はできるが、Luaはグローバル変数を多用し、またクラスを定義してインスタンスを作るのすら相当難しいので、プログラムがわからない人が触ると崩壊する。
ただミニゲーム程度ならばむしろすごく簡単だし、もちろんプログラムができる人ならば普通の規模のゲームでも開発できる。
ちなみにローグライクSTGことDiGLoGは現在プログラム崩壊中。Luaマジむずい。
3Dが扱えない
特に問題になるのが背景で、適当なモデル作ってフォグやシェーダーでごまかすという楽な逃げが使えない。気合でマップチップを作る必要がある。
ムービーは再生できるのであらかじめレンダリングした動画を背景として使う事は多分可能。