]> git.localhorst.tv Git - blobs.git/commitdiff
load universe from file
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Mon, 18 Dec 2017 12:34:43 +0000 (13:34 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Mon, 18 Dec 2017 12:34:43 +0000 (13:34 +0100)
assets
src/app/Assets.hpp
src/app/app.cpp
src/app/states.cpp
src/blobs.cpp
src/world/Simulation.hpp
src/world/sim.cpp
tst/app/AssetTest.cpp
tst/app/AssetTest.hpp

diff --git a/assets b/assets
index 7c4c2fb847cfdf25d90d6b2c46442b8cf899a96a..ea14b7c01b5470c7f10eb349f355a6885ea184d4 160000 (submodule)
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 7c4c2fb847cfdf25d90d6b2c46442b8cf899a96a
+Subproject commit ea14b7c01b5470c7f10eb349f355a6885ea184d4
index 0d725ccef34a527e1c5c540a1df91f96256db9c8..950ad34cc580656c04637f71a3e36b28edaedd3c 100644 (file)
@@ -23,6 +23,12 @@ namespace blobs {
 namespace io {
        class TokenStreamReader;
 }
+namespace world {
+       class Body;
+       class Planet;
+       class Simulation;
+       class Sun;
+}
 namespace app {
 
 struct Assets {
@@ -80,6 +86,12 @@ struct Assets {
        void LoadSkinTexture(const std::string &name, graphics::ArrayTexture &, int layer) const;
        void LoadSkyTexture(const std::string &name, graphics::CubeMap &) const;
 
+       void LoadUniverse(const std::string &name, world::Simulation &) const;
+       world::Body *ReadBody(io::TokenStreamReader &, world::Simulation &) const;
+       void ReadBodyProperty(const std::string &name, io::TokenStreamReader &, world::Body &, world::Simulation &) const;
+       void ReadPlanetProperty(const std::string &name, io::TokenStreamReader &, world::Planet &, world::Simulation &) const;
+       void ReadSunProperty(const std::string &name, io::TokenStreamReader &, world::Sun &, world::Simulation &) const;
+
 };
 
 }
index 0f50aa75d00104a21fe5a32a988bef297a98580f..950eda8cb3610c08e779ea478c578a68abc90c2b 100644 (file)
@@ -6,6 +6,9 @@
 #include "../graphics/Viewport.hpp"
 #include "../io/Token.hpp"
 #include "../io/TokenStreamReader.hpp"
+#include "../world/Planet.hpp"
+#include "../world/Simulation.hpp"
+#include "../world/Sun.hpp"
 
 #include <fstream>
 #include <SDL.h>
@@ -457,5 +460,138 @@ void Assets::LoadSkyTexture(const string &name, graphics::CubeMap &cm) const {
        SDL_FreeSurface(srf);
 }
 
+void Assets::LoadUniverse(const string &name, world::Simulation &sim) const {
+       std::ifstream universe_file(data_path + name);
+       io::TokenStreamReader universe_reader(universe_file);
+       ReadBody(universe_reader, sim);
+       universe_reader.Skip(io::Token::SEMICOLON);
+}
+
+world::Body *Assets::ReadBody(io::TokenStreamReader &in, world::Simulation &sim) const {
+       std::unique_ptr<world::Body> body;
+       string name;
+       in.ReadIdentifier(name);
+       if (name == "Sun") {
+               world::Sun *sun = new world::Sun;
+               body.reset(sun);
+               sim.AddSun(*sun);
+               in.Skip(io::Token::ANGLE_BRACKET_OPEN);
+               while (in.Peek().type != io::Token::ANGLE_BRACKET_CLOSE) {
+                       in.ReadIdentifier(name);
+                       in.Skip(io::Token::EQUALS);
+                       ReadSunProperty(name, in, *sun, sim);
+                       in.Skip(io::Token::SEMICOLON);
+               }
+               in.Skip(io::Token::ANGLE_BRACKET_CLOSE);
+               in.Skip(io::Token::SEMICOLON);
+       } else if (name == "Planet") {
+               in.Skip(io::Token::PARENTHESIS_OPEN);
+               int sidelength = in.GetInt();
+               in.Skip(io::Token::PARENTHESIS_CLOSE);
+               world::Planet *planet = new world::Planet(sidelength);
+               sim.AddPlanet(*planet);
+               body.reset(planet);
+               in.Skip(io::Token::ANGLE_BRACKET_OPEN);
+               while (in.Peek().type != io::Token::ANGLE_BRACKET_CLOSE) {
+                       in.ReadIdentifier(name);
+                       in.Skip(io::Token::EQUALS);
+                       ReadPlanetProperty(name, in, *planet, sim);
+                       in.Skip(io::Token::SEMICOLON);
+               }
+               in.Skip(io::Token::ANGLE_BRACKET_CLOSE);
+       } else {
+               throw std::runtime_error("unknown body class " + name);
+       }
+       return body.release();
+}
+
+void Assets::ReadSunProperty(const std::string &name, io::TokenStreamReader &in, world::Sun &sun, world::Simulation &sim) const {
+       if (name == "color") {
+               glm::dvec3 color(0.0);
+               in.ReadVec(color);
+               sun.Color(color);
+       } else if (name == "luminosity") {
+               sun.Luminosity(in.GetDouble());
+       } else {
+               ReadBodyProperty(name, in, sun, sim);
+       }
+}
+
+void Assets::ReadPlanetProperty(const std::string &name, io::TokenStreamReader &in, world::Planet &planet, world::Simulation &sim) const {
+       if (name == "generate") {
+               string gen;
+               in.ReadIdentifier(gen);
+               if (gen == "earthlike") {
+                       world::GenerateEarthlike(data.tile_types, planet);
+               } else if (gen == "test") {
+                       world::GenerateTest(data.tile_types, planet);
+               } else {
+                       throw std::runtime_error("unknown surface generator " + gen);
+               }
+       } else if (name == "atmosphere") {
+               string atm;
+               in.ReadIdentifier(atm);
+               planet.Atmosphere(data.resources[atm].id);
+       } else {
+               ReadBodyProperty(name, in, planet, sim);
+       }
+}
+
+void Assets::ReadBodyProperty(const std::string &name, io::TokenStreamReader &in, world::Body &body, world::Simulation &sim) const {
+       if (name == "name") {
+               string value;
+               in.ReadString(value);
+               body.Name(value);
+       } else if (name == "mass") {
+               body.Mass(in.GetDouble());
+       } else if (name == "radius") {
+               body.Radius(in.GetDouble());
+       } else if (name == "axial_tilt") {
+               glm::dvec2 tilt(0.0);
+               in.ReadVec(tilt);
+               body.AxialTilt(tilt);
+       } else if (name == "rotation") {
+               body.Rotation(in.GetDouble());
+       } else if (name == "angular_momentum") {
+               body.AngularMomentum(in.GetDouble());
+       } else if (name == "orbit") {
+               in.Skip(io::Token::ANGLE_BRACKET_OPEN);
+               while (in.Peek().type != io::Token::ANGLE_BRACKET_CLOSE) {
+                       string oname;
+                       in.ReadIdentifier(oname);
+                       in.Skip(io::Token::EQUALS);
+                       if (oname == "SMA" || oname == "semi_major_axis") {
+                               body.GetOrbit().SemiMajorAxis(in.GetDouble());
+                       } else if (oname == "ECC" || oname == "eccentricity") {
+                               body.GetOrbit().Eccentricity(in.GetDouble());
+                       } else if (oname == "INC" || oname == "inclination") {
+                               body.GetOrbit().Inclination(in.GetDouble());
+                       } else if (oname == "ASC" || oname == "ascending_node" || oname == "longitude_ascending") {
+                               body.GetOrbit().LongitudeAscending(in.GetDouble());
+                       } else if (oname == "ARG" || oname == "APE" || oname == "argument_periapsis") {
+                               body.GetOrbit().ArgumentPeriapsis(in.GetDouble());
+                       } else if (oname == "MNA" || oname == "mean_anomaly") {
+                               body.GetOrbit().MeanAnomaly(in.GetDouble());
+                       } else {
+                               throw std::runtime_error("unknown orbit property " + oname);
+                       }
+                       in.Skip(io::Token::SEMICOLON);
+               }
+               in.Skip(io::Token::ANGLE_BRACKET_CLOSE);
+       } else if (name == "children") {
+               in.Skip(io::Token::BRACKET_OPEN);
+               while (in.Peek().type != io::Token::BRACKET_CLOSE) {
+                       world::Body *b = ReadBody(in, sim);
+                       b->SetParent(body);
+                       if (in.Peek().type == io::Token::COMMA) {
+                               in.Skip(io::Token::COMMA);
+                       }
+               }
+               in.Skip(io::Token::BRACKET_CLOSE);
+       } else {
+               throw std::runtime_error("unknown body property " + name);
+       }
+}
+
 }
 }
index 3736331cb54532935d4b16ec9ac0098eae19f09a..8af5a8515815db212e2c646d5e57fa3ad1ab4f8c 100644 (file)
@@ -25,7 +25,7 @@ MasterState::MasterState(Assets &assets, world::Simulation &sim) noexcept
 : State()
 , assets(assets)
 , sim(sim)
-, cam(sim.Root())
+, cam(**sim.Suns().begin())
 , cam_pos(0.0, 0.0, 1.0)
 , cam_tgt_pos(0.0, 0.0, 1.0)
 , cam_focus(0.0)
index 475c3fac9c548494c209fd0b73164ed3e00bfe4d..9562f84cde5740a5f3c820293c2f01a11eade3f2 100644 (file)
@@ -19,53 +19,12 @@ int main(int argc, char *argv[]) {
        app::Init init(true, 8);
        app::Assets assets;
 
-       world::Sun sun;
-       sun.Name("Sun");
-       sun.Mass(1.0e17);
-       sun.Radius(200.0);
-       sun.Color(glm::dvec3(1.0));
-       sun.Luminosity(1.0e8);
-       sun.AxialTilt(glm::dvec2(PI * 0.25, PI * 0.25));
-       sun.AngularMomentum(1.0e18);
-
-       world::Planet planet(25);
-       planet.Name("Planet");
-       planet.SetParent(sun);
-       planet.Mass(1.0e13);
-       planet.GetOrbit().SemiMajorAxis(8184.0);
-       planet.AxialTilt(glm::dvec2(PI * 0.127, 0.0));
-       planet.AngularMomentum(6.5e13);
-
-       world::Planet moon(5);
-       moon.Name("Moon");
-       moon.SetParent(planet);
-       moon.Mass(1.0e7);
-       moon.GetOrbit().SemiMajorAxis(72.5);
-       moon.Rotation(PI * 0.25);
-       moon.AngularMomentum(5.22e5);
-
-       world::Planet second_planet(14);
-       second_planet.Name("Second planet");
-       second_planet.SetParent(sun);
-       second_planet.Mass(1.0e12);
-       second_planet.GetOrbit().SemiMajorAxis(4350.0);
-       second_planet.AxialTilt(glm::dvec2(PI * 0.95, 0.0));
-       second_planet.AngularMomentum(1.0e12);
-
-       world::Simulation sim(sun, assets);
-       sim.AddSun(sun);
-       sim.AddPlanet(planet);
-       sim.AddPlanet(second_planet);
-       sim.AddPlanet(moon);
-
-       world::GenerateEarthlike(assets.data.tile_types, planet);
-       planet.Atmosphere(assets.data.resources["air"].id);
-       world::GenerateTest(assets.data.tile_types, moon);
-       world::GenerateTest(assets.data.tile_types, second_planet);
+       world::Simulation sim(assets);
+       assets.LoadUniverse("universe", sim);
 
        auto blob = new creature::Creature(sim);
        blob->Name(assets.name.Sequential());
-       Spawn(*blob, planet);
+       Spawn(*blob, sim.PlanetByName("Planet"));
        // decrease chances of ur-blob dying without splitting
        blob->GetProperties().Fertility() = 1.0;
        blob->BuildVAO();
index 3be86a7b130fd9c42166eb746f5c387fd5432e27..3357e520ec86d0ee0619ab4e78e56c386ae8a15c 100644 (file)
@@ -25,7 +25,7 @@ class TileType;
 class Simulation {
 
 public:
-       explicit Simulation(Body &root, app::Assets &);
+       explicit Simulation(app::Assets &);
        ~Simulation();
 
        Simulation(const Simulation &) = delete;
@@ -37,9 +37,6 @@ public:
 public:
        void Tick(double dt);
 
-       Body &Root() noexcept { return root; }
-       const Body &Root() const noexcept { return root; }
-
        app::Assets &Assets() noexcept { return assets; }
        const app::Assets &Assets() const noexcept { return assets; }
        const Set<Resource> &Resources() const noexcept { return assets.data.resources; }
@@ -52,6 +49,7 @@ public:
        const std::set<Body *> &Bodies() const noexcept { return bodies; }
        const std::set<Planet *> &Planets() const noexcept { return planets; }
        const std::set<Sun *> &Suns() const noexcept { return suns; }
+       Planet &PlanetByName(const std::string &);
 
        void SetAlive(creature::Creature *);
        std::vector<creature::Creature *> &LiveCreatures() noexcept { return alive; }
@@ -70,7 +68,6 @@ public:
        std::ostream &Log();
 
 private:
-       Body &root;
        app::Assets &assets;
 
        std::set<Body *> bodies;
index 350d2440f0a8739a877bcbf86c6b7072bcca8477..8b4ecd47a7be431c1f7a7a392bfa6fd970f0d75b 100644 (file)
@@ -69,9 +69,8 @@ std::string Record::ValueString(int i) const {
        }
 }
 
-Simulation::Simulation(Body &r, app::Assets &assets)
-: root(r)
-, assets(assets)
+Simulation::Simulation(app::Assets &assets)
+: assets(assets)
 , bodies()
 , planets()
 , suns()
@@ -79,7 +78,6 @@ Simulation::Simulation(Body &r, app::Assets &assets)
 , dead()
 , time(0.0)
 , records(7) {
-       AddBody(r);
        records[0].name = "Age";
        records[0].type = Record::TIME;
        records[1].name = "Mass";
@@ -126,6 +124,15 @@ void Simulation::AddSun(Sun &s) {
        suns.insert(&s);
 }
 
+Planet &Simulation::PlanetByName(const std::string &name) {
+       for (auto &p : planets) {
+               if (p->Name() == name) {
+                       return *p;
+               }
+       }
+       throw std::runtime_error("planet named \"" + name + "\" not found");
+}
+
 void Simulation::SetAlive(creature::Creature *c) {
        alive.push_back(c);
 }
index d6b5a0e8b9899dc59da270c77c32f20fa5ce8472..2bd132fb9efa5d923f5f7bab6f3c77f0f4e0ad41 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "app/Assets.hpp"
 #include "app/init.hpp"
+#include "world/Simulation.hpp"
 
 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(blobs::app::test::AssetTest, "headed");
 
@@ -17,7 +18,7 @@ void AssetTest::tearDown() {
 }
 
 
-void AssetTest::testLoadAll() {
+void AssetTest::testLoadBasic() {
        Init init(false, 1);
        Assets assets;
 
@@ -70,6 +71,27 @@ void AssetTest::testLoadAll() {
        );
 }
 
+void AssetTest::testLoadUniverse() {
+       Init init(false, 1);
+       Assets assets;
+
+       world::Simulation sim(assets);
+       assets.LoadUniverse("universe", sim);
+
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "wrong number of suns in default universe",
+               std::set<world::Sun *>::size_type(1), sim.Suns().size()
+       );
+       CPPUNIT_ASSERT_EQUAL_MESSAGE(
+               "wrong number of planets in default universe",
+               std::set<world::Planet *>::size_type(3), sim.Planets().size()
+       );
+       CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+               "spawn planet does not exist",
+               sim.PlanetByName("Planet")
+       );
+}
+
 }
 }
 }
index fa158bf3ff4f33acc2a6a0df1cab88b4b5660638..9fbe728f1b7014662608c59b8c9db044518b8ab7 100644 (file)
@@ -13,7 +13,8 @@ class AssetTest
 
 CPPUNIT_TEST_SUITE(AssetTest);
 
-CPPUNIT_TEST(testLoadAll);
+CPPUNIT_TEST(testLoadBasic);
+CPPUNIT_TEST(testLoadUniverse);
 
 CPPUNIT_TEST_SUITE_END();
 
@@ -21,7 +22,8 @@ public:
        void setUp();
        void tearDown();
 
-       void testLoadAll();
+       void testLoadBasic();
+       void testLoadUniverse();
 
 };