トックのCG部屋-トップ別室へ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
  1. --/--/--(--) --:--:--|
  2. スポンサー広告

プログラミングメモ(キーの状態を管理するクラス)

今回はゲームでのキー入力の管理的なこと

ただ今回のは「こうすればできるよ」とかそんなんじゃなくて
何となく思いついた自分なりの解決案
この手のプログラミングは独学だから定石も知らない
ついでに言うとゲーム自体が全くできてないから
まだ動きを確認していないのよね

だから挙動の保証もできないわけだけど
書きたくなったから記事を作った

説明は追記で

ゲームでキー入力を受け付けるとき
メインループでイベントを確認してプロシージャを呼ぶわけだけど
現在の画面の状況によって同じキーでも処理が異なるため(戦闘画面とメニュー画面等)
キーイベントが発生したそのときにプロシージャから直接
「キャラの移動」や「決定」などの処理をするのは不可能
そのためプロシージャでは押した離したでフラグの上げ下げをして
キー入力がされているかどうかの確認はゲーム内の処理でやる

しかしゲーム内の処理では
基本的に毎フレームキーの状態を確認して処理を決めるわけだから
押してるかどうかの簡単なフラグ判定できないもので
「決定を一回押す」といったことをやるためには
1フレームの間だけキーを押した状態にする技術がプレイヤーに求められる
んでまぁ当然そんなアホな話はありえない

さらに決定等のキー操作、フィールド上のキャラの移動
メニューでのカーソル移動などなど
その時々に応じて
・一回押すたびに一回の処理
・押しっぱなしは毎フレーム処理
・押しっぱなしは一定間隔の連打として処理
のように処理の仕方が違ってくる

そこでキーの状態を管理するクラスを作って
必要なときに必要な判定をもらえるようにしようというわけ

んで今回作ったクラスが下
class key{
public:
int keyCode;
int pressed;
int holdTime;
int intervalCount;
int first;

void press();
void release();
void countUp();

int once();
int knock(int firstInterval,int interval);

Key(int code);
};

英語苦手だから変数名関数名は適当
それぞれの変数と関数について軽く説明すると

・メンバ変数
keyCode:アサインされてるキーコード
pressed:現在キーが押されているかどうかのフラグ
holdTime:押しっぱなしにされている時間
intervalCount:連打間隔のカウント
first:押されてから一度でもキー処理がされたかどうかのフラグ(今回は一度もされてなければ1)
・メンバ関数
press():キーが押されたらプロシージャから呼ぶ
release():キーが離されたらプロシージャから呼ぶ
countUp():押しっぱなしのときにカウンターを回す
once():押されたときに一度だけ処理したい時
knock(int,int):押しっぱなしを連打として判定したい時、引数は連打の間隔
Key(int):コンストラクタ、引数はアサインするキーコード

こんな感じ
ちょっと変数が余分かなぁと思うところもあるかなぁ
場合によってはholdTimeだけあればintervalCountとfirstはなくてもいいかもしれない
ただ今回は用途や処理のタイミングが少し不安だったから一応全部分けた
knock()で引数二つとってるのは一打目から二打目とそれ以降の間隔を変えたいから
説明し辛いけどあのカッ……カカカカカカって動きね
あとめんどくさがりだからとりあえず全部publicにしてるけど
気になる人は変数をprivate指定して必要なやつにgetter,setter作ればいいと思うよ

次にメンバ関数の中身
まずは上三つ
void Key::press(){
pressed=1;
};

void Key::release(){
pressed=0;
holdTime=0;
intervalCount=0;
first=1;
};

void Key::countUp(){
if(pressed){
holdTime++;
}
};

まぁ単純だからほとんど解説しようがないね
ただ一つ注意しなきゃいけないのが各カウンターをリセットするタイミング
押されたときじゃなくて離したときにリセットしてるのは理由があって
キーボードって押しっぱなしにすると連打と同じようにイベントが発生するらしく
press()は押しっぱなしの間に何度も呼ばれる可能性がある
そんな関数でリセットさせたら不都合が起こるからrelease()でリセットをしてる
まぁpressedで判定すればpress()でリセットさせることもできるけど
わざわざそうする理由がない気がする

次に下の三つ
int Key::once(){
if(pressed&&first){
first=0;
return 1;
}else{
return 0;
}
};

int Key::knock(int firstInterval,int interval){
if(pressed){
if(intervalCount==0||(intervalCount-firstInterval)%interval==0){
intervalCount++;
first=0
return 1;
}else{
intervalCount++;
}
}
return 0;
};


Key::Key(int code){
keyCode=code;
};

これも特に説明することはないかなぁ
knock()はもう少し綺麗にかけそうな気がする
-----2011/3/8追記------
というかこのknock()ちゃんと動作しない気がする
実際に書こうとして見直してみて何となく思った
-----2011/4/1追記------
このonceは最初に呼んだやつしか1を返さないから
同じフレームでも複数回呼び出すと当然2回目以降は0が返ってくる
キーボード処理で同じキー入力を複数個のイベントの条件にするのは
個人的にあまりよくないようなきがするから問題ないと思ってるけど
気になる人はフラグの上げ下ろしのタイミングを考えたほうがいいかも
それと逆に呼ばなければ実際に押したフレームより後になっても
最初に呼ばれたのなら1が帰ってくるから
これも毎フレーム確認してれば問題にならないはずだけど
やっぱり気になるなら考えたほうがいいかもしれないね
ついでに言うとマウスにこれを適用しようとすると
ボタンの処理とかするのに上のことが問題になってくると思うから
それはまた別に作らなきゃいけないかなぁと
ちなみに今作ってるゲームでは考え方は上のやつだけど中身は結構変えてたりする
-----追記ここまで------

こんな感じのクラスを作っておけばキーの処理が楽になるんじゃないかな
ゲームによって必要な処理が違うから書き方も違ってくるかもしれないけど
何かしらキーの状態を管理するクラスがあった方がいろいろと便利だと思うよ
コードとか載っけてみたけど今回言いたかったのはそれだけ
  1. 2010/09/02(木) 09:33:24|
  2. 試験的な物
  3. | トラックバック:0
  4. | コメント:0
<<顔モデリング終了 | ホーム | キャラ制作>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバックURLはこちら
http://took.blog72.fc2.com/tb.php/702-b160b08b
この記事にトラックバックする(FC2ブログユーザー)

プロフィール

トック

Author:トック

プロフィール(仮)

twitter:elgraiv_took
└ブログ更新情報

twitter:elgraiv_take
└無駄な日常つぶやき用

FC2カウンター

コンテンツ一覧

本棚

最近の記事

カテゴリー

月別アーカイブ

ブログ内検索

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。