敵との当たり判定

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

敵との当たり判定

#1

投稿記事 by heyman » 11年前

http://dixq.net/forum/viewtopic.php?f=3&t=14734 の続きです
前回アドバイスをいただいた通り、別レイヤで敵を書きました。
そして、当たり判定を行う関数を作ったのですが、うまく機能していません。
どこが間違っているのでしょうか?
当たり判定の参考にしたサイトは、
http://homepage2.nifty.com/natupaji/DxL ... re1_6.html
です

コード:

#include "DxLib.h"

#define MAP_SIZE    32          // マップチップ一つのドットサイズ
#define MAP_WIDTH   25          // マップの幅
#define MAP_HEIGHT  20          // マップの縦長さ

int Pls(); //プレイや-の初期化
int Mps(); //マップの初期化
int Ens(); //敵の初期化
int Chractermove(); //キャラの移動処理
int MapDraw(); //マップの画像
int NpcDraw(); //npcの画像
int ataru;
int Hit(char g1,int x1,int y1,char g2,int x2,int y2);
int mapc[MAP_HEIGHT][MAP_WIDTH]={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,0,0,0,0,0,0,0,0,0,0,1,
						   	     1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
								 1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
	                             1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
	                             1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
								 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
						   	     1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
								 1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
	                             1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
	                             1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,
	                             1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
								 1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
								 1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
	                             1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
	                             1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,
	                             1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
	                             1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
	                             1,0,0,0,0,0,0,0,0,0,0,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};


int mape[MAP_HEIGHT][MAP_WIDTH]={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,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,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,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,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,
	                             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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
struct MAP
{
	int mhandle;
	int mscrx,mscry;
	int scrx,scry; //スクロール
};

struct PLAYER
{
	int px,py; //キャラの座標
	int movex,movey; //移動した距離
	int dm; //ダメージ
	int hp; //主人公のライフ
	int mp; //マジックポイント
	int at; //攻撃力
	int df; //防御力
	int sp; //歩く速さ
	int mwalkx,mwalky; //歩く方向
	int xflag,yflag; //縦横のいどうのフラグ
	float xp; //経験値
	int lv; //レベル
	int mflag; //動けるか?
	int kflag; //攻撃したか?
	int handle[20]; //キャラの画像
	int state; //キャラの状態
	int mcount; //アニメーションさせるカウント
	int img; //プレイヤーの画像番号
};

struct ENEMY
{
	int tlv;
	int tx;
	int ty;
	int thp;
	int tat;
	int tdf;
	int tsp;
	int thandle[3];
	int tstate;
};


PLAYER pl;
MAP mp;
ENEMY t1;

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
	// ウインドウモードで起動
	ChangeWindowMode( TRUE ) ;
	// DXライブラリの初期化
    if( DxLib_Init() < 0 ) return -1;
	
	Pls();
	Mps();
	Ens();NpcDraw();
	// 描画先を裏画面にする
	SetDrawScreen( DX_SCREEN_BACK ) ;
	
	while( ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0 )
    {
		ClearDrawScreen();
		
		switch( pl.state ){
		case 0: //移動できる
			MapDraw();
			Chractermove();
			
			ataru=Hit(pl.handle[1],pl.movex,pl.movey,t1.thandle[1],t1.tx+mp.scrx,t1.ty+mp.scry);
			break;

		}
			
		// 裏画面の内容を表画面に反映
        ScreenFlip() ;
	}


	 // DXライブラリの後始末
    DxLib_End();
	return 0;
}
int Pls()
{
	pl.px=300;
	pl.py=150;
	pl.hp=100;
	pl.lv=1;
	pl.at=1;
	pl.df=1;
	pl.sp=2;
	LoadDivGraph("キャラ.png",20,4,5,23,32,pl.handle);
	return 0;
}
int Mps()
{
	mp.mhandle=LoadGraph( "マップチップ.png" ) ;
	return 0;
}
int Ens()
{
	LoadDivGraph("敵.png",3,3,1,25,20,t1.thandle);
	return 0;
}
int MapDraw()
{        

	int i,j;
	
	for(i=0;i<MAP_WIDTH;i++)
	{
		for(j=0;j<MAP_HEIGHT;j++)
		{
			if(mapc[j][i]==0)DrawGraph(mp.scrx+MAP_SIZE*i,mp.scry+MAP_SIZE*j,mp.mhandle,TRUE);
		}
	}
	return 0;
}

