2Dアクションゲームの障害物の当たり判定の不具合

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

2Dアクションゲームの障害物の当たり判定の不具合

#1

投稿記事 by うまお » 7年前

現在2DアクションゲームのBlockの当たり判定を作成しています。
PlayerとなるポリゴンがBlockのポリゴンと当たった際に衝突処理を行い位置修正を行うようにプログラムを書いてみたのですが、画面内の一番左端にPlayerがいて、Blockも一番左端にいる際衝突判定が抜けてしまい、原因がわかりません。なぜこうなるのか原因を教えてください。

衝突判定のコード

コード:

//ブロック判定処理
	for (int i = 0; i < BLOCK_MAX; i++) {
		if (GetPlayerPointer()->Vertex_minX() + GetPlayerPointer()->Vector.x < GetBlockPointer(i)->Vertex_maxX(i) &&
			GetPlayerPointer()->Vertex_minY() + GetPlayerPointer()->Vector.y < GetBlockPointer(i)->Vertex_maxY(i) &&
			GetPlayerPointer()->Vertex_maxX() + GetPlayerPointer()->Vector.x > GetBlockPointer(i)->Vertex_minX(i) &&
			GetPlayerPointer()->Vertex_maxY() + GetPlayerPointer()->Vector.y > GetBlockPointer(i)->Vertex_minY(i)) {
			//ブロック上判定処理
			if (GetBlockPointer(i)->Vertex_minY(i) < GetPlayerPointer()->Vertex_maxY() + GetPlayerPointer()->Vector.y) {
				//落下中でなおかつ元の位置がBlockの位置より高いの場合
				if (0.0f < GetPlayerPointer()->Vector.y &&
					GetPlayerPointer()->Vertex_maxY() <= GetBlockPointer(i)->Vertex_minY(i)) {
					GetPlayerPointer()->Pos.y += GetBlockPointer(i)->Vertex_minY(i) - GetPlayerPointer()->Vertex_maxY();
					GetPlayerPointer()->Vector.y = 0.0f;
					GetPlayerPointer()->bJump = true;
				}
			}
			//ブロック下判定処理
			if (GetPlayerPointer()->Vertex_minY() + GetPlayerPointer()->Vector.y < GetBlockPointer(i)->Vertex_maxY(i)) {
				//上昇中なおかつ元の位置がBlockの位置より低い場合
				if (GetPlayerPointer()->Vector.y < 0.0f &&
					GetBlockPointer(i)->Vertex_maxY(i) <= GetPlayerPointer()->Vertex_minY()) {
					GetPlayerPointer()->Pos.y += GetBlockPointer(i)->Vertex_maxY(i) - GetPlayerPointer()->Vertex_minY();
					GetPlayerPointer()->Vector.y = 0.0f;
					GetPlayerPointer()->bJump = false;
				}
			}
			//上下判定が行われなかった場合
			if (((GetPlayerPointer()->Vertex_minY() < GetBlockPointer(i)->Vertex_minY(i) || GetPlayerPointer()->Vertex_minY() < GetBlockPointer(i)->Vertex_maxY(i)) && GetBlockPointer(i)->Vertex_maxY(i) < GetPlayerPointer()->Vertex_maxY()) ||
				((GetBlockPointer(i)->Vertex_minY(i) < GetPlayerPointer()->Vertex_maxY() || GetBlockPointer(i)->Vertex_maxY(i) < GetPlayerPointer()->Vertex_maxY()) && GetPlayerPointer()->Vertex_minY() < GetBlockPointer(i)->Vertex_minY(i))) {
				//ブロック左判定処理
				if (GetBlockPointer(i)->Vertex_minX(i) < GetPlayerPointer()->Vertex_maxX() + GetPlayerPointer()->Vector.x) {
					//元の位置がBlockの位置より左側の場合
					if (GetPlayerPointer()->Vertex_maxX() <= GetBlockPointer(i)->Vertex_minX(i)) {
						GetPlayerPointer()->Pos.x += GetBlockPointer(i)->Vertex_minX(i) - GetPlayerPointer()->Vertex_maxX();
						GetPlayerPointer()->Vector.x = 0.0f;
					}
				}
				//ブロック右判定処理
				if (GetPlayerPointer()->Vertex_minX() + GetPlayerPointer()->Vector.x < GetBlockPointer(i)->Vertex_maxX(i)) {
					//元の位置がBlockの位置より右側の場合
					if (GetBlockPointer(i)->Vertex_maxX(i) <= GetPlayerPointer()->Vertex_minX()) {
						GetPlayerPointer()->Pos.x += GetBlockPointer(i)->Vertex_maxX(i) - GetPlayerPointer()->Vertex_minX();
						GetPlayerPointer()->Vector.x = 0.0f;
					}
				}
			}
		}
	}

	//画面外上判定処理
	if (GetPlayerPointer()->Vertex_minY() + GetPlayerPointer()->Vector.y < 0.0f) {
		GetPlayerPointer()->Pos.y += 0.0f - GetPlayerPointer()->Vertex_minY();
		GetPlayerPointer()->Vector.y = 0.0f;
		GetPlayerPointer()->bJump = false;
	}
	//画面外下判定処理
	if (SCREEN_HEIGHT < GetPlayerPointer()->Vertex_maxY() + GetPlayerPointer()->Vector.y) {
		GetPlayerPointer()->Pos.y += SCREEN_HEIGHT - GetPlayerPointer()->Vertex_maxY();
		GetPlayerPointer()->Vector.y = 0.0f;
		GetPlayerPointer()->bJump = true;
	}
	//画面外左判定処理
	if (GetPlayerPointer()->Vertex_minX() + GetPlayerPointer()->Vector.x < 0.0f) {
		GetPlayerPointer()->Pos.x += 0.0f - GetPlayerPointer()->Vertex_minX();
		GetPlayerPointer()->Vector.x = 0.0f;
	}
	//画面外右判定処理
	if (SCREEN_WIDTH < GetPlayerPointer()->Vertex_maxX() + GetPlayerPointer()->Vector.x) {
		GetPlayerPointer()->Pos.x += SCREEN_WIDTH - GetPlayerPointer()->Vertex_maxX();
		GetPlayerPointer()->Vector.x = 0.0f;
	}
	

	GetPlayerPointer()->Pos += GetPlayerPointer()->Vector;																		//現在地にベクトルを足して移動値を確定させる

	//位置更新処理
	GetPlayerPointer()->SetPos(GetPlayerPointer()->Pos.x, GetPlayerPointer()->Pos.y, GetPlayerPointer()->Pos.z, GetPlayerPointer()->Zoom.x, GetPlayerPointer()->Zoom.y, GetPlayerPointer()->Zoom.z, GetPlayerPointer()->Angle);
実際の不具合動画


環境  
 [2.1] OS:Windows10
 [2.2] コンパイラ名: Visual C++ 2017

初心者ゲームプログラマー

Re: 2Dアクションゲームの障害物の当たり判定の不具合

#2

投稿記事 by 初心者ゲームプログラマー » 7年前

ソースを読んでいると少しわからないとこがあるのですが、

コード:

if (GetPlayerPointer()->Vertex_minX() + GetPlayerPointer()->Vector.x < GetBlockPointer(i)->Vertex_maxX(i) &&
GetBlockPointer()でi番目のブロックをとってきているのはわかるのですが、Vertex_maxX()でiを指定しているのは何故でしょうか?
おそらく

コード:

Block* g_blockList[BLOCK_MAX];

Block* GetBlockPointer(int i)
{
    return g_blockList[i];
}
こんな感じのコードになってるかと思うのですが、Vertex_maxX(i)だけがわからないです。
Vertex_maxX(i)の中身を教えてもらえると原因がわかるかもです。

それとGetPlayerPointer()やGetPlayerPointer()などを多用するより、一度変数に格納してそちらを使うようにしたほうが可読性があがるのでおすすめします。

うまお

Re: 2Dアクションゲームの障害物の当たり判定の不具合

#3

投稿記事 by うまお » 7年前

初心者ゲームプログラマー さんが書きました:
7年前
ソースを読んでいると少しわからないとこがあるのですが、

コード:

if (GetPlayerPointer()->Vertex_minX() + GetPlayerPointer()->Vector.x < GetBlockPointer(i)->Vertex_maxX(i) &&
GetBlockPointer()でi番目のブロックをとってきているのはわかるのですが、Vertex_maxX()でiを指定しているのは何故でしょうか?
おそらく

コード:

Block* g_blockList[BLOCK_MAX];

Block* GetBlockPointer(int i)
{
    return g_blockList[i];
}
こんな感じのコードになってるかと思うのですが、Vertex_maxX(i)だけがわからないです。
Vertex_maxX(i)の中身を教えてもらえると原因がわかるかもです。

それとGetPlayerPointer()やGetPlayerPointer()などを多用するより、一度変数に格納してそちらを使うようにしたほうが可読性があがるのでおすすめします。
► スポイラーを表示

Vertex_maxX()等は関数で、以下のように取得しようとしているのでiを入れています
(以下のものはminX,YとmaxYもほぼ同じ)

コード:

float t_Block::Vertex_maxX(int num)																
{
	float max = NULL;																			

	//一番高いX値を求める
	for (int i = 0; i < NUM_VERTEX; i++) {
		if (max == NULL) max = obj_Block[num].pFormat[i].pos.x;
		else if (max < obj_Block[num].pFormat[i].pos.x) max = obj_Block[num].pFormat[i].pos.x;
	}

	return max;
}
また、GetPlayerPointer()とGetBlockPointer()はポインタ取得関数なのですが、こちらを変数にしてもあまり意味がないと思いやっていません。

うまお

Re: 2Dアクションゲームの障害物の当たり判定の不具合

#4

投稿記事 by うまお » 7年前

コード:

if (GetPlayerPointer()->Vertex_minX() + GetPlayerPointer()->Vector.x < GetBlockPointer(i)->Vertex_maxX(i) &&
			GetPlayerPointer()->Vertex_minY() + GetPlayerPointer()->Vector.y < GetBlockPointer(i)->Vertex_maxY(i) &&
			GetPlayerPointer()->Vertex_maxX() + GetPlayerPointer()->Vector.x > GetBlockPointer(i)->Vertex_minX(i) &&
			GetPlayerPointer()->Vertex_maxY() + GetPlayerPointer()->Vector.y > GetBlockPointer(i)->Vertex_minY(i)) {
少しだけ分かったことがあり、上のコード部分が一番左側の場合のみ通ってないことが分かりました。
ここが原因?なのかもしれませんが対処法が分かりません…

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

Re: 2Dアクションゲームの障害物の当たり判定の不具合

#5

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

うまお さんが書きました:
7年前

コード:

float t_Block::Vertex_maxX(int num)																
{
	float max = NULL;																			

	//一番高いX値を求める
	for (int i = 0; i < NUM_VERTEX; i++) {
		if (max == NULL) max = obj_Block[num].pFormat[i].pos.x;
		else if (max < obj_Block[num].pFormat[i].pos.x) max = obj_Block[num].pFormat[i].pos.x;
	}

	return max;
}
NULLは通常空ポインタを表すものであり、数値として使うものではありません。
多くの場合はNULLを数値として使うと0に変換されると思います。
その結果、左端(=x座標0)の処理に不都合が生じている可能性が考えられます。

コード:

float t_Block::Vertex_maxX(int num)																
{
	float max = obj_Block[num].pFormat[0].pos.x;																			

	//一番高いX値を求める
	for (int i = 1; i < NUM_VERTEX; i++) {
		if (max < obj_Block[num].pFormat[i].pos.x) max = obj_Block[num].pFormat[i].pos.x;
	}

	return max;
}
のようにするとどうなりますか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

うまお

Re: 2Dアクションゲームの障害物の当たり判定の不具合

#6

投稿記事 by うまお » 7年前

みけCAT さんが書きました:
7年前
うまお さんが書きました:
7年前

コード:

float t_Block::Vertex_maxX(int num)																
{
	float max = NULL;																			

	//一番高いX値を求める
	for (int i = 0; i < NUM_VERTEX; i++) {
		if (max == NULL) max = obj_Block[num].pFormat[i].pos.x;
		else if (max < obj_Block[num].pFormat[i].pos.x) max = obj_Block[num].pFormat[i].pos.x;
	}

	return max;
}
NULLは通常空ポインタを表すものであり、数値として使うものではありません。
多くの場合はNULLを数値として使うと0に変換されると思います。
その結果、左端(=x座標0)の処理に不都合が生じている可能性が考えられます。

コード:

float t_Block::Vertex_maxX(int num)																
{
	float max = obj_Block[num].pFormat[0].pos.x;																			

	//一番高いX値を求める
	for (int i = 1; i < NUM_VERTEX; i++) {
		if (max < obj_Block[num].pFormat[i].pos.x) max = obj_Block[num].pFormat[i].pos.x;
	}

	return max;
}
のようにするとどうなりますか?
変更してみたところきちんと作動して無事すり抜けがなくなりました!
ありがとうございます!

返信

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