From fc57e98a96f715b82cdb7f2351ba0e7f43423f3e Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 14 Mar 2026 15:47:26 +0300 Subject: [PATCH] feat: third-person camera now checks solid entities --- src/logic/PlayerController.cpp | 26 ++++++++++++++++++++------ src/objects/Entities.cpp | 8 ++++++-- src/objects/Entities.hpp | 4 +++- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index 3d8c75872..663ff1fa1 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -44,7 +44,9 @@ namespace { const float CROUCH_SHIFT_Y = -0.2f; } -CameraControl::CameraControl(Player& player, const CameraSettings& settings) +CameraControl::CameraControl( + Player& player, const CameraSettings& settings +) : player(player), camera(player.fpCamera), settings(settings), @@ -195,18 +197,30 @@ void CameraControl::update( refreshPosition(); + auto castRay = [](Player& player, Camera& camera, const glm::vec3& front) + -> glm::vec3 { + auto blockEnd = player.chunks->rayCastToObstacle(camera.position, front, 3.0f); + auto entityRay = player.getLevel().entities->rayCast( + camera.position, front, 3.0f, player.getEntity(), true + ); + if (entityRay.has_value() && + entityRay->distance < glm::distance(camera.position, blockEnd)) { + return (camera.position + front * entityRay->distance); + } else { + return blockEnd; + } + }; + camera->updateVectors(); if (player.currentCamera == spCamera) { spCamera->position = - chunks.rayCastToObstacle(camera->position, camera->front, 3.0f) - - 0.4f * camera->front; + castRay(player, *camera, camera->front) - 0.4f * camera->front; spCamera->dir = -camera->dir; spCamera->front = -camera->front; spCamera->right = -camera->right; } else if (player.currentCamera == tpCamera) { - tpCamera->position = - chunks.rayCastToObstacle(camera->position, -camera->front, 3.0f) + - 0.4f * camera->front; + tpCamera->position = castRay(player, *camera, camera->front * -1.0f) + + 0.4f * camera->front; tpCamera->dir = camera->dir; tpCamera->front = camera->front; tpCamera->right = camera->right; diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index 259e9e3c6..e445b738a 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -162,7 +162,11 @@ void Entities::loadEntity(const dv::value& map, Entity entity) { } std::optional Entities::rayCast( - glm::vec3 start, glm::vec3 dir, float maxDistance, entityid_t ignore + glm::vec3 start, + glm::vec3 dir, + float maxDistance, + entityid_t ignore, + bool solidOnly ) { Ray ray(start, dir); auto view = registry->view(); @@ -171,7 +175,7 @@ std::optional Entities::rayCast( glm::ivec3 foundNormal; for (auto [entity, eid, transform, body] : view.each()) { - if (eid.uid == ignore || !body.enabled) { + if (eid.uid == ignore || !body.enabled || (solidOnly && !eid.def.solid)) { continue; } auto& hitbox = body.hitbox; diff --git a/src/objects/Entities.hpp b/src/objects/Entities.hpp index 804ce17f4..33786118a 100644 --- a/src/objects/Entities.hpp +++ b/src/objects/Entities.hpp @@ -88,12 +88,14 @@ public: /// @param dir Ray direction normalized vector /// @param maxDistance Max ray length /// @param ignore Ignored entity ID + /// @param solidOnly If true, only entities with solid hitboxes will be checked /// @return An optional structure containing entity, normal and distance std::optional rayCast( glm::vec3 start, glm::vec3 dir, float maxDistance, - entityid_t ignore = -1 + entityid_t ignore = -1, + bool solidOnly = false ); void loadEntities(dv::value map);