From: Daniel Karbach Date: Thu, 16 Nov 2017 22:47:17 +0000 (+0100) Subject: fun with resources X-Git-Url: http://git.localhorst.tv/?p=blobs.git;a=commitdiff_plain;h=7ae2bd120fd0e1800edc9cbeb61e72bd06ffcf10 fun with resources --- diff --git a/src/app/Assets.hpp b/src/app/Assets.hpp index 4ea7f57..05a45ac 100644 --- a/src/app/Assets.hpp +++ b/src/app/Assets.hpp @@ -5,6 +5,9 @@ #include "../graphics/CreatureSkin.hpp" #include "../graphics/PlanetSurface.hpp" #include "../graphics/SunSurface.hpp" +#include "../world/Resource.hpp" +#include "../world/Set.hpp" +#include "../world/TileType.hpp" #include @@ -18,6 +21,11 @@ struct Assets { std::string tile_path; std::string skin_path; + struct { + world::Set resources; + world::Set tiles; + } data; + struct { graphics::ArrayTexture tiles; graphics::ArrayTexture skins; diff --git a/src/app/app.cpp b/src/app/app.cpp index 62de9ab..cfdbf80 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -169,6 +169,55 @@ Assets::Assets() : path("assets/") , tile_path(path + "tiles/") , skin_path(path + "skins/") { + data.resources.Add({ "air", "Air", 0 }); + data.resources.Add({ "biomass", "Biomass", 0 }); + data.resources.Add({ "dirt", "Dirt", 0 }); + data.resources.Add({ "ice", "Ice", 0 }); + data.resources.Add({ "rock", "Rock", 0 }); + data.resources.Add({ "sand", "Sand", 0 }); + data.resources.Add({ "water", "Water", 0 }); + data.resources.Add({ "wood", "Wood", 0 }); + + data.tiles.Add({ "algae", "Algae", 0, 0 }); + data.tiles.Add({ "desert", "Desert", 0, 1 }); + data.tiles.Add({ "forest", "Forest", 0, 2 }); + data.tiles.Add({ "grass", "Grass", 0, 3 }); + data.tiles.Add({ "ice", "Ice", 0, 4 }); + data.tiles.Add({ "jungle", "Jungle", 0, 5 }); + data.tiles.Add({ "mountain", "Mountain", 0, 6 }); + data.tiles.Add({ "ocean", "Ocean", 0, 7 }); + data.tiles.Add({ "rock", "Rock", 0, 8 }); + data.tiles.Add({ "sand", "Sand", 0, 9 }); + data.tiles.Add({ "taiga", "Taiga", 0, 10 }); + data.tiles.Add({ "tundra", "Tundra", 0, 11 }); + data.tiles.Add({ "water", "Water", 0, 12 }); + data.tiles.Add({ "wheat", "Wheat", 0, 13 }); + + data.tiles["algae"] .resources.push_back({ data.resources["water"].id, 1.0 }); + data.tiles["algae"] .resources.push_back({ data.resources["biomass"].id, 0.5 }); + data.tiles["desert"] .resources.push_back({ data.resources["sand"].id, 1.0 }); + data.tiles["forest"] .resources.push_back({ data.resources["wood"].id, 1.0 }); + data.tiles["forest"] .resources.push_back({ data.resources["dirt"].id, 0.5 }); + data.tiles["grass"] .resources.push_back({ data.resources["dirt"].id, 0.5 }); + data.tiles["grass"] .resources.push_back({ data.resources["biomass"].id, 0.25 }); + data.tiles["grass"] .resources.push_back({ data.resources["water"].id, 0.25 }); + data.tiles["ice"] .resources.push_back({ data.resources["ice"].id, 1.0 }); + data.tiles["ice"] .resources.push_back({ data.resources["water"].id, 0.25 }); + data.tiles["jungle"] .resources.push_back({ data.resources["wood"].id, 0.5 }); + data.tiles["jungle"] .resources.push_back({ data.resources["biomass"].id, 0.5 }); + data.tiles["mountain"].resources.push_back({ data.resources["rock"].id, 1.0 }); + data.tiles["ocean"] .resources.push_back({ data.resources["water"].id, 1.0 }); + data.tiles["rock"] .resources.push_back({ data.resources["rock"].id, 1.0 }); + data.tiles["sand"] .resources.push_back({ data.resources["sand"].id, 1.0 }); + data.tiles["taiga"] .resources.push_back({ data.resources["wood"].id, 1.0 }); + data.tiles["taiga"] .resources.push_back({ data.resources["water"].id, 0.5 }); + data.tiles["tundra"] .resources.push_back({ data.resources["rock"].id, 1.0 }); + data.tiles["tundra"] .resources.push_back({ data.resources["ice"].id, 0.5 }); + data.tiles["water"] .resources.push_back({ data.resources["water"].id, 1.0 }); + data.tiles["water"] .resources.push_back({ data.resources["biomass"].id, 0.25 }); + data.tiles["wheat"] .resources.push_back({ data.resources["biomass"].id, 1.0 }); + data.tiles["wheat"] .resources.push_back({ data.resources["water"].id, 0.25 }); + graphics::Format format; textures.tiles.Bind(); textures.tiles.Reserve(256, 256, 14, format); @@ -186,6 +235,7 @@ Assets::Assets() LoadTileTexture("tundra", textures.tiles, 11); LoadTileTexture("water", textures.tiles, 12); LoadTileTexture("wheat", textures.tiles, 13); + textures.skins.Bind(); textures.skins.Reserve(256, 256, 9, format); LoadSkinTexture("1", textures.skins, 0); diff --git a/src/blobs.cpp b/src/blobs.cpp index dcc7590..9189256 100644 --- a/src/blobs.cpp +++ b/src/blobs.cpp @@ -5,9 +5,9 @@ #include "app/MasterState.hpp" #include "world/Creature.hpp" #include "world/Planet.hpp" +#include "world/Set.hpp" #include "world/Simulation.hpp" #include "world/Sun.hpp" -#include "world/TileSet.hpp" #include "world/TileType.hpp" #include @@ -20,22 +20,6 @@ int main(int argc, char *argv[]) { app::Init init(true, 8); app::Assets assets; - world::TileSet tiles; - tiles.Add({ "algae", "Algae", 0, 0 }); - tiles.Add({ "desert", "Desert", 0, 1 }); - tiles.Add({ "forest", "Forest", 0, 2 }); - tiles.Add({ "grass", "Grass", 0, 3 }); - tiles.Add({ "ice", "Ice", 0, 4 }); - tiles.Add({ "jungle", "Jungle", 0, 5 }); - tiles.Add({ "mountain", "Mountain", 0, 6 }); - tiles.Add({ "ocean", "Ocean", 0, 7 }); - tiles.Add({ "rock", "Rock", 0, 8 }); - tiles.Add({ "sand", "Sand", 0, 9 }); - tiles.Add({ "taiga", "Taiga", 0, 10 }); - tiles.Add({ "tundra", "Tundra", 0, 11 }); - tiles.Add({ "water", "Water", 0, 12 }); - tiles.Add({ "wheat", "Wheat", 0, 13 }); - world::Sun sun; sun.Mass(1.0e14); sun.Radius(20.0); @@ -71,9 +55,9 @@ int main(int argc, char *argv[]) { sim.AddPlanet(second_planet); sim.AddPlanet(moon); - world::GenerateEarthlike(tiles, planet); - world::GenerateTest(tiles, moon); - world::GenerateTest(tiles, second_planet); + world::GenerateEarthlike(assets.data.tiles, planet); + world::GenerateTest(assets.data.tiles, moon); + world::GenerateTest(assets.data.tiles, second_planet); std::cout << "length of year: " << planet.OrbitalPeriod() << "s" << std::endl; std::cout << "length of moon cycle: " << moon.OrbitalPeriod() << "s" << std::endl; diff --git a/src/world/Planet.hpp b/src/world/Planet.hpp index 900ebbb..af3b512 100644 --- a/src/world/Planet.hpp +++ b/src/world/Planet.hpp @@ -3,6 +3,7 @@ #include "Body.hpp" +#include "Set.hpp" #include "Tile.hpp" #include "../graphics/glm.hpp" #include "../graphics/SimpleVAO.hpp" @@ -15,7 +16,7 @@ namespace blobs { namespace world { -class TileSet; +class TileType; /// A planet has six surfaces, numbered 0 to 5, each filled with /// sidelength² tiles. @@ -63,7 +64,7 @@ public: glm::dvec3 TileCenter(int surface, int x, int y) const noexcept; - void BuildVAO(const TileSet &); + void BuildVAO(const Set &); void Draw(app::Assets &, graphics::Viewport &) override; private: @@ -78,8 +79,8 @@ private: }; -void GenerateEarthlike(const TileSet &, Planet &) noexcept; -void GenerateTest(const TileSet &, Planet &) noexcept; +void GenerateEarthlike(const Set &, Planet &) noexcept; +void GenerateTest(const Set &, Planet &) noexcept; } } diff --git a/src/world/Resource.hpp b/src/world/Resource.hpp new file mode 100644 index 0000000..5dd3834 --- /dev/null +++ b/src/world/Resource.hpp @@ -0,0 +1,22 @@ +#ifndef BLOBS_WORLD_RESOURCE_HPP_ +#define BLOBS_WORLD_RESOURCE_HPP_ + +#include + + +namespace blobs { +namespace world { + +struct Resource { + + std::string name; + std::string label; + + int id; + +}; + +} +} + +#endif diff --git a/src/world/Resources.hpp b/src/world/Resources.hpp new file mode 100644 index 0000000..af30af0 --- /dev/null +++ b/src/world/Resources.hpp @@ -0,0 +1,17 @@ +#ifndef BLOBS_WORLD_RESOURCES_HPP_ +#define BLOBS_WORLD_RESOURCES_HPP_ + + +namespace blobs { +namespace world { + +struct Resource; + +class Resources { + +}; + +} +} + +#endif diff --git a/src/world/Set.hpp b/src/world/Set.hpp new file mode 100644 index 0000000..c4aa6e9 --- /dev/null +++ b/src/world/Set.hpp @@ -0,0 +1,55 @@ +#ifndef BLOBS_WORLD_SET_HPP_ +#define BLOBS_WORLD_SET_HPP_ + +#include +#include +#include +#include + +namespace blobs { +namespace world { + +template +class Set { + +public: + int Add(const Type &t) { + int id = types.size(); + if (!names.emplace(t.name, id).second) { + throw std::runtime_error("duplicate type name " + t.name); + } + types.emplace_back(t); + types.back().id = id; + return id; + } + + Type &operator [](int id) noexcept { return types[id]; } + const Type &operator [](int id) const noexcept { return types[id]; } + + Type &operator [](const std::string &name) { + auto entry = names.find(name); + if (entry != names.end()) { + return types[entry->second]; + } else { + throw std::runtime_error("unknown type " + name); + } + } + const Type &operator [](const std::string &name) const { + auto entry = names.find(name); + if (entry != names.end()) { + return types[entry->second]; + } else { + throw std::runtime_error("unknown type " + name); + } + } + +private: + std::vector types; + std::map names; + +}; + +} +} + +#endif diff --git a/src/world/TileSet.hpp b/src/world/TileSet.hpp deleted file mode 100644 index 683109e..0000000 --- a/src/world/TileSet.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef BLOBS_WORLD_TILESET_HPP_ -#define BLOBS_WORLD_TILESET_HPP_ - -#include -#include -#include - -namespace blobs { -namespace world { - -class TileType; - -class TileSet { - -public: - TileSet(); - ~TileSet(); - - TileSet(const TileSet &) = delete; - TileSet &operator =(const TileSet &) = delete; - - TileSet(TileSet &&) = delete; - TileSet &operator =(TileSet &&) = delete; - -public: - int Add(const TileType &); - - TileType &operator [](int id) noexcept { return types[id]; } - const TileType &operator [](int id) const noexcept { return types[id]; } - - TileType &operator [](const std::string &name); - const TileType &operator [](const std::string &name) const; - -private: - std::vector types; - std::map names; - -}; - -} -} - -#endif diff --git a/src/world/TileType.hpp b/src/world/TileType.hpp index 58294df..c4eadcf 100644 --- a/src/world/TileType.hpp +++ b/src/world/TileType.hpp @@ -2,6 +2,7 @@ #define BLOBS_WORLD_TILETYPE_HPP_ #include +#include namespace blobs { @@ -15,6 +16,12 @@ struct TileType { int id; int texture; + struct Yield { + int resource; + double ubiquity; + }; + std::vector resources; + }; } diff --git a/src/world/world.cpp b/src/world/world.cpp index a3494b3..ed2ade3 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -1,10 +1,11 @@ #include "Body.hpp" #include "Orbit.hpp" #include "Planet.hpp" +#include "Resource.hpp" +#include "Set.hpp" #include "Simulation.hpp" #include "Sun.hpp" #include "Tile.hpp" -#include "TileSet.hpp" #include "TileType.hpp" #include "Creature.hpp" @@ -282,7 +283,7 @@ glm::dvec3 Planet::TileCenter(int surface, int x, int y) const noexcept { return center; } -void Planet::BuildVAO(const TileSet &ts) { +void Planet::BuildVAO(const Set &ts) { vao.Bind(); vao.BindAttributes(); vao.EnableAttribute(0); @@ -385,8 +386,9 @@ void Planet::Draw(app::Assets &assets, graphics::Viewport &viewport) { } -void GenerateEarthlike(const TileSet &tiles, Planet &p) noexcept { +void GenerateEarthlike(const Set &tiles, Planet &p) noexcept { rand::SimplexNoise elevation_gen(0); + rand::SimplexNoise variation_gen(45623752346); const int ice = tiles["ice"].id; const int ocean = tiles["ocean"].id; @@ -394,17 +396,24 @@ void GenerateEarthlike(const TileSet &tiles, Planet &p) noexcept { const int sand = tiles["sand"].id; const int grass = tiles["grass"].id; const int tundra = tiles["tundra"].id; + const int taiga = tiles["taiga"].id; const int desert = tiles["desert"].id; const int mntn = tiles["mountain"].id; + const int algae = tiles["algae"].id; + const int forest = tiles["forest"].id; + const int jungle = tiles["jungle"].id; + const int rock = tiles["rock"].id; + const int wheat = tiles["wheat"].id; constexpr double ocean_thresh = -0.2; constexpr double water_thresh = 0.0; - constexpr double beach_thresh = 0.1; + constexpr double beach_thresh = 0.05; + constexpr double highland_thresh = 0.4; constexpr double mountain_thresh = 0.5; const glm::dvec3 axis(glm::dvec4(0.0, 1.0, 0.0, 0.0) * glm::eulerAngleXY(p.SurfaceTilt().x, p.SurfaceTilt().y)); const double cap_thresh = std::abs(std::cos(p.AxialTilt().x)); - const double equ_thresh = 2.0 * (1.0 - cap_thresh); + const double equ_thresh = std::abs(std::sin(p.AxialTilt().x)) / 2.0; const double fzone_start = equ_thresh - (equ_thresh - cap_thresh) / 3.0; const double fzone_end = cap_thresh + (equ_thresh - cap_thresh) / 3.0; @@ -422,26 +431,58 @@ void GenerateEarthlike(const TileSet &tiles, Planet &p) noexcept { to_tile / p.Radius(), 3, // octaves 0.5, // persistence - 2 / p.Radius(), // frequency + 5 / p.Radius(), // frequency + 2, // amplitude + 2 // growth + ); + float variation = rand::OctaveNoise( + variation_gen, + to_tile / p.Radius(), + 3, // octaves + 0.5, // persistence + 16 / p.Radius(), // frequency 2, // amplitude 2 // growth ); if (elevation < ocean_thresh) { p.TileAt(surface, x, y).type = ocean; } else if (elevation < water_thresh) { - p.TileAt(surface, x, y).type = water; + if (variation > 0.3) { + p.TileAt(surface, x, y).type = algae; + } else { + p.TileAt(surface, x, y).type = water; + } } else if (elevation < beach_thresh) { p.TileAt(surface, x, y).type = sand; - } else if (elevation < mountain_thresh) { - // TODO: perturb climate rings a little + } else if (elevation < highland_thresh) { if (near_axis < equ_thresh) { - p.TileAt(surface, x, y).type = desert; + if (variation > 0.6) { + p.TileAt(surface, x, y).type = grass; + } else if (variation > 0.2) { + p.TileAt(surface, x, y).type = sand; + } else { + p.TileAt(surface, x, y).type = desert; + } } else if (near_axis < fzone_start) { - p.TileAt(surface, x, y).type = grass; + if (variation > 0.4) { + p.TileAt(surface, x, y).type = forest; + } else if (variation < -0.5) { + p.TileAt(surface, x, y).type = jungle; + } else if (variation > -0.02 && variation < 0.02) { + p.TileAt(surface, x, y).type = wheat; + } else { + p.TileAt(surface, x, y).type = grass; + } } else if (near_axis < fzone_end) { p.TileAt(surface, x, y).type = tundra; } else { - p.TileAt(surface, x, y).type = grass; + p.TileAt(surface, x, y).type = taiga; + } + } else if (elevation < mountain_thresh) { + if (variation > 0.3) { + p.TileAt(surface, x, y).type = mntn; + } else { + p.TileAt(surface, x, y).type = rock; } } else { p.TileAt(surface, x, y).type = mntn; @@ -452,7 +493,7 @@ void GenerateEarthlike(const TileSet &tiles, Planet &p) noexcept { p.BuildVAO(tiles); } -void GenerateTest(const TileSet &tiles, Planet &p) noexcept { +void GenerateTest(const Set &tiles, Planet &p) noexcept { for (int surface = 0; surface <= 5; ++surface) { for (int y = 0; y < p.SideLength(); ++y) { for (int x = 0; x < p.SideLength(); ++x) { @@ -475,41 +516,5 @@ Sun::Sun() Sun::~Sun() { } -TileSet::TileSet() -: types() -, names() { -} - -TileSet::~TileSet() { -} - -int TileSet::Add(const TileType &t) { - int id = types.size(); - if (!names.emplace(t.name, id).second) { - throw std::runtime_error("duplicate tile type name " + t.name); - } - types.emplace_back(t); - types.back().id = id; - return id; -} - -TileType &TileSet::operator [](const std::string &name) { - auto entry = names.find(name); - if (entry != names.end()) { - return types[entry->second]; - } else { - throw std::runtime_error("unknown tile type " + name); - } -} - -const TileType &TileSet::operator [](const std::string &name) const { - auto entry = names.find(name); - if (entry != names.end()) { - return types[entry->second]; - } else { - throw std::runtime_error("unknown tile type " + name); - } -} - } }