Add line-of-sight check to perception
This commit is contained in:
parent
6d35fdb455
commit
d58c356ef4
2 changed files with 35 additions and 3 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue