Add line-of-sight check to perception

This commit is contained in:
Vsevolod Kremianskii 2021-03-23 15:36:56 +07:00
parent 6d35fdb455
commit d58c356ef4
2 changed files with 35 additions and 3 deletions

View file

@ -20,7 +20,8 @@
#include <set>
#include <stdexcept>
#include "object/creature.h"
#include "../common/log.h"
#include "object/area.h"
using namespace std;
@ -56,35 +57,62 @@ void Perception::doUpdate() {
float hearingRange2 = creature->perception().hearingRange * creature->perception().hearingRange;
for (auto &other : creatures) {
// Skip self
if (other == object) continue;
bool seen = false;
bool heard = false;
float distance2 = creature->getDistanceTo2(*object);
if (distance2 <= sightRange2) {
// TODO: check line-of-sight
seen = true;
seen = isInLineOfSight(*creature, *other);
}
if (distance2 <= hearingRange2) {
heard = true;
}
// Sight
bool wasSeen = creature->perception().seen.count(other) > 0;
if (!wasSeen && seen) {
creature->onObjectSeen(other);
debug(boost::format("Perception: %s seen by %s") % other->tag() % creature->tag(), 2);
} else if (wasSeen && !seen) {
creature->onObjectVanished(other);
debug(boost::format("Perception: %s vanished from %s") % other->tag() % creature->tag(), 2);
}
// Hearing
bool wasHeard = creature->perception().heard.count(other) > 0;
if (!wasHeard && heard) {
creature->onObjectHeard(other);
debug(boost::format("Perception: %s heard by %s") % other->tag() % creature->tag(), 2);
} else if (wasHeard && !heard) {
creature->onObjectInaudible(other);
debug(boost::format("Perception: %s inaudible to %s") % other->tag() % creature->tag(), 2);
}
}
}
}
bool Perception::isInLineOfSight(const Creature &subject, const SpatialObject &target) const {
glm::vec3 subjectPos(subject.getModelSceneNode()->getCenterOfAABB());
glm::vec3 targetPos(target.getModelSceneNode()->getCenterOfAABB());
glm::vec3 subjectToTarget(targetPos - subjectPos);
// Ensure that subjects line of sight is not blocked by room and door walkmeshes
RaycastProperties castProps;
castProps.flags = RaycastFlags::rooms;
castProps.origin = subjectPos;
castProps.direction = glm::normalize(subjectToTarget);
castProps.objectTypes = { ObjectType::Door };
castProps.distance = glm::length(subjectToTarget);
RaycastResult castResult;
return !_area->collisionDetector().raycast(castProps, castResult);
}
} // namespace game
} // namespace reone

View file

@ -19,6 +19,8 @@
#include "../common/timer.h"
#include "object/creature.h"
namespace reone {
namespace game {
@ -40,6 +42,8 @@ private:
Timer _updateTimer;
void doUpdate();
bool isInLineOfSight(const Creature &subject, const SpatialObject &target) const;
};
} // namespace game