namespace blobs {
namespace creature {
+class Creature;
+
class Steering {
public:
- Steering();
+ explicit Steering(const Creature &);
~Steering();
public:
double MaxSpeed() const noexcept { return max_speed; }
public:
+ void Separate(double min_distance, double max_lookaround) noexcept;
+ void DontSeparate() noexcept;
void Halt() noexcept;
void Pass(const glm::dvec3 &) noexcept;
void GoTo(const glm::dvec3 &) noexcept;
glm::dvec3 TargetVelocity(const Situation::State &, const glm::dvec3 &) const noexcept;
private:
+ const Creature &c;
glm::dvec3 target;
- double max_accel = 1.0;
- double max_speed = 1.0;
+ double max_accel;
+ double max_speed;
+ double min_dist;
+ double max_look;
+ bool separating;
bool halting;
bool seeking;
bool arriving;
, needs()
, goals()
, situation()
-, steering()
+, steering(*this)
, vao() {
+ // all creatures avoid each other for now
+ steering.Separate(0.1, 1.5);
}
Creature::~Creature() {
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();
}
}
}
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));
}
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;
}
}
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);
}
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());
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();
}
}
-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) {
}
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;
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);
}