Skip to content

Commit

Permalink
Raycast function returns what it hit (#2631)
Browse files Browse the repository at this point in the history
- Raycast function that returns what raycast hit
- Fix random segfault?
- Use union for hit
  • Loading branch information
MatusGuy authored Sep 18, 2023
1 parent b855913 commit a81441b
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 9 deletions.
46 changes: 37 additions & 9 deletions src/collision/collision_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -709,29 +713,53 @@ 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) {
if (object == ignore_object) continue;
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<CollisionObject*>
Expand Down
18 changes: 18 additions & 0 deletions src/collision/collision_system.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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<CollisionObject*> get_nearby_objects(const Vector& center, float max_distance) const;
Expand Down

0 comments on commit a81441b

Please sign in to comment.