ページ 1 / 1
特定のキーが押されるまで待つ
Posted: 2011年9月22日(木) 04:08
by 奥兵
現在サイトを見ながら簡単なスクリプトを作っているのですが
文字を表示した後、特定のキーが押されるまで処理を待つようにしたいのですがうまくいきません。
ループを使うと走らせた際に「"プログラム名".exeは応答していません」となってしまいます。
エンター、もしくはスペースが押されるまで待ちたいのですが・・・
VC2008 DXライブラリ使用 OSは7です
C++歴は半年ありません
↓問題の部分です
コード:
int Print(char* string){
char KeyBuf[ 256 ] ;
GetHitKeyStateAll( KeyBuf ) ;
int x=40;
int y=500;
static char* string1;
static char* string2;
string2=string1;
string1=string;
if(string2==NULL){
string2="";
}
SetFontSize( 26 ) ;
DrawFormatString(x,y,GetColor(255,255,255),"%s",string1);
DrawFormatString(x,y+26,GetColor(255,255,255),"%s",string2);
//ここで待ちたいのですが・・・
for(;;){
GetHitKeyStateAll( KeyBuf ) ;
if((KeyBuf[ KEY_INPUT_RETURN ]==1)
||(KeyBuf[KEY_INPUT_SPACE==1])){
break;
}
}
return 0;
}
Re: 特定のキーが押されるまで待つ
Posted: 2011年9月22日(木) 06:47
by a5ua
以下のような“状態遷移”を実現する必要があります。
コード:
[文字表示]
↓
[入力待ち]
↓ キーが押された
…
[]でくくった箇所がひとつの状態を表し、↓の横に書いてあるのが遷移の条件を表します。
何も書かれていない場合は、無条件で即座に遷移するものとします。
最も単純な方法は、switch-case文による分岐です。以下のサンプルプログラムを示します。
参考にしてみてください。
► スポイラーを表示
コード:
#include "DxLib.h"
// 各フェイズを表す列挙体
enum Phase
{
INITIALIZING_PHASE, RUNNING_PHASE, WAITING_PHASE, UNKNOWN_PHASE
};
// 各フェイズで共有する変数
int StartCount;
// 初期化フェイズ
Phase InitializingPhaseTask(void)
{
StartCount = GetNowCount();
return RUNNING_PHASE;
}
// 動作フェイズ
Phase RunningPhaseTask(void)
{
// 経過時間
int elapsed = GetNowCount() - StartCount;
DrawFormatString(50, 50, GetColor(255, 255, 255), _T("%d ms"), elapsed);
// 一秒経過したら入力待ちフェイズへ
if (1000 <= elapsed) {
return WAITING_PHASE;
}
// 動作フェイズ継続
return RUNNING_PHASE;
}
// 入力待ちフェイズ
Phase WaitingPhaseTask(void)
{
DrawString(0, 0, _T("EnterキーかSpaceキーを押してください"), GetColor(255, 255, 255));
// キーが押されたら、実行フェイズへ
if (CheckHitKey(KEY_INPUT_RETURN) || CheckHitKey(KEY_INPUT_SPACE)) {
StartCount = GetNowCount();
return RUNNING_PHASE;
}
// 入力待ちフェイズ継続
return WAITING_PHASE;
}
// 現在のフェイズによって、処理を振り分ける
// 戻り値は、次に実行すべきフェイズを表す
Phase UpdatePhase(Phase phase)
{
switch (phase) {
case INITIALIZING_PHASE:
return InitializingPhaseTask();
case RUNNING_PHASE:
return RunningPhaseTask();
case WAITING_PHASE:
return WaitingPhaseTask();
}
return UNKNOWN_PHASE;
}
int WINAPI _tWinMain(HINSTANCE, HINSTANCE,LPTSTR, int)
{
ChangeWindowMode(TRUE);
if (DxLib_Init() == -1) {
return -1;
}
SetDrawScreen(DX_SCREEN_BACK);
// 初期フェイズの設定
Phase phase = INITIALIZING_PHASE;
while (ProcessMessage() == 0) {
// Escapeキーで終了
if (CheckHitKey(KEY_INPUT_ESCAPE)) {
break;
}
// 変な値が入ってたら、エラー終了
if (phase == UNKNOWN_PHASE) {
MessageBox(NULL, _T("unkonow phase"), _T("error"), MB_ICONERROR);
break;
}
ClearDrawScreen();
// フェイズの更新
phase = UpdatePhase(phase);
ScreenFlip();
}
DxLib_End();
return 0;
}
このプログラムは、1秒間実行したあと入力待ちをし、キーが入力されたら再び1秒間実行を繰り返すものです。
状態遷移図を書くと以下のようになります。
コード:
↓
[初期化]
↓
特定の ┌→[実行中]
キーが │ ↓ 実行開始から1秒間経過
押された└─[入力待ち]
現在の状態を保持する変数としてphaseを用意し、phaseの値によって処理をswitch-caseで振り分けます。
ここでは、各フェイズの処理関数は次のフェイズを表す値を返すようにしてみました。
コード:
// フェイズの更新
phase = UpdatePhase(phase);
この部分で、特定の条件を満たしたときにはphaseが変更されるので、状態遷移が実現できます。
(値が変わらない場合は、フェイズが継続していることを意味する)
何か分からないことがありましたら、言ってください。
Re: 特定のキーが押されるまで待つ
Posted: 2011年9月22日(木) 09:23
by バグ
待機するだけでしたら、下記のようにWaitKey関数を使えばいいのではないでしょうか?
WaitKey関数でしたら、待機中もProcessMessage関数が実行されていますから、固まってしまうことはないと思います。
コード:
for (; ;)
{
int key = WaitKey();
if (key == KEY_INPUT_RETURN || key == KEY_INPUT_SPACE)
{
break;
}
}
Re: 特定のキーが押されるまで待つ
Posted: 2011年9月22日(木) 12:33
by 奥兵
お二人とも素早い御返事ありがとうございます。
おかげで無事解決することができました。
今回は簡単そうだったのでWaitKeyを使う事にしました。
Re: 特定のキーが押されるまで待つ
Posted: 2011年9月22日(木) 17:25
by ISLe
バグ さんが書きました:WaitKey関数でしたら、待機中もProcessMessage関数が実行されていますから、固まってしまうことはないと思います。
WaitKey関数を実行中にアプリが終了する可能性を考慮しないと無限ループに陥ることはありそうですけど。
Re: 特定のキーが押されるまで待つ
Posted: 2011年9月22日(木) 18:15
by バグ
>>ISLeさん
>>WaitKey関数を実行中にアプリが終了する可能性を考慮しないと無限ループに陥ることはありそうですけど。
そうですね、たしかに今回はそこまで考慮しておりません。
ただ、今回の質問に対しての回答という意味では問題ないかと・・・(別に意地悪で書いている訳ではありませんよ(汗))
もし、そこまで必要だというのであれば、a5uaさんの提案されている状態遷移を取り入れるのがベターでしょう。