#include "precompile.h" #include #include #include #include #include #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>(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); }