feat: third-person camera now checks solid entities

This commit is contained in:
MihailRis 2026-03-14 15:47:26 +03:00
parent 15bbf55e29
commit fc57e98a96
3 changed files with 29 additions and 9 deletions

View file

@ -44,7 +44,9 @@ namespace {
const float CROUCH_SHIFT_Y = -0.2f; const float CROUCH_SHIFT_Y = -0.2f;
} }
CameraControl::CameraControl(Player& player, const CameraSettings& settings) CameraControl::CameraControl(
Player& player, const CameraSettings& settings
)
: player(player), : player(player),
camera(player.fpCamera), camera(player.fpCamera),
settings(settings), settings(settings),
@ -195,18 +197,30 @@ void CameraControl::update(
refreshPosition(); 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(); camera->updateVectors();
if (player.currentCamera == spCamera) { if (player.currentCamera == spCamera) {
spCamera->position = spCamera->position =
chunks.rayCastToObstacle(camera->position, camera->front, 3.0f) - castRay(player, *camera, camera->front) - 0.4f * camera->front;
0.4f * camera->front;
spCamera->dir = -camera->dir; spCamera->dir = -camera->dir;
spCamera->front = -camera->front; spCamera->front = -camera->front;
spCamera->right = -camera->right; spCamera->right = -camera->right;
} else if (player.currentCamera == tpCamera) { } else if (player.currentCamera == tpCamera) {
tpCamera->position = tpCamera->position = castRay(player, *camera, camera->front * -1.0f) +
chunks.rayCastToObstacle(camera->position, -camera->front, 3.0f) + 0.4f * camera->front;
0.4f * camera->front;
tpCamera->dir = camera->dir; tpCamera->dir = camera->dir;
tpCamera->front = camera->front; tpCamera->front = camera->front;
tpCamera->right = camera->right; tpCamera->right = camera->right;

View file

@ -162,7 +162,11 @@ void Entities::loadEntity(const dv::value& map, Entity entity) {
} }
std::optional<Entities::RaycastResult> Entities::rayCast( std::optional<Entities::RaycastResult> 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); Ray ray(start, dir);
auto view = registry->view<EntityId, Transform, Rigidbody>(); auto view = registry->view<EntityId, Transform, Rigidbody>();
@ -171,7 +175,7 @@ std::optional<Entities::RaycastResult> Entities::rayCast(
glm::ivec3 foundNormal; glm::ivec3 foundNormal;
for (auto [entity, eid, transform, body] : view.each()) { 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; continue;
} }
auto& hitbox = body.hitbox; auto& hitbox = body.hitbox;

View file

@ -88,12 +88,14 @@ public:
/// @param dir Ray direction normalized vector /// @param dir Ray direction normalized vector
/// @param maxDistance Max ray length /// @param maxDistance Max ray length
/// @param ignore Ignored entity ID /// @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 /// @return An optional structure containing entity, normal and distance
std::optional<RaycastResult> rayCast( std::optional<RaycastResult> rayCast(
glm::vec3 start, glm::vec3 start,
glm::vec3 dir, glm::vec3 dir,
float maxDistance, float maxDistance,
entityid_t ignore = -1 entityid_t ignore = -1,
bool solidOnly = false
); );
void loadEntities(dv::value map); void loadEntities(dv::value map);