From a81441b1e98f21f537a9709a2b640b2826a712d2 Mon Sep 17 00:00:00 2001 From: Marty <85036874+MatusGuy@users.noreply.github.com> Date: Mon, 18 Sep 2023 20:50:21 +0100 Subject: [PATCH] Raycast function returns what it hit (#2631) - Raycast function that returns what raycast hit - Fix random segfault? - Use union for hit --- src/collision/collision_system.cpp | 46 ++++++++++++++++++++++++------ src/collision/collision_system.hpp | 18 ++++++++++++ 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/collision/collision_system.cpp b/src/collision/collision_system.cpp index 35afbbf74cf..7a5dedd11c4 100644 --- a/src/collision/collision_system.cpp +++ b/src/collision/collision_system.cpp @@ -690,10 +690,14 @@ CollisionSystem::is_free_of_movingstatics(const Rectf& rect, const CollisionObje return true; } -bool -CollisionSystem::free_line_of_sight(const Vector& line_start, const Vector& line_end, bool ignore_objects, const CollisionObject* ignore_object) const +CollisionSystem::RaycastResult +CollisionSystem::get_first_line_intersection(const Vector& line_start, + const Vector& line_end, + bool ignore_objects, + const CollisionObject* ignore_object) const { using namespace collision; + RaycastResult result{}; // Check if no tile is in the way. const float lsx = std::min(line_start.x, line_end.x); @@ -709,16 +713,26 @@ CollisionSystem::free_line_of_sight(const Vector& line_start, const Vector& line { continue; } - - const Tile& tile = solids->get_tile_at(test_vector); + + const Tile* tile = &solids->get_tile_at(test_vector); + // FIXME: check collision with slope tiles - if ((tile.get_attributes() & Tile::SOLID)) return false; + if ((tile->get_attributes() & Tile::SOLID)) + { + result.is_valid = true; + result.hit.tile = tile; + result.box = {glm::floor((test_vector - solids->get_offset()) / 32.0f), Sizef(32.f, 32.f)}; + return result; + } } } } if (ignore_objects) - return true; + { + result.is_valid = false; + return result; + } // Check if no object is in the way. for (const auto& object : m_objects) { @@ -726,12 +740,26 @@ CollisionSystem::free_line_of_sight(const Vector& line_start, const Vector& line if (!object->is_valid()) continue; if ((object->get_group() == COLGROUP_MOVING) || (object->get_group() == COLGROUP_MOVING_STATIC) - || (object->get_group() == COLGROUP_STATIC)) { - if (intersects_line(object->get_bbox(), line_start, line_end)) return false; + || (object->get_group() == COLGROUP_STATIC)) + { + if (intersects_line(object->get_bbox(), line_start, line_end)) + { + result.is_valid = true; + result.hit.object = object; + result.box = object->get_bbox(); + return result; + } } } - return true; + result.is_valid = false; + return result; +} + +bool +CollisionSystem::free_line_of_sight(const Vector& line_start, const Vector& line_end, bool ignore_objects, const CollisionObject* ignore_object) const +{ + return !get_first_line_intersection(line_start, line_end, ignore_objects, ignore_object).is_valid; } std::vector diff --git a/src/collision/collision_system.hpp b/src/collision/collision_system.hpp index c422f9755ab..a263e439d3c 100644 --- a/src/collision/collision_system.hpp +++ b/src/collision/collision_system.hpp @@ -34,6 +34,18 @@ class Sector; class CollisionSystem final { +public: + struct RaycastResult + { + bool is_valid; /**< true if raycast hit something */ + union + { + const CollisionObject* object; + const Tile* tile; + } hit; /**< tile/object that the raycast hit */ + Rectf box = {}; /**< hitbox of tile/object */ + }; + public: CollisionSystem(Sector& sector); @@ -56,6 +68,12 @@ class CollisionSystem final bool is_free_of_tiles(const Rectf& rect, const bool ignoreUnisolid = false, uint32_t tiletype = Tile::SOLID) const; bool is_free_of_statics(const Rectf& rect, const CollisionObject* ignore_object, const bool ignoreUnisolid) const; bool is_free_of_movingstatics(const Rectf& rect, const CollisionObject* ignore_object) const; + + + RaycastResult get_first_line_intersection(const Vector& line_start, + const Vector& line_end, + bool ignore_objects, + const CollisionObject* ignore_object) const; bool free_line_of_sight(const Vector& line_start, const Vector& line_end, bool ignore_objects, const CollisionObject* ignore_object) const; std::vector get_nearby_objects(const Vector& center, float max_distance) const;