キャラを一区間単位で移動させる単元

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
moke

キャラを一区間単位で移動させる単元

#1

投稿記事 by moke » 6年前

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;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: キャラを一区間単位で移動させる単元

#2

投稿記事 by softya(ソフト屋) » 6年前

インデントがアバウトなので非常にソースコードが読みづらいです。
整形してみました。

コード:

#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の値を表示させてみれば分かります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
Dixq (管理人)
管理人
記事: 1661
登録日時: 9年前
住所: 北海道札幌市
連絡を取る:

Re: キャラを一区間単位で移動させる単元

#3

投稿記事 by Dixq (管理人) » 6年前

コード:

if( 条件式1 ){
    処理1();
} else if( 条件式2 ){
    処理1();
}

コード:

if( 条件式1 || 条件式2 ){
    処理1();
}
は同じことですよ。

また、32単位で動かしているのにキャラの初期位置が32の倍数じゃないのが気になります。

moke

Re: キャラを一区間単位で移動させる単元

#4

投稿記事 by moke » 6年前

返信ありがとうございます。

指摘されたように、確認ポイントの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の置き方が悪いのは少しわかりました。

しかし、コードがお互いに相殺しあってしまっているのか、ほかにまだ要因があるのかよくわかりません。

プログラムの中で何が起こっているのでしょうか

アバター
みけCAT
記事: 6246
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: キャラを一区間単位で移動させる単元

#5

投稿記事 by みけCAT » 6年前

デバッガなどでプログラムの流れを追ってみると、わかりやすくなると思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

KORYUOH
記事: 44
登録日時: 7年前

Re: キャラを一区間単位で移動させる単元

#6

投稿記事 by KORYUOH » 6年前

補足といっては何ですがprintfデバッグ系列をする場合は値などを変更した跡に特定の文字+現在の値で出すとわかりやすくなります。

printfデバッグ系列というのは、文字列を描画させて行うデバッグ全般のことです。
ほかの方はなんといっているか知りませんが私はこう呼んでいます。
C言語を使うと自分の足を誤って撃ち抜いてしまうことがある。 C++を使えばそのような間違いを犯しにくくなる。しかし、やってしまったときには足全体が無くなる。

moke

Re: キャラを一区間単位で移動させる単元

#7

投稿記事 by moke » 6年前

返信遅くなり、申し訳ないです。

初めの時のプログラムだと、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さん。的確な返信有難うございました。

またわからないことがありましたらここで質問させて頂きます。

閉鎖

“C言語何でも質問掲示板” へ戻る