From: Daniel Karbach Date: Fri, 23 Oct 2015 21:01:27 +0000 (+0200) Subject: brought some order to the whole controller thing X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=0ab149c70b3f984b2cc0c7a122b4aa347bc5fd79;p=blank.git brought some order to the whole controller thing --- diff --git a/src/ai/AIController.hpp b/src/ai/AIController.hpp index 0eca2b7..8e50733 100644 --- a/src/ai/AIController.hpp +++ b/src/ai/AIController.hpp @@ -22,7 +22,7 @@ public: void Update(Entity &, float dt) override; - glm::vec3 ControlForce(const EntityState &) const override; + glm::vec3 ControlForce(const Entity &, const EntityState &) const override; static glm::vec3 Heading(const EntityState &) noexcept; @@ -36,7 +36,16 @@ public: bool IsSeeking() const noexcept; const Entity &GetSeekTarget() const noexcept; - void StartWandering() noexcept; + /// start wandering randomly at given speed + /// the trajectory is modified by targetting a blip on a sphere + /// in front of the entity which moves randomly + /// the displacement is given (roughly) in units per second + void StartWandering( + float speed, + float distance = 2.0f, + float radius = 1.0f, + float displacement = 1.0f + ) noexcept; void StopWandering() noexcept; private: @@ -51,10 +60,10 @@ private: bool wandering; glm::vec3 wander_pos; + float wander_speed; float wander_dist; float wander_radius; float wander_disp; - float wander_speed; }; diff --git a/src/ai/Spawner.cpp b/src/ai/Spawner.cpp index 94220d4..6404e44 100644 --- a/src/ai/Spawner.cpp +++ b/src/ai/Spawner.cpp @@ -26,7 +26,7 @@ Spawner::Spawner(World &world, ModelRegistry &models, GaloisLFSR &rand) , timer(64) , despawn_range(128 * 128) , spawn_distance(16 * 16) -, max_entities(16) +, max_entities(32) , chunk_range(4) , model_offset(0) , model_length(models.size()) { diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp index 837c412..f24d069 100644 --- a/src/ai/ai.cpp +++ b/src/ai/ai.cpp @@ -24,15 +24,15 @@ AIController::AIController(GaloisLFSR &rand) : random(rand) , state(&idle) , flee_target(nullptr) -, flee_speed(-5.0f) +, flee_speed(5.0f) , seek_target(nullptr) -, seek_speed(-5.0f) +, 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); } @@ -48,13 +48,15 @@ void AIController::SetState(const AIState &s) { 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()) { @@ -66,22 +68,25 @@ void AIController::Update(Entity &e, float dt) { } } -glm::vec3 AIController::ControlForce(const EntityState &state) const { +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 (dot(diff, diff) > std::numeric_limits::epsilon()) { - force += normalize(diff) * flee_speed; + 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 (dot(diff, diff) > std::numeric_limits::epsilon()) { - force += normalize(diff) * seek_speed; + if (MaxOutForce(force, TargetVelocity(normalize(diff) * seek_speed, state, 0.5f), entity.MaxControlForce())) { + return force; } } if (wandering) { - force += (Heading(state) * wander_dist + wander_pos) * wander_speed; + 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; } @@ -129,8 +134,17 @@ const Entity &AIController::GetSeekTarget() const noexcept { return *seek_target; } -void AIController::StartWandering() noexcept { +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; @@ -138,7 +152,7 @@ void AIController::StopWandering() noexcept { void IdleState::Enter(AIController &ctrl) const { - ctrl.StartWandering(); + ctrl.StartWandering(1.0f); } void IdleState::Update(AIController &ctrl, Entity &e, float dt) const { diff --git a/src/model/geometry.hpp b/src/model/geometry.hpp index fd2c42b..0bc17c1 100644 --- a/src/model/geometry.hpp +++ b/src/model/geometry.hpp @@ -2,6 +2,7 @@ #define BLANK_MODEL_GEOMETRY_H_ #include +#include #include @@ -28,6 +29,12 @@ constexpr float rad2deg(float r) { } +template +inline bool iszero(const T &v) { + return dot(v, v) < std::numeric_limits::epsilon(); +} + + template T manhattan_distance(const glm::tvec3 &a, const glm::tvec3 &b) { glm::tvec3 diff(abs(a - b)); diff --git a/src/ui/PlayerController.hpp b/src/ui/PlayerController.hpp index 2245413..9d54c29 100644 --- a/src/ui/PlayerController.hpp +++ b/src/ui/PlayerController.hpp @@ -34,7 +34,7 @@ public: void SetMovement(const glm::vec3 &) noexcept; const glm::vec3 &GetMovement() const noexcept { return move_dir; } - glm::vec3 ControlForce(const EntityState &) const override; + glm::vec3 ControlForce(const Entity &, const EntityState &) const override; /// turn the controlled entity's head by given pitch and yaw deltas void TurnHead(float pitch, float yaw) noexcept; diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index 1af9e87..dd113ca 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -52,9 +52,8 @@ void PlayerController::SetMovement(const glm::vec3 &m) noexcept { Invalidate(); } -glm::vec3 PlayerController::ControlForce(const EntityState &s) const { - glm::vec3 target(rotateY(move_dir * player.GetEntity().MaxVelocity(), s.yaw) - s.velocity); - return target * player.GetEntity().MaxControlForce(); +glm::vec3 PlayerController::ControlForce(const Entity &e, const EntityState &s) const { + return TargetVelocity(rotateY(move_dir * e.MaxVelocity(), s.yaw), s, 5.0f); } void PlayerController::TurnHead(float dp, float dy) noexcept { diff --git a/src/world/EntityController.hpp b/src/world/EntityController.hpp index 8b14ca8..526a322 100644 --- a/src/world/EntityController.hpp +++ b/src/world/EntityController.hpp @@ -1,13 +1,14 @@ #ifndef BLANK_WORLD_ENTITYCONTROLLER_HPP_ #define BLANK_WORLD_ENTITYCONTROLLER_HPP_ +#include "EntityState.hpp" + #include namespace blank { class Entity; -class EntityState; struct EntityController { @@ -15,7 +16,25 @@ struct EntityController { virtual void Update(Entity &, float dt) = 0; - virtual glm::vec3 ControlForce(const EntityState &) const = 0; + virtual glm::vec3 ControlForce(const Entity &, const EntityState &) const = 0; + + + /// try to add as much of add to out so it doesn't exceed max + /// returns true if it's maxed out + static bool MaxOutForce( + glm::vec3 &out, + const glm::vec3 &add, + float max + ) noexcept; + /// give a force that makes state's velocity converge with given target velocity + /// over 1/n seconds + static inline glm::vec3 TargetVelocity( + const glm::vec3 &target, + const EntityState &state, + float n + ) noexcept { + return (target - state.velocity) * n; + } }; diff --git a/src/world/world.cpp b/src/world/world.cpp index ee5bf02..925046c 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -80,7 +80,7 @@ void Entity::UnsetController() noexcept { glm::vec3 Entity::ControlForce(const EntityState &s) const noexcept { if (HasController()) { - return GetController().ControlForce(s); + return GetController().ControlForce(*this, s); } else { return -s.velocity; } @@ -153,6 +153,29 @@ EntityController::~EntityController() { } +bool EntityController::MaxOutForce( + glm::vec3 &out, + const glm::vec3 &add, + float max +) noexcept { + if (iszero(add) || any(isnan(add))) { + return false; + } + float current = iszero(out) ? 0.0f : length(out); + float remain = max - current; + if (remain <= 0.0f) { + return true; + } + float additional = length(add); + if (additional > remain) { + out += normalize(add) * remain; + return true; + } else { + out += add; + return false; + } +} + EntityState::EntityState() : chunk_pos(0)