ボンバーマン風ゲームの当たり判定について

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

ボンバーマン風ゲームの当たり判定について

#1

投稿記事 by ぐれーと » 14年前

僕はDXライブラリでボンバーマン風のゲームを作っています。
いまのところ「24. 行けない所を作る。~2D~」のように、 配列でマップを作ってブロックとの当たり判定をしています。
そして、ブロックとの当たり判定は大体作り終わったのですが、致命的な問題を抱えています。
キャラクターのスピードを設定しているのですが、そのスピードが1や2なら大丈夫なのですが、
3や5になるとブロックとブロックの間にキャラクターが入れなくなる所が発生してしまいました。
どうやったらちゃんとブロックの間に入れるでしょうか?
(キャラクターがスムーズにブロックの間に入れるように、壁にあたると滑るように動くプログラムも組んでいます)

コード:

 
#include "DxLib.h"
 
int Key[256];
 
int GetHitKeyStateAll_2(int GetHitKeyStateAll_InputKey[]){
	char GetHitKeyStateAll_Key[256];
	GetHitKeyStateAll( GetHitKeyStateAll_Key );
	for(int i=0;i<256;i++){
		if(GetHitKeyStateAll_Key[i]==1) GetHitKeyStateAll_InputKey[i]++;
		else                            GetHitKeyStateAll_InputKey[i]=0;
	}
	return 0;
}

typedef struct{
	int x , y , gazou , muki , speed;
}ch_t;


int map[15][20] = { // 0が床 1がブロック
	{9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9},
	{0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,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,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,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,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,0,1,0,0},
	{0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0},
	{0,1,0,1,0,1,1,1,0,0,0,1,0,1,0,1,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,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,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,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0},
	{0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
};

int atarihantei(int *x , int *y , int muki , int speed){//当たり判定
	
	int x1 , x2 , y1 , y2;
	
	x1 = *x/32;    //キャラの左端の座標のマップ上の位置
	y1 = *y/32;    //キャラの上端の座標のマップ上の位置
	x2 =(*x+31)/32;//キャラの右端の座標のマップ上の位置 
	y2 =(*y+31)/32;//キャラの下端の座標のマップ上の位置
	
	if(map[y1][x1]==1 && muki == 4){//左判定(下移動)
		*x = x2*32;
		y2 =(*y+31-9)/32;
		if(map[y2][x1] ==0)
			*y +=speed; 
	}
	if(map[y2][x1]==1 && muki == 4){//左判定(上移動)
		*x = x2*32;
		y1 =(*y+9)/32;
		if(map[y1][x1] ==0)
			*y -=speed;
	}
	
	if(map[y1][x2]==1 && muki == 3){//右判定(下移動)
		*x = x1*32;
		y2 =(*y+31-9)/32;
		if(map[y2][x2]==0)
			*y +=speed;
	}
	if(map[y2][x2]==1 && muki == 3){//右判定(上移動)
		*x = x1*32;
		y1 =(*y+9)/32;
		if(map[y1][x2]==0)
			*y -=speed;
	}
	
	if(map[y1][x1]==1 && muki == 1){//上判定(右移動)
		*y = y2*32;
		x2 =(*x+31-9)/32;
		if(map[y1][x2]==0)
			*x +=speed;
	}
	if(map[y1][x2]==1 && muki == 1){//上判定(左移動)
		*y = y2*32;
		x1 =(*x+9)/32;
		if(map[y1][x1]==0)
			*x -=speed;
	}
	
	if(map[y2][x1]==1 && muki == 2){//下判定(右移動)
		*y = y1*32;
		x2 =(*x+31-9)/32;
		if(map[y2][x2]==0)
			*x +=speed;
	}
	if(map[y2][x2]==1 && muki == 2){//下判定(左移動)
		*y = y1*32;
		x1 =(*x+9)/32;
		if(map[y2][x1]==0)
			*x -=speed;
	}
	
	DrawFormatString(300, 0,GetColor(255,255,255),"x1:%d y1:%d",x1,y1);
	DrawFormatString(300,15,GetColor(255,255,255),"x2:%d y2:%d",x2,y2);
	                                          
	return 0;
}


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
	ChangeWindowMode(TRUE);//ウィンドウモード
	if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化
	
	ch_t ch;
	
	
	ch.x    = 320;
	ch.y    = 240;
	ch.muki = 0;
	ch.speed= 2;
	
	ch.gazou = LoadGraph("char1.png");
	
	int i , j , k = 0, 
	    siro , haiiro , b1gazou , y1gazou ;
	
	siro   = GetColor(255,255,255);
	haiiro = GetColor(130,130,130);
	b1gazou= LoadGraph("block1.png");
	y1gazou= LoadGraph("yuka1.png");
	
	
	while(ProcessMessage()==0 && ClearDrawScreen()==0 && GetHitKeyStateAll_2(Key)==0 && Key[KEY_INPUT_ESCAPE]==0){
		//↑メッセージ処理          ↑画面をクリア           ↑入力状態を保存       ↑ESCが押されていない
		
		if(Key[KEY_INPUT_UP] >= 1){//上が押されたら
			ch.y -= ch.speed;
			ch.muki = 1;
		}
		if(Key[KEY_INPUT_DOWN] >= 1 && Key[KEY_INPUT_UP]==0){//上が押されず下が押されたら
			ch.y += ch.speed;
			ch.muki = 2;
		}
		if(Key[KEY_INPUT_RIGHT] >= 1&& Key[KEY_INPUT_UP]==0 
		&& Key[KEY_INPUT_DOWN]  == 0){//上下が押されず右が押されたら
			ch.x += ch.speed;
			ch.muki = 3;
		}
		if(Key[KEY_INPUT_LEFT] >= 1 && Key[KEY_INPUT_UP]==0 
		&& Key[KEY_INPUT_DOWN] == 0 && Key[KEY_INPUT_RIGHT]==0){//上下右が押されず左が押されたら
			ch.x -= ch.speed;
			ch.muki = 4;
		}
		
		atarihantei(&ch.x , &ch.y , ch.muki , ch.speed );
		
		
		for(i=0;i<20;i++)
			for(j=0;j<15;j++){
				if(map[j][i] == 1)
					DrawGraph(i*32,j*32,b1gazou,FALSE);
				if(map[j][i] == 0)
					DrawGraph(i*32,j*32,y1gazou,FALSE);
			}
		
		DrawGraph(ch.x , ch.y , ch.gazou , TRUE);
		
		DrawFormatString(0,0,siro,"x座標:%d y座標:%d",ch.x , ch.y );
		DrawFormatString(180,0,siro,"向き:%d",ch.muki);
		DrawFormatString(0,40,siro,"%d",k);
		ScreenFlip();
	}
	DxLib_End();
	return 0;
}

アバター
a5ua
記事: 199
登録日時: 14年前

Re: ボンバーマン風ゲームの当たり判定について

#2

投稿記事 by a5ua » 14年前

滑る処理のときは、speedを1にするというのはどうでしょうか?

ぐれーと

Re: ボンバーマン風ゲームの当たり判定について

#3

投稿記事 by ぐれーと » 14年前

それもやってみたのですが、いきなり遅くなって変な動きになってしまうんですよね。
本当のボンバーマンも遅くなりませんし。

アバター
kimuchi
記事: 163
登録日時: 14年前
住所: 東京

Re: ボンバーマン風ゲームの当たり判定について

#4

投稿記事 by kimuchi » 14年前

言ってみるだけですが、
3や5が32の約数ではないから。というのはどうでしょう?

追伸:
此方で動かしたところspeedが4、8、16で正常に動作しました。
滑る動作の所をspeedの値で加減しているようなので、3や5では公倍数以外の場所で
ズレが生じて行ったり来たりの状態になるようです。

関係ないですが、Keyの判定分岐はelseを使えばコンパクトになると思います。

アバター
a5ua
記事: 199
登録日時: 14年前

Re: ボンバーマン風ゲームの当たり判定について

#5

投稿記事 by a5ua » 14年前

滑る処理の補正座標を、次のブロックの位置までに制限すればいいのではないでしょうか?
合ってるかわかりませんが、以下のような感じです。

コード:

*y = min(*y + speed, y2 * 32); // 最大でも隣のブロックまでしか移動しない

ぐれーと

Re: ボンバーマン風ゲームの当たり判定について

#6

投稿記事 by ぐれーと » 14年前

minってどういう意味でしたっけ?

匿名希望の774さん

Re: ボンバーマン風ゲームの当たり判定について

#7

投稿記事 by 匿名希望の774さん » 14年前

ぐれーと さんが書きました:minってどういう意味でしたっけ?
それぐらい自分で調べなさい

ぐれーと

Re: ボンバーマン風ゲームの当たり判定について

#8

投稿記事 by ぐれーと » 14年前

minの意味自分で調べました。何でもかんでも質問してすいませんm(_ _)m

教えてもらった方法で解決しました。a5uaさんありがとうございます。
kimuchi さんもご指摘ありがとうございます。とんだバカなプログラム組んでましたね。
今後とも宜しくお願いします。

閉鎖

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