ページ 1 / 1
キャラを一区間単位で移動させる単元
Posted: 2013年9月10日(火) 20:29
by moke
C言語の館、キャラを一区間単位で移動させる単元で
一定区間を割り算の余りを使って求めるところですが、
左または右キーを一つだけ受け入れるならif文を一つ作ってキー入力を待つ関数を
入れればよいことはわかりました。
しかし、if文を複数用意すると、画像が区間移動しなくなり、一切動かなくなってしまいました。
関数や構造体を試し、お手本を見ながらやったのですが結局だめでした。
コードは背景とキャラクタを表示させます。キャラクタを左右キーで動かすためのコードを作りました。
どうしたらよいのでしょうかご指摘よろしくお願いします。
コード:
#include"DxLib.h"
typedef struct person{
int x,y; }ch_t;
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
ChangeWindowMode(TRUE ),DxLib_Init(),SetDrawScreen( DX_SCREEN_BACK);//ウィンドウモードの変更と初期化と裏画面設定
ch_t ch={50,300};//構造体初期化
int Handle[2];
Handle[0] = LoadGraph("画像");//画像のロード
Handle[1] = LoadGraph("画像") ;
// while(裏画面を表画面に反映, メッセージ処理, 画面クリア)
while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 )
{
if( ProcessMessage() != 0 )
{ break;}
if(CheckHitKey(KEY_INPUT_RIGHT) == 1){//右キーの入力待ち
ch.x= ch.x+2;
}else if(ch.x%32!=0){
ch.x= ch.x+2; }
if(CheckHitKey(KEY_INPUT_LEFT) == 1){左キーの入力待ち
ch.x= ch.x-2;
}else if(ch.x%32!=0){
ch.x= ch.x-2; }
DrawGraph(0,0,Handle[0],TRUE);
DrawGraph(ch.x,ch.y,Handle[1],TRUE);
}
DxLib_End(); // DXライブラリ終了処理
return 0;
}
Re: キャラを一区間単位で移動させる単元
Posted: 2013年9月10日(火) 20:47
by softya(ソフト屋)
インデントがアバウトなので非常にソースコードが読みづらいです。
整形してみました。
コード:
#include"DxLib.h"
typedef struct person {
int x, y;
} ch_t;
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) {
ChangeWindowMode( TRUE ), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモードの変更と初期化と裏画面設定
ch_t ch = {50, 300}; //構造体初期化
int Handle[2];
Handle[0] = LoadGraph( "画像" ); //画像のロード
Handle[1] = LoadGraph( "画像" ) ;
// while(裏画面を表画面に反映, メッセージ処理, 画面クリア)
while( ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 ) {
if( ProcessMessage() != 0 ) {
break;
}
if( CheckHitKey( KEY_INPUT_RIGHT ) == 1 ) { //右キーの入力待ち
ch.x = ch.x + 2;
} else if( ch.x % 32 != 0 ) {
ch.x = ch.x + 2;
}
// 確認ポイント1
if( CheckHitKey( KEY_INPUT_LEFT ) == 1 ) { //左キーの入力待ち
ch.x = ch.x - 2;
} else if( ch.x % 32 != 0 ) {
ch.x = ch.x - 2;
}
// 確認ポイント2
DrawGraph( 0, 0, Handle[0], TRUE );
DrawGraph( ch.x, ch.y, Handle[1], TRUE );
}
DxLib_End(); // DXライブラリ終了処理
return 0;
}
気になる所は、ProcessMessage()が2つ有ることです。while中のProcessMessageだけで問題ないので、まず2つ目のを抹消しましましょう。
それと歩かないことと、関数化や構造体、if文を複数用意することは直接は関係ないです(バグを誘発する可能性はあります)。
このプログラムの場合、プログラムの流れの中で問題を引き起こしているので、DrawFotmatString()で変数を確認してみましょう。
コメントで確認ポイントと書いた所でch.xの値を表示させてみれば分かります。
Re: キャラを一区間単位で移動させる単元
Posted: 2013年9月10日(火) 21:26
by Dixq (管理人)
コード:
if( 条件式1 ){
処理1();
} else if( 条件式2 ){
処理1();
}
と
コード:
if( 条件式1 || 条件式2 ){
処理1();
}
は同じことですよ。
また、32単位で動かしているのにキャラの初期位置が32の倍数じゃないのが気になります。
Re: キャラを一区間単位で移動させる単元
Posted: 2013年9月10日(火) 22:34
by moke
返信ありがとうございます。
指摘されたように、確認ポイントのch.xの値を
DrawFotmatString関数で確認したところ、if文は処理が一度で終了していて、
DrawGraph関数のポイントでも同じ現象が。
if文の構造について指摘をしていただいたので見てみると
コード:
//右キー入力待ち
if(CheckHitKey(KEY_INPUT_RIGHT) == 1 || ch.x%32!=0){
ch.x= ch.x+2;
と
コード:
//左キー入力待ち
if(CheckHitKey(KEY_INPUT_LEFT) == 1 || ch.x%32!=0){
ch.x= ch.x-2;
上のch.x%32!=0の置き方が悪いのは少しわかりました。
しかし、コードがお互いに相殺しあってしまっているのか、ほかにまだ要因があるのかよくわかりません。
プログラムの中で何が起こっているのでしょうか
Re: キャラを一区間単位で移動させる単元
Posted: 2013年9月10日(火) 22:38
by みけCAT
デバッガなどでプログラムの流れを追ってみると、わかりやすくなると思います。
Re: キャラを一区間単位で移動させる単元
Posted: 2013年9月11日(水) 00:02
by KORYUOH
補足といっては何ですがprintfデバッグ系列をする場合は値などを変更した跡に特定の文字+現在の値で出すとわかりやすくなります。
printfデバッグ系列というのは、文字列を描画させて行うデバッグ全般のことです。
ほかの方はなんといっているか知りませんが私はこう呼んでいます。
Re: キャラを一区間単位で移動させる単元
Posted: 2013年9月12日(木) 01:46
by moke
返信遅くなり、申し訳ないです。
初めの時のプログラムだと、ch.x%32の処理が右キー、左キーの入力を待たずに処理されていたみたいです。
そこでmain関数内に構造体のほかにright、left変数を新たに作ることで右キー左キーが押された
時のch.x%32の処理を分けることができるようにしたところ、無事問題が解決しました。
コード:
#include"DxLib.h"
typedef struct person{
int x,y;
} ch_t;
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
ChangeWindowMode(TRUE ),DxLib_Init(),SetDrawScreen( DX_SCREEN_BACK);//ウィンドウモードの変更と初期化と裏画面設定
ch_t ch={64,300};//構造体初期化
int Handle[2];
int right=0,left=0;//right,leftの初期状態を 0
int Green = GetColor( 0, 255, 0 );//確認用
Handle[0] = LoadGraph("画像");
Handle[1] = LoadGraph("画像") ;
// while(裏画面を表画面に反映, メッセージ処理, 画面クリア)
while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0)//while の中で呼んでいる関数は共通してエラーが起きると0以外を返します。
{
DrawGraph(0,0,Handle[0],TRUE);
if(CheckHitKey(KEY_INPUT_RIGHT) == 1 ){
right=ch.x+2;
ch.x =right;
right = 1; //右キーが押されたときright==1,left==0
left = 0;
}else if(CheckHitKey(KEY_INPUT_LEFT) == 1){
left = ch.x-2;
ch.x = left;
right=0; //左キーが押されたときright==0,left==1
left = 1;
}else if(ch.x%32!=0){
if(right==1){//right==1の時処理する
ch.x=ch.x+2;
}else if(left==1){//left==1の時処理する
ch.x=ch.x-2;
}
}
// 確認ポイント1
DrawFormatString( 0, 0, Green, "座標[%d,%d]", ch.x, ch.y ); // 文字を描画する
DrawGraph(ch.x,ch.y,Handle[1],TRUE);
}
DxLib_End(); // DXライブラリ終了処理
return 0;
}
DrawFotmatString()関数によって視覚的にプログラムの問題点を見つけられたのが
とても大きかったです。
softyaさん、Dixq さん、みけCATさん、KORYUOHさん。的確な返信有難うございました。
またわからないことがありましたらここで質問させて頂きます。