キャラの移動

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
だんごさん
記事: 273
登録日時: 13年前

キャラの移動

#1

投稿記事 by だんごさん » 13年前

こんにちは。
現在こちらを参考に
キャラの移動プログラムを組んでおります。
プログラムの構造はURL先とほぼ同じですので、ソースの方は
URL先をご覧ください。
ただし、

コード:

         if( x %16①==0 && y %16① ==0 ){         //座標が16で割り切れたら入力可能
            walking_flag=1;         //歩くフラグを立てる。
			if     ( Key[ KEY_INPUT_UP   ]  >= 1② ){  //上ボタンが押されたら
					mukiA=3;        //上向きフラグを立てる
					
			}		
URL先のプログラムを変更した箇所があります。
①32→16へ変更
②'=='を'>='に変更
その他多々ありますが基本的にこの程度です。

ここからが本題です。

コード:

		{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0, 0,  0, 0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},//0
		{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0, 0,  0, 0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},//1
		{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,-1, -1,-1,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},//2
		{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,C,D,-1,-1, -1,-1,-1,B,A,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},//3
		{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,-1, -1,-1,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},//4
上記はマップデータだと思ってください。
またA,B,C,Dは0と思ってください。
(-1は移動できない場所)
キャラクターがA地点から左方向へ移動したとします。この時、-1へ当たった時は
移動できないはずです。ところが、B地点の場所で移動できなくなるのです。
これは下から上へ移動した場合も一個手前のマップチップで止まります。
しかし、CからD、上から下への移動時は正しく-1で止まります。

これには法則もあります。
A→Bへ移動する際、変化しているのはx座標です。本来移動は16で割り切れた場所区切りと
なります(①で変更したため)。ところがBで止まった時の座標を16で割ると、小数点が
0.875になります。これは下から上へ移動して手前で止まってしまう場合も同じです。

そこでちょっといじくって、0.875だったら移動できるようにプログラミングしました。
すると今度は0.875では通過しましたが、0.75で止まってしまうのです。
どうやら1-0.875=0.125ずつ減っていることが分かります。(つまり0.875/0.125でも0.75/0.125でも割り切れる)

意味が分からないと思います。すみません。
まとめます。

マップの当たり判定である-1の一歩手前の座標で止まってしまう。
ただしそれは右から左方向、下から上方向の際だけ。
また止まってしまう時の座標を16で割ると0.125の倍数である。

えー、解決方法は自分で考えます。ただ、その解決につながるヒント
を頂けたら十分です。~が原因だろう、というような解答でおkです。

よろしくお願いいたします。

環境:
OS:Windows7
コンパイラ:Visual C++ 2008 EE

腕は初心者です。
 Dango San

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

Re: キャラの移動

#2

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

移動単位を16ピクセルとしたのなら、IsAbleToGoは32ピクセル単位での移動の当たり判定をしているので、ここも直す必要がありますよ。
ただし、マップ自体の当たり判定情報が32ピクセル単位のままだとちょっと工夫が必要です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: キャラの移動

#3

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

当たり範囲を描画するようにしてみました。
これで当たり判定の範囲がおかしな事が絵で見てわかると思います。

コード:

#include "DxLib.h"

typedef struct {
	int x, y, img, muki, walking_flag;
} ch_t;

int hantei[15][20] = {
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
};

int IsAbleToGo( int x, int y, int muki ) //進めるかを判定する
{
	if( muki == 0 ) //上向きなら
		if( hantei[y / 32 - 1][x / 32] == 1 ) { //進めるか判定
			//	衝突ブロックの表示
			int bx = (x/32) * 32;
			int by = (y/32-1) * 32;
			DrawBox(bx,by,bx+31,by+31,GetColor(255,0,0),FALSE);
			return 1;//エラー
		}
	if( muki == 1 ) //左向きなら
		if( hantei[y / 32][x / 32 - 1] == 1 ) {
			//	衝突ブロックの表示
			int bx = (x/32-1) * 32;
			int by = (y/32) * 32;
			DrawBox(bx,by,bx+31,by+31,GetColor(255,0,0),FALSE);
			return 1;
		}
	if( muki == 2 ) //下向きなら
		if( hantei[y / 32 + 1][x / 32] == 1 ) {
			//	衝突ブロックの表示
			int bx = (x/32) * 32;
			int by = (y/32+1) * 32;
			DrawBox(bx,by,bx+31,by+31,GetColor(255,0,0),FALSE);
			return 1;
		}
	if( muki == 3 ) //右向きなら
		if( hantei[y / 32][x / 32 + 1] == 1 ) {
			//	衝突ブロックの表示
			int bx = (x/32+1) * 32;
			int by = (y/32) * 32;
			DrawBox(bx,by,bx+31,by+31,GetColor(255,0,0),FALSE);
			return 1;
		}
	return 0;//正常
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{

	int image[16], i, j;
	char Key[256];
	ch_t ch;

	if( ChangeWindowMode( TRUE ) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理

	ch.x    = 320;
	ch.y    = 160;
	ch.walking_flag = 0;
	ch.muki = 3;

	SetDrawScreen( DX_SCREEN_BACK ) ;                                                 //描画先を裏画面に設定
	LoadDivGraph( "char.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//画像を分割してimage配列に保存

	while( !ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE] ) {
		//↑メッセージ処理        ↑画面をクリア         ↑キーボード入力状態取得       ↑ESCが押されると終了

		/*白い壁を描画*/
		for( i = 0; i < 15; i++ )
			for( j = 0; j < 20; j++ )
				if( hantei[i][j] == 1 )
					DrawBox( j * 32, i * 32, ( j + 1 ) * 32, ( i + 1 ) * 32, GetColor( 255, 255, 255 ), TRUE );

		if( ch.x % 16 == 0 && ch.y % 16 == 0 ) { //座標が32で割り切れたら入力可能
			ch.walking_flag = 1;       //歩くフラグを立てる。
			if     ( Key[ KEY_INPUT_UP   ]  >= 1 )  //上ボタンが押されたら
				ch.muki = 0;       //上向きフラグを立てる
			else if( Key[ KEY_INPUT_LEFT ]  >= 1 )  //左ボタンが押されたら
				ch.muki = 1;       //左向きフラグを立てる
			else if( Key[ KEY_INPUT_DOWN ]  >= 1 )  //下ボタンが押されたら
				ch.muki = 2;       //下向きフラグを立てる
			else if( Key[ KEY_INPUT_RIGHT]  >= 1 )  //右ボタンが押されたら
				ch.muki = 3;       //右向きフラグを立てる
			else                                    //何のボタンも押されてなかったら
				ch.walking_flag = 0; //歩かないフラグを立てる
			if( ch.walking_flag == 1 ) //もし歩くなら
				if( IsAbleToGo( ch.x, ch.y, ch.muki ) == 1 ) //行き先が歩けないなら
					ch.walking_flag = 0;                //歩かないフラグを立てる。
		}

		if( ch.walking_flag == 1 ) {   //歩くフラグが立っていたら
			if     ( ch.muki == 0 )    //上向きならch.y座標を減らす
				ch.y--;
			else if( ch.muki == 1 )    //左向きならch.x座標を減らす
				ch.x--;
			else if( ch.muki == 2 )    //下向きならch.y座標を増やす
				ch.y++;
			else if( ch.muki == 3 )    //右向きならch.x座標を増やす
				ch.x++;
		}

		ch.img = image[( ch.x % 32 + ch.y % 32 ) / 8 + ch.muki * 4]; //画像をセット

		DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;//画像を描画

		ScreenFlip();
	}

	DxLib_End();
	return 0;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

だんごさん
記事: 273
登録日時: 13年前

Re: キャラの移動

#4

投稿記事 by だんごさん » 13年前

おお、確かにおかしいです。
言い忘れましたが、IsAbleToGo関数の中も16へ直しています。

書いてもらいましたサンプルソースを試してみました。
下から上、右から左が当たり判定がおかしいことがわかりますね。

参考にさせていただきます^^。
 Dango San

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

Re: キャラの移動

#5

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

だんごさん さんが書きました:おお、確かにおかしいです。
言い忘れましたが、IsAbleToGo関数の中も16へ直しています。

書いてもらいましたサンプルソースを試してみました。
下から上、右から左が当たり判定がおかしいことがわかりますね。

参考にさせていただきます^^。
int型の小数点以下の切り捨てを意識してプログラムを書かないとちゃんと動きません。
私の当たり判定表示をご自分のIsAbleToGo関数に合わせて変更してみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

だんごさん
記事: 273
登録日時: 13年前

Re: キャラの移動

#6

投稿記事 by だんごさん » 13年前

当たり判定を描画するようにプログラミングをしてみました。
するとやはり-1の手前でも当たり判定が作動していることが分かりました。

あと、先ほどのサンプルソースでは手前で止まってもそのまま操作は可能ですが、
私のはそのまま移動不能になります。
それは多分当たり判定に引っかかった時の座標が16で割り切れないため
操作が不能になるのかなと思っています。
 Dango San

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

Re: キャラの移動

#7

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

そこまでわかっているのなら解決策は見えてくると思いますが如何なのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

だんごさん
記事: 273
登録日時: 13年前

Re: キャラの移動

#8

投稿記事 by だんごさん » 13年前

なぜ下から上、右から左へ移動するときだけ
引っかかるかが分からないです。そんなこと考えれば分かるだろう、、というかもしれませんが
分からないのです。頭が働いていないか理解不足です。
 Dango San

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

Re: キャラの移動

#9

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

現状のソースコードを全部見せて頂けますか。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

だんごさん
記事: 273
登録日時: 13年前

Re: キャラの移動

#10

投稿記事 by だんごさん » 13年前

IsAbleToGo関数です。

コード:

int IsAbleToGo(int x,int y,int muki,int *bx,int *by){//進めるかを判定する
        if(muki==3)//上向きなら
			if(Nmap[y/16-1][x/16]!=0){//進めるか判定
                *bx = (x/16) * 16;
				*by = (y/16-1) * 16;        
				return 1;//エラー
			}
        if(muki==1)//左向きなら
			if(Nmap[y/16][x/16-1]!=0){
				*bx = (x/16-1) * 16;
				*by = (y/16) * 16;                       
				return 1;
			}
        if(muki==0)//下向きなら
			if(Nmap[y/16+1][x/16]!=0){
				*bx = (x/16) * 16;
				*by = (y/16+1) * 16;
                return 1;
			}
        if(muki==2)//右向きなら
			if(Nmap[y/16][x/16+1]!=0){
				*bx = (x/16+1) * 16;
				*by = (y/16) * 16;
                
				return 1;
			}
		return 0;//正常
}
先ほどの当たり判定を*bx,*byへ返しています。
画像の関係でmukiの番号順がバラバラですみません。

コード:

         if(sy_da.x_ichi%16 ==0 && sy_da.y_ichi%16 ==0 ){         //座標が16で割り切れたら入力可能
            walking_flag=1;         //歩くフラグを立てる。
			if     ( Key[ KEY_INPUT_UP   ]  >= 1 ){  //上ボタンが押されたら
					mukiA=3;        //上向きフラグを立てる
					
			}		
			else if( Key[ KEY_INPUT_LEFT ]  >= 1 ){  //左ボタンが押されたら
                    mukiA=1;         //左向きフラグを立てる
					
			}
			else if( Key[ KEY_INPUT_DOWN ]  >= 1 ){  //下ボタンが押されたら
                    mukiA=0;         //下向きフラグを立てる
					
			}
			else if( Key[ KEY_INPUT_RIGHT]  >= 1 ){  //右ボタンが押されたら
                    mukiA=2;         //右向きフラグを立てる
				
			}
		
            else                                    //何のボタンも押されてなかったら
                    walking_flag=0; //歩かないフラグを立てる

        }

コード:

if(IsAbleToGo( sy_da.x_ichi , sy_da.y_ichi , mukiA ,&bx,&by)==1)
            walking_flag = 0;
&bx,&byで返り値を取って、当たり判定を表示しました。(別々のソースファイルなのでそうしました…)

えーととりあえずこのくらいで良いですか?
 Dango San

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

Re: キャラの移動

#11

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

質問ですが、マップチップのサイズも16x16になっていてNmapもそのチップのサイズ単位に成っているのでしょうか?
なっていない場合は問題だと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

だんごさん
記事: 273
登録日時: 13年前

Re: キャラの移動

#12

投稿記事 by だんごさん » 13年前

はい。
x座標 640/16=40
y座標 480/16=30
の大きさになっています。

マップデータも一つ一つ数えまして、何度も確認しましたが40*30です。
チップも16*16pixelです。
 Dango San

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

Re: キャラの移動

#13

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

あとは自キャラの絵のサイズとの兼ね合いでそう見える事象でしょうか。
とりあえず16x16にして表示してみました(手抜きなので15x20しかデータがありません)
当たり判定ブロックを白と赤で表示させています(当たる時は赤)
自キャラの絵があっていなこと除けばちゃんと判定しているように見えます。

コード:

#include "DxLib.h"

typedef struct {
	int x, y, img, muki, walking_flag;
} ch_t;

int hantei[15][20] = {
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
};

int IsAbleToGo( int x, int y, int muki ) //進めるかを判定する
{
	if( muki == 0 ) {//上向きなら
		int bx = (x/16) * 16;
		int by = (y/16-1) * 16;
		if( hantei[by/16][bx/16] == 1 ) { //進めるか判定
			//	衝突ブロックの表示
			DrawBox(bx,by,bx+15,by+15,GetColor(255,0,0),FALSE);
			return 1;//エラー
		} else {
			//	判定ブロックの表示
			DrawBox(bx,by,bx+15,by+15,GetColor(255,255,255),FALSE);
		}
	}
	if( muki == 1 ) {//左向きなら
		int bx = (x/16-1) * 16;
		int by = (y/16) * 16;
		if( hantei[by/16][bx/16] == 1 ) { //進めるか判定
			//	衝突ブロックの表示
			DrawBox(bx,by,bx+15,by+15,GetColor(255,0,0),FALSE);
			return 1;
		} else {
			//	判定ブロックの表示
			DrawBox(bx,by,bx+15,by+15,GetColor(255,255,255),FALSE);
		}
	}
	if( muki == 2 ) {//下向きなら
		int bx = (x/16) * 16;
		int by = (y/16+1) * 16;
		if( hantei[by/16][bx/16] == 1 ) { //進めるか判定
			//	衝突ブロックの表示
			DrawBox(bx,by,bx+15,by+15,GetColor(255,0,0),FALSE);
			return 1;
		} else {
			//	判定ブロックの表示
			DrawBox(bx,by,bx+15,by+15,GetColor(255,255,255),FALSE);
		}
	}
	if( muki == 3 ) {//右向きなら
		int bx = (x/16+1) * 16;
		int by = (y/16) * 16;
		if( hantei[by/16][bx/16] == 1 ) { //進めるか判定
			//	衝突ブロックの表示
			DrawBox(bx,by,bx+15,by+15,GetColor(255,0,0),FALSE);
			return 1;
		} else {
			//	判定ブロックの表示
			DrawBox(bx,by,bx+15,by+15,GetColor(255,255,255),FALSE);
		}
	}
	return 0;//正常
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{

	int image[16], i, j;
	char Key[256];
	ch_t ch;

	if( ChangeWindowMode( TRUE ) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理

	ch.x    = 10 * 16;
	ch.y    = 5 * 16;
	ch.walking_flag = 0;
	ch.muki = 3;

	SetDrawScreen( DX_SCREEN_BACK ) ;                                                 //描画先を裏画面に設定
	LoadDivGraph( "char.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//画像を分割してimage配列に保存

	while( !ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE] ) {
		//↑メッセージ処理        ↑画面をクリア         ↑キーボード入力状態取得       ↑ESCが押されると終了

		/*白い壁を描画*/
		for( i = 0; i < 15; i++ )
			for( j = 0; j < 20; j++ )
				if( hantei[i][j] == 1 )
					DrawBox( j * 16, i * 16, ( j + 1 ) * 16, ( i + 1 ) * 16, GetColor( 255, 255, 255 ), TRUE );

		if( ch.x % 16 == 0 && ch.y % 16 == 0 ) { //座標が32で割り切れたら入力可能
			ch.walking_flag = 1;       //歩くフラグを立てる。
			if     ( Key[ KEY_INPUT_UP   ]  >= 1 )  //上ボタンが押されたら
				ch.muki = 0;       //上向きフラグを立てる
			else if( Key[ KEY_INPUT_LEFT ]  >= 1 )  //左ボタンが押されたら
				ch.muki = 1;       //左向きフラグを立てる
			else if( Key[ KEY_INPUT_DOWN ]  >= 1 )  //下ボタンが押されたら
				ch.muki = 2;       //下向きフラグを立てる
			else if( Key[ KEY_INPUT_RIGHT]  >= 1 )  //右ボタンが押されたら
				ch.muki = 3;       //右向きフラグを立てる
			else                                    //何のボタンも押されてなかったら
				ch.walking_flag = 0; //歩かないフラグを立てる
			if( ch.walking_flag == 1 ) //もし歩くなら
				if( IsAbleToGo( ch.x, ch.y, ch.muki ) == 1 ) //行き先が歩けないなら
					ch.walking_flag = 0;                //歩かないフラグを立てる。
		}

		if( ch.walking_flag == 1 ) {   //歩くフラグが立っていたら
			if     ( ch.muki == 0 )    //上向きならch.y座標を減らす
				ch.y--;
			else if( ch.muki == 1 )    //左向きならch.x座標を減らす
				ch.x--;
			else if( ch.muki == 2 )    //下向きならch.y座標を増やす
				ch.y++;
			else if( ch.muki == 3 )    //右向きならch.x座標を増やす
				ch.x++;
		}

		ch.img = image[( ch.x % 16 + ch.y % 16 ) / 4 + ch.muki * 4]; //画像をセット

		DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;//画像を描画

		ScreenFlip();
	}

	DxLib_End();
	return 0;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

だんごさん
記事: 273
登録日時: 13年前

Re: キャラの移動

#14

投稿記事 by だんごさん » 13年前

そういえばキャラの表示方法がDrawExtendGraph(拡大縮小描画)になっています。

コード:

		DrawExtendGraph( sy_da.x_ichi  , sy_da.y_ichi , sy_da.x_ichi +15  ,  sy_da.y_ichi +15 , g_Syujinko_1[image] , TRUE  ) ;                          
うっすらと原因が出てきたような気がします。
 Dango San

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

Re: キャラの移動

#15

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

縮小してみました。
DrawExtendGraphで+16なのはリファレンスをお読みください。
そういう間違いの意味で私のDrawBoxも訂正しました。

コード:

#include "DxLib.h"

typedef struct {
	int x, y, img, muki, walking_flag;
} ch_t;

int hantei[15][20] = {
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
};

int IsAbleToGo( int x, int y, int muki ) //進めるかを判定する
{
	if( muki == 0 ) {//上向きなら
		int bx = (x/16) * 16;
		int by = (y/16-1) * 16;
		if( hantei[by/16][bx/16] == 1 ) { //進めるか判定
			//	衝突ブロックの表示
			DrawBox(bx,by,bx+16,by+16,GetColor(255,0,0),FALSE);
			return 1;//エラー
		} else {
			//	判定ブロックの表示
			DrawBox(bx,by,bx+16,by+16,GetColor(255,255,255),FALSE);
		}
	}
	if( muki == 1 ) {//左向きなら
		int bx = (x/16-1) * 16;
		int by = (y/16) * 16;
		if( hantei[by/16][bx/16] == 1 ) { //進めるか判定
			//	衝突ブロックの表示
			DrawBox(bx,by,bx+16,by+16,GetColor(255,0,0),FALSE);
			return 1;
		} else {
			//	判定ブロックの表示
			DrawBox(bx,by,bx+16,by+16,GetColor(255,255,255),FALSE);
		}
	}
	if( muki == 2 ) {//下向きなら
		int bx = (x/16) * 16;
		int by = (y/16+1) * 16;
		if( hantei[by/16][bx/16] == 1 ) { //進めるか判定
			//	衝突ブロックの表示
			DrawBox(bx,by,bx+16,by+16,GetColor(255,0,0),FALSE);
			return 1;
		} else {
			//	判定ブロックの表示
			DrawBox(bx,by,bx+16,by+16,GetColor(255,255,255),FALSE);
		}
	}
	if( muki == 3 ) {//右向きなら
		int bx = (x/16+1) * 16;
		int by = (y/16) * 16;
		if( hantei[by/16][bx/16] == 1 ) { //進めるか判定
			//	衝突ブロックの表示
			DrawBox(bx,by,bx+16,by+16,GetColor(255,0,0),FALSE);
			return 1;
		} else {
			//	判定ブロックの表示
			DrawBox(bx,by,bx+16,by+16,GetColor(255,255,255),FALSE);
		}
	}
	return 0;//正常
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{

	int image[16], i, j;
	char Key[256];
	ch_t ch;

	if( ChangeWindowMode( TRUE ) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理

	ch.x    = 10 * 16;
	ch.y    = 5 * 16;
	ch.walking_flag = 0;
	ch.muki = 3;

	SetDrawScreen( DX_SCREEN_BACK ) ;                                                 //描画先を裏画面に設定
	LoadDivGraph( "char.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//画像を分割してimage配列に保存

	while( !ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE] ) {
		//↑メッセージ処理        ↑画面をクリア         ↑キーボード入力状態取得       ↑ESCが押されると終了

		/*白い壁を描画*/
		for( i = 0; i < 15; i++ )
			for( j = 0; j < 20; j++ )
				if( hantei[i][j] == 1 )
					DrawBox( j * 16, i * 16, ( j + 1 ) * 16, ( i + 1 ) * 16, GetColor( 255, 255, 255 ), TRUE );

		if( ch.x % 16 == 0 && ch.y % 16 == 0 ) { //座標が32で割り切れたら入力可能
			ch.walking_flag = 1;       //歩くフラグを立てる。
			if     ( Key[ KEY_INPUT_UP   ]  >= 1 )  //上ボタンが押されたら
				ch.muki = 0;       //上向きフラグを立てる
			else if( Key[ KEY_INPUT_LEFT ]  >= 1 )  //左ボタンが押されたら
				ch.muki = 1;       //左向きフラグを立てる
			else if( Key[ KEY_INPUT_DOWN ]  >= 1 )  //下ボタンが押されたら
				ch.muki = 2;       //下向きフラグを立てる
			else if( Key[ KEY_INPUT_RIGHT]  >= 1 )  //右ボタンが押されたら
				ch.muki = 3;       //右向きフラグを立てる
			else                                    //何のボタンも押されてなかったら
				ch.walking_flag = 0; //歩かないフラグを立てる
			if( ch.walking_flag == 1 ) //もし歩くなら
				if( IsAbleToGo( ch.x, ch.y, ch.muki ) == 1 ) //行き先が歩けないなら
					ch.walking_flag = 0;                //歩かないフラグを立てる。
		}

		if( ch.walking_flag == 1 ) {   //歩くフラグが立っていたら
			if     ( ch.muki == 0 )    //上向きならch.y座標を減らす
				ch.y--;
			else if( ch.muki == 1 )    //左向きならch.x座標を減らす
				ch.x--;
			else if( ch.muki == 2 )    //下向きならch.y座標を増やす
				ch.y++;
			else if( ch.muki == 3 )    //右向きならch.x座標を増やす
				ch.x++;
		}

		ch.img = image[( ch.x % 16 + ch.y % 16 ) / 4 + ch.muki * 4]; //画像をセット

//		DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;//画像を描画
		DrawExtendGraph( ch.x, ch.y, ch.x+16, ch.y+16 , ch.img , TRUE  ) ;

		ScreenFlip();
	}

	DxLib_End();
	return 0;
}
あちこち出ている16は定数化すべきだとは思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

だんごさん
記事: 273
登録日時: 13年前

Re: キャラの移動

#16

投稿記事 by だんごさん » 13年前

DrawExtendGraphは+15にしていますが、あっていますよね?
現在改良中です、お待ちください
 Dango San

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: キャラの移動

#17

投稿記事 by ISLe » 13年前

だんごさん さんが書きました:えーととりあえずこのくらいで良いですか?
この断片からは読み取れないので以下はあくまで想像ですが。

IsAbleToGo関数を常に呼び出しているのでしょう。
IsAbleToGo関数は座標が割り切れるときにしか正しく動きません。

整数の割り算は端数切り捨てです。
右に15ピクセル移動しても前のマスですが左に1ピクセル移動したら左のマスです。

IsAbleToGo関数をそのまま使うなら、方向転換可能なときにだけ呼び出すようにしましょう。

そのつもりは無さそうですがいつでも入力できて途中で引き返せるようにしたかったらIsAbleToGo関数の中身を変更する必要があります。

だんごさん
記事: 273
登録日時: 13年前

Re: キャラの移動

#18

投稿記事 by だんごさん » 13年前

なるほど。試して見ます。
 Dango San

だんごさん
記事: 273
登録日時: 13年前

Re: キャラの移動

#19

投稿記事 by だんごさん » 13年前

ISLe さんが書きました:IsAbleToGo関数をそのまま使うなら、方向転換可能なときにだけ呼び出すようにしましょう。
を参考に、この関数を呼び出すために条件として、現座標が16で割り切れたらおkという風にしてみました。

するとあら、、解決いたしました。。

softya様、ISLe様、ありがとうございました^^
 Dango San

閉鎖

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