game2006/server/gameserver/collider.cc
aozhiwei d4790c4b5b 1
2022-09-22 21:41:36 +08:00

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;
}