トップページ > 過去ログ > 記事閲覧
特定のキーを押した”瞬間”のみを取得
名前:tm 日時: 2007/12/26 18:45

 失礼ながら、質問させていただきます。 あるキー、例えばESCキーが押されているかどうかを調べたいときはCheckHitKey関数を使いますよね。 しかし、この関数は”押されている/押されていない”の二通りしか表現出来ません。 これをループする部分で使うと、”押された瞬間”が取得できませんよね(ゲームの場合は、プログラム実行状態のほとんどがループだと思います)。  私は、これを拡張し、”押した瞬間”や”離した瞬間”を取得したいと思ってるのですが、どうやって再現すればいいでしょうか。  管理人さんのサンプルを勝手に引用させて頂きますと(いいのかな……)、 例 ESCキーが押されているか調べる if( CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { // 押されていない } else { // 押されている } となっています。 今のところ、私が考えたものでは、 if( CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { // 押されていない if ( ESC > 0 ) ESC = -1; // ESCキーが離れた瞬間 else ESC = 0; // ESCキーが離れている状態 } else { // 押されている ESC++; // ESCキーが押されている間は値を増やし続ける } としています(ESCはint型の変数)。 押された瞬間を得たい場合は、例えば、 if ( ESC == 1 ) // 処理 と言う風にしています。  現状でも問題なく動作はするのですが、こうしなければならない箇所が多くなってきており、ごちゃごちゃしてきてしまいまして。 もっとスマートな方法があれば、ご教授願いたいです。 お願いします。

Page: 1 |

Re: 特定のキーを押した”瞬間”のみを取得 ( No.1 )
名前:TNT 日時:2007/12/26 19:37

基本的な考え方は、tmさんのプログラムで良いと思いますよ。 あとはプログラムの全体図としてどう描くか、ということなのだと思いますが… まず、スマートに組むためにはクラスを活用することをお勧めします。 で、処理はクラスの中に全部突っ込んで、メインプログラムからはフレームに1回呼び出せば良いようにします。 あまりサンプルとして良くないかもしれませんが、私自身の例を載せてみますね。 (大分前に作ったのがそのままなので、作法的に変な部分もあると思います) //------------------------------------------------------------------------------ // ボタンのテンプレート //------------------------------------------------------------------------------ class csButton{ public: void Check(int state, int curx, int cury, int prevx, int prevy); // 状態チェック int DownFlag, UpFlag, ClickFlag; // 各フラグ POS Down, Up, Click; // イベントが起きた座標 int State[MAXINPUTLOG]; // 状態のログ int MovedValueFromDown; // Downしてから移動した距離 }; //------------------------------------------------------------------------------ // 管理クラス //------------------------------------------------------------------------------ class csInput{ public: void Check(); // 入力バッファ int MouseBuf; int JoypadBuf[USEPADNUM]; char KeyBuf[256]; // マウス class csMouse{ public: int InputData; int X[MAXINPUTLOG]; int Y[MAXINPUTLOG]; csButton Left, Right; } Mouse; // ゲームパッド class csJoypad{ public: int InputData; csButton Up, Down, Left, Right; csButton Btn[16]; } Joypad[4]; // キーボード class csKeyBoard{ public: int InputData; csButton Key[256]; } KeyBoard; }; 内容的には ・Input.Check()をフレームに1回呼び出す ・Input.Check()からは各ボタンのCheck()が呼び出される(座標などの引数付き) ・各ボタンのCheck()では座標や状態の記録、フラグの取得が行われる 各ボタンのState配列には、現在を要素0として、MAXINPUTLOG分の過去の状態が要素1〜に記録されています。 つまり、要素0の値が1で要素1の値が0ならDownFlagがtrue、逆ならUpFlagがtrueとなるよう関数を作ります。 実際にボタンの状態が知りたいときは、メンバ引数を直接参照します。 例えば if(Input.KeyBoard.Key[KEY_INPUT_ESCAPE].DownFlag) break; などです。 (もし完全にカプセル化したい場合、読み出し専用のメンバ関数を作ることで解決できます) こうすることで、メインプログラムからは Input.Check() を呼び出すだけで、入力の全状態を得られるようにできます。 (もちろん、クラスの中身をどう書くかは腕の見せ所ですが…)
Re: 特定のキーを押した”瞬間”のみを取得 ( No.2 )
名前:TNT 日時:2007/12/26 20:00

補足ですが、問題の「押した/離した瞬間」については、Check関数をこんな風に記述しています。 //------------------------------------------------------------------------------ // ボタンの入力 //------------------------------------------------------------------------------ void csButton::Check(int state, int curx, int cury, int prevx, int prevy){ shift(State, MAXINPUTLOG); state ? State[0] = 1 : State[0] = 0; DownFlag = 0; UpFlag = 0; ClickFlag = 0; // ボタンダウン直後 if(State[0] && !State[1]){ DownFlag = 1; Down.X = curx; Down.Y = cury; MovedValueFromDown = 0; // ボタンダウン中 }else if(State[0]){ MovedValueFromDown += abs(curx - prevx) + abs(cury - prevy); } // ボタンアップ直後 if(!State[0] && State[1]){ UpFlag = 1; Up.X = curx; Up.Y = cury; } } 注:shiftは、配列の要素を後ろに1つずらす自作関数 注2:ClickFlagの取得はいい例では無いので削ってあります
Re: 特定のキーを押した”瞬間”のみを取得 ( No.3 )
名前:tm 日時:2007/12/26 21:13

 なるほど、参考になります。 クラスを扱うのは不慣れなので、練習しなければですね 涙 現状のものを改造してみたいと思います、ありがとうございました。

Page: 1 |