ページ 1 / 1
入力キーのチェック
Posted: 2008年4月11日(金) 16:37
by kazuoni
お邪魔します。
題名が管理人さんが投稿したものににてしまいましたがっ^^;まずは下のコードを見てください。
void state(){
...
while(①){
...
switch(flag){
case 0:
...②
break;
case 1:
...
break;
case 2:
...
break;
}
ScreenFlip();
}
...
return;
}
こんな単純なものなんですが。。やりたいことは、flagが1、2のときで、バックスペースが押されたらflag=0になり、case 0を実行し、case 0でバックスペースが押されたらwhileを抜けるというものにしたいんです。上のコードの①、②に Key[ KEY_INPUT_BACK ]を書いてしまうと、case 2→case 0→脱出までが一瞬で行われてしまいます。どうしたらうまくいくでしょうか?なんだか管理人さんの上げたものにヒントがありそうな臭いがプンプンするんですが・・・^^;
よろしくお願いします。
Re:入力キーのチェック
Posted: 2008年4月11日(金) 17:03
by 管理人
私のたてた他トピでも紹介していますが、こちらをご覧下さい。
http://dixq.net/g/#40
GetHitKeyStateAll_2なる関数を実装してあります。
これは、どれ位キーが押されたかを判定する関数です。
キー情報が
0なら押されてない、
1なら今押された、
2なら押されてから2カウント、
3なら押されてから3カウント、
4なら押されてから4カウント、
・・・
となるわけです。今やりたいことは、「今押された」時に処理をしたいわけですよね。
・・ということは・・?
if(Key[KEY_INPUT_BACK]==1)
flag=○○;
Re:入力キーのチェック
Posted: 2008年4月11日(金) 20:44
by kazuoni
必死に考えました^^;
Keyがcharからintに変わっていたのですね^^;額に汗をかくぐらいにらめっこしてましたww
疑問はint GetHitKeyStateAll_2(){...}をどこに書くかなんですが・・・ヘッダーに書く場合どうしたら一番よいでしょうか?"DxLib.h"の中に入れられたらなぁなんて思っているのですが・・・やり方が全く分かりません。。
Re:入力キーのチェック
Posted: 2008年4月11日(金) 21:03
by 管理人
ご自分で実装された関数などは、別のヘッダファイルに入れたほうがいいと思いますよ。
というのも、もし、他のゲームを作ったり、作り直したりするとき、
DxLib.hと自分で実装した.hファイルをインクルードすればよく、
DXライブラリのバージョンアップなどにも、対応がしやすいです。
int GetHitKeyStateAll_2(int KeyStateBuf[/url]){
char GetHitKeyStateAll_Key[256];
GetHitKeyStateAll( GetHitKeyStateAll_Key );
for(int i=0;i<256;i++){
if(GetHitKeyStateAll_Key==1) KeyStateBuf++;
else KeyStateBuf=0;
}
return 0;
}
これをDxLib2.hとでも、名前をつけてインクルードファイルがおいてあるフォルダに入れておけばいいと思います。
プログラムを書くときは
#include "DxLib.h"
#include "DxLib2.h"
と書いて下さい。
また、これはオーバーフローを考慮していない関数なので、きちんとライブラリ化するなら、
オーバーフローをしないように関数をつくった方がいいと思います。
具体的には
if(GetHitKeyStateAll_Key==1) KeyStateBuf++;
ここの加算はKeyStateBuf+1がint型の扱える範囲内か、というif文を追加することです。
Re:入力キーのチェック
Posted: 2008年4月11日(金) 21:30
by トウラ
はじめましてトウラと言います & はじめましてが横からですみません。
私も同じ(?)ところで躓いていたので、思わず書き込みです。
>>kazuoniさん
whileでbackspaceの入力状態をチェックしたあと
switchに入る前、あるいはcase 0と②の間に最初にもう一度GetHitKeyStateAll(key)を呼ぶとどうでしょう?
while内でチェックしてそのままswitchに入るので
switch内ではすでにkey[KEY_INPUT_BACK]が1になってるのが原因だと思います。
とりあえず私はこれで何とかなりました。
これが正しいやり方なのかは不明ですが・・・
もし、よろしくない場合はどなたかつっこんでください。
Re:入力キーのチェック
Posted: 2008年4月11日(金) 23:31
by トウラ
あれ・・・もう一度試してきたら思ったように動作してなかった。
最初の1回だけうまくできたように見えてて、できたと勘違いしてたみたいです。
やっぱりどこかおかしかったのかな・・・
しゃしゃり出てきておいて申し訳ありません。
Re:入力キーのチェック
Posted: 2008年4月11日(金) 23:47
by kazuoni
>管理人さん
>
> int GetHitKeyStateAll_2(int KeyStateBuf[/url]){
> char GetHitKeyStateAll_Key[256];
> GetHitKeyStateAll( GetHitKeyStateAll_Key );
> for(int i=0;i<256;i++){
> if(GetHitKeyStateAll_Key==1) KeyStateBuf++;
> else KeyStateBuf=0;
> }
> return 0;
> }
>
>
> これをDxLib2.hとでも、名前をつけてインクルードファイルがおいてあるフォルダに入れておけばいいと思います。
> プログラムを書くときは
>
> #include "DxLib.h"
> #include "DxLib2.h"
>
> と書いて下さい。
普通に書いたらint GetHitKeyStateAll_2が重複に定義されてしまいました。こういう関数の定義ってヘッダーではどうかいたらよいのでしょうか?
ちなみに自分はすべてのファイルが読み込むGV.hにDxLib2.hをインクルードしたのですが。。
> if(GetHitKeyStateAll_Key==1) KeyStateBuf++;
>
> ここの加算はKeyStateBuf+1がint型の扱える範囲内か、というif文を追加することです。
これを書き、戻り値でエラーが返ってきたら終了・・・みたいな感じですか?
Re:入力キーのチェック
Posted: 2008年4月12日(土) 03:07
by 管理人
>トウラさん
40節にサンプルを置いていますけど、それをみてもよくわからなかったでしょうか?
もしご覧になっていない場合はどうぞ。
>kazuoniさん
ヘッダに書いたのでしたら、Cファイルの方の記述は消しました?
GetHitKeyStateAll_2の関数はCファイルから消してください。
>これを書き、戻り値でエラーが返ってきたら終了・・・みたいな感じですか?
そういうことですね。
if文の中にはいらず、elseにはいったらreturn -1;しましょう。
Re:入力キーのチェック
Posted: 2008年4月12日(土) 16:32
by トウラ
>>管理人さん
40節のコードはつまり
「33節のものを全てのキーに対応させ、さらにどれだけの間押されているのかも計算するように拡張した」
という風な理解の仕方でいいのでしょうか?
また40節のコードを利用してみましたが、やはりkazuoniさんと同じように処理が一瞬で行われてしまいます。
私の場合は、
if( ( Key[KEY_INPUT_SPACE]==1 && flag==0 ) || flag>0 ){
if( flag==0 )
flag=1;
if( flag==1 ){
画像描画
if( Key[KEY_INPUT_SPACE]==1 && flag==1 ) ・・・①
flag=2;
}
if( flag==2 ){
画像描画
if( Key[KEY_INPUT_SPACE]==1 && flag==2 ) ・・・②
flag=0;
}
}
という感じです。
①をKey[KEY_INPUT_RETURN]==1、②をKey[KEY_INPUT_BACK]==1
など、チェックするキーを分けると私の考える動作をしてくれます。
書き方自体がいけないでしょうか?
Re:入力キーのチェック
Posted: 2008年4月12日(土) 16:37
by トウラ
すみません。忘れてました・・・
if( ( Key[KEY_INPUT_SPACE]==1 && flag==0 ) || flag>0 ){
if( flag==0 )
flag=1;
if( flag==1 ){
画像描画
if( Key[KEY_INPUT_SPACE]==1 && flag==1 ) ・・・①
flag=2;
}
if( flag==2 ){
画像描画
if( Key[KEY_INPUT_SPACE]==1 && flag==2 ) ・・・②
flag=0;
}
}
こんな感じです。
Re:入力キーのチェック
Posted: 2008年4月12日(土) 16:52
by バグ
面白そうなので、クラスにしてみました。自前のミリ秒タイマーと組み合わせて、押した時間がミリ秒単位で取得できます。デバッグしていないので、バグがあった場合は申告してもらうか、自己修正で対応をお願いします(ぉぃぉぃ)
クラス名:DxLibExtra
以下、publicメンバ関数のリファレンスです。
BOOL GetHitKeyStateAllEx()
戻り値:関数の成否です。TRUEは成功、FALSEは失敗です。基本的にはGetHitKeyStateAll関数と同じように使用します。
BOOL GetKeyState(INT iVirtKey)
戻り値:指定されたキーの押下状態を取得します。押されている場合はTRUE、そうでない場合はFALSEです。引数にありえない数値が指定された場合もFALSEになります。これも基本的には元祖の同名関数と同じように使用しますが、戻り値が違う部分だけ注意して下さい。
ULONGLONG GetKeyPushTime(INT iVirtKey)
戻り値:指定されたキーの押下状態の継続時間を取得します。GetHitKeyStateAllEx関数で押されたと判定された瞬間から現在までの時間をミリ秒単位で返します。指定されたキーが押されていない、もしくは引数にありえない数値が指定された場合は0が返ります。※『64ビット非負整数なので大丈夫だろう♪』という事で、とりあえずオーバーフローは考慮しておりません(苦笑)
Re:入力キーのチェック
Posted: 2008年4月12日(土) 22:27
by kazuoni
> ヘッダに書いたのでしたら、Cファイルの方の記述は消しました?
> GetHitKeyStateAll_2の関数はCファイルから消してください。
消してます。
すべてが読み込むヘッダーをGv.hとして、その冒頭に#include "DxLib2.hをし、DxLib2.hの中身は、
int GetHitKeyStateAll_2(int KeyStateBuf[/url]){
char GetHitKeyStateAll_Key[256];
GetHitKeyStateAll( GetHitKeyStateAll_Key );
for(int i=0;i<256;i++){
if(GetHitKeyStateAll_Key==1) KeyStateBuf++;
else KeyStateBuf=0;
}
return 0;
}
です。DxLib2.hはGv.hと同じ場所にあります。(visual c++ 2008でいう、ヘッダーファイルにあります。Gv.hもここです)
現状はこんな感じなんですが・・・。
Re:入力キーのチェック
Posted: 2008年4月12日(土) 23:47
by 管理人
> トウラさん
if文はelseでつなげないと期待する動作をしないことが多いです。
今の場合、どういう順序でプログラムが流れているかみてみましょう。
また、flag==1でイフ文に入ってるので、その中でさらにflag==1を判定する必要はないです。
2も同様。
そして、
flag=2をしてif文を出た瞬間、次のif文に入っているので、連続してしまうのです。
if(){
}
else if(){
}
という風につなげればいいです。
Re:入力キーのチェック
Posted: 2008年4月12日(土) 23:49
by 管理人
>kazuoniさん
DxLib2.hの中で最初に
#include "DxLib.h"
は書いていますか?これを書くとDxLib.hを他でインクルードする必要はありません。
Re:入力キーのチェック
Posted: 2008年4月13日(日) 00:00
by Justy
#kazuoniさん
>すべてが読み込むヘッダーをGv.hとして、その冒頭に#include "DxLib2.hをし、DxLib2.hの中身は
> ~
これはマズイです。ヘッダファイルに関数の実体を書いて、それをあちらこちらでインクルードすると
その全部で定義されるのでリンク時に多重定義になります。
ヘッダファイルである "DxLib2.h"には関数のプロトタイプ宣言を書いて、
対になる DxLib2.cppを作ってそちらに実体であるその関数の中身を書いて下さい。
これが面倒なら、"DxLib2.h"の
int GetHitKeyStateAll_2(int KeyStateBuf[/url]){
の部分を
inline int GetHitKeyStateAll_2(int KeyStateBuf[/url]){
としても構いません。
関数がインライン化されるので、リンク時の多重定義にはならなくなります。
Re:入力キーのチェック
Posted: 2008年4月13日(日) 01:15
by 管理人
すみません、ボケてました;
#include"DxLib.h"を書くべきは、cppファイル内です。
Re:入力キーのチェック
Posted: 2008年4月13日(日) 01:22
by kazuoni
管理人さん、Justyさんご回答ありがとうございます!
とりあえずはJustyさんの前者のやり方でできました。
DxLib2.h DxLib2.cpp両方で、GetHitKeyStateAll_2(int KeyStateBuf[/url])という風にかいて、一方の(int KeyStateBuf[/url])のカッコの中身省略したい(統一したい)なぁ~なんて考えてたんですけど、(まぁこれでいいんですけどねっ^^;)GetHitKeyStateAll_2()ってしてしまうと(void)と認識されてしまって、戻り値っておかしくなってしまいますかね?
メイン文で
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE] && !GetHitKeyStateAll_2(Key_n))
をかいているのですが・・・
これで解決なんですけど、Justyさんのおっしゃっていた後者のほうがどうもよく分かりません。。ググってもいまいち分からな
かったのですが・・・関数のインライン化の意味は何なんでしょうか?あと何がしたいときに使用するものなのでしょうか?
Re:入力キーのチェック
Posted: 2008年4月13日(日) 12:12
by Justy
>GetHitKeyStateAll_2()ってしてしまうと(void)と認識されてしまって、戻り値っておかしくなってしまいますかね?
引数と戻り値の指定を省略したプロトタイプ宣言をする、ってことですか?
コンパイル時かリンク時に怒られると思いますよ。万が一動いても正常な動作は
期待できないと思います。
引数の変数名くらいは省力しても構いませんが、あとは同じにしておいて下さい。
>関数のインライン化の意味は何なんでしょうか?
>あと何がしたいときに使用するものなのでしょうか?
一言で言えば高速化が目的です。
通常関数呼び出しは少し時間がかかるのですが、インライン関数は幾つかのデメリットと引き替えに
その呼び出し時間を極力減らすようコンパイラが努力してくれます。
ただ、努力してくれるだけで実際にしてくれるとは限りませんし、実はインライン指定しなくても
もう既に努力済みである可能性もありますが。
インライン関数は普通の関数とは異なり、各モジュール(cpp)単位で“定義”が必要なので、
大抵の場合関数の中身はヘッダに書いておくのですが、リンク時に多重定義に
ならないようにコンパイラ・リンカが調整してくれます。
細かいところは
インライン関数 - Wikipedia
http://ja.wikipedia.org/wiki/%E3%82%A4% ... 2%E6%95%B0
インライン展開 - Wikipedia
http://ja.wikipedia.org/wiki/%E3%82%A4% ... 0.E7.82.B9
インライン関数
http://wisdom.sakura.ne.jp/programming/cpp/cpp14.html
とかを読んでみて下さい。
Re:入力キーのチェック
Posted: 2008年4月13日(日) 13:49
by kazuoni
Justyさんお返事ありがとうございます!
もう少し自分で煮詰めてみたいと思います^^ご丁寧な解説ありがとうございました!
またよろしくお願いします。