aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2021-05-30 17:39:54 -0400
committerJon Santmyer <jon@jonsantmyer.com>2021-05-30 17:39:54 -0400
commitbb250f93ead3a14eabbff6cad0a11f8e79a42948 (patch)
tree9f95fdd2c7b2ca4bc3b143e0168754a2d5b79db4
parente1925a6c3837931d04aee6e94234310fb59f33e2 (diff)
downloadpostmodern-bb250f93ead3a14eabbff6cad0a11f8e79a42948.tar.gz
postmodern-bb250f93ead3a14eabbff6cad0a11f8e79a42948.tar.bz2
postmodern-bb250f93ead3a14eabbff6cad0a11f8e79a42948.zip
initial tectonic plate generation. customization through subwindowHEADmaster
-rw-r--r--264
-rw-r--r--Makefile1
m---------boxii0
-rw-r--r--include/game.h1
-rw-r--r--include/testscreen.h13
-rw-r--r--include/world/map.h48
-rw-r--r--include/world/tectonicphase.h22
-rw-r--r--src/game.cpp6
-rw-r--r--src/main.cpp2
-rw-r--r--src/pausescreen.cpp7
-rw-r--r--src/testscreen.cpp103
-rw-r--r--src/titlescreen.cpp10
-rw-r--r--src/world/map.cpp91
-rw-r--r--src/world/tectonicphase.cpp57
14 files changed, 420 insertions, 5 deletions
diff --git a/2 b/2
new file mode 100644
index 0000000..cc0ebef
--- /dev/null
+++ b/2
@@ -0,0 +1,64 @@
+#include "world/tectonicphase.h"
+#include "boxii/input.h"
+
+TectonicPhase::TectonicPhase(std::shared_ptr<GenerationPhase> prev, std::shared_ptr<WorldMap> map) :
+ GenerationPhase(prev, map)
+{
+ std::uniform_real_distribution<float> xDist(0.f, 1.f);
+ std::uniform_real_distribution<float> yDist(0.f, 1.f);
+
+ for(int i = 0; i < TECTONIC_PLATES; i++){
+ m_plates[i].x = xDist(map->getRandom()) * map->getWidth();
+ m_plates[i].y = yDist(map->getRandom()) * map->getHeight();
+ m_plates[i].continental = rand() % 2;
+
+ printf("Plate %i : %i %i (%i)\n\r", i, m_plates[i].x, m_plates[i].y, m_plates[i].continental);
+ Boxii::Input::getch(true);
+ }
+
+ rasterize(map);
+}
+
+static float
+dist(float x1, float x2, float y1, float y2)
+{
+ return sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
+}
+
+void
+TectonicPhase::rasterize(std::shared_ptr<WorldMap> map)
+{
+ int w = map->getWidth();
+ int h = map->getHeight();
+
+ for(int y = 0; y < h; y++)
+ for(int x = 0; x < w; x++)
+ {
+ Plate *closest = nullptr;
+ float cdist = INT_MAX;
+
+ //Iterate through plates
+ for(int i = 0; i < TECTONIC_PLATES; i++){
+ Plate *plate = &m_plates[i];
+
+ float d = dist(x, y, plate->x, plate->y);
+
+ if(d < cdist){
+ closest = plate;
+ cdist = d;
+ }
+ }
+
+ if(closest == nullptr) {
+ printf("Skipping tile with no clear closest?\n");
+ Boxii::Input::getch(true);
+ continue;
+ }
+
+ if(closest->continental) {
+ map->setProperties(x, y, 1024, 0, 0);
+ }else{
+ map->setProperties(x, y, 0, 0, 0);
+ }
+ }
+}
diff --git a/Makefile b/Makefile
index cf7eddd..7a5122a 100644
--- a/Makefile
+++ b/Makefile
@@ -7,6 +7,7 @@ PWD := $(shell pwd)
SRCDIR := $(PWD)/src
INCDIR := $(PWD)/include
SRCFILES := $(wildcard $(SRCDIR)/*.cpp)
+SRCFILES += $(wildcard $(SRCDIR)/*/*.cpp)
OBJFILES := $(patsubst %.cpp,%.o,$(SRCFILES))
diff --git a/boxii b/boxii
-Subproject 916c00bd409f5ff7bad34714254d93744e6fd55
+Subproject 08a180e2e6e5989a57dfca787c8de4409931bfb
diff --git a/include/game.h b/include/game.h
index 4e00bb8..0ee63aa 100644
--- a/include/game.h
+++ b/include/game.h
@@ -29,6 +29,7 @@ public:
static bool popScreen();
static bool popUpto(const std::string &key);
static bool popUptoIncluding(const std::string &key);
+ static void popAll();
static void stop() { m_running = false; }
};
diff --git a/include/testscreen.h b/include/testscreen.h
index 67d98dc..a517700 100644
--- a/include/testscreen.h
+++ b/include/testscreen.h
@@ -1,15 +1,28 @@
#ifndef POSTMODERN_TESTSCREEN_H
#define POSTMODERN_TESTSCREEN_H 1
+#include "boxii/window.h"
+#include "boxii/textwindow.h"
+
#include "screen.h"
class TestScreen : public Screen {
private:
+ std::shared_ptr<Boxii::Window> m_canvasWindow;
+ std::shared_ptr<Boxii::TextWindow> m_infoWindow;
+
+ int m_option;
+ int *m_optionValues;
protected:
public:
TestScreen();
~TestScreen();
+ void activate() override;
+ void deactivate() override;
+
+ void refresh();
+
void update() override;
};
diff --git a/include/world/map.h b/include/world/map.h
new file mode 100644
index 0000000..7729ecf
--- /dev/null
+++ b/include/world/map.h
@@ -0,0 +1,48 @@
+#ifndef POSTMODERN_WORLD_MAP_H
+#define POSTMODERN_WORLD_MAP_H 1
+
+#include <memory>
+#include <random>
+
+#include "boxii/window.h"
+
+class WorldMap;
+
+class GenerationPhase {
+private:
+public:
+ GenerationPhase(std::shared_ptr<GenerationPhase> prev, std::shared_ptr<WorldMap> map) {}
+ ~GenerationPhase() {}
+};
+
+//1.024 km tile resolution
+class WorldMap {
+private:
+ int m_width;
+ int m_height;
+ int m_seed;
+
+ float *m_landElevation;
+ float *m_waterElevation;
+ float *m_vegetation;
+
+ std::mt19937 m_random;
+
+public:
+ WorldMap(int w, int h, int seed);
+ ~WorldMap();
+
+ void begin(std::shared_ptr<WorldMap> self);
+ void draw(std::shared_ptr<Boxii::Window> window, int zoom);
+
+ void getProperties(int x, int y, float &le, float &we, float &v);
+ void setProperties(int x, int y, float le, float we, float v);
+
+ int getWidth() { return m_width; }
+ int getHeight() { return m_height; }
+ int getSeed() { return m_seed; }
+
+ std::mt19937 &getRandom() { return m_random; }
+};
+
+#endif
diff --git a/include/world/tectonicphase.h b/include/world/tectonicphase.h
new file mode 100644
index 0000000..62a6455
--- /dev/null
+++ b/include/world/tectonicphase.h
@@ -0,0 +1,22 @@
+#include "map.h"
+
+struct Plate
+{
+ Plate() { x = 0; y = 0; continental = false; }
+ float x, y;
+ bool continental;
+};
+
+class TectonicPhase : public GenerationPhase
+{
+private:
+ std::vector<Plate> m_plates;
+ static int m_plateCount;
+public:
+ TectonicPhase(std::shared_ptr<GenerationPhase> prev, std::shared_ptr<WorldMap> map);
+ ~TectonicPhase() {}
+
+ void rasterize(std::shared_ptr<WorldMap> map);
+
+ static void setPlateCount(int c) { m_plateCount = c; }
+};
diff --git a/src/game.cpp b/src/game.cpp
index 9644010..f93406b 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -113,3 +113,9 @@ Game::popUptoIncluding(const std::string &key)
m_order.pop_back();
return true;
}
+
+void
+Game::popAll()
+{
+ m_order.clear();
+}
diff --git a/src/main.cpp b/src/main.cpp
index d8cb026..6c28ac0 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,6 +1,7 @@
#include "game.h"
#include "titlescreen.h"
#include "pausescreen.h"
+#include "testscreen.h"
#include "boxii/boxii.h"
@@ -15,6 +16,7 @@ main(int argc, char **argv)
Game::addScreen("title", std::make_shared<TitleScreen>());
Game::addScreen("pause", std::make_shared<PauseScreen>());
+ Game::addScreen("test", std::make_shared<TestScreen>());
Game::pushScreen("title");
diff --git a/src/pausescreen.cpp b/src/pausescreen.cpp
index 399bf54..9077de4 100644
--- a/src/pausescreen.cpp
+++ b/src/pausescreen.cpp
@@ -9,7 +9,7 @@ static const std::string selectionText[selectionCount] =
{
"Resume ",
"Settings",
- "Abort "
+ "Quit "
};
static void
@@ -103,6 +103,9 @@ PauseScreen::parseSelection()
return;
}
if(m_selection == 2){
- Game::stop();
+ Game::popAll();
+ Game::pushScreen("title");
+ Boxii::damage(0, 0, Boxii::getTerminalWidth(), Boxii::getTerminalHeight());
+ return;
}
}
diff --git a/src/testscreen.cpp b/src/testscreen.cpp
index 43dcd3f..b0c04d9 100644
--- a/src/testscreen.cpp
+++ b/src/testscreen.cpp
@@ -1,17 +1,118 @@
#include "testscreen.h"
+#include "game.h"
+#include "world/map.h"
-TestScreen::TestScreen()
+#include "boxii/boxii.h"
+#include "boxii/input.h"
+
+static const int optionCount = 2;
+static const std::string optionStrings[optionCount] =
+{
+ "Seed:",
+ "Plates:"
+};
+
+static void
+printSelections(std::shared_ptr<Boxii::TextWindow> window, int selection, int *values)
{
+ int optx = 0;
+ int opty = 0;
+
+ for(int i = 0; i < optionCount; i++){
+ window->setfg(0xFFFFFF);
+ window->setbg(0x0);
+ if(selection == i){
+ window->setfg(0x0);
+ window->setbg(0xFFFFFF);
+ }
+ window->moveCursor(optx, opty++);
+ window->print("%s %i", optionStrings[i].c_str(), values[i]);
+ }
+}
+
+TestScreen::TestScreen() :
+ m_canvasWindow(nullptr), m_infoWindow(nullptr),
+ m_option(0), m_optionValues(new int[optionCount])
+{
+ int sw = Boxii::getTerminalWidth();
+ int sh = Boxii::getTerminalHeight();
+
+ m_canvasWindow = Boxii::makeWindow<Boxii::Window>(0, 0, sw, sh);
+ m_infoWindow = Boxii::makeWindow<Boxii::TextWindow>(0, 0, 24, 16);
+
+ Boxii::remove(m_canvasWindow);
+ Boxii::remove(m_infoWindow);
+
+ m_infoWindow->border('+', '+', '+', '+', '-', '|', 0xFFFFFF, 0x0);
+
+ m_optionValues[0] = 0;
+ m_optionValues[1] = 20;
+ refresh();
}
TestScreen::~TestScreen()
{
+ delete[] m_optionValues;
+}
+
+void
+TestScreen::activate()
+{
+ Boxii::pushToFront(m_canvasWindow);
+ Boxii::pushToFront(m_infoWindow);
+}
+void
+TestScreen::deactivate()
+{
+ Boxii::remove(m_canvasWindow);
+ Boxii::remove(m_infoWindow);
}
void
TestScreen::update()
{
+ int c = Boxii::Input::getch(true);
+ if(c == Boxii::KEY_ESCAPE) {
+ Game::pushScreen("pause");
+ }
+
+ if(c == Boxii::KEY_DOWN){
+ m_option++;
+ if(m_option == optionCount) m_option = 0;
+ }
+
+ if(c == Boxii::KEY_UP){
+ m_option--;
+ if(m_option == -1) m_option = optionCount - 1;
+ }
+
+ if(c == Boxii::KEY_LEFT){
+ m_optionValues[m_option]--;
+ if(m_optionValues[m_option] < 0) m_optionValues[m_option] = 0;
+ refresh();
+ }
+
+ if(c == Boxii::KEY_RIGHT){
+ m_optionValues[m_option]++;
+ refresh();
+ }
+
+ printSelections(m_infoWindow, m_option, m_optionValues);
+}
+
+#include "world/tectonicphase.h"
+void
+TestScreen::refresh()
+{
+ int sw = Boxii::getTerminalWidth();
+ int sh = Boxii::getTerminalHeight();
+
+ TectonicPhase::setPlateCount(m_optionValues[1]);
+
+ std::shared_ptr<WorldMap> world = std::make_shared<WorldMap>(sw, sh, m_optionValues[0]);
+ world->begin(world);
+ world->draw(m_canvasWindow, 0);
}
diff --git a/src/titlescreen.cpp b/src/titlescreen.cpp
index fc23a75..a416338 100644
--- a/src/titlescreen.cpp
+++ b/src/titlescreen.cpp
@@ -80,6 +80,8 @@ TitleScreen::TitleScreen() :
m_graphicWindow = Boxii::makeWindow<Boxii::Window>(0, 0, sw, graphicHeight + 1);
m_selectionWindow = Boxii::makeWindow<Boxii::TextWindow>(0, graphicHeight + 1, sw, selectionHeight + 1);
+ m_selectionWindow->border('_', '_', '_', '_', '_', ' ', 0xFFFFFF, 0x0);
+
printTitle(m_graphicWindow);
printSelections(m_selectionWindow, m_selection);
}
@@ -87,7 +89,7 @@ TitleScreen::TitleScreen() :
TitleScreen::~TitleScreen()
{
-}
+ }
void
TitleScreen::activate()
@@ -107,6 +109,10 @@ void
TitleScreen::parseSelection()
{
if(m_selection == static_cast<int>(Selection::QUIT)) Game::stop();
+ if(m_selection == static_cast<int>(Selection::TESTGEN)) {
+ Game::popScreen();
+ Game::pushScreen("test");
+ }
}
void
@@ -114,7 +120,7 @@ TitleScreen::update()
{
int c = Boxii::Input::getch(true);
if(c == Boxii::KEY_ESCAPE) {
- Game::pushScreen("pause");
+ Game::stop();
}
if(c == Boxii::KEY_LEFT){
diff --git a/src/world/map.cpp b/src/world/map.cpp
new file mode 100644
index 0000000..48701d8
--- /dev/null
+++ b/src/world/map.cpp
@@ -0,0 +1,91 @@
+#include "world/map.h"
+#include "world/tectonicphase.h"
+
+#include "boxii/input.h"
+
+WorldMap::WorldMap(int w, int h, int seed) :
+ m_width(w), m_height(h), m_seed(seed),
+ m_random(seed)
+{
+ m_landElevation = new float[w * h];
+ m_waterElevation = new float[w * h];
+ m_vegetation = new float[w * h];
+}
+
+WorldMap::~WorldMap()
+{
+ delete[] m_landElevation;
+ delete[] m_waterElevation;
+ delete[] m_vegetation;
+}
+
+void
+WorldMap::begin(std::shared_ptr<WorldMap> self)
+{
+ std::shared_ptr<GenerationPhase> phase1 = std::make_shared<TectonicPhase>(nullptr, self);
+}
+
+void
+WorldMap::draw(std::shared_ptr<Boxii::Window> window, int zoom)
+{
+ //TODO: Zoom
+ (void)zoom;
+
+ int cx, cy;
+ int sx, sy;
+
+ window->getCenter(cx, cy);
+ sx = cx - (m_width / 2);
+ sy = cy - (m_height / 2);
+
+ for(int y = 0; y < m_height; y++)
+ for(int x = 0; x < m_width; x++)
+ {
+ int index = x + (y * m_width);
+
+ unsigned int r = 256;
+ unsigned int g = 256;
+ unsigned int b = 256;
+ unsigned int color;
+
+ float landElevation = m_landElevation[index];
+ float waterElevation = m_waterElevation[index];
+
+ float landScale = std::clamp(landElevation / 1024.f, 0.f, 1.f);
+ float waterScale = std::clamp(waterElevation / 6.f, 0.f, 1.f);
+
+ r *= 1.f - waterScale;
+ g *= 1.f - waterScale;
+
+ r *= landScale;
+ g *= landScale;
+ b *= landScale;
+
+ color = ((r & 0xFF) << 16) + ((g & 0xFF) << 8) + (b & 0xFF);
+ //window->plot(sx + x, sy + y, ' ', color, color);
+ window->plot(x, y, ' ', color, color);
+ }
+}
+
+void
+WorldMap::getProperties(int x, int y, float &le, float &we, float &v)
+{
+ int index = x + (y * m_width);
+ if(index >= m_width * m_height) return;
+
+ le = m_landElevation[index];
+ we = m_waterElevation[index];
+ v = m_vegetation[index];
+}
+
+void
+WorldMap::setProperties(int x, int y, float le, float we, float v)
+{
+ int index = x + (y * m_width);
+ if(index >= m_width * m_height)
+ return;
+
+ m_landElevation[index] = le;
+ m_waterElevation[index] = we;
+ m_vegetation[index] = v;
+}
diff --git a/src/world/tectonicphase.cpp b/src/world/tectonicphase.cpp
new file mode 100644
index 0000000..5e8ce96
--- /dev/null
+++ b/src/world/tectonicphase.cpp
@@ -0,0 +1,57 @@
+#include "world/tectonicphase.h"
+#include "boxii/input.h"
+
+int TectonicPhase::m_plateCount = 10;
+
+TectonicPhase::TectonicPhase(std::shared_ptr<GenerationPhase> prev, std::shared_ptr<WorldMap> map) :
+ GenerationPhase(prev, map)
+{
+ std::uniform_real_distribution<float> xDist(0.f, 1.f);
+ std::uniform_real_distribution<float> yDist(0.f, 1.f);
+ std::uniform_int_distribution<int> cDist(0, 1);
+
+ m_plates.reserve(m_plateCount);
+
+ for(int i = 0; i < m_plateCount; i++){
+ m_plates.push_back(Plate());
+ m_plates[i].x = xDist(map->getRandom()) * map->getWidth();
+ m_plates[i].y = yDist(map->getRandom()) * map->getHeight();
+ m_plates[i].continental = cDist(map->getRandom());
+ }
+
+ rasterize(map);
+}
+
+static float
+dist(float x1, float y1, float x2, float y2)
+{
+ return ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
+}
+
+void
+TectonicPhase::rasterize(std::shared_ptr<WorldMap> map)
+{
+ for(int y = 0; y < map->getHeight(); y++){
+ for(int x = 0; x < map->getWidth(); x++){
+
+ int closest = 0;
+ float cdist = INT_MAX;
+
+ //Iterate through plates
+ for(int i = 0; i < m_plateCount; i++){
+ float d = dist(static_cast<float>(x), static_cast<float>(y), m_plates[i].x, m_plates[i].y);
+
+ if(d < cdist){
+ closest = i;
+ cdist = d;
+ }
+ }
+
+ if(m_plates[closest].continental){
+ map->setProperties(x, y, 600, 0, 0);
+ }else{
+ map->setProperties(x, y, 512, 88, 0);
+ }
+ }
+ }
+}