キー処理(偽NaGu-Ru開発日記) 99/12/12

掲示板とかでキー処理、というか格闘ゲームにおける「コマンド」の処理方法についての 話題があがったので、ちょっと取り上げてみます。しかも、「極み」のコーナーにしては 珍しく、ソースファイル&サンプルプログラムつきです(^^;)実行にはDelphiXというコンポーネント が必要ですので、別途用意しておいてください。

使ってみれば分かってもらえると思うんですが、DirectInput、つまり入力系コンポーネントにはたいてい
「ボタンが押されているかどうか」を調べることが出来るだけです。しかし、ゲームでは「ボタンが押された瞬間」「ボタンが離された瞬間」を知りたいときがよくあります。格闘ゲームならなおさらです。というわけで、まずは これらを判定することから始めましょう。幸い「ボタンが押されているかどうか」さえわかれば実現可能ですので。

さて、その手順ですが、まずはコンポーネントから入力情報をゲットし、それを自分の使いやすい形式(Booleanなど)に変換します。 ここではBoolean型に変換したとして話を進めることにします。変換したものがTrueなら「ボタンが押されている」という フラグをTrueにセットし、Falseなら「ボタンが押されていない」というフラグをTrueにセットします。 なお、これらのフラグのセットは必ずコンポーネントから入力をゲットしたあとで行わなければなりません。

で、先ほどセットした「ボタンが押されている」フラグがTrueのとき、コンポーネントからゲットした入力情報で ボタンが押されていないことが検出できたときが、「ボタンを離した瞬間」です。また、このとき「ボタンが押されている」 というフラグをFalseにセットします。
「ボタンが押されて瞬間」も同じように、「ボタンが離されている」フラグがTrueのとき、コンポーネントからゲットした入力情報で ボタンが押されていることが検出できたときが「ボタンを押した瞬間」です。また、このとき「ボタンが離されている」 というフラグをFalseにセットします。

説明がへたくそなので、ソース見たほうが早いかも(^^;) コンボ処理についてはまた次回。

※コマンド
格闘ゲームとかでよくあるアレ。「波動拳」とか。

※DelphiX
DELPHIからMicrosoftのDirectXテクノロジが利用できるようになるナイスなコンポーネント。 これについての書籍も出ているほどの有名コンポーネント。http://www.ingjapan.ne.jp/hori/

※DirectInput
DirectXコンポーネントのひとつ。 キーボード、ジョイスティックなどさまざまな入力装置から入力を調べることができる。

※フラグが立つ
「フラグが立っていれば攻撃、そうでなければ防御」みたいな感じで使う。 Boolean型。プログラムでよく出てくる用語。

ソース&サンプルダウンロード
さて、コマンド処理についての下準備が整ったところで早速やってみますか。 実は先ほどの「ボタンが押された瞬間」などは「OnKeyDown」イベントハンドラやWinAPIを使うことによって できることはできたんですが、ゲームに必須(?)の「ジョイスティック」に対応できないので あえて上のような方法を取りました。実際僕も「OnKeyDown」を使って手抜きをしていたら 「ジョイスティックには対応してないの?」とユーザーさんから苦情がきて、「押された瞬間」などの 処理を実装するのにかなり悩んだクチなんです(^^;)

んじゃ、ぽくむら流コマンド処理の流れを説明していきます。
下の図では、「ボタンが押された、話された瞬間」を「キーイベント」と呼ぶことにします。

[初期化]
データの初期化
各種変数の初期化、バッファの作成、データの読み込み、設定などを行う。 コマンドのデータの用意もここで行う。

[メインループ]
入力情報を調べる
キーイベントが検出された
データの追加
どのボタンが押されたか、そのときの時間、イベントの種類(押された、離れたなど))などの情報を 用意したバッファに追加していく。

コマンドの判定
バッファにたまったデータを元に、コマンド判定を行う。方法としては、バッファに追加されたデータを 新しい→古いの順でデータを見ていき、用意されたコマンドのデータと照らし合わせていく。 詳しくは後述。

