円と線分の当たり判定

アバター
もるも
記事: 54
登録日時: 9年前
連絡を取る:

円と線分の当たり判定

投稿記事 by もるも » 9年前

ベクトルを再勉強して、
サンプルやっとできた(--;)
あとはゲームに組み込むのみ。

参考ページ
http://marupeke296.com/COL_2D_No5_PolygonToCircle.html
http://www.sousakuba.com/Programming/gs ... tance.html

CODE:

//main.cpp
#include "DxLib.h"
#include 
char key[256];//キー入力用
struct vector2D {
	float X;
	float Y;

};
vector2D A, B, P;//座標用
vector2D AB, AP, BP;//ベクトル用


float R;		//半径
float GetVector2D_Dot(vector2D A, vector2D B);
float GetVector2D_Cross(vector2D A, vector2D B);
float GetVector2D_Length(vector2D A, vector2D B);
bool LineCircleCollision(float r, vector2D A, vector2D B, vector2D P);

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK); //ウィンドウモード変更と初期化と裏画面設定
	//初期化
	R = 50;
	P.X = 200;
	P.Y = 200;
	// while(裏画面を表画面に反映, メッセージ処理, 画面クリア)
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
		A.X = 100;
		A.Y = 300;
		B.X = 400;
		B.Y = 300;

		GetHitKeyStateAll(key);
		if (key[KEY_INPUT_RIGHT] != 0) { P.X++; }
		if (key[KEY_INPUT_LEFT] != 0) { P.X--; }
		if (key[KEY_INPUT_UP] != 0) { P.Y--; }
		if (key[KEY_INPUT_DOWN] != 0) { P.Y++; }
     //円を描画
		DrawCircle(P.X, P.Y, R, GetColor(255, 255, 0));
		//線を描画
		DrawLine(A.X, A.Y, B.X, B.Y, GetColor(255, 0, 0));
		
		//当たり判定
		if (LineCircleCollision(R, A, B, P));

	}
	DxLib_End(); // DXライブラリ終了処理
	return 0;
}
// キーの入力状態を更新する
int gpUpdateKey() {
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i < 256; i++) {
		if (tmpKey[i] != 0) { // i番のキーコードに対応するキーが押されていたら
			key[i]++;     // 加算
		}
		else {              // 押されていなければ
			key[i] = 0;   // 0にする
		}
	}
	return 0;
}
//内積
float GetVector2D_Dot(vector2D A, vector2D B) {
	float Dot = A.X*B.X + A.Y*B.Y;
	return Dot;
}
//外積
float GetVector2D_Cross(vector2D A, vector2D B) {
	float Cross = A.X*B.Y - A.Y*B.X;
	return Cross;
}
//大きさ
float GetVector2D_Length(vector2D A, vector2D B) {
	float X = fabsf(B.X - A.X);
	float Y = fabsf(B.Y - A.Y);
	return pow(X * X + Y * Y, 0.5);

}

bool LineCircleCollision(float r, vector2D A, vector2D B, vector2D P) {
	//座標からベクトルを得る
	AB.X = B.X - A.X;
	AB.Y = B.Y - A.Y;
	AP.X = P.X - A.X;
	AP.Y = P.Y - A.Y;
	BP.X = P.X - B.X;
	BP.Y = P.Y - B.Y;

	//円と線分の距離を求める
	//ベクトルAB、APの外積の絶対値が平行四辺形Dの面積になる
	double D = abs(GetVector2D_Cross(AB, AP));
	double L = GetVector2D_Length(A, B);	//AB間の距離
	double H = D / L;

	DrawFormatString(0, 0, GetColor(255, 255, 255), "H%d", (int)H);
	DrawFormatString(0, 20, GetColor(255, 255, 255), "D%d", (int)D);
	DrawFormatString(0, 40, GetColor(255, 255, 255), "L%d", (int)L);
	float dot1 = GetVector2D_Dot(AP, AB);
	float dot2 = GetVector2D_Dot(BP, AB);
	DrawFormatString(0, 60, GetColor(255, 255, 255), "dot%d", (int)dot1);
	DrawFormatString(0, 80, GetColor(255, 255, 255), "dot%d", (int)dot2);

	//線と円の中心の距離が半径より小さい
	if (H <= R) {
		if (dot1*dot2 <= 0) {//角度が90度以下なので円の中心が線分の両端の内側にある
			DrawString(0, 460, "HIT!!!", GetColor(0, 255, 255));
			return true;

		}
		//鈍角になるスペシャルケースの場合(円の中心が線分の両端の外側にある)
		float AP = GetVector2D_Length(A, P);
		float BP = GetVector2D_Length(B, P);
		DrawFormatString(0, 100, GetColor(255, 255, 255), "AP%d", (int)AP);
		DrawFormatString(0, 120, GetColor(255, 255, 255), "BP%d", (int)BP);
		if (AP < R || BP < R) {
			DrawString(0, 460, "HIT!!!", GetColor(255, 0, 255));
			return true;
		}

	}
}
スクリーンショット (44).png
スクリーンショット (44).png (5.61 KiB) 閲覧数: 100 回

コメントはまだありません。