game2006/server/gameserver/collision.cc
aozhiwei 55ed1af4b6 1
2024-05-14 16:42:04 +08:00

173 lines
5.5 KiB
C++

#include "precompile.h"
#include <math.h>
#include <a8/collision.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/intersect.hpp>
#include "collision.h"
#include "creature.h"
#include "obstacle.h"
#include "roomobstacle.h"
#include "room.h"
#include "mt/Map.h"
#include "mt/MapThing.h"
#include "mt/Hero.h"
static const float GUN_HEIGHT = 20.0f;
bool Collision::CheckBullet(IBullet* bullet, Creature* c)
{
glm::vec3 bullet_real_pos = bullet->GetPos().ToGlmVec3() - bullet->GetDir() * bullet->GetHitRadius();
if (bullet->NoAdjustPos()) {
bullet_real_pos = bullet->GetPos().ToGlmVec3();
}
float bullet_hit_radius = bullet->GetHitRadius();
bool ret = a8::IntersectCylinderCylinder
(
bullet_real_pos, bullet_hit_radius * 1.0, GUN_HEIGHT,
c->GetPos().ToGlmVec3(), c->GetHitRadius(), c->GetHeroMeta()->GetHeight()
);
if (!ret) {
bullet_real_pos = bullet->GetPos().ToGlmVec3() - bullet->GetDir() * (bullet->GetHitRadius() - 2);
ret = a8::IntersectCylinderCylinder
(
bullet_real_pos, bullet_hit_radius * 1.0, GUN_HEIGHT,
c->GetPos().ToGlmVec3(), c->GetHitRadius(), c->GetHeroMeta()->GetHeight()
);
}
return ret;
}
bool Collision::CheckBullet(IBullet* bullet, Entity* e)
{
glm::vec3 bullet_real_pos = bullet->GetPos().ToGlmVec3() - bullet->GetDir() * bullet->GetHitRadius();
if (e->IsEntityType(ET_Obstacle) && ((Obstacle*)e)->IsRoomObstacle()) {
RoomObstacle* ob = (RoomObstacle*)e;
float distance = std::fabs(bullet->GetPos().GetX() - e->GetPos().GetX()) + std::fabs(bullet->GetPos().GetZ() - e->GetPos().GetZ());
if (distance > 300) {
return false;
}
if (ob->init_args) {
auto wobj = ob->init_args->Get<std::shared_ptr<mt::WorldObject>>(0);
return a8::IntersectCylinderCylinder
(
bullet_real_pos, bullet->GetHitRadius() * 1.0, GUN_HEIGHT,
e->GetPos().ToGlmVec3(), std::max(wobj->size.x/2.0f, wobj->size.z/2.0f), GUN_HEIGHT
);
} else {
return a8::IntersectCylinderCylinder
(
bullet_real_pos, bullet->GetHitRadius() * 1.0, GUN_HEIGHT,
e->GetPos().ToGlmVec3(), ob->meta->width(), GUN_HEIGHT
);
}
}
return false;
}
bool Collision::CheckCC(Creature* a, Creature* b)
{
return false;
}
bool Collision::CheckCC(Creature* a, float a_radius, Creature* b, float b_radius)
{
return a8::IntersectCylinderCylinder
(
a->GetPos().ToGlmVec3(), a_radius, 10,
b->GetPos().ToGlmVec3(), b_radius, 10
);
}
bool Collision::CheckCB(Creature* c, Obstacle* b)
{
return false;
}
bool Collision::CheckCB(Creature* c, float c_radius, Obstacle* b, float b_radius)
{
return a8::IntersectCylinderCylinder
(
c->GetPos().ToGlmVec3(), c_radius, 10,
b->GetPos().ToGlmVec3(), b_radius, 10
);
}
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 Collision::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 MYDEBUG1
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;
}
bool Collision::IntersectRaySphere(float ray_width,
glm::vec3 ray_starting, glm::vec3 ray_normalized_direction,
glm::vec3 sphere_center, float sphere_radius,
float &intersection_distance
)
{
ray_starting.y = 0.0f;
ray_normalized_direction.y = 0.0f;
sphere_center.y = 0.0f;
sphere_radius += ray_width * 0.5f;
glm::vec3 intersection_position;
glm::vec3 intersection_normal;
bool ret = glm::intersectRaySphere(ray_starting, ray_normalized_direction, sphere_center, sphere_radius,
intersection_position, intersection_normal);
return ret;
}
bool Collision::InSquare(const glm::vec3& center, const glm::vec3& pos, float side_len)
{
float x_distance = std::fabs(pos.x - center.x);
float z_distance = std::fabs(pos.z - center.z);
return (x_distance < side_len &&
z_distance < side_len);
}