ひさしぶりです。
今回はキーボードからの入力があるまでループし続ける関数を作ったのですが、この関数の do{}while(CheckHitKeyAll() == 0); のぶぶんを使うとゲームが動かなくなってしまうのですが、何が原因なのでしょうか?
char Key[256] はグローバルで宣言してあります。
int player_input(int num){
int player_key;
/* do{
GetHitKeyStateAll( Key ) ;
if(Key[ KEY_INPUT_A ] == 1){
player_key=0;
}
if(Key[ KEY_INPUT_S ] == 1){
player_key=1;
}
if(Key[ KEY_INPUT_D ] == 1){
player_key=2;
}
if(Key[ KEY_INPUT_F ] == 1){
player_key=3;
}
if(Key[ KEY_INPUT_G ] == 1){
player_key=4;
}
}while(CheckHitKeyAll() == 0);*/
player_key=num;//インプットがうまくできないため臨時に代入
return player_key;
}
入力関数がうまくできません
Re:入力関数がうまくできません
コピペして試したところ特に問題無く動いてしまいました(以下のコード)。
「ゲームが動かなくなってしまう」とは、もしかして「予想外のキーを押されると警告が出て止まる」というものでしょうか。
もしそうならば player_key が初期化されていないことが原因のようなので、宣言時に適当な値で初期化してみてください。
以下、私が検証した際のコードです。
「ゲームが動かなくなってしまう」とは、もしかして「予想外のキーを押されると警告が出て止まる」というものでしょうか。
もしそうならば player_key が初期化されていないことが原因のようなので、宣言時に適当な値で初期化してみてください。
以下、私が検証した際のコードです。
#include "DxLib.h" int player_input(); char Key[256]; int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ChangeWindowMode(TRUE); if( DxLib_Init() == -1 ) // DXライブラリ初期化処理 { return -1; // エラーが起きたら直ちに終了 } player_input(); DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 } int player_input(){ int player_key; //ここで=-1などの初期化を行うと警告は出ない。 do{ GetHitKeyStateAll( Key ) ; if(Key[ KEY_INPUT_A ] == 1){ player_key=0; } if(Key[ KEY_INPUT_S ] == 1){ player_key=1; } if(Key[ KEY_INPUT_D ] == 1){ player_key=2; } if(Key[ KEY_INPUT_F ] == 1){ player_key=3; } if(Key[ KEY_INPUT_G ] == 1){ player_key=4; } }while(CheckHitKeyAll() == 0); return player_key; //予想外のキー入力があると、初期化されない値が返されてエラーになる模様 }
Re:入力関数がうまくできません
警告が出るのではなく、全く動かなくなってしまいます。
なので、終了するときはタスクマネージャーから直接プロセスの終了をしています。
ソースのほとんどを載せます。
多々変更があります。
画像のロード関係はほかのcppファイルにあります。
内容は旗揚げゲームです。
CPが出してくる旗を暗記して、自分の番に順番どおりにキーボードを入力するのもです。
#include"extern.h"
#include"DxLib.h"
#define N 100 //やる回数
#define FFT 50//旗をあげている時間
#define FCT 75//旗を変えるまでの時間
char Key[256];
void flagman_draw(int num);
int player_check(int flag_num,int* count);
//////////////////////////////////////////////////////////////////////////////////////////////////////////
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
SetDrawScreen( DX_SCREEN_BACK ); //裏画面に設定
int flag_num[N];
int time=1,count=1,cpu=1,flag_fly_time=0,change_count=2;
int white= GetColor( 255 , 255 , 255 ) ;
for(int i=0;i<N;i++){
flag_num=GetRand( 4 );
}
img_load();
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE] && count<N){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されていな
DrawFormatString( 0, 250, white, "カウントの値は %d です\n", count ) ;
DrawFormatString( 0, 270, white, "チェンジカウントの値は %d です\n", change_count ) ;
DrawGraph( 0 , 0 , body_img , FALSE ) ;
/////////////////////////////////////////////////////////////////////////////
if(cpu==1){
DrawString( 0 , 300 , "CPUの番です。" , white );
if(time%FCT==0) count++;
if(flag_fly_time<FFT) flagman_draw(flag_num[count]);
//else DrawGraph(0,0,body_img,FALSE);
flag_fly_time++;
if(flag_fly_time>=FCT) flag_fly_time=0;
if(change_count<count){
cpu=0;count=1;
}
}
/////////////////////////////////////////////////////////////////////////////
if(cpu==0){
int player_num;
DrawString( 0 , 300 , "プレイヤーの番です。" , white );
player_num=player_check(flag_num[count],&count);
if(flag_fly_time<FFT)
flagman_draw(player_num);
WaitTimer(1000);
flag_fly_time++;
if(flag_fly_time>=FCT){
flag_fly_time=0;
}
if(count>change_count){
cpu=1;change_count++;count=1;
}
}
//////////////////////////////////////////////////////////////////////////////
ScreenFlip();//裏画面を表画面に反映
time++;
}
DxLib_End();
return 0;
}
void flagman_draw(int flag_num){
switch(flag_num){
case 0: DrawGraph( 0 , 0 , left_arm_img , FALSE ) ;break;
case 1: DrawGraph( 0 , 0 , left_leg_img , FALSE ) ;break;
case 2: DrawGraph( 0 , 0 , right_leg_img , FALSE ) ;break;
case 3: DrawGraph( 0 , 0 , right_arm_img , FALSE ) ;break;
case 4: DrawGraph( 0 , 0 , head_img , FALSE ) ;break;
case 5: DrawGraph( 0 , 0 , miss_img ,FALSE) ;break;
}
}
int player_check(int flag_num,int* P_count){
int player_num=-1;
/*do{
GetHitKeyStateAll( Key ) ;
if(Key[ KEY_INPUT_1 ] == 1){
player_num=0;
}
if(Key[ KEY_INPUT_2 ] == 1){
player_num=1;
}
if(Key[ KEY_INPUT_3 ] == 1){
player_num=2;
}
if(Key[ KEY_INPUT_4 ] == 1){
player_num=3;
}
if(Key[ KEY_INPUT_5 ] == 1){
player_num=4;
}
}while(CheckHitKeyAll() == 0);*/
player_num=flag_num;//臨時
if(player_num==flag_num){
(*P_count)++;
return player_num;
}
else{
return 5;
}
}
なので、終了するときはタスクマネージャーから直接プロセスの終了をしています。
ソースのほとんどを載せます。
多々変更があります。
画像のロード関係はほかのcppファイルにあります。
内容は旗揚げゲームです。
CPが出してくる旗を暗記して、自分の番に順番どおりにキーボードを入力するのもです。
#include"extern.h"
#include"DxLib.h"
#define N 100 //やる回数
#define FFT 50//旗をあげている時間
#define FCT 75//旗を変えるまでの時間
char Key[256];
void flagman_draw(int num);
int player_check(int flag_num,int* count);
//////////////////////////////////////////////////////////////////////////////////////////////////////////
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
SetDrawScreen( DX_SCREEN_BACK ); //裏画面に設定
int flag_num[N];
int time=1,count=1,cpu=1,flag_fly_time=0,change_count=2;
int white= GetColor( 255 , 255 , 255 ) ;
for(int i=0;i<N;i++){
flag_num=GetRand( 4 );
}
img_load();
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE] && count<N){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されていな
DrawFormatString( 0, 250, white, "カウントの値は %d です\n", count ) ;
DrawFormatString( 0, 270, white, "チェンジカウントの値は %d です\n", change_count ) ;
DrawGraph( 0 , 0 , body_img , FALSE ) ;
/////////////////////////////////////////////////////////////////////////////
if(cpu==1){
DrawString( 0 , 300 , "CPUの番です。" , white );
if(time%FCT==0) count++;
if(flag_fly_time<FFT) flagman_draw(flag_num[count]);
//else DrawGraph(0,0,body_img,FALSE);
flag_fly_time++;
if(flag_fly_time>=FCT) flag_fly_time=0;
if(change_count<count){
cpu=0;count=1;
}
}
/////////////////////////////////////////////////////////////////////////////
if(cpu==0){
int player_num;
DrawString( 0 , 300 , "プレイヤーの番です。" , white );
player_num=player_check(flag_num[count],&count);
if(flag_fly_time<FFT)
flagman_draw(player_num);
WaitTimer(1000);
flag_fly_time++;
if(flag_fly_time>=FCT){
flag_fly_time=0;
}
if(count>change_count){
cpu=1;change_count++;count=1;
}
}
//////////////////////////////////////////////////////////////////////////////
ScreenFlip();//裏画面を表画面に反映
time++;
}
DxLib_End();
return 0;
}
void flagman_draw(int flag_num){
switch(flag_num){
case 0: DrawGraph( 0 , 0 , left_arm_img , FALSE ) ;break;
case 1: DrawGraph( 0 , 0 , left_leg_img , FALSE ) ;break;
case 2: DrawGraph( 0 , 0 , right_leg_img , FALSE ) ;break;
case 3: DrawGraph( 0 , 0 , right_arm_img , FALSE ) ;break;
case 4: DrawGraph( 0 , 0 , head_img , FALSE ) ;break;
case 5: DrawGraph( 0 , 0 , miss_img ,FALSE) ;break;
}
}
int player_check(int flag_num,int* P_count){
int player_num=-1;
/*do{
GetHitKeyStateAll( Key ) ;
if(Key[ KEY_INPUT_1 ] == 1){
player_num=0;
}
if(Key[ KEY_INPUT_2 ] == 1){
player_num=1;
}
if(Key[ KEY_INPUT_3 ] == 1){
player_num=2;
}
if(Key[ KEY_INPUT_4 ] == 1){
player_num=3;
}
if(Key[ KEY_INPUT_5 ] == 1){
player_num=4;
}
}while(CheckHitKeyAll() == 0);*/
player_num=flag_num;//臨時
if(player_num==flag_num){
(*P_count)++;
return player_num;
}
else{
return 5;
}
}
Re:入力関数がうまくできません
色々と検討してみました。
結果、私には原因を特定する事ができませんでした。orz
「動かない」と言うよりは「処理を受け付けなくなる」と言ったところでしょうか。
入力待ちになってから反応がなくなり、右上×ボタンを押してもウィンドウが閉じるだけでプログラムは生きたままでした(私もタスクマネージャから強制終了)。
CheckHitKeyAll()関数は入力があった時には-1と0以外の何らかの数値を返すようなので、ループ中にキー入力があればループを抜けるように思えるのですけれど……。
つまるところこのdo{}whileループを抜けなくなったために応答しなくなり、ProcessMessage()も呼んでいなかったので右上×ボタンでは正常終了できなかったのでしょう(ちなみに無限ループ中では毎回ProcessMessage()を一回は呼び出すべきです)。
なぜそうなったか、それはわからず。私が最初に検証した時は抜けたのに……。
首を突っ込んでおきながら力になれず申し訳ないです。
でも何だか悔しいのでdo{}whileなしで動作するようにコードを書き変えてみました(添付ファイル)。
私が見やすいように色々コメントを書き加えていますが、参考になればと思います。
結果、私には原因を特定する事ができませんでした。orz
「動かない」と言うよりは「処理を受け付けなくなる」と言ったところでしょうか。
入力待ちになってから反応がなくなり、右上×ボタンを押してもウィンドウが閉じるだけでプログラムは生きたままでした(私もタスクマネージャから強制終了)。
CheckHitKeyAll()関数は入力があった時には-1と0以外の何らかの数値を返すようなので、ループ中にキー入力があればループを抜けるように思えるのですけれど……。
つまるところこのdo{}whileループを抜けなくなったために応答しなくなり、ProcessMessage()も呼んでいなかったので右上×ボタンでは正常終了できなかったのでしょう(ちなみに無限ループ中では毎回ProcessMessage()を一回は呼び出すべきです)。
なぜそうなったか、それはわからず。私が最初に検証した時は抜けたのに……。
首を突っ込んでおきながら力になれず申し訳ないです。
でも何だか悔しいのでdo{}whileなしで動作するようにコードを書き変えてみました(添付ファイル)。
私が見やすいように色々コメントを書き加えていますが、参考になればと思います。
Re:入力関数がうまくできません
ありがとうございます!!
これで、何とか動くようになりました。
超初心者である私のプログラムは難解だったにちがいありません。
まだ、プログラムの書き方がわからないのですいませんでした。
これからは無限ループにはきをつけるようにします。
私だけの力では解決策がわからず、どうすることもできませんでした。
迷彩吹雪様にはまさに感謝です。
これで、何とか動くようになりました。
超初心者である私のプログラムは難解だったにちがいありません。
まだ、プログラムの書き方がわからないのですいませんでした。
これからは無限ループにはきをつけるようにします。
私だけの力では解決策がわからず、どうすることもできませんでした。
迷彩吹雪様にはまさに感謝です。