コマンドが検出された

用意されたコマンドのデータにある「コマンド番号」を「コマンド識別変数」にセットする。 この変数にはいつもは「-1」が入っていて、コマンドが検出されたときにはそれ以外の数値が セットされる。よって、コマンド発生を読み取る場合は「コマンド識別変数」が「-1」以外のとき に読み取ることになる。

このようになります。上の図でわかってもらえたでしょうか?
次に、この処理のメイン部分である「コマンドの判定」について書いてみます。

[コマンドの判定のアルゴリズム]
コマンドデータの個数をチェック
コマンドのデータがなければ判定を行わない(判定しようがない)。

全コマンドをチェック
全コマンドをチェックするため、コマンドデータの個数分ループする。

コマンドデータのバッファを取得する

コマンドデータのバッファの個数分だけループ
コマンドデータのバッファと、入力状況をためたバッファを後ろのほうから ひとつずつチェックしていく。データが食い違ったらコマンドは失敗とする。

すべてのチェックに成功した

用意されたコマンドのデータにある「コマンド番号」を「コマンド識別変数」にセットする。 この変数にはいつもは「-1」が入っていて、コマンドが検出されたときにはそれ以外の数値が セットされる。よって、コマンド発生を読み取る場合は「コマンド識別変数」が「-1」以外のとき に読み取ることになる。

時間内にコマンドが成功したかをチェック
成功したコマンドが、コマンドのデータにある制限時間内に行われたかをチェックする。 時間を超えていれば、コマンドは不成功となる。

キーバッファのクリア
入力状況をためたバッファのデータ数が多くなってきたら クリアする。あまり頻繁にクリアするとコマンドが成功しないのである程度バッファは大きくとっておく。 僕は1000個たまったらクリアしているが、これだとコマンド入力に支障をきたしたことはない。 支障をきたしていたとしてもユーザーは「コマンド入力のミス」だとみなすので、何ら問題ない(ごまかし)。
こうなります。
長くなってしまったので混乱してしまう人も多いと思いますが、そうなってしまった場合は 実際に自分でこのような処理を作ってみるといいと思います。論より証拠です。その過程でつまづいたときに、 このページをもう一度みて、「なるほど〜」とうなづいていただければ幸いです。

よくわからないところがあれば、メールや掲示板で質問してください。

※OnKeyDown
DELPHIのコンポーネントのほとんどについている 「キーボードが押された瞬間」に発生するイベント。リアルタイムゲームではここでキー処理を行うゲームは少ない。

※イベント
クリスマスやお正月など。プログラミングでは、「ある出来事とコードを関連付けるメカニズム」のこと。

※イベントハンドラ
イベントに直接応答するコード。現実世界ではイベントに「報道陣」が応答し、全国に報道したりする。

※WinAPI
「Windows Application Programing Interface(ウィンドウズアプリケーションプログラミングインターフェース)」の略称。 単に「API」と呼ばれることもある。これを極めると一冊10000円くらいする書籍を販売することができたりする。

※バッファ
正確な詳細は知らないが、僕はこれを「データを複数入れることができるもの」として扱っている。 あいまいな解釈ゆえ、これはあまり信じてはいけないかもしれない。

※アルゴリズム
物事がなりたっている仕組み。解説などを行うとき、「〜のアルゴリズム」などというと格好よく聞こえる(と思う)。

※コマンドデータのバッファ
コマンドデータにある「ボタンやスティックの状態が集まったもの」。 波動拳のものなら「下、左下、左、ボタン」となる、

※ループ
何回も処理を行うこと。「無限ループ」もこれの仲間である。

※ごまかし
プログラミング全般、特に速度重視であるゲームプログラムなどでは頻繁に使われている テクニック。流行の3Dなどでも使われている。また、圧縮法としても使われていて MP3は人間の耳に聞こえない音はごまかすという、これの代表格である。
考えようによっては 「見えないところでは何をやってもいい」という考えが顕著に表れているともいえる。






もどる