int Chractermove()
{
	int key;
	key=CheckHitKeyAll();
	pl.movex=pl.px;
	pl.movey=pl.py;
	mp.mscrx=mp.scrx;
	mp.mscry=mp.scry;
	pl.mwalkx=3;
	pl.mwalky=3;
	if(CheckHitKey(KEY_INPUT_UP)==1)pl.mwalky=0, pl.yflag=1;//上に移動
	if(CheckHitKey(KEY_INPUT_DOWN)==1)pl.mwalky=1, pl.yflag=1;//下に移動
	if(CheckHitKey(KEY_INPUT_LEFT)==1)pl.mwalkx=0, pl.xflag=1;//左に移動
	if(CheckHitKey(KEY_INPUT_RIGHT)==1)pl.mwalkx=1, pl.xflag=1;//右に移動

	if( key != 0)
	{
		if(pl.yflag==1)
		{
			if(pl.mwalky==0)/*pl.movey-=pl.sp,*/mp.mscry += pl.sp;//上に移動
			if(pl.mwalky==1)/*pl.movey+=pl.sp,*/mp.mscry -= pl.sp;//下に移動
			pl.yflag=0;
		}

		if(pl.xflag==1)
		{
			if(pl.mwalkx==0)/*pl.movex-=pl.sp,*/mp.mscrx += pl.sp;//左に移動
			if(pl.mwalkx==1)/*pl.movex+=pl.sp,*/mp.mscrx -= pl.sp;//右に移動
			pl.xflag=0;
		}
	}



	if(pl.mflag==0 && mapc[(pl.movey-mp.mscry)/32][(pl.movex-mp.mscrx)/32]==0 && mapc[(pl.movey+32-1-mp.mscry)/32][(pl.movex-mp.mscrx)/32]==0 
					&& mapc[(pl.movey+32-1-mp.mscry)/32][(pl.movex+25-1-mp.mscrx)/32]==0 && mapc[(pl.movey-mp.mscry)/32][(pl.movex+25-1-mp.mscrx)/32]==0
					&& ataru==0)
	{
	//pl.px=pl.movex; //x座標の更新
	//pl.py=pl.movey; //y座標の更新
	mp.scrx=mp.mscrx;
	mp.scry=mp.mscry;
	}

	pl.mcount++;
	if(pl.mwalky==1)
	{
		pl.img=8+(pl.mcount%32)/8;
	}
	if(pl.mwalky==0)
	{
		pl.img=(pl.mcount%32)/8;
	}
	if(pl.mwalkx==1)
	{
		pl.img=4+(pl.mcount%32)/8;
	}
	if(pl.mwalkx==0)
	{
		pl.img=12+(pl.mcount%32)/8;
	}
	//DrawGraph(t1.tx+mp.scrx,t1.ty+mp.scry,t1.thandle[1],TRUE);
	DrawGraph(pl.px,pl.py,pl.handle[pl.img],TRUE);
	return 0;
}

int NpcDraw()
{        

	int i,j;
	
	for(i=0;i<MAP_WIDTH;i++)
	{
		for(j=0;j<MAP_HEIGHT;j++)
		{
			if(mape[j][i]==1)
			{
				t1.tx=25*i;
				t1.ty=20*j;
				//DrawGraph(t1.tx,t1.ty,t1.thandle[1],TRUE);
			}
		}
	}
	return 0;
}
int Hit(char g1,int x1,int y1,char g2,int x2 ,int y2)
{

	int g1w,g1h,g2w,g2h;

	GetGraphSize( g1 ,&g1w,&g1h ) ;
	GetGraphSize( g2 ,&g2w,&g2h ) ;

	if( ( ( x1 >= x2 && x1 <= x2 + g2w ) || ( x2 >= x1 && x2 <= x1 + g1w ) ) && ( ( y1 >=y2 && y1 <= y2 + g2h ) || ( y2 >= y1 && y2 <= y1 + g1h ) ) )
	{
		return 1;
	}
DrawFormatString(0,0,GetColor(255,0,255), "%d %d %d %d %d",ataru,x2,y2,x1,y1);
DrawGraph(x2,y2,t1.thandle[1],TRUE);
	return 0;
}

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

Re: 敵との当たり判定

#2

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

プログラムを作るときに何となく作っていませんか?
+mp.scrxや+mp.scryと当たり判定時にマップの座標を足している理由を教えて下さい。
あとデバッガでちゃんと動作を確認していますでしょうか。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

heyman
記事: 99
登録日時: 12年前

Re: 敵との当たり判定

#3

投稿記事 by heyman » 11年前

softya(ソフト屋) さんが書きました:+mp.scrxや+mp.scryと当たり判定時にマップの座標を足している理由を教えて下さい。
これは、この二つを足さないと、敵がスクロールしてくれないからです

動作はしてます

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

Re: 敵との当たり判定

#4

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

スクロールする画面の座標は見かけの問題で、当たり判定は実際にいる座標なのでは?
表示している画面の座標とマップ上の座標は分けて考えたほうが良いですよ。

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

heyman
記事: 99
登録日時: 12年前

Re: 敵との当たり判定

#5

投稿記事 by heyman » 11年前

softya(ソフト屋) さんが書きました:で、デバッガで値は調べられたのですか?
どこの値でしょうか?

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

Re: 敵との当たり判定

#6

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

ソースコード見て気づきましたが、自キャラ(px,py)とか移動していなくて表示上だけ移動していたんですね。
これだとmp.scrxとmp.scryを毎回全ての座標系に足す必要が有るので処理がややこしくなります。
表示上の座標(表示座標)と、地形や敵との当たり判定などの座標(実座標あるいはマップ座標)は別に処理するほうが良いです。

>どこの値でしょうか?
もちろん問題と成るHit関数の中での値です。
x2 + g2w他の値がちゃんと狙った値となっているか確認しなければ、いけませんよね。
この長いif文
if( ( ( x1 >= x2 && x1 <= x2 + g2w ) || ( x2 >= x1 && x2 <= x1 + g1w ) ) && ( ( y1 >=y2 && y1 <= y2 + g2h ) || ( y2 >= y1 && y2 <= y1 + g1h ) ) )
の動作を検証するわけですから。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

heyman
記事: 99
登録日時: 12年前

Re: 敵との当たり判定

#7

投稿記事 by heyman » 11年前

softya(ソフト屋) さんが書きました:もちろん問題と成るHit関数の中での値です。
x2 + g2w他の値がちゃんと狙った値となっているか確認しなければ、いけませんよね。
この長いif文
if( ( ( x1 >= x2 && x1 <= x2 + g2w ) || ( x2 >= x1 && x2 <= x1 + g1w ) ) && ( ( y1 >=y2 && y1 <= y2 + g2h ) || ( y2 >= y1 && y2 <= y1 + g1h ) ) )
の動作を検証するわけですから。
確認してみたところ、画像の縦の値が異常な値になっていました。
縦の値は、GetGraphSize()関数を使って、調べたのですが、
どうしてかおかしくなりました。なぜなのでしょうか?
softya(ソフト屋) さんが書きました:表示上の座標(表示座標)と、地形や敵との当たり判定などの座標(実座標あるいはマップ座標)は別に処理するほうが良いです。
これの意味がよくわかりません。(表示座標、実座標、マップ座標)
何の事でしょうか?

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

Re: 敵との当たり判定

#8

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

> 確認してみたところ、画像の縦の値が異常な値になっていました。

気になるのは、char g1とハンドルの型がintじゃない点ですね。ちゃんとハンドル値受け取れてますか?
LoadGraph直後に GetGraphSizeして異常がないのなら、途中の経路でおかしくなったことになります。
途中でおかしくなるのはプログラムでよく有ることです。
※ と言うような確認手段を考えるのがデバッグするということです。プログラミングではデバッグできないと完成しませんから、デバッグするというのは最重要なのです。

> これの意味がよくわかりません。(表示座標、実座標、マップ座標)
前に描いたやつですが、マップ全体における座標と表示上の座標は別って事です。
scroll.png
scroll.png (5.13 KiB) 閲覧数: 4605 回
これを混ぜてしまうと混乱しますので、完全に分離することをおすすめします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

heyman
記事: 99
登録日時: 12年前

Re: 敵との当たり判定

#9

投稿記事 by heyman » 11年前

softya(ソフト屋) さんが書きました:気になるのは、char g1とハンドルの型がintじゃない点ですね。ちゃんとハンドル値受け取れてますか?
int型に直したら、正常に動作しました。ありがとうございます。

表示座標というのはウィンドウ上の座標、
マップ座標というのはつまりmapcの配列という事でしょうか?

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

Re: 敵との当たり判定

#10

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

マップ全体の場合、ブロックの座標(配列の添字)とドットの座標が考えれると思います。
よく使って分かりやすいのはドットの座標だと思いますので、ドットの座標で全体的には統括して、マップとの当たり判定時だけブロックの座標(配列の添字)を使うべきかと思います。
あちこちに違う座標系が出てくると混乱しますから、できるだけ局所的に押し込めるのと変数名でどちらの座標系か区別できるようにするなど工夫が必要です。
それに構造体に何でも入れるのではなく、ローカル変数を効果的に使うのもバグを減らすコツです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

heyman
記事: 99
登録日時: 12年前

Re: 敵との当たり判定

#11

投稿記事 by heyman » 11年前

ということは、キャラの座標はすべて表示座標ではなくてマップ座標に直して当たり判定は、
マップ座標でするということでいいですか?

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

Re: 敵との当たり判定

#12

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

> 当たり判定は、マップ座標でするということでいいですか?

その方がシンプルになりバグが減ります。
毎回、+mp.scrxや+mp.scryするのはコードが増えるに従って間違いやすいし、非効率的だと思いませんか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

heyman
記事: 99
登録日時: 12年前

Re: 敵との当たり判定

#13

投稿記事 by heyman » 11年前

softya(ソフト屋) さんが書きました:その方がシンプルになりバグが減ります。
毎回、+mp.scrxや+mp.scryするのはコードが増えるに従って間違いやすいし、非効率的だと思いませんか?
なるほどそうですね。さっそく書き直してみます。ありがとうございました。

閉鎖

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