Posts
KFX の enemy.lst の入力方式
enemy.lst は乱数によって行動が決まることもあり、動作から正確な仕様を読み取ることが難しい。これが直接的な原因となったのかは分からないが、enemy.lst はエンジンによって微妙に仕様が異なる。基本仕様となった KFX、同じように見えて根本から異なる KFA、仕様変更が行われた KFM、それぞれの入力方式について解説する。
KFX
enemy.lst の Command は command.lst とほぼ同じものが使えることもあり、まるで書いたコマンドがそのままコマンドバッファに流れて行くような印象を受けるが、実際はそのような処理になっていない。
これを理解するには、先にプレイヤー入力がどのように処理されているのかを知っておく必要がある。以下は KFX の入力フローを単純化したもの。
- プレイヤーがコントローラーを操作する。
- プログラムがコントローラーから入力を読み取る。
- 入力をコマンド処理で扱いやすい形式に変換する。
- 変換済みコマンドをコマンドバッファに溜める。
KFX の enemy.lst は、この入力フローに割り込む形で実装されていて、Command に書いたものは「コントローラーからの入力」として展開される。例えば Command に p と書いた場合、物理的にコントローラーの弱パンチボタンを押したのと同じ扱いになり、これは自動演奏ピアノが譜面データを元に鍵盤を物理的に叩くのとよく似ている。
コントローラーのように振る舞う関係で、コマンドの入力状態は「押している間」しか存在しない。方向ボタンだけでなく攻撃ボタンもその対象に含まれるが、KFX は攻撃ボタンを連続して記述することができないため、結果的に「押した瞬間」と同じ挙動となる。
KFX の enemy.lst がこのような作りになっているのは、おそらく実装の手間を軽減するためで、Command をコントローラー入力へ変換する部分さえ作ってしまえば、それ以外は考えなくて済むというメリットがある。デメリットを挙げるとすれば、コントローラーの物理構造に合わせて斜め方向入力を縦軸と横軸の 2 方向に分離しなければいけないことくらい。
KFA
KFX が加工前の「コントローラーからの入力」をベースとしているのに対し、KFA は加工後の「変換済みコマンド」がベースとなっている。
「変換済みコマンド」には基本的な入力データに加え、コマンド処理で必要な状態情報も含んでいるため、コントローラーでは入力することができないコマンドも表現可能となっている。例えば「離した瞬間」は一度ボタンを押した後に離さないと発生しないが、「変換済みコマンド」であれば「離した瞬間のみを連打」といった物理的に不可能な入力をすることができる。
KFA で追加された「丸括弧内に書かれたコマンドは 1 フレームで入力される」という機能の存在からも分かるように、入力時間や入力状態といった物理的な入力とは切り離された方式となっている。
KFM
以前は、KFA と同じ「変換済みコマンド」ベースだったが、入力表示に対応させるにはプレイヤーと同じ入力方式にする必要があり、KFX の「コントローラーからの入力」ベースへ切り替えを行った。
KFM の enemy.lst は KFX と大差ないので仕様変更による影響は小さいはずだが、KFX 特有の処理や KFA との互換性の関係から、入力状態の扱いに注意しなければいけないケースがある。
押した瞬間
KFX は攻撃ボタンを連続して記述することはできないが、方向ボタンと攻撃ボタンの結合を経由することで、その制約を回避できてしまう問題がある。
例えば 1p1p と記述した場合、以下のように展開される。
フレーム | 記述 | 読込後 | 自動結合 |
---|---|---|---|
1 | 1 | _1 | _1+_p |
2 | p | _p | _1+_p |
3 | 1 | _1 | |
4 | p | _p |
結合によって _p が連続するようになり、弱パンチを「押し続けている」と認識されてしまう。
ただ、KFX はこのような記述をしても「押し続けている」とは認識しない。KFX は以前に入力されたコマンドが再び有効にならないよう「コマンドバッファ内にある攻撃ボタンをクリアする」という強引な処理を行っていて、この副作用によって攻撃ボタンを押し続けても「押した瞬間」として認識される。
KFM は「KFX の入力方式」と「KFA の拡張コマンド」の両方に対応する関係上、KFX の振る舞いを完全再現することができない。そのため、攻撃ボタンの後ろに方向ボタンを追加して連続入力を抑制する必要がある。
フレーム | 記述 | 読込後 | 自動結合 |
---|---|---|---|
1 | 1 | _1 | _1+_p |
2 | p | _p | _1 |
3 | 1 | _1 | _1+_p |
4 | 1 | _1 | _1 |
5 | p | _p | |
6 | 1 | _1 |
単体の方向ボタンが入力されている間は攻撃ボタンの入力が途切れるため「押した瞬間」として認識される。
離した瞬間
KFM は「押している間」以外の状態を自動的に生成する。
例えば 111 と記述した場合、「離した瞬間」は以下のように補完される。
フレーム | 記述 | 読込後 | 自動生成 |
---|---|---|---|
1 | 1 | _1 | _1 |
2 | 1 | _1 | _1 |
3 | 1 | _1 | _1 |
4 | !1 |
実際は enemy.lst 上ではなく、コントローラー入力と同様に入力時に都度生成が行われている。
KFA は「変換済みコマンド」を前提とした仕様のため、KFM と KFA の両方に対応する場合は自動生成に頼らず KFA 基準で記述する必要がある。
フレーム | 記述 | 読込後 | 自動生成 |
---|---|---|---|
1 | 1 | _1 | _1 |
2 | 1 | _1 | _1 |
3 | 1 | _1 | _1 |
4 | !1 | _1 | _1 |
5 | !1 |
KFM は修飾子も「押している間」として扱うので、KFA 用の「離した瞬間」は「押している間」に変換され、末尾に自動生成された「離した瞬間」が付加される。KFM と KFA で 1 フレームのズレが生じているが、離し入力は頻繁に行うものではないので大きな問題にはならないはず。