衝突判定なんて円と円・長方形と長方形の2種を駆使するだけでも何とかなりそうだしコードも簡単だから低負荷でイイや
と軽く思っていましたが、改めてちゃんとしたゲームを作る為の基礎知識を養いたく勉強してみる事にしました。
#include
#include
//円と長方形の接触判定
//(cx = 円の中心x座標, cy = 円の中心y座標, cr = 円の半径, rx = 長方形の中心x座標, ry = 長方形の中心y座標, rh = 長方形の高さ, rw = 長方形の幅, ra = 長方形の回転描画角度[ラジアン])
//返り値:TRUE → 接触している
//返り値:FALSE → 接触していない
BOOL Collision_Circle_With_Rectangle(double cx, double cy, double cr, double rx, double ry, double rh, double rw, double ra)
{
double dx = rx - cx; //cxのrxからの相対値
double dy = ry - cy; //cyのryからの相対値
double dr = sqrt(dx * dx + dy * dy); //(cx, cy)(rx, ry)の距離
double da = atan2(dy, dx); //(rx, ry)から見たdrの角度
//(rx, ry)を基点に(dx, dy)を-raラジアン回転する
if (ra != 0)
{
dx = dr * cos(da - ra); //回転後のdx
dy = dr * sin(da - ra); //回転後のdy
}
//接触判定
rh /= 2.0; //rhを半分に
rw /= 2.0; //rwを半分に
if (dx < 0) dx = -dx; //dxの符号を取る
if (dy < 0) dy = -dy; //dyの符号を取る
if (dx <= cr + rw && dy <= rh) return TRUE; //x軸方向の接触判定
if (dx <= rw && dy <= cr + rh) return TRUE; //y軸方向の接触判定
dx = dx - rw; //dxを角からの相対値に変換
dy = dy - rh; //dyを角からの相対値に変換
if (dx * dx + dy * dy <= cr * cr) return TRUE; //角の接触判定
return FALSE; //非接触フラグ返還
}
自分が作るであろうチンケなゲームでは引数その物や引数同士を足したり引いたり掛けたりした値がオーバーフローする
事はない気がする(画面を遥かにハミ出すBIGな画像や天文学的な座標は使わない)ので、素直に計算するだけのシンプル
な設計にしました。
関数は序でに長方形がナナメっている場合でも判定出来る様にしました。
確認用テストプログラムでは一様に正しく判定できているものの、計算式が本当にこれで合っているのかは不明です。
math.h(三角関数と平方根)は重いから使いたくないのですが、今の自分には別の算出方法を考えたり近似値を求める事
すらできないので、渋々取り入れました。
あと、絶対値の求め方は、(0 - a)(a * -1)(-1 * a)・・・等色々試した結果、アセンブリ出力を見る限りでは3通りに纏められた
ので、一番良さげ?な符号を取るだけの方法を採用しました。
浮動小数点数型特有?の0だけで構成の負数-0.00…0は実質0なので、実数0に関しては符号があろうがなかろうが触れ
ずに無視しています。
微量に重いfabsの利用を却下しましたが、正しいのかは分かりません。(汗)
その他、条件式を簡略化した時の必要条件として座標と角度以外を示す引数は全て正の実数でなければいけなかったの
ですが、負数の半径・幅・高さなんて(次元が捻れそうでw)普通は使わないし、敢えてコメントアウトしておりません。
接触後の跳ね返りを計算する機能の追加は、更に何やかんや考慮しなければいけない様だし、今は気力が追いつけないからw
また後日行けそうな時にチャレンジしてみようかな?
相も変わらず、【About】なコーディングをやっています。