プログラマーの卵の日記

備忘録になってます!小難しそうなことから超簡単なことまでやってます!!

【C++】【DxLib】四角形と円のあたり判定やってみたい【2D】

描画に関してDxLibを使ってるだけで処理関係はDxLib関係ないです。

構成


No.1 四角形同士
No.2 丸同士
No.3 四角形と丸







        No.1 四角形同士


 四角形同士の当たり判定は、双方の四辺が当たっているかどうかを調べるだけで行けます。
特に説明不要!


struct BOX
{
	float left, top, right, bottom;
};


bool CheckHit(const BOX& t_direA, const BOX& t_direB)
{
	if ((t_direA.right > t_direB.left) &&
		(t_direA.left < t_direB.right))
	{
		if ((t_direA.bottom > t_direB.top) &&
			(t_direA.top < t_direB.bottom))
		{
			return true;
		}
	}

	return false;
}


void MoveRect(BOX& t_dire)
{
	if (CheckHitKey(KEY_INPUT_LEFT))
	{
		t_dire.left -= 5.0f;
		t_dire.right -= 5.0f;
	}
	if (CheckHitKey(KEY_INPUT_RIGHT)) 
	{
		t_dire.left += 5.0f;
		t_dire.right += 5.0f;
	}
	if (CheckHitKey(KEY_INPUT_UP))
	{
		t_dire.top -= 5.0f;
		t_dire.bottom -= 5.0f;
	}
	if (CheckHitKey(KEY_INPUT_DOWN))
	{
		t_dire.top += 5.0f;
		t_dire.bottom += 5.0f;
	}
}


main関数内のループ含む一部


	BOX direA, direB;

	direA.left	 = 100.0f;
	direA.top	 = 100.0f;
	direA.right	 = 250.0f;
	direA.bottom = 200.0f;

	direB.left	 = 300.0f;
	direB.top	 = 150.0f;
	direB.right	 = 400.0f;
	direB.bottom = 300.0f;

	// メインループ
	while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen() && !CheckHitKey(KEY_INPUT_ESCAPE))
	{
		if(CheckHit(direA, direB))
		{
			DrawBox(direA.left, direA.top, direA.right, direA.bottom, GetColor(125, 125, 125), true);
			DrawBox(direB.left, direB.top, direB.right, direB.bottom, GetColor(125, 125, 125), true);
		}
		else
		{
			DrawBox(direA.left, direA.top, direA.right, direA.bottom, GetColor(255, 255, 255), true);
			DrawBox(direB.left, direB.top, direB.right, direB.bottom, GetColor(125, 125, 125), true);
		}
		MoveRect(direA);
	}

f:id:yutateno:20191127003100g:plain







        No.2 丸同士


 これは双方の半径の加算した値に対して双方の中心からの距離が大きいか小さいかで判断させます。
それをやるためにピタゴラスの定理を利用します。
特に説明不要!


struct CIRCLE
{
	float x, y, r;
};


bool CheckHit(const CIRCLE& t_circleA, const CIRCLE& t_circleB)
{
	float dx = t_circleA.x - t_circleB.x;
	float dy = t_circleA.y - t_circleB.y;
	float dr = dx * dx + dy * dy;

	float ar = t_circleA.r + t_circleB.r;
	float dl = ar * ar;
	if (dr < dl)
	{
		return true;
	}

	return false;
}


void MoveRect(CIRCLE& t_circle)
{
	if (CheckHitKey(KEY_INPUT_LEFT))
	{
		t_circle.x -= 5.0f;
	}
	if (CheckHitKey(KEY_INPUT_RIGHT)) 
	{
		t_circle.x += 5.0f;
	}
	if (CheckHitKey(KEY_INPUT_UP))
	{
		t_circle.y -= 5.0f;
	}
	if (CheckHitKey(KEY_INPUT_DOWN))
	{
		t_circle.y += 5.0f;
	}
}


main関数内のループ含む一部


	CIRCLE circleA, circleB;

	circleA.x = 100.0f;
	circleA.y = 100.0f;
	circleA.r = 80.0f;

	circleB.x = 300.0f;
	circleB.y = 270.0f;
	circleB.r = 120.0f;

	// メインループ
	while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen() && !CheckHitKey(KEY_INPUT_ESCAPE))
	{
		if(CheckHit(circleA, circleB))
		{
			DrawCircle(circleA.x, circleA.y, circleA.r, GetColor(125, 125, 125));
			DrawCircle(circleB.x, circleB.y, circleB.r, GetColor(125, 125, 125));
		}
		else
		{
			DrawCircle(circleA.x, circleA.y, circleA.r, GetColor(255, 255, 255));
			DrawCircle(circleB.x, circleB.y, circleB.r, GetColor(125, 125, 125));
		}
		MoveRect(circleA);
	}

 

f:id:yutateno:20191127002633g:plain






        No.3 四角形と丸


 これは、四辺に対して円の半径分を足したとき、四角形に円が含まれているようなところにいるかをまず調べます。そのあとに四辺のうち、円の中心から一番近い頂点が円に含まれているかをピタゴラスの定理から調べるようにしています。
特に説明不要!


struct BOX
{
	float fLeft, fTop, fRight, fBottom;
};

struct CIRCLE
{
	float x, y, r;
};



float DistanceSqrf(const float t_x1, const float t_y1, const float t_x2, const float t_y2)
{
	float dx = t_x2 - t_x1;
	float dy = t_y2 - t_y1;

	return (dx * dx) + (dy * dy);
}


bool CheckHit(const BOX& t_box, const CIRCLE& t_circle)
{
	bool nResult = false;

	// 四角形の四辺に対して円の半径分だけ足したとき円が重なっていたら
	if ((t_circle.x > t_box.fLeft - t_circle.r) &&
		(t_circle.x < t_box.fRight + t_circle.r) &&
		(t_circle.y > t_box.fTop - t_circle.r) &&
		(t_circle.y < t_box.fBottom + t_circle.r))
	{
		nResult = true;
		float fl = t_circle.r * t_circle.r;


		// 左
		if (t_circle.x < t_box.fLeft)
		{
			// 左上
			if ((t_circle.y < t_box.fTop))
			{
				if ((DistanceSqrf(t_box.fLeft, t_box.fTop, t_circle.x, t_circle.y) >= fl))
				{
					nResult = false;
				}
			}
			else
			{
				// 左下
				if ((t_circle.y > t_box.fBottom))
				{
					if ((DistanceSqrf(t_box.fLeft, t_box.fBottom, t_circle.x, t_circle.y) >= fl))
					{
						nResult = false;
					}
				}
			}
		}
		else
		{
			// 右
			if (t_circle.x > t_box.fRight)
			{
				// 右上
				if ((t_circle.y < t_box.fTop))
				{
					if ((DistanceSqrf(t_box.fRight, t_box.fTop, t_circle.x, t_circle.y) >= fl))
					{
						nResult = false;
					}
				}
				else
				{
					// 右下
					if ((t_circle.y > t_box.fBottom))
					{
						if ((DistanceSqrf(t_box.fRight, t_box.fBottom, t_circle.x, t_circle.y) >= fl))
						{
							nResult = false;
						}
					}
				}
			}
		}
	}

	return nResult;
}


void MoveCircle(CIRCLE& t_circle)
{
	if (CheckHitKey(KEY_INPUT_LEFT))
	{
		t_circle.x -= 5.0f;
	}
	if (CheckHitKey(KEY_INPUT_RIGHT))
	{
		t_circle.x += 5.0f;
	}
	if (CheckHitKey(KEY_INPUT_UP))
	{
		t_circle.y -= 5.0f;
	}
	if (CheckHitKey(KEY_INPUT_DOWN))
	{
		t_circle.y += 5.0f;
	}
}


main関数内のループ含む一部


	BOX				box;
	CIRCLE			circle;

	circle.x = 100.0f;
	circle.y = 100.0f;
	circle.r = 80.0f;

	box.fLeft = 200.0f;
	box.fTop = 150.0f;
	box.fRight = 500.0f;
	box.fBottom = 350.0f;

	// メインループ
	while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen() && !CheckHitKey(KEY_INPUT_ESCAPE))
	{
		if(CheckHit(box, circle))
		{
			DrawCircle(circle.x, circle.y, circle.r, GetColor(125, 125, 125));
			DrawBox(box.fLeft, box.fTop, box.fRight, box.fBottom, GetColor(125, 125, 125), true);
		}
		else
		{
			DrawCircle(circle.x, circle.y, circle.r, GetColor(255, 255, 255));
			DrawBox(box.fLeft, box.fTop, box.fRight, box.fBottom, GetColor(125, 125, 125), true);
		}
		MoveCircle(circle);
	}

 

f:id:yutateno:20191127002312g:plain