]> git.localhorst.tv Git - blobs.git/blobdiff - src/creature/creature.cpp
avoid others when steering
[blobs.git] / src / creature / creature.cpp
index 456e08102ebbb2d5cd45a7337a7f02ea508dd27f..5bfac3cf91939e3be417a2147657391534ff337c 100644 (file)
@@ -19,6 +19,7 @@
 #include <algorithm>
 #include <sstream>
 #include <glm/gtx/transform.hpp>
+#include <glm/gtx/vector_angle.hpp>
 
 #include <iostream>
 #include <glm/gtx/io.hpp>
@@ -46,8 +47,10 @@ Creature::Creature(world::Simulation &sim)
 , needs()
 , goals()
 , situation()
-, steering()
+, steering(*this)
 , vao() {
+       // all creatures avoid each other for now
+       steering.Separate(0.1, 1.5);
 }
 
 Creature::~Creature() {
@@ -77,7 +80,7 @@ void Creature::Hurt(double dt) noexcept {
        health = std::max(0.0, health - dt);
        if (health == 0.0) {
                std::cout << "[" << int(sim.Time()) << "s] "
-               << name << " died" << std::endl;
+                       << name << " died" << std::endl;
                Die();
        }
 }
@@ -128,7 +131,6 @@ double Creature::Fertility() const noexcept {
 }
 
 void Creature::AddGoal(std::unique_ptr<Goal> &&g) {
-       std::cout << "[" << int(sim.Time()) << "s] " << name << " new goal: " << g->Describe() << std::endl;
        g->Enable();
        goals.emplace_back(std::move(g));
 }
@@ -148,6 +150,9 @@ void Creature::Tick(double dt) {
                        std::cout << "[" << int(sim.Time()) << "s] "
                                << name << " died of old age" << std::endl;
                        Die();
+               } else {
+                       std::cout << "[" << int(sim.Time()) << "s] "
+                               << name << " grew up to " << AgeName() << std::endl;
                }
        }
 
@@ -159,10 +164,14 @@ void Creature::Tick(double dt) {
                Situation::Derivative d(Step(c, dt));
                Situation::Derivative f(
                        (1.0 / 6.0) * (a.vel + 2.0 * (b.vel + c.vel) + d.vel),
-                       (1.0 / 6.0) * (a.acc + 2.0 * (b.acc + c.acc) + d.acc)
+                       (1.0 / 6.0) * (a.acc + 2.0 * (b.acc + c.acc) + d.acc),
+                       (1.0 / 6.0) * (a.turn + 2.0 * (b.turn + c.turn) + d.turn)
                );
                state.pos += f.vel * dt;
                state.vel += f.acc * dt;
+               constexpr double turn_speed = 10.0;
+               // TODO: this is crap
+               state.dir = glm::normalize(state.dir + f.turn * turn_speed * dt);
                situation.SetState(state);
        }
 
@@ -182,20 +191,11 @@ void Creature::Tick(double dt) {
        }
        // if active goal can be interrupted, check priorities
        if (goals.size() > 1 && goals[0]->Interruptible()) {
-               Goal *old_top = &*goals[0];
                std::sort(goals.begin(), goals.end(), GoalCompare);
-               Goal *new_top = &*goals[0];
-               if (new_top != old_top) {
-                       std::cout << "[" << int(sim.Time()) << "s] " << name
-                               << " changing goal from " << old_top->Describe()
-                               << " to " << new_top->Describe() << std::endl;
-               }
        }
        goals[0]->Action();
        for (auto goal = goals.begin(); goal != goals.end();) {
                if ((*goal)->Complete()) {
-                       std::cout << "[" << int(sim.Time()) << "s] " << name
-                               << " complete goal: " << (*goal)->Describe() << std::endl;
                        goals.erase(goal);
                } else {
                        ++goal;
@@ -207,7 +207,12 @@ Situation::Derivative Creature::Step(const Situation::Derivative &ds, double dt)
        Situation::State s = situation.GetState();
        s.pos += ds.vel * dt;
        s.vel += ds.acc * dt;
-       return { s.vel, steering.Acceleration(s) };
+       s.dir = normalize(s.dir + ds.turn * dt);
+       return {
+               s.vel,
+               steering.Acceleration(s),
+               allzero(s.vel) ? glm::dvec3(0.0) : normalize(s.vel) - s.dir
+       };
 }
 
 glm::dmat4 Creature::LocalTransform() noexcept {
@@ -215,6 +220,8 @@ glm::dmat4 Creature::LocalTransform() noexcept {
        const double half_size = size * 0.5;
        const glm::dvec3 &pos = situation.Position();
        return glm::translate(glm::dvec3(pos.x, pos.y, pos.z + half_size))
+               * glm::dmat4(world::Planet::SurfaceOrientation(situation.Surface()))
+               * glm::rotate(glm::orientedAngle(glm::dvec3(0.0, 0.0, -1.0), situation.Heading(), glm::dvec3(0.0, 1.0, 0.0)), glm::dvec3(0.0, 1.0, 0.0))
                * glm::scale(glm::dvec3(half_size, half_size, half_size));
 }
 
@@ -492,6 +499,8 @@ void Split(Creature &c) {
                s.GetPlanet(), s.Surface(),
                s.Position() + glm::dvec3(0.0, a->Size() * 0.51, 0.0));
        a->BuildVAO();
+       std::cout << "[" << int(c.GetSimulation().Time()) << "s] "
+               << a->Name() << " was born" << std::endl;
 
        Creature *b = new Creature(c.GetSimulation());
        b->Name(c.GetSimulation().Assets().name.Sequential());
@@ -501,6 +510,8 @@ void Split(Creature &c) {
                s.GetPlanet(), s.Surface(),
                s.Position() + glm::dvec3(0.0, b->Size() * -0.51, 0.0));
        b->BuildVAO();
+       std::cout << "[" << int(c.GetSimulation().Time()) << "s] "
+               << b->Name() << " was born" << std::endl;
 
        c.Die();
 }
@@ -612,11 +623,15 @@ void Situation::SetPlanetSurface(world::Planet &p, int srf, const glm::dvec3 &po
 }
 
 
-Steering::Steering()
-: target(0.0)
+Steering::Steering(const Creature &c)
+: c(c)
+, target(0.0)
 , max_accel(1.0)
 , max_speed(1.0)
-, halting(false)
+, min_dist(0.0)
+, max_look(0.0)
+, separating(false)
+, halting(true)
 , seeking(false)
 , arriving(false) {
 }
@@ -624,6 +639,16 @@ Steering::Steering()
 Steering::~Steering() {
 }
 
+void Steering::Separate(double min_distance, double max_lookaround) noexcept {
+       separating = true;
+       min_dist = min_distance;
+       max_look = max_lookaround;
+}
+
+void Steering::DontSeparate() noexcept {
+       separating = false;
+}
+
 void Steering::Halt() noexcept {
        halting = true;
        seeking = false;
@@ -646,6 +671,21 @@ void Steering::GoTo(const glm::dvec3 &t) noexcept {
 
 glm::dvec3 Steering::Acceleration(const Situation::State &s) const noexcept {
        glm::dvec3 acc(0.0);
+       if (separating) {
+               // TODO: off surface situation
+               glm::dvec3 repulse(0.0);
+               const Situation &s = c.GetSituation();
+               for (auto &other : s.GetPlanet().Creatures()) {
+                       if (&*other == &c) continue;
+                       glm::dvec3 diff = s.Position() - other->GetSituation().Position();
+                       if (length2(diff) > max_look * max_look) continue;
+                       double sep = length(diff) - other->Size() * 0.707 - c.Size() * 0.707;
+                       if (sep < min_dist) {
+                               repulse += normalize(diff) * (1.0 - sep / min_dist);
+                       }
+               }
+               SumForce(acc, repulse);
+       }
        if (halting) {
                SumForce(acc, s.vel * -max_accel);
        }