主頁 | 自己紹介 | 日記 | 農業 | 台所 | 電算機 | | 本棚 | | Git

Xlibで遊んでみる5

前回: Xlibで遊んでみる4

言語: C言語
ソースコード: git

円の衝突判定とその処理

前回四角形で行っていた衝突判定とその処理を今回は円でした。衝突の判定は二つの円の中心間の距離と、各円の半径の和を比較するだけなので簡単である:

struct circle {
	float ppx, ppy;  // previous position (center)
	float px, py;    // current position (center)
	float vx, vy;    // velocity
	int r;           // radius
	int m;           // mass
};

int
circle_test_collision(struct circle *c1, struct circle *c2)
{
	return (c1->px - c2->px) * (c1->px - c2->px) +
	       (c1->py - c2->py) * (c1->py - c2->py) <
		   (c1->r + c2->r) * (c1->r + c2->r);
}

衝突後は前回と同じく弾性衝突として処理した。四角形とは違い、衝突方向の場合分けが不要なので楽である。


void
circle_handle_collision_mm(struct circle *c1, struct circle *c2)
{
	if (!circle_test_collision(c1, c2))
		return;

	float col_px = c2->px - c1->px;
	float col_py = c2->py - c1->py;
	float col_pr = sqrtf(col_px * col_px + col_py * col_py);
	col_px /= col_pr;
	col_py /= col_pr;

	c1->px = c1->px - col_px / 2;
	c1->py = c1->py - col_py / 2;
	c2->px = c2->px + col_px / 2;
	c2->py = c2->py + col_py / 2;
}

void
circle_handle_collision_elastic(struct circle *c1, struct circle *c2)
{
	if(!circle_test_collision(c1, c2))
		return;

	float col_px = c2->px - c1->px;
	float col_py = c2->py - c1->py;
	float col_pr = sqrtf(col_px * col_px + col_py * col_py);
	col_px /= col_pr;
	col_py /= col_pr;
	float nor_px = col_py;
	float nor_py = -col_px;

	float m1 = c1->m;
	float m2 = c2->m;

	float col_1v = c1->vx * col_px + c1->vy * col_py;
	float col_2v = c2->vx * col_px + c2->vy * col_py;

	float col_1vxn = (2*m2/(m1+m2)*col_2v + (m1-m2)/(m1+m2)*col_1v) * col_px;
	float col_1vyn = (2*m2/(m1+m2)*col_2v + (m1-m2)/(m1+m2)*col_1v) * col_py;
	float col_2vxn = (2*m1/(m1+m2)*col_1v + (m2-m1)/(m1+m2)*col_2v) * col_px;
	float col_2vyn = (2*m1/(m1+m2)*col_1v + (m2-m1)/(m1+m2)*col_2v) * col_py;

	float nor_1vx = nor_px * (c1->vx * nor_px + c1->vy * nor_py);
	float nor_1vy = nor_py * (c1->vx * nor_px + c1->vy * nor_py);
	float nor_2vx = nor_px * (c2->vx * nor_px + c2->vy * nor_py);
	float nor_2vy = nor_py * (c2->vx * nor_px + c2->vy * nor_py);

	c1->vx = col_1vxn + nor_1vx;
	c1->vy = col_1vyn + nor_1vy;
	c2->vx = col_2vxn + nor_2vx;
	c2->vy = col_2vyn + nor_2vy;

	circle_handle_collision_mm(c1, c2);
}

完成品

git

参考

次の記事: Xlibで遊んでみる6