X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fai%2Fai.cpp;h=f24d0694e0838222d457471ba1f254a76417471c;hb=0ab149c70b3f984b2cc0c7a122b4aa347bc5fd79;hp=1d424cc218c73c9224f3d0abe6eea37a41bae06f;hpb=150d065f431d665326fd8028748c48a74ad956bb;p=blank.git diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp index 1d424cc..f24d069 100644 --- a/src/ai/ai.cpp +++ b/src/ai/ai.cpp @@ -1,4 +1,5 @@ #include "AIController.hpp" +#include "IdleState.hpp" #include "../model/geometry.hpp" #include "../rand/GaloisLFSR.hpp" @@ -13,33 +14,49 @@ namespace blank { +namespace { + +IdleState idle; + +} + AIController::AIController(GaloisLFSR &rand) : random(rand) -, chase_speed(2.0f) -, flee_speed(-5.0f) -, stop_dist(10.0f) -, flee_dist(5.0f) +, state(&idle) +, flee_target(nullptr) +, flee_speed(5.0f) +, seek_target(nullptr) +, seek_speed(5.0f) +, wandering(false) , wander_pos(1.0f, 0.0f, 0.0f) +, wander_speed(1.0f) , wander_dist(2.0f) -, wander_radius(1.0f) -, wander_disp(1.0f) -, wander_speed(1.0f) { - +, wander_radius(1.5f) +, wander_disp(1.0f) { + state->Enter(*this); } AIController::~AIController() { + state->Exit(*this); +} +void AIController::SetState(const AIState &s) { + state->Exit(*this); + state = &s; + state->Enter(*this); } void AIController::Update(Entity &e, float dt) { // movement: for now, wander only - glm::vec3 displacement( - random.SNorm() * wander_disp, - random.SNorm() * wander_disp, - random.SNorm() * wander_disp - ); - if (dot(displacement, displacement) > std::numeric_limits::epsilon()) { - wander_pos = normalize(wander_pos + displacement * dt) * wander_radius; + if (wandering) { + glm::vec3 displacement( + random.SNorm() * wander_disp, + random.SNorm() * wander_disp, + random.SNorm() * wander_disp + ); + if (!iszero(displacement)) { + wander_pos = normalize(wander_pos + displacement * dt) * wander_radius; + } } if (e.Moving()) { @@ -51,8 +68,27 @@ void AIController::Update(Entity &e, float dt) { } } -glm::vec3 AIController::ControlForce(const EntityState &state) const { - return (Heading(state) * wander_dist + wander_pos) * wander_speed; +glm::vec3 AIController::ControlForce(const Entity &entity, const EntityState &state) const { + glm::vec3 force(0.0f); + if (IsFleeing()) { + glm::vec3 diff(GetFleeTarget().GetState().Diff(state)); + if (MaxOutForce(force, TargetVelocity(normalize(diff) * flee_speed, state, 0.5f), entity.MaxControlForce())) { + return force; + } + } + if (IsSeeking()) { + glm::vec3 diff(state.Diff(GetSeekTarget().GetState())); + if (MaxOutForce(force, TargetVelocity(normalize(diff) * seek_speed, state, 0.5f), entity.MaxControlForce())) { + return force; + } + } + if (wandering) { + glm::vec3 wander_target(normalize(Heading(state) * wander_dist + wander_pos) * wander_speed); + if (MaxOutForce(force, TargetVelocity(wander_target, state, 2.0f), entity.MaxControlForce())) { + return force; + } + } + return force; } glm::vec3 AIController::Heading(const EntityState &state) noexcept { @@ -64,4 +100,66 @@ glm::vec3 AIController::Heading(const EntityState &state) noexcept { } } +void AIController::StartFleeing(const Entity &e, float speed) noexcept { + flee_target = &e; + flee_speed = speed; +} + +void AIController::StopFleeing() noexcept { + flee_target = nullptr; +} + +bool AIController::IsFleeing() const noexcept { + return flee_target; +} + +const Entity &AIController::GetFleeTarget() const noexcept { + return *flee_target; +} + +void AIController::StartSeeking(const Entity &e, float speed) noexcept { + seek_target = &e; + seek_speed = speed; +} + +void AIController::StopSeeking() noexcept { + seek_target = nullptr; +} + +bool AIController::IsSeeking() const noexcept { + return seek_target; +} + +const Entity &AIController::GetSeekTarget() const noexcept { + return *seek_target; +} + +void AIController::StartWandering( + float speed, + float distance, + float radius, + float displacement +) noexcept { + wandering = true; + wander_speed = speed; + wander_dist = distance; + wander_radius = radius; + wander_disp = displacement; +} +void AIController::StopWandering() noexcept { + wandering = false; +} + + +void IdleState::Enter(AIController &ctrl) const { + ctrl.StartWandering(1.0f); +} + +void IdleState::Update(AIController &ctrl, Entity &e, float dt) const { +} + +void IdleState::Exit(AIController &ctrl) const { + ctrl.StopWandering(); +} + }