425 lines
15 KiB
C++
425 lines
15 KiB
C++
#include "precompile.h"
|
|
|
|
#include <math.h>
|
|
|
|
#include <a8/collision.h>
|
|
|
|
#include "entity.h"
|
|
#include "collider.h"
|
|
|
|
bool ColliderComponent::IntersectSegment(a8::Vec2& p0, a8::Vec2& p1)
|
|
{
|
|
switch (type) {
|
|
case CT_None:
|
|
break;
|
|
case CT_Aabb:
|
|
{
|
|
AabbCollider* a_aabb = (AabbCollider*)this;
|
|
return a8::IntersectSegmentAabb(p0,
|
|
p1,
|
|
a_aabb->owner->GetPos() + a_aabb->_min,
|
|
a_aabb->owner->GetPos() + a_aabb->_max);
|
|
}
|
|
break;
|
|
case CT_Circle:
|
|
{
|
|
CircleCollider* a_circle = (CircleCollider*)this;
|
|
return a8::IntersectSegmentCircle(p0,
|
|
p1,
|
|
a_circle->owner->GetPos() + a_circle->pos,
|
|
a_circle->rad);
|
|
}
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ColliderComponent::Intersect(ColliderComponent* b)
|
|
{
|
|
switch (type) {
|
|
case CT_None:
|
|
break;
|
|
case CT_Aabb:
|
|
{
|
|
AabbCollider* a_aabb = (AabbCollider*)this;
|
|
switch (b->type) {
|
|
case CT_None:
|
|
break;
|
|
case CT_Aabb:
|
|
{
|
|
AabbCollider* b_aabb = (AabbCollider*)b;
|
|
return a8::IntersectAabbAabb(a_aabb->owner->GetPos() + a_aabb->_min,
|
|
a_aabb->owner->GetPos() + a_aabb->_max,
|
|
b_aabb->owner->GetPos() + b_aabb->_min,
|
|
b_aabb->owner->GetPos() + b_aabb->_max
|
|
);
|
|
}
|
|
break;
|
|
case CT_Circle:
|
|
{
|
|
CircleCollider* b_circle = (CircleCollider*)b;
|
|
return a8::IntersectAabbCircle(a_aabb->owner->GetPos() + a_aabb->_min,
|
|
a_aabb->owner->GetPos() + a_aabb->_max,
|
|
b_circle->owner->GetPos() + b_circle->pos,
|
|
b_circle->rad);
|
|
}
|
|
break;
|
|
case CT_Obb:
|
|
{
|
|
ObbCollider* b_obb = (ObbCollider*)b;
|
|
return a8::IntersectAabbObb(a_aabb->owner->GetPos() + a_aabb->_min,
|
|
a_aabb->owner->GetPos() + a_aabb->_max,
|
|
b_obb->owner->GetPos(),
|
|
b_obb->rotate);
|
|
}
|
|
break;
|
|
case CT_Arc:
|
|
{
|
|
ArcCollider* b_arc = (ArcCollider*)b;
|
|
#if 0
|
|
return a8::IntersectAabbArc(a_aabb->owner->GetPos() + a_aabb->_min,
|
|
a_aabb->owner->GetPos() + a_aabb->_max,
|
|
b_arc->owner->GetPos(),
|
|
b_arc->width);
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
break;
|
|
case CT_Circle:
|
|
{
|
|
CircleCollider* a_circle = (CircleCollider*)this;
|
|
switch (b->type) {
|
|
case CT_None:
|
|
break;
|
|
case CT_Aabb:
|
|
{
|
|
AabbCollider* b_aabb = (AabbCollider*)b;
|
|
return a8::IntersectAabbCircle(b_aabb->owner->GetPos() + b_aabb->_min,
|
|
b_aabb->owner->GetPos() + b_aabb->_max,
|
|
a_circle->owner->GetPos() + a_circle->pos,
|
|
a_circle->rad);
|
|
}
|
|
break;
|
|
case CT_Circle:
|
|
{
|
|
CircleCollider* b_circle = (CircleCollider*)b;
|
|
return a8::IntersectCircleCircle(
|
|
a_circle->owner->GetPos() + a_circle->pos,
|
|
a_circle->rad,
|
|
b_circle->owner->GetPos() + b_circle->pos,
|
|
b_circle->rad);
|
|
}
|
|
break;
|
|
case CT_Arc:
|
|
{
|
|
ArcCollider* b_arc = (ArcCollider*)b;
|
|
#if 0
|
|
return a8::IntersectCircleArc(a_circle->owner->GetPos(),
|
|
a_circle->rad,
|
|
b_arc->owner->GetPos(),
|
|
b_arc->width);
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ColliderComponent::IntersectEx(const a8::Vec2& pos, ColliderComponent* b)
|
|
{
|
|
switch (type) {
|
|
case CT_None:
|
|
break;
|
|
case CT_Aabb:
|
|
{
|
|
AabbCollider* a_aabb = (AabbCollider*)this;
|
|
switch (b->type) {
|
|
case CT_None:
|
|
break;
|
|
case CT_Aabb:
|
|
{
|
|
AabbCollider* b_aabb = (AabbCollider*)b;
|
|
return a8::IntersectAabbAabb(a_aabb->owner->GetPos() + a_aabb->_min,
|
|
a_aabb->owner->GetPos() + a_aabb->_max,
|
|
pos + b_aabb->_min,
|
|
pos + b_aabb->_max
|
|
);
|
|
}
|
|
break;
|
|
case CT_Circle:
|
|
{
|
|
CircleCollider* b_circle = (CircleCollider*)b;
|
|
return a8::IntersectAabbCircle(a_aabb->owner->GetPos() + a_aabb->_min,
|
|
a_aabb->owner->GetPos() + a_aabb->_max,
|
|
pos + b_circle->pos,
|
|
b_circle->rad);
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
break;
|
|
case CT_Circle:
|
|
{
|
|
CircleCollider* a_circle = (CircleCollider*)this;
|
|
switch (b->type) {
|
|
case CT_None:
|
|
break;
|
|
case CT_Aabb:
|
|
{
|
|
AabbCollider* b_aabb = (AabbCollider*)b;
|
|
return a8::IntersectAabbCircle(pos + b_aabb->_min,
|
|
pos + b_aabb->_max,
|
|
a_circle->owner->GetPos() + a_circle->pos,
|
|
a_circle->rad);
|
|
}
|
|
break;
|
|
case CT_Circle:
|
|
{
|
|
CircleCollider* b_circle = (CircleCollider*)b;
|
|
return a8::IntersectCircleCircle(
|
|
a_circle->owner->GetPos() + a_circle->pos,
|
|
a_circle->rad,
|
|
pos + b_circle->pos,
|
|
b_circle->rad);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ColliderComponent::CalcSafePoint(ColliderComponent* b, a8::Vec2& new_pos)
|
|
{
|
|
switch (type) {
|
|
case CT_None:
|
|
break;
|
|
case CT_Aabb:
|
|
{
|
|
AabbCollider* a_aabb = (AabbCollider*)this;
|
|
switch (b->type) {
|
|
case CT_Aabb:
|
|
{
|
|
AabbCollider* b_aabb = (AabbCollider*)b;
|
|
return a8::CalcAabbAabbSafePoint(a_aabb->owner->GetPos() + a_aabb->_min,
|
|
a_aabb->owner->GetPos() + a_aabb->_max,
|
|
b_aabb->owner->GetPos() + b_aabb->_min,
|
|
b_aabb->owner->GetPos() + b_aabb->_max,
|
|
new_pos);
|
|
}
|
|
break;
|
|
case CT_Circle:
|
|
{
|
|
CircleCollider* b_circle = (CircleCollider*)b;
|
|
return a8::CalcAabbAabbSafePoint(a_aabb->owner->GetPos() + a_aabb->_min,
|
|
a_aabb->owner->GetPos() + a_aabb->_max,
|
|
b_circle->owner->GetPos() + b_circle->pos,
|
|
b_circle->rad,
|
|
new_pos);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case CT_Circle:
|
|
{
|
|
CircleCollider* a_circle = (CircleCollider*)this;
|
|
switch (b->type) {
|
|
case CT_Aabb:
|
|
{
|
|
AabbCollider* b_aabb = (AabbCollider*)b;
|
|
return a8::CalcCircleAabbSafePoint(
|
|
a_circle->owner->GetPos() + a_circle->pos,
|
|
a_circle->rad,
|
|
b_aabb->owner->GetPos() + b_aabb->_min,
|
|
b_aabb->owner->GetPos() + b_aabb->_max,
|
|
new_pos);
|
|
}
|
|
break;
|
|
case CT_Circle:
|
|
{
|
|
CircleCollider* b_circle = (CircleCollider*)b;
|
|
return a8::CalcCircleCircleSafePoint(
|
|
a_circle->owner->GetPos() + a_circle->pos,
|
|
a_circle->rad,
|
|
b_circle->owner->GetPos() + b_circle->pos,
|
|
b_circle->rad,
|
|
new_pos);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ColliderComponent::CalcSafePointEx(const a8::Vec2& a_pos, ColliderComponent* b, a8::Vec2& new_pos)
|
|
{
|
|
switch (type) {
|
|
case CT_None:
|
|
break;
|
|
case CT_Aabb:
|
|
{
|
|
AabbCollider* a_aabb = (AabbCollider*)this;
|
|
switch (b->type) {
|
|
case CT_Aabb:
|
|
{
|
|
AabbCollider* b_aabb = (AabbCollider*)b;
|
|
return a8::CalcAabbAabbSafePoint(a_pos + a_aabb->_min,
|
|
a_pos + a_aabb->_max,
|
|
b_aabb->owner->GetPos() + b_aabb->_min,
|
|
b_aabb->owner->GetPos() + b_aabb->_max,
|
|
new_pos);
|
|
}
|
|
break;
|
|
case CT_Circle:
|
|
{
|
|
CircleCollider* b_circle = (CircleCollider*)b;
|
|
return a8::CalcAabbAabbSafePoint(a_pos + a_aabb->_min,
|
|
a_pos + a_aabb->_max,
|
|
b_circle->owner->GetPos() + b_circle->pos,
|
|
b_circle->rad,
|
|
new_pos);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case CT_Circle:
|
|
{
|
|
CircleCollider* a_circle = (CircleCollider*)this;
|
|
switch (b->type) {
|
|
case CT_Aabb:
|
|
{
|
|
AabbCollider* b_aabb = (AabbCollider*)b;
|
|
return a8::CalcCircleAabbSafePoint(
|
|
a_pos + a_circle->pos,
|
|
a_circle->rad,
|
|
b_aabb->owner->GetPos() + b_aabb->_min,
|
|
b_aabb->owner->GetPos() + b_aabb->_max,
|
|
new_pos);
|
|
}
|
|
break;
|
|
case CT_Circle:
|
|
{
|
|
CircleCollider* b_circle = (CircleCollider*)b;
|
|
return a8::CalcCircleCircleSafePoint(
|
|
a_pos + a_circle->pos,
|
|
a_circle->rad,
|
|
b_circle->owner->GetPos() + b_circle->pos,
|
|
b_circle->rad,
|
|
new_pos);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void AabbCollider::MoveCenter(float x, float y)
|
|
{
|
|
_min.x += x;
|
|
_min.y += y;
|
|
_max.x += x;
|
|
_max.y += y;
|
|
}
|
|
|
|
void DestoryCollider(ColliderComponent* collider)
|
|
{
|
|
switch (collider->type) {
|
|
case CT_Aabb:
|
|
{
|
|
delete (AabbCollider*)collider;
|
|
}
|
|
break;
|
|
case CT_Circle:
|
|
{
|
|
delete (CircleCollider*)collider;
|
|
}
|
|
break;
|
|
case CT_Obb:
|
|
{
|
|
delete (ObbCollider*)collider;
|
|
}
|
|
break;
|
|
case CT_Arc:
|
|
{
|
|
delete (ArcCollider*)collider;
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
delete collider;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static float TwoDistance(float x1, float y1, float x2, float y2)
|
|
{
|
|
return pow(pow((x1 - x2), 2.0f) + pow((y1 - y2), 2.0f), 0.5);
|
|
}
|
|
|
|
static float rot(float x1, float y1, float x2, float y2)
|
|
{
|
|
float value = (y1 - y2) / (x1 - x2);
|
|
return atan(value) * 180 / A8_PI;
|
|
}
|
|
|
|
static void GetNewRxRy(float x1, float y1, float x2, float y2, float dro, float& new_rx, float& new_ry)
|
|
{
|
|
float distance = TwoDistance(x1, y1, x2, y2);
|
|
float new_rot = rot(x1, y1, x2, y2) - dro;
|
|
new_rx = cos(new_rot / 180 * A8_PI) * distance;
|
|
new_ry = sin(new_rot / 180 * A8_PI) * distance;
|
|
}
|
|
|
|
bool Check2dRotationRectangle(float rx, float ry, float r, float dx, float dy, float dw, float dh, float dro)
|
|
{
|
|
float new_rx = 0.0f;
|
|
float new_ry = 0.0f;
|
|
GetNewRxRy(rx, ry, dx, dy, dro, new_rx, new_ry);
|
|
|
|
float tmp_dx = std::min(new_rx, dw * 0.5f);
|
|
float tmp_dx1 = std::max(tmp_dx, -dw * 0.5f);
|
|
float tmp_dy = std::min(new_ry, dh * 0.5f);
|
|
float tmp_dy1 = std::max(tmp_dy, -dh * 0.5f);
|
|
|
|
#ifdef DEBUG1
|
|
a8::XPrintf("new_rx:%f new_ry:%f dx1:%f dy1:%f dro:%f v1:%f v2:%f r:%f,%f d:%f,%f\n",
|
|
{
|
|
new_rx,
|
|
new_ry,
|
|
tmp_dx1,
|
|
tmp_dy1,
|
|
dro,
|
|
(tmp_dx1 - new_rx) * (tmp_dx1 - new_rx) + (tmp_dy1 - new_ry) * (tmp_dy1 - new_ry) ,
|
|
r*r,
|
|
rx,ry,
|
|
dx,dy
|
|
});
|
|
#endif
|
|
return (tmp_dx1 - new_rx) * (tmp_dx1 - new_rx) + (tmp_dy1 - new_ry) * (tmp_dy1 - new_ry) <= r * r;
|
|
}
|