diff --git a/CMakeLists.txt b/CMakeLists.txt index b316597..d1a4b80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ set (mapgen_VERSION_MINOR 1) file(GLOB SOURCE "src/*.cpp" "include/mapgen/*.h") file(COPY "font.ttf" DESTINATION "bin") +file(COPY "images" DESTINATION "bin") configure_file ( "${PROJECT_SOURCE_DIR}/MapgenConfig.h.in" diff --git a/images/anchor.png b/images/anchor.png new file mode 100644 index 0000000..a64273a Binary files /dev/null and b/images/anchor.png differ diff --git a/images/capital.png b/images/capital.png new file mode 100644 index 0000000..62f10ac Binary files /dev/null and b/images/capital.png differ diff --git a/include/mapgen/City.hpp b/include/mapgen/City.hpp new file mode 100644 index 0000000..d50890c --- /dev/null +++ b/include/mapgen/City.hpp @@ -0,0 +1,14 @@ +#ifndef CITY_H_ +#define CITY_H_ + +#include "Region.hpp" + +class City { +public: + City(Region* r, std::string n); + Region* region; + std::string name; + bool isCapital; +}; + +#endif diff --git a/include/mapgen/MapGenerator.hpp b/include/mapgen/MapGenerator.hpp index 8ebd48f..227049e 100644 --- a/include/mapgen/MapGenerator.hpp +++ b/include/mapgen/MapGenerator.hpp @@ -8,6 +8,7 @@ #include "Region.hpp" #include "River.hpp" +#include "City.hpp" class MapGenerator { public: @@ -35,6 +36,7 @@ class MapGenerator { std::vector rivers; + std::vector cities; std::vector clusters; std::vector megaClusters; bool simpleRivers; @@ -59,6 +61,7 @@ class MapGenerator { void simplifyRivers(); void makeBorders(); void makeMinerals(); + void makeCities(); int _seed; VoronoiDiagramGenerator _vdg; int _pointsCount; diff --git a/include/mapgen/Region.hpp b/include/mapgen/Region.hpp index 9ad9d51..ef1060b 100644 --- a/include/mapgen/Region.hpp +++ b/include/mapgen/Region.hpp @@ -12,6 +12,7 @@ typedef std::map HeightMap; struct Cluster; typedef Cluster MegaCluster; +class City; class Region { public: Region(); @@ -29,6 +30,9 @@ class Region { float temperature; float minerals; float nice; + City* city; + float distanceFormCapital; + bool coast; private: PointList _verticies; HeightMap _heights; @@ -46,6 +50,7 @@ struct Cluster { PointList border; std::vector resourcePoints; std::vector goodPoints; + std::vector cities; }; #endif diff --git a/src/Biom.cpp b/src/Biom.cpp index 66149cb..9c87184 100644 --- a/src/Biom.cpp +++ b/src/Biom.cpp @@ -16,6 +16,7 @@ Biom ICE = {1.2000, sf::Color(220, 220, 255), "Ice", 0.9}; Biom PRAIRIE = {999.000, sf::Color(239, 220, 124), "Prairie", 0.1}; Biom MEADOW = {999.000, sf::Color(126, 190, 75), "Meadow", 0.1}; Biom DESERT = {999.000, sf::Color(244, 164, 96), "Desert", 0.3}; +Biom CITY = {999.000, sf::Color(220,220,220), "City", 0.3}; Biom RAIN_FORREST = {0.3750, sf::Color(51, 90, 75), "Rain forrest", 0.6}; @@ -25,6 +26,7 @@ std::vector BIOMS = {{ Biom LAKE = {999.000, sf::Color(51, 51, 91), "Lake", 1}; Biom MARK = {999.000, sf::Color::Red, "Mark"}; +Biom MARK2 = {999.000, sf::Color::Black, "Mark"}; Biom LAND = {0.500, sf::Color(136, 170, 85), "Land", 1}; Biom SEA = {-1.000, sf::Color(39, 39, 70), "Sea", 1}; diff --git a/src/City.cpp b/src/City.cpp new file mode 100644 index 0000000..578d111 --- /dev/null +++ b/src/City.cpp @@ -0,0 +1,8 @@ +#include "mapgen/City.hpp" +#include "mapgen/Region.hpp" + +City::City(Region *r, std::string n) : region(r), name(n) { + isCapital = false; + region->biom = CITY; + region->city = this; +} diff --git a/src/MapGenerator.cpp b/src/MapGenerator.cpp index b3fc597..ee3abc0 100644 --- a/src/MapGenerator.cpp +++ b/src/MapGenerator.cpp @@ -3,6 +3,7 @@ #include #include #include "Biom.cpp" +#include "City.cpp" #include "names.cpp" const int DEFAULT_RELAX = 5; @@ -56,6 +57,13 @@ MapGenerator::MapGenerator(int w, int h): _w(w), _h(h) { temperature = DEFAULT_TEMPERATURE; } +double getDistance(Point p, Point p2) { + double distancex = (p2->x - p->x); + double distancey = (p2->y - p->y); + + return std::sqrt(distancex * distancex + distancey * distancey); +} + void MapGenerator::simplifyRivers() { currentOperation = "Simplify rivers..."; for (auto r : rivers) { @@ -74,19 +82,8 @@ void MapGenerator::simplifyRivers() { Point p3 = (*rvr)[i+2]; Point sp; - double distancex = (p2->x - p->x); - distancex *= distancex; - double distancey = (p2->y - p->x); - distancey *= distancey; - - double d1 = sqrt(distancex + distancey); - - distancex = (p3->x - p->x); - distancex *= distancex; - distancey = (p3->y - p->x); - distancey *= distancey; - - double d2 = sqrt(distancex + distancey); + double d1 = getDistance(p, p2); + double d2 = getDistance(p, p3); if (d2 < d1) { sp = p2; @@ -178,9 +175,59 @@ void MapGenerator::update() { makeFinalRegions(); makeClusters(); + makeCities(); + ready = true; } +void MapGenerator::makeCities() { + currentOperation = "Founding cities..."; + double minDistance = std::numeric_limits::max(); + Region* betterPlace; + MegaCluster* biggestCluster; + for (auto c: megaClusters) { + if (c->isLand) { + biggestCluster = c; + break; + } + } + + std::vector places; + std::copy_if(biggestCluster->regions.begin(), biggestCluster->regions.end(), std::back_inserter(places), [](Region* r){ + return r->biom.name != LAKE.name && r->nice >= 0.5 && r->minerals >= 0.5 && r->temperature >= DEFAULT_TEMPERATURE/3; + }); + std::sort(places.begin(), places.end(), [&](Region* r, Region* r2){ + if (r->nice + r->minerals >= r2->nice + r2->minerals){ + return true; + } + return false; + }); + City* capital = new City(places[0], generateCityName()); + capital->isCapital = true; + cities.push_back(capital); + + // std::vector::iterator portPlace = std::find_if(biggestCluster->regions.begin(), biggestCluster->regions.end(), [](Region* r){ + // return r->border && r->hasRiver; + // }); + + places.clear(); + std::copy_if(biggestCluster->regions.begin(), biggestCluster->regions.end(), std::back_inserter(places), [&](Region* r){ + return r->border && r->hasRiver && r->coast && r != capital->region; + }); + std::sort(places.begin(), places.end(), [&](Region* r, Region* r2){ + if ( getDistance(r->site, capital->region->site) <= getDistance(r2->site, capital->region->site)){ + return true; + } + return false; + }); + City* port = new City(places[0], generateCityName()); + cities.push_back(port); + + for (auto r : *_regions) { + r->distanceFormCapital = getDistance(r->site, capital->region->site); + } +} + void MapGenerator::makeMinerals() { currentOperation = "Search for minerals..."; utils::NoiseMapBuilderPlane heightMapBuilder; @@ -484,6 +531,8 @@ void MapGenerator::makeRegions() { h.insert(std::make_pair(&p, ht)); Biom b = ht < 0.0625 ? SEA : LAND; Region *region = new Region(b, verts, h, &p); + region->city = nullptr; + region->coast = false; region->cell = c; region->humidity = DEFAULT_HUMIDITY; region->border = false; @@ -569,6 +618,7 @@ void MapGenerator::makeMegaClusters() { Region* rn = _cells[n]; if (r->biom.name != rn->biom.name){ r->border = true; + r->coast = r->biom.name == LAND.name && rn->biom.name == SEA.name; } else if (_megaClusters.count(rn) != 0) { cu = false; if (knownCluster == nullptr) { diff --git a/src/application.cpp b/src/application.cpp index 8edc8b0..40a560a 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -20,7 +20,10 @@ class Application { std::vector polygons; std::vector poi; std::vector infoPolygons; + std::vector sprites; std::vector verticies; + sf::Texture *capitalIcon; + sf::Texture *anchorIcon; sf::Color bgColor; AppLog log; MapGenerator *mapgen; @@ -86,6 +89,18 @@ class Application { sffont.loadFromFile("./font.ttf"); + capitalIcon = new sf::Texture(); + if (!capitalIcon->loadFromFile("images/capital.png")) { + std::cout<<"Image error"<setSmooth(true); + + anchorIcon = new sf::Texture(); + if (!anchorIcon->loadFromFile("images/anchor.png")) { + std::cout<<"Image error"<setSmooth(true); + sf::Vector2u windowSize = window->getSize(); cachedMap.create(windowSize.x, windowSize.y); log.AddLog("Welcome to Mapgen\n"); @@ -294,10 +309,10 @@ class Application { regen(); } - if (ImGui::SliderFloat("Base temperature", &temperature, -20.f, 50.f)) { - mapgen->temperature = temperature; - regen(); - } + // if (ImGui::SliderFloat("Base temperature", &temperature, -20.f, 50.f)) { + // mapgen->temperature = temperature; + // regen(); + // } // if (ImGui::Button("Relax")) { // log.AddLog("Update map\n"); @@ -466,6 +481,9 @@ class Application { } drawRivers(); + for (auto sprite : sprites) { + window->draw(sprite); + } sf::Vector2u windowSize = window->getSize(); cachedMap.create(windowSize.x, windowSize.y); @@ -579,6 +597,7 @@ class Application { polygons.clear(); poi.clear(); verticies.clear(); + sprites.clear(); for (auto mc: mapgen->megaClusters) { for (auto p: mc->resourcePoints) { @@ -624,7 +643,25 @@ class Application { } col.a = a; } + if (region->city != nullptr) { + sf::Sprite sprite; + if (region->city->isCapital) { + sprite.setTexture(*capitalIcon); + auto p = region->site; + sprite.setScale(0.05, 0.05); + auto size = capitalIcon->getSize(); + sprite.setPosition(sf::Vector2f(p->x-size.x*0.05/2.f, p->y-size.y*0.05/2.f)); + } else { + sprite.setTexture(*anchorIcon); + auto p = region->site; + sprite.setScale(0.1, 0.1); + auto size = anchorIcon->getSize(); + sprite.setPosition(sf::Vector2f(p->x-size.x*0.05/2.f, p->y-size.y*0.05/2.f)); + } + sprites.push_back(sprite); + } polygon.setFillColor(col); + if (edges) { polygon.setOutlineColor(sf::Color(100, 100, 100)); polygon.setOutlineThickness(1); diff --git a/src/infoWindow.cpp b/src/infoWindow.cpp index a7d5679..4fcc5d7 100644 --- a/src/infoWindow.cpp +++ b/src/infoWindow.cpp @@ -17,6 +17,8 @@ void infoWindow(sf::RenderWindow* window, Region* currentRegion) { ImGui::Text("Cluster: %p", cluster); ImGui::Text("Cluster size: %zu", cluster->regions.size()); ImGui::Text("Mega Cluster: %s", currentRegion->megaCluster->name.c_str()); + ImGui::Text("Distance from capital: %f", currentRegion->distanceFormCapital); + ImGui::Text("Coast: %s", currentRegion->coast ? "true" : "false"); ImGui::Text("Site: x:%f y:%f z:%f", currentRegion->site->x, currentRegion->site->y, diff --git a/src/names.cpp b/src/names.cpp index 789c9a4..d175ddf 100644 --- a/src/names.cpp +++ b/src/names.cpp @@ -1,6 +1,7 @@ #include #include #include +#include const std::string _river_first_names[] = {"Alligator","Amazon","Arching","Arctic","Arrowhead","Bamboo","Black","Bland","Blue","Bogbeast","Boundless","Brilliant","Bursting","Calm","Charmed","Choral","Climbing","Cobalt","Cold","Coral","Crocodile","Crystal","Cursed","Dancing","Dark","Darkest","Dead","Deep","Distant","Dragonfly","Dread","Dreaded","Eastern","Emerald","Empty","Enchanted","Ethereal","Ever Reaching","Fair","Flowing","Foaming","Forbidden","Frothy","Frozen","Glassy","Gleaming","Glistening","Gray","Green","Harmony","Heaving","Homeless","Hungry","Infernal","Infinite","Invisible","Iris","Isolated","Jade","Laughing","Lifeless","Lilypad","Lion's Tail","Living","Lonely","Lotus","Lucent","Majestic","Mesmerizing","Mighty","Mirrored","Misty","Moaning","Molten","Moon-lit","Motionless","Moving","Narrow","New","Northern","Peaceful","Perfumed","Pleasant","Quiet","Raging","Rainy","Red","Restless","Rippling","Rocking","Rolling","Rough","Rushing","Sandy","Sanguine","Savage","Serene","Serpent","Shimmering","Silent","Sleeping","Slumbrous","Soundless","Southern","Sparkling","Sterile","Stern","Straitened","Sunny","Surging","Tadpole","Teal","Throbbing","Thundering","Tinted","Tortoise","Tossing","Tranquil","Treacherous","Troubled","Turbulent","Turquoise","Turtle","Uncanny","Unknown","Violent","Waveless","Western","Whispering","White","Wild","Windy","Wondering","Wrinkled"}; const std::string _river_second_names[] = {"Creek","River","Stream","Brook","Run","Tributary","Beck","Rill"}; @@ -20,6 +21,13 @@ const std::string _sea_second_names[] = {"Abyss","Tides","Waves","Bay","Deep","D std::vector sea_first_names (_sea_first_names, _sea_first_names + sizeof(_sea_first_names) / sizeof(_sea_first_names[0]) ); std::vector sea_second_names (_sea_second_names, _sea_second_names + sizeof(_sea_second_names) / sizeof(_sea_second_names[0]) ); +const std::string _city_first_names[] = {"amber","angel","spirit","basin","lagoon","basin","arrow","autumn","bare","bay","beach","bear","bell","black","bleak","blind","bone","boulder","bridge","brine","brittle","bronze","castle","cave","chill","clay","clear","cliff","cloud","cold","crag","crow","crystal","curse","dark","dawn","dead","deep","deer","demon","dew","dim","dire","dirt","dog","dragon","dry","dusk","dust","eagle","earth","east","ebon","edge","elder","ember","ever","fair","fall","false","far","fay","fear","flame","flat","frey","frost","ghost","glimmer","gloom","gold","grass","gray","green","grim","grime","hazel","heart","high","hollow","honey","hound","ice","iron","kil","knight","lake","last","light","lime","little","lost","mad","mage","maple","mid","might","mill","mist","moon","moss","mud","mute","myth","never","new","night","north","oaken","ocean","old","ox","pearl","pine","pond","pure","quick","rage","raven","red","rime","river","rock","rogue","rose","rust","salt","sand","scorch","shade","shadow","shimmer","shroud","silent","silk","silver","sleek","sleet","sly","small","smooth","snake","snow","south","spring","stag","star","steam","steel","steep","still","stone","storm","summer","sun","swamp","swan","swift","thorn","timber","trade","west","whale","whit","white","wild","wilde","wind","winter","wolf"}; +const std::string _city_second_names[] = {"acre","band","barrow","bay","bell","born","borough","bourne","breach","break","brook","burgh","burn","bury","cairn","call","chill","cliff","coast","crest","cross","dale","denn","drift","fair","fall","falls","fell","field","ford","forest","fort","front","frost","garde","gate","glen","grasp","grave","grove","guard","gulch","gulf","hall","hallow","ham","hand","harbor","haven","helm","hill","hold","holde","hollow","horn","host","keep","land","light","maw","meadow","mere","mire","mond","moor","more","mount","mouth","pass","peak","point","pond","port","post","reach","rest","rock","run","scar","shade","shear","shell","shield","shore","shire","side","spell","spire","stall","wich","minster","star","storm","strand","summit","tide","town","vale","valley","vault","vein","view","ville","wall","wallow","ward","watch","water","well","wharf","wick","wind","wood","yard"}; + +std::vector city_first_names (_city_first_names, _city_first_names + sizeof(_city_first_names) / sizeof(_city_first_names[0]) ); +std::vector city_second_names (_city_second_names, _city_second_names + sizeof(_city_second_names) / sizeof(_city_second_names[0]) ); + + template Iter select_randomly(Iter start, Iter end, int s) { std::mt19937 gen(s); @@ -41,3 +49,9 @@ std::string generateLandName() { std::string generateSeaName() { return *select_randomly(sea_first_names.begin(), sea_first_names.end(), std::clock()) + " " + *select_randomly(sea_second_names.begin(), sea_second_names.end(), std::clock()); } + +std::string generateCityName() { + auto name = *select_randomly(city_first_names.begin(), city_first_names.end(), std::clock()) + *select_randomly(city_second_names.begin(), city_second_names.end(), std::clock()); + name[0] = toupper(name[0]); + return name; +}