class Situation {
+public:
+ struct State {
+ glm::dvec3 pos;
+ glm::dvec3 vel;
+ State(
+ const glm::dvec3 &pos = glm::dvec3(0.0),
+ const glm::dvec3 &vel = glm::dvec3(0.0))
+ : pos(pos), vel(vel) { }
+ };
+ struct Derivative {
+ glm::dvec3 vel;
+ glm::dvec3 acc;
+ Derivative(
+ const glm::dvec3 &vel = glm::dvec3(0.0),
+ const glm::dvec3 &acc = glm::dvec3(0.0))
+ : vel(vel), acc(acc) { }
+ };
+
public:
Situation();
~Situation();
world::Planet &GetPlanet() const noexcept { return *planet; }
bool OnSurface() const noexcept;
int Surface() const noexcept { return surface; }
- const glm::dvec3 &Position() const noexcept { return position; }
+ const glm::dvec3 &Position() const noexcept { return state.pos; }
bool OnTile() const noexcept;
glm::ivec2 SurfacePosition() const noexcept;
world::Tile &GetTile() const noexcept;
const world::TileType &GetTileType() const noexcept;
+ void SetState(const State &s) noexcept { state = s; }
+ const State &GetState() const noexcept { return state; }
+
+ bool Moving() const noexcept { return glm::length2(state.vel) < 0.00000001; }
void Move(const glm::dvec3 &dp) noexcept;
void SetPlanetSurface(world::Planet &, int srf, const glm::dvec3 &pos) noexcept;
public:
world::Planet *planet;
- glm::dvec3 position;
+ State state;
int surface;
enum {
LOST,
, goals()
, situation()
, steering()
-, vel(0.0)
, vao() {
}
}
void Creature::Tick(double dt) {
- // TODO: better integration method
- glm::dvec3 acc(steering.Acceleration(*this));
- situation.Move(vel * dt);
- vel += acc * dt;
+ {
+ Situation::State state(situation.GetState());
+ Situation::Derivative a(Step(Situation::Derivative(), 0.0));
+ Situation::Derivative b(Step(a, dt * 0.5));
+ Situation::Derivative c(Step(b, dt * 0.5));
+ 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)
+ );
+ state.pos += f.vel * dt;
+ state.vel += f.acc * dt;
+ situation.SetState(state);
+ }
if (Age() > properties.death_age) {
std::cout << "[" << int(sim.Time()) << "s] "
}
}
+Situation::Derivative Creature::Step(const Situation::Derivative &ds, double dt) const noexcept {
+ Situation::State s = situation.GetState();
+ s.pos += ds.vel * dt;
+ s.vel += ds.acc * dt;
+ return { s.vel, steering.Acceleration(s) };
+}
+
glm::dmat4 Creature::LocalTransform() noexcept {
// TODO: surface transform
const double half_size = size * 0.5;
Situation::Situation()
: planet(nullptr)
-, position(0.0)
+, state(glm::dvec3(0.0), glm::dvec3(0.0))
, surface(0)
, type(LOST) {
}
}
bool Situation::OnTile() const noexcept {
- glm::ivec2 t(planet->SurfacePosition(surface, position));
+ glm::ivec2 t(planet->SurfacePosition(surface, state.pos));
return type == PLANET_SURFACE
&& t.x >= 0 && t.x < planet->SideLength()
&& t.y >= 0 && t.y < planet->SideLength();
}
glm::ivec2 Situation::SurfacePosition() const noexcept {
- return planet->SurfacePosition(surface, position);
+ return planet->SurfacePosition(surface, state.pos);
}
world::Tile &Situation::GetTile() const noexcept {
- glm::ivec2 t(planet->SurfacePosition(surface, position));
+ glm::ivec2 t(planet->SurfacePosition(surface, state.pos));
return planet->TileAt(surface, t.x, t.y);
}
const world::TileType &Situation::GetTileType() const noexcept {
- glm::ivec2 t(planet->SurfacePosition(surface, position));
+ glm::ivec2 t(planet->SurfacePosition(surface, state.pos));
return planet->TypeAt(surface, t.x, t.y);
}
void Situation::Move(const glm::dvec3 &dp) noexcept {
- position += dp;
+ state.pos += dp;
if (OnSurface()) {
// enforce ground constraint
if (Surface() < 3) {
- position[(Surface() + 2) % 3] = std::max(0.0, position[(Surface() + 2) % 3]);
+ state.pos[(Surface() + 2) % 3] = std::max(0.0, state.pos[(Surface() + 2) % 3]);
} else {
- position[(Surface() + 2) % 3] = std::min(0.0, position[(Surface() + 2) % 3]);
+ state.pos[(Surface() + 2) % 3] = std::min(0.0, state.pos[(Surface() + 2) % 3]);
}
}
}
type = PLANET_SURFACE;
planet = &p;
surface = srf;
- position = pos;
+ state.pos = pos;
}
seeking = true;
}
-glm::dvec3 Steering::Acceleration(Creature &c) const noexcept {
+glm::dvec3 Steering::Acceleration(const Situation::State &s) const noexcept {
glm::dvec3 acc(0.0);
if (halting) {
- SumForce(acc, c.Velocity() * -max_accel);
+ SumForce(acc, s.vel * -max_accel);
}
if (seeking) {
- glm::dvec3 diff = seek_target - c.GetSituation().Position();
+ glm::dvec3 diff = seek_target - s.pos;
if (!allzero(diff)) {
- SumForce(acc, ((normalize(diff) * max_speed) - c.Velocity()) * max_accel);
+ SumForce(acc, ((normalize(diff) * max_speed) - s.vel) * max_accel);
}
}
return acc;