From: Daniel Karbach Date: Sun, 19 Nov 2017 15:06:32 +0000 (+0100) Subject: basic needs X-Git-Url: http://git.localhorst.tv/?p=blobs.git;a=commitdiff_plain;h=343b4f7e7cdd53dc1eab7dc32196ae5fa604ba48 basic needs --- diff --git a/src/app/states.cpp b/src/app/states.cpp index 5a9ae0a..d344e87 100644 --- a/src/app/states.cpp +++ b/src/app/states.cpp @@ -1,7 +1,7 @@ #include "MasterState.hpp" +#include "../creature/Creature.hpp" #include "../world/Body.hpp" -#include "../world/Creature.hpp" #include "../world/Planet.hpp" #include "../world/Simulation.hpp" #include "../world/Sun.hpp" diff --git a/src/blobs.cpp b/src/blobs.cpp index e0a4769..49813d5 100644 --- a/src/blobs.cpp +++ b/src/blobs.cpp @@ -3,7 +3,7 @@ #include "app/Assets.hpp" #include "app/init.hpp" #include "app/MasterState.hpp" -#include "world/Creature.hpp" +#include "creature/Creature.hpp" #include "world/Planet.hpp" #include "world/Set.hpp" #include "world/Simulation.hpp" @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) { std::cout << "moon cycle in days: " << (moon.OrbitalPeriod() / planet.RotationalPeriod()) << std::endl; std::cout << "moon cycles per year: " << (planet.OrbitalPeriod() / moon.OrbitalPeriod()) << std::endl; - auto blob = new world::Creature; + auto blob = new creature::Creature; blob->BuildVAO(); Spawn(*blob, planet, assets); diff --git a/src/creature/Creature.hpp b/src/creature/Creature.hpp new file mode 100644 index 0000000..e912553 --- /dev/null +++ b/src/creature/Creature.hpp @@ -0,0 +1,84 @@ +#ifndef BLOBS_CREATURE_CREATURE_HPP_ +#define BLOBS_CREATURE_CREATURE_HPP_ + +#include "Need.hpp" +#include "../graphics/glm.hpp" +#include "../graphics/SimpleVAO.hpp" + +#include +#include + + +namespace blobs { +namespace app { + struct Assets; +} +namespace graphics { + class Viewport; +} +namespace world { + class Body; + class Planet; +} +namespace creature { + +class Creature { + +public: + Creature(); + ~Creature(); + + Creature(const Creature &) = delete; + Creature &operator =(const Creature &) = delete; + + Creature(Creature &&) = delete; + Creature &operator =(Creature &&) = delete; + +public: + void SetBody(world::Body &b) noexcept { body = &b; } + world::Body &GetBody() noexcept { return *body; } + const world::Body &GetBody() const noexcept { return *body; } + + void Surface(int s) noexcept { surface = s; } + void Position(const glm::dvec3 &p) noexcept { position = p; } + + void Name(const std::string &n) noexcept { name = n; } + const std::string &Name() const noexcept { return name; } + + void Health(double h) noexcept { health = h; } + double Health() const noexcept { return health; } + + void AddNeed(const Need &n) { needs.push_back(n); } + + void Tick(double dt); + + glm::dmat4 LocalTransform() noexcept; + + void BuildVAO(); + void Draw(app::Assets &, graphics::Viewport &); + +private: + world::Body *body; + int surface; + glm::dvec3 position; + + std::string name; + double health; + std::vector needs; + + struct Attributes { + glm::vec3 position; + glm::vec3 normal; + glm::vec3 texture; + }; + graphics::SimpleVAO vao; + +}; + +/// put creature on planet and configure it to (hopefully) survive +void Spawn(Creature &, world::Planet &, app::Assets &); + +} +} + +#endif diff --git a/src/creature/Need.hpp b/src/creature/Need.hpp new file mode 100644 index 0000000..93d46e8 --- /dev/null +++ b/src/creature/Need.hpp @@ -0,0 +1,28 @@ +#ifndef BLOBS_CREATURE_NEED_HPP_ +#define BLOBS_CREATURE_NEED_HPP_ + +namespace blobs { +namespace creature { + +struct Need { + + int resource = -1; + double value = 0.0; + + // how fast value grows per second + double gain = 0.0; + // the value at which this need is no longer satisfied + double critical = 0.0; + // the price to pay for not satsfying the need + double penalty = 0.0; + + void Tick(double dt) noexcept; + + bool IsSatisfied() const noexcept { return value < critical; } + +}; + +} +} + +#endif diff --git a/src/creature/creature.cpp b/src/creature/creature.cpp new file mode 100644 index 0000000..ed8551c --- /dev/null +++ b/src/creature/creature.cpp @@ -0,0 +1,201 @@ +#include "Creature.hpp" +#include "Need.hpp" + +#include "../app/Assets.hpp" +#include "../world/Body.hpp" +#include "../world/Planet.hpp" +#include "../world/TileType.hpp" + +#include + +#include + + +namespace blobs { +namespace creature { + +Creature::Creature() +: body(nullptr) +, surface(0) +, position() +, name() +, health(1.0) +, needs() +, vao() { +} + +Creature::~Creature() { +} + + +void Creature::Tick(double dt) { + for (Need &need : needs) { + need.Tick(dt); + if (!need.IsSatisfied()) { + health = std::max(0.0, health - need.penalty * dt); + } + } +} + +glm::dmat4 Creature::LocalTransform() noexcept { + // TODO: surface transform + constexpr double half_height = 0.25; + return glm::translate(glm::dvec3(position.x, position.y, position.z + body->Radius() + half_height)) + * glm::scale(glm::dvec3(half_height, half_height, half_height)); +} + +void Creature::BuildVAO() { + vao.Bind(); + vao.BindAttributes(); + vao.EnableAttribute(0); + vao.EnableAttribute(1); + vao.EnableAttribute(2); + vao.AttributePointer(0, false, offsetof(Attributes, position)); + vao.AttributePointer(1, false, offsetof(Attributes, normal)); + vao.AttributePointer(2, false, offsetof(Attributes, texture)); + vao.ReserveAttributes(6 * 4, GL_STATIC_DRAW); + { + auto attrib = vao.MapAttributes(GL_WRITE_ONLY); + const float offset = 1.0f; + for (int surface = 0; surface < 6; ++surface) { + const float tex_u_begin = surface < 3 ? 1.0f : 0.0f; + const float tex_u_end = surface < 3 ? 0.0f : 1.0f; + + attrib[4 * surface + 0].position[(surface + 0) % 3] = -offset; + attrib[4 * surface + 0].position[(surface + 1) % 3] = -offset; + attrib[4 * surface + 0].position[(surface + 2) % 3] = surface < 3 ? offset : -offset; + attrib[4 * surface + 0].normal[(surface + 0) % 3] = 0.0f; + attrib[4 * surface + 0].normal[(surface + 1) % 3] = 0.0f; + attrib[4 * surface + 0].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f; + attrib[4 * surface + 0].texture.x = tex_u_begin; + attrib[4 * surface + 0].texture.y = 1.0f; + attrib[4 * surface + 0].texture.z = surface; + + attrib[4 * surface + 1].position[(surface + 0) % 3] = -offset; + attrib[4 * surface + 1].position[(surface + 1) % 3] = offset; + attrib[4 * surface + 1].position[(surface + 2) % 3] = surface < 3 ? offset : -offset; + attrib[4 * surface + 1].normal[(surface + 0) % 3] = 0.0f; + attrib[4 * surface + 1].normal[(surface + 1) % 3] = 0.0f; + attrib[4 * surface + 1].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f; + attrib[4 * surface + 1].texture.x = tex_u_end; + attrib[4 * surface + 1].texture.y = 1.0f; + attrib[4 * surface + 1].texture.z = surface; + + attrib[4 * surface + 2].position[(surface + 0) % 3] = offset; + attrib[4 * surface + 2].position[(surface + 1) % 3] = -offset; + attrib[4 * surface + 2].position[(surface + 2) % 3] = surface < 3 ? offset : -offset; + attrib[4 * surface + 2].normal[(surface + 0) % 3] = 0.0f; + attrib[4 * surface + 2].normal[(surface + 1) % 3] = 0.0f; + attrib[4 * surface + 2].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f; + attrib[4 * surface + 2].texture.x = tex_u_begin; + attrib[4 * surface + 2].texture.y = 0.0f; + attrib[4 * surface + 2].texture.z = surface; + + attrib[4 * surface + 3].position[(surface + 0) % 3] = offset; + attrib[4 * surface + 3].position[(surface + 1) % 3] = offset; + attrib[4 * surface + 3].position[(surface + 2) % 3] = surface < 3 ? offset : -offset; + attrib[4 * surface + 3].normal[(surface + 0) % 3] = 0.0f; + attrib[4 * surface + 3].normal[(surface + 1) % 3] = 0.0f; + attrib[4 * surface + 3].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f; + attrib[4 * surface + 3].texture.x = tex_u_end; + attrib[4 * surface + 3].texture.y = 0.0f; + attrib[4 * surface + 3].texture.z = surface; + } + } + vao.BindElements(); + vao.ReserveElements(6 * 6, GL_STATIC_DRAW); + { + auto element = vao.MapElements(GL_WRITE_ONLY); + for (int surface = 0; surface < 3; ++surface) { + element[6 * surface + 0] = 4 * surface + 0; + element[6 * surface + 1] = 4 * surface + 2; + element[6 * surface + 2] = 4 * surface + 1; + element[6 * surface + 3] = 4 * surface + 1; + element[6 * surface + 4] = 4 * surface + 2; + element[6 * surface + 5] = 4 * surface + 3; + } + for (int surface = 3; surface < 6; ++surface) { + element[6 * surface + 0] = 4 * surface + 0; + element[6 * surface + 1] = 4 * surface + 1; + element[6 * surface + 2] = 4 * surface + 2; + element[6 * surface + 3] = 4 * surface + 2; + element[6 * surface + 4] = 4 * surface + 1; + element[6 * surface + 5] = 4 * surface + 3; + } + } + vao.Unbind(); +} + +void Creature::Draw(app::Assets &assets, graphics::Viewport &viewport) { + vao.Bind(); + vao.DrawTriangles(6 * 6); +} + + +void Spawn(Creature &c, world::Planet &p, app::Assets &assets) { + p.AddCreature(&c); + c.Surface(0); + c.Position(glm::dvec3(0.0, 0.0, 0.0)); + + // probe surrounding area for common resources + int start = p.SideLength() / 2 - 2; + int end = start + 5; + std::map yields; + for (int y = start; y < end; ++y) { + for (int x = start; x < end; ++x) { + const world::TileType &t = assets.data.tiles[p.TileAt(0, x, y).type]; + for (auto yield : t.resources) { + yields[yield.resource] += yield.ubiquity; + } + } + } + int liquid = -1; + int solid = -1; + for (auto e : yields) { + if (assets.data.resources[e.first].state == world::Resource::LIQUID) { + if (liquid < 0 || e.second > yields[liquid]) { + liquid = e.first; + } + } else if (assets.data.resources[e.first].state == world::Resource::SOLID) { + if (solid < 0 || e.second > yields[solid]) { + solid = e.first; + } + } + } + + if (p.HasAtmosphere()) { + std::cout << "require breathing " << assets.data.resources[p.Atmosphere()].label << std::endl; + Need need; + need.resource = p.Atmosphere(); + need.gain = 0.25; + need.critical = 0.95; + need.penalty = 0.1; + c.AddNeed(need); + } + if (liquid > -1) { + std::cout << "require drinking " << assets.data.resources[liquid].label << std::endl; + Need need; + need.resource = liquid; + need.gain = 0.0001; + need.critical = 0.95; + need.penalty = 0.01; + c.AddNeed(need); + } + if (solid > -1) { + std::cout << "require eating " << assets.data.resources[solid].label << std::endl; + Need need; + need.resource = solid; + need.gain = 0.00001; + need.critical = 0.95; + need.penalty = 0.001; + c.AddNeed(need); + } +} + + +void Need::Tick(double dt) noexcept { + value = std::min(1.0, value + gain * dt); +} + +} +} diff --git a/src/world/Body.hpp b/src/world/Body.hpp index fba121b..3db5e37 100644 --- a/src/world/Body.hpp +++ b/src/world/Body.hpp @@ -11,12 +11,14 @@ namespace blobs { namespace app { class Assets; } +namespace creature { + class Creature; +} namespace graphics { class Viewport; } namespace world { -class Creature; class Simulation; class Body { @@ -82,12 +84,18 @@ public: virtual void Draw(app::Assets &, graphics::Viewport &) { } + void Tick(double dt); void Cache() noexcept; // body takes over ownership of given pointer - void AddCreature(Creature *); - std::vector &Creatures() noexcept { return creatures; } - const std::vector &Creatures() const noexcept { return creatures; } + void AddCreature(creature::Creature *); + void RemoveCreature(creature::Creature *); + std::vector &Creatures() noexcept { return creatures; } + const std::vector &Creatures() const noexcept { return creatures; } + + void Atmosphere(int a) noexcept { atmosphere = a; } + int Atmosphere() const noexcept { return atmosphere; } + bool HasAtmosphere() const noexcept { return atmosphere >= 0; } private: void AddChild(Body &); @@ -110,7 +118,8 @@ private: glm::dmat4 local; glm::dmat4 inverse_local; - std::vector creatures; + std::vector creatures; + int atmosphere; }; diff --git a/src/world/Creature.hpp b/src/world/Creature.hpp deleted file mode 100644 index 83623a2..0000000 --- a/src/world/Creature.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef BLOBS_WORLD_CREATURE_HPP_ -#define BLOBS_WORLD_CREATURE_HPP_ - -#include "../graphics/glm.hpp" -#include "../graphics/SimpleVAO.hpp" - - -namespace blobs { -namespace app { - struct Assets; -} -namespace graphics { - class Viewport; -} -namespace world { - -class Body; -class Planet; - -class Creature { - -public: - Creature(); - ~Creature(); - - Creature(const Creature &) = delete; - Creature &operator =(const Creature &) = delete; - - Creature(Creature &&) = delete; - Creature &operator =(Creature &&) = delete; - -public: - void SetBody(Body &b) noexcept { body = &b; } - Body &GetBody() noexcept { return *body; } - const Body &GetBody() const noexcept { return *body; } - - void Surface(int s) noexcept { surface = s; } - void Position(const glm::dvec3 &p) noexcept { position = p; } - - void RequireBreathing(int r) noexcept { breathes = r; } - int Breathes() const noexcept { return breathes; } - bool MustBreathe() const noexcept { return breathes > -1; } - - void RequireDrinking(int r) noexcept { drinks = r; } - int Drinks() const noexcept { return drinks; } - bool MustDrink() const noexcept { return drinks > -1; } - - void RequireEating(int r) noexcept { eats = r; } - int Eats() const noexcept { return eats; } - bool MustEat() const noexcept { return eats > -1; } - - glm::dmat4 LocalTransform() noexcept; - - void BuildVAO(); - void Draw(app::Assets &, graphics::Viewport &); - -private: - Body *body; - int surface; - glm::dvec3 position; - - int breathes; - int drinks; - int eats; - - struct Attributes { - glm::vec3 position; - glm::vec3 normal; - glm::vec3 texture; - }; - graphics::SimpleVAO vao; - -}; - -/// put creature on planet and configure it to (hopefully) survive -void Spawn(Creature &, Planet &, app::Assets &); - -} -} - -#endif diff --git a/src/world/Planet.hpp b/src/world/Planet.hpp index 991985f..af3b512 100644 --- a/src/world/Planet.hpp +++ b/src/world/Planet.hpp @@ -64,10 +64,6 @@ public: glm::dvec3 TileCenter(int surface, int x, int y) const noexcept; - void Atmosphere(int a) noexcept { atmosphere = a; } - int Atmosphere() const noexcept { return atmosphere; } - bool HasAtmosphere() const noexcept { return atmosphere >= 0; } - void BuildVAO(const Set &); void Draw(app::Assets &, graphics::Viewport &) override; @@ -75,8 +71,6 @@ private: int sidelength; std::vector tiles; - int atmosphere; - struct Attributes { glm::vec3 position; glm::vec3 tex_coord; diff --git a/src/world/creature.cpp b/src/world/creature.cpp deleted file mode 100644 index 8018e7c..0000000 --- a/src/world/creature.cpp +++ /dev/null @@ -1,171 +0,0 @@ -#include "Creature.hpp" - -#include "Body.hpp" -#include "Planet.hpp" -#include "TileType.hpp" -#include "../app/Assets.hpp" - -#include - -#include - - -namespace blobs { -namespace world { - -Creature::Creature() -: body(nullptr) -, surface(0) -, position() -, breathes(-1) -, drinks(-1) -, eats(-1) -, vao() { -} - -Creature::~Creature() { -} - - -glm::dmat4 Creature::LocalTransform() noexcept { - // TODO: surface transform - constexpr double half_height = 0.25; - return glm::translate(glm::dvec3(position.x, position.y, position.z + body->Radius() + half_height)) - * glm::scale(glm::dvec3(half_height, half_height, half_height)); -} - -void Creature::BuildVAO() { - vao.Bind(); - vao.BindAttributes(); - vao.EnableAttribute(0); - vao.EnableAttribute(1); - vao.EnableAttribute(2); - vao.AttributePointer(0, false, offsetof(Attributes, position)); - vao.AttributePointer(1, false, offsetof(Attributes, normal)); - vao.AttributePointer(2, false, offsetof(Attributes, texture)); - vao.ReserveAttributes(6 * 4, GL_STATIC_DRAW); - { - auto attrib = vao.MapAttributes(GL_WRITE_ONLY); - const float offset = 1.0f; - for (int surface = 0; surface < 6; ++surface) { - const float tex_u_begin = surface < 3 ? 1.0f : 0.0f; - const float tex_u_end = surface < 3 ? 0.0f : 1.0f; - - attrib[4 * surface + 0].position[(surface + 0) % 3] = -offset; - attrib[4 * surface + 0].position[(surface + 1) % 3] = -offset; - attrib[4 * surface + 0].position[(surface + 2) % 3] = surface < 3 ? offset : -offset; - attrib[4 * surface + 0].normal[(surface + 0) % 3] = 0.0f; - attrib[4 * surface + 0].normal[(surface + 1) % 3] = 0.0f; - attrib[4 * surface + 0].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f; - attrib[4 * surface + 0].texture.x = tex_u_begin; - attrib[4 * surface + 0].texture.y = 1.0f; - attrib[4 * surface + 0].texture.z = surface; - - attrib[4 * surface + 1].position[(surface + 0) % 3] = -offset; - attrib[4 * surface + 1].position[(surface + 1) % 3] = offset; - attrib[4 * surface + 1].position[(surface + 2) % 3] = surface < 3 ? offset : -offset; - attrib[4 * surface + 1].normal[(surface + 0) % 3] = 0.0f; - attrib[4 * surface + 1].normal[(surface + 1) % 3] = 0.0f; - attrib[4 * surface + 1].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f; - attrib[4 * surface + 1].texture.x = tex_u_end; - attrib[4 * surface + 1].texture.y = 1.0f; - attrib[4 * surface + 1].texture.z = surface; - - attrib[4 * surface + 2].position[(surface + 0) % 3] = offset; - attrib[4 * surface + 2].position[(surface + 1) % 3] = -offset; - attrib[4 * surface + 2].position[(surface + 2) % 3] = surface < 3 ? offset : -offset; - attrib[4 * surface + 2].normal[(surface + 0) % 3] = 0.0f; - attrib[4 * surface + 2].normal[(surface + 1) % 3] = 0.0f; - attrib[4 * surface + 2].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f; - attrib[4 * surface + 2].texture.x = tex_u_begin; - attrib[4 * surface + 2].texture.y = 0.0f; - attrib[4 * surface + 2].texture.z = surface; - - attrib[4 * surface + 3].position[(surface + 0) % 3] = offset; - attrib[4 * surface + 3].position[(surface + 1) % 3] = offset; - attrib[4 * surface + 3].position[(surface + 2) % 3] = surface < 3 ? offset : -offset; - attrib[4 * surface + 3].normal[(surface + 0) % 3] = 0.0f; - attrib[4 * surface + 3].normal[(surface + 1) % 3] = 0.0f; - attrib[4 * surface + 3].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f; - attrib[4 * surface + 3].texture.x = tex_u_end; - attrib[4 * surface + 3].texture.y = 0.0f; - attrib[4 * surface + 3].texture.z = surface; - } - } - vao.BindElements(); - vao.ReserveElements(6 * 6, GL_STATIC_DRAW); - { - auto element = vao.MapElements(GL_WRITE_ONLY); - for (int surface = 0; surface < 3; ++surface) { - element[6 * surface + 0] = 4 * surface + 0; - element[6 * surface + 1] = 4 * surface + 2; - element[6 * surface + 2] = 4 * surface + 1; - element[6 * surface + 3] = 4 * surface + 1; - element[6 * surface + 4] = 4 * surface + 2; - element[6 * surface + 5] = 4 * surface + 3; - } - for (int surface = 3; surface < 6; ++surface) { - element[6 * surface + 0] = 4 * surface + 0; - element[6 * surface + 1] = 4 * surface + 1; - element[6 * surface + 2] = 4 * surface + 2; - element[6 * surface + 3] = 4 * surface + 2; - element[6 * surface + 4] = 4 * surface + 1; - element[6 * surface + 5] = 4 * surface + 3; - } - } - vao.Unbind(); -} - -void Creature::Draw(app::Assets &assets, graphics::Viewport &viewport) { - vao.Bind(); - vao.DrawTriangles(6 * 6); -} - - -void Spawn(Creature &c, Planet &p, app::Assets &assets) { - p.AddCreature(&c); - c.Surface(0); - c.Position(glm::dvec3(0.0, 0.0, 0.0)); - - // probe surrounding area for common resources - int start = p.SideLength() / 2 - 2; - int end = start + 5; - std::map yields; - for (int y = start; y < end; ++y) { - for (int x = start; x < end; ++x) { - const TileType &t = assets.data.tiles[p.TileAt(0, x, y).type]; - for (auto yield : t.resources) { - yields[yield.resource] += yield.ubiquity; - } - } - } - int liquid = -1; - int solid = -1; - for (auto e : yields) { - if (assets.data.resources[e.first].state == Resource::LIQUID) { - if (liquid < 0 || e.second > yields[liquid]) { - liquid = e.first; - } - } else if (assets.data.resources[e.first].state == Resource::SOLID) { - if (solid < 0 || e.second > yields[solid]) { - solid = e.first; - } - } - } - - if (p.HasAtmosphere()) { - std::cout << "require breathing " << assets.data.resources[p.Atmosphere()].label << std::endl; - c.RequireBreathing(p.Atmosphere()); - } - if (liquid > -1) { - std::cout << "require drinking " << assets.data.resources[liquid].label << std::endl; - c.RequireDrinking(liquid); - } - if (solid > -1) { - std::cout << "require eating " << assets.data.resources[solid].label << std::endl; - c.RequireEating(solid); - } -} - -} -} diff --git a/src/world/sim.cpp b/src/world/sim.cpp index 8b4c214..aedc5cf 100644 --- a/src/world/sim.cpp +++ b/src/world/sim.cpp @@ -40,8 +40,7 @@ void Simulation::Tick() { constexpr double dt = 0.01666666666666666666666666666666; time += dt; for (auto body : bodies) { - body->Rotation(body->Rotation() + dt * body->AngularMomentum() / body->Inertia()); - body->Cache(); + body->Tick(dt); } } diff --git a/src/world/world.cpp b/src/world/world.cpp index 9f19b68..18cb241 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -8,9 +8,9 @@ #include "Tile.hpp" #include "TileType.hpp" -#include "Creature.hpp" #include "../const.hpp" #include "../app/Assets.hpp" +#include "../creature/Creature.hpp" #include "../graphics/Viewport.hpp" #include "../rand/OctaveNoise.hpp" #include "../rand/SimplexNoise.hpp" @@ -50,11 +50,12 @@ Body::Body() , inverse_orbital(1.0) , local(1.0) , inverse_local(1.0) -, creatures() { +, creatures() +, atmosphere(-1) { } Body::~Body() { - for (Creature *c : creatures) { + for (creature::Creature *c : creatures) { delete c; } } @@ -137,6 +138,14 @@ glm::dmat4 Body::FromUniverse() const noexcept { return m; } +void Body::Tick(double dt) { + rotation += dt * AngularMomentum() / Inertia(); + Cache(); + for (creature::Creature *c : Creatures()) { + c->Tick(dt); + } +} + void Body::Cache() noexcept { if (parent) { orbital = @@ -157,11 +166,18 @@ void Body::Cache() noexcept { * glm::eulerAngleY(-rotation); } -void Body::AddCreature(Creature *c) { +void Body::AddCreature(creature::Creature *c) { c->SetBody(*this); creatures.push_back(c); } +void Body::RemoveCreature(creature::Creature *c) { + auto entry = std::find(creatures.begin(), creatures.end(), c); + if (entry != creatures.end()) { + creatures.erase(entry); + } +} + Orbit::Orbit() : sma(1.0) @@ -268,7 +284,6 @@ Planet::Planet(int sidelength) : Body() , sidelength(sidelength) , tiles(TilesTotal()) -, atmosphere(-1) , vao() { Radius(double(sidelength) / 2.0); }