summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2017-10-10 19:33:33 +0200
committerPaweł Redman <pawel.redman@gmail.com>2017-10-10 19:33:33 +0200
commit753f71536339b78c49468ba6452c96d6b3c345b2 (patch)
tree0f3edbef6b2a34a738dc37cc8dd8c11a98e54c85 /src
parentff4929c650e6ed446b6faff9f6b0f078d0a3644c (diff)
Finish work on world entities, start experimenting with world generation.
Diffstat (limited to 'src')
-rw-r--r--src/common.hpp24
-rw-r--r--src/game.cpp16
-rw-r--r--src/interface.cpp12
-rw-r--r--src/procgen.cpp5
-rw-r--r--src/render.cpp69
-rw-r--r--src/world.cpp128
6 files changed, 176 insertions, 78 deletions
diff --git a/src/common.hpp b/src/common.hpp
index 6a30f9e..06e9d9f 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -1,7 +1,9 @@
#include <iostream>
#include <cstdint>
#include <cmath>
+#include <cassert>
#include <map>
+#include <list>
#include <unordered_set>
#include <SFML/Graphics.hpp>
@@ -45,6 +47,7 @@ namespace world {
sector_index_t ();
sector_index_t (int64_t x_, int64_t y_);
+ sector_index_t (float x_, float y_);
bool operator<(sector_index_t B) const;
};
@@ -52,6 +55,7 @@ namespace world {
class sector_t {
public:
+ sector_index_t index;
sf::FloatRect bounds;
std::unordered_set<entity_t*> ents;
@@ -64,6 +68,7 @@ namespace world {
procgen::perlin_noise_t perlin;
std::map<sector_index_t, sector_t> sectors;
+ void generate_tile(ssize_t lx, ssize_t ly, tile_t *tile);
void generate(sector_t *sector, sector_index_t index);
public:
@@ -71,7 +76,13 @@ namespace world {
sector_t *get_sector(sector_index_t index);
tile_t *get_tile(ssize_t x, ssize_t y);
+ // FIXME: iterators instead of returning std::lists
+ std::list<sector_t*> get_sectors(sf::FloatRect rect);
+ std::list<entity_t*> get_entities(sf::FloatRect rect);
+
void render(sf::RenderWindow *window);
+
+ void debug_point(sf::Vector2f point);
};
class entity_t {
@@ -80,6 +91,10 @@ namespace world {
void link_to_sector(sector_t *sector);
+ protected:
+ friend world_t;
+ size_t cookie = 0;
+
public:
sf::FloatRect bounds;
@@ -92,9 +107,9 @@ namespace world {
namespace game {
class state_t {
+ public:
world::world_t world;
- public:
void start(void);
void tick(void);
void render(sf::RenderWindow *window_);
@@ -142,13 +157,6 @@ T divide_rmi(T x, T y, T *rem)
return rv;
}
-// Modulo operation. y is expected to be positive.
-template <typename T>
-T mod(T x, T y)
-{
- return (x % y) + (x < 0 ? y : 0);
-}
-
// Linear interpolation.
template <typename T>
T lerp(T a, T b, T x)
diff --git a/src/game.cpp b/src/game.cpp
index 6fff821..6416f93 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -2,20 +2,24 @@
namespace game {
+static human_t *human;
+
void state_t::start(void)
{
- human_t *human;
-
human = new human_t;
- human->bounds.left = 0.2f;
- human->bounds.top = 0.2f;
- human->bounds.width = 1.0f;
- human->bounds.height = 1.0f;
+ human->bounds.left = -0.2f;
+ human->bounds.top = -0.2f;
+ human->bounds.width = 3.0f;
+ human->bounds.height = 3.0f;
human->link(&world);
}
void state_t::tick(void)
{
+ human->unlink();
+ human->bounds.left += 0.05f;
+ human->bounds.top += 0.05f;
+ human->link(&world);
}
} //namespace game
diff --git a/src/interface.cpp b/src/interface.cpp
index 16fc77d..17c1727 100644
--- a/src/interface.cpp
+++ b/src/interface.cpp
@@ -68,8 +68,16 @@ void state_t::tick(void)
camera.target_zoom -= event.mouseWheelScroll.delta;
if (camera.target_zoom < 0)
camera.target_zoom = 0;
- if (camera.target_zoom > 10)
- camera.target_zoom = 10;
+ if (camera.target_zoom > 11)
+ camera.target_zoom = 11;
+ break;
+
+ case sf::Event::KeyPressed:
+ if (event.key.code == sf::Keyboard::Key::I) {
+ sf::Vector2i mouse = sf::Mouse::getPosition(*window);
+ sf::Vector2f vmouse = window->mapPixelToCoords(mouse);
+ game->world.debug_point(vmouse);
+ }
break;
default:;
diff --git a/src/procgen.cpp b/src/procgen.cpp
index 09ccae5..b5e1d6f 100644
--- a/src/procgen.cpp
+++ b/src/procgen.cpp
@@ -63,8 +63,9 @@ float perlin_noise_t::get(float x, float y, float scale)
x /= scale;
y /= scale;
- nx = mod<ssize_t>(floor(x), size);
- ny = mod<ssize_t>(floor(y), size);
+ nx = (ssize_t)floor(x) & (size - 1);
+ ny = (ssize_t)floor(y) & (size - 1);
+
nx1 = (nx == size - 1 ? 0 : nx + 1);
ny1 = (ny == size - 1 ? 0 : ny + 1);
diff --git a/src/render.cpp b/src/render.cpp
index d63ca6f..1baf0e0 100644
--- a/src/render.cpp
+++ b/src/render.cpp
@@ -6,9 +6,32 @@ static sf::RectangleShape wot_rect;
static void draw_tile(sf::RenderWindow *window, float x, float y,
world::tile_t *tile)
{
+ sf::Color color;
+
wot_rect.setSize(sf::Vector2f(1.0f, 1.0f));
wot_rect.setPosition(sf::Vector2f(x, y));
- wot_rect.setFillColor(sf::Color(tile->type, tile->type, tile->type));
+
+ switch (tile->type) {
+ case -1:
+ color = sf::Color(30, 30, 150);
+ break;
+ case 0:
+ color = sf::Color(50, 70, 200);
+ break;
+ case 1:
+ color = sf::Color(255, 255, 90);
+ break;
+ case 2:
+ color = sf::Color(30, 210, 40);
+ break;
+ case 3:
+ color = sf::Color(29, 190, 45);
+ break;
+ default:
+ ;
+ }
+
+ wot_rect.setFillColor(color);
wot_rect.setOutlineColor(sf::Color::Transparent);
window->draw(wot_rect);
}
@@ -21,18 +44,12 @@ static void draw_sector(sf::RenderWindow *window, world::sector_t *sector)
sector->bounds.left + x, sector->bounds.top + y,
sector->tiles + y * SECTOR_SIZE + x);
- wot_rect.setSize(sf::Vector2f(SECTOR_SIZE, SECTOR_SIZE));
- wot_rect.setPosition(sf::Vector2f(sector->bounds.left, sector->bounds.top));
- wot_rect.setOutlineColor(sf::Color::Yellow);
- wot_rect.setOutlineThickness(0.06f);
- wot_rect.setFillColor(sf::Color::Transparent);
- window->draw(wot_rect);
-}
-
-static void draw_sector_entities(sf::RenderWindow *window, world::sector_t *sector)
-{
- for (world::entity_t *ent : sector->ents)
- ent->render(window);
+ if ((sector->index.x & 2) ^ (sector->index.y & 2)) {
+ wot_rect.setSize(sf::Vector2f(SECTOR_SIZE, SECTOR_SIZE));
+ wot_rect.setPosition(sf::Vector2f(sector->bounds.left, sector->bounds.top));
+ wot_rect.setFillColor(sf::Color(0, 0, 0, 50));
+ window->draw(wot_rect);
+ }
}
void game::state_t::render(sf::RenderWindow *window)
@@ -40,8 +57,6 @@ void game::state_t::render(sf::RenderWindow *window)
sf::Vector2u size = window->getSize();
sf::Vector2f A, B, C, D;
sf::Rect<float> bbox;
- sf::Rect<ssize_t> index_box;
- std::list<world::sector_t*> sectors;
A = window->mapPixelToCoords(sf::Vector2i(0, 0));
B = window->mapPixelToCoords(sf::Vector2i(size.x, 0));
@@ -50,28 +65,14 @@ void game::state_t::render(sf::RenderWindow *window)
bbox.left = std::min({A.x, B.x, C.x, D.x});
bbox.top = std::min({A.y, B.y, C.y, D.y});
- bbox.width = std::max({A.x, B.x, C.x, D.x});
- bbox.height = std::max({A.y, B.y, C.y, D.y});
-
- index_box.left = floor(bbox.left / SECTOR_SIZE);
- index_box.top = floor(bbox.top / SECTOR_SIZE);
- index_box.width = ceil(bbox.width / SECTOR_SIZE);
- index_box.height = ceil(bbox.height / SECTOR_SIZE);
-
- for (ssize_t y = index_box.top; y < index_box.height; y++)
- for (ssize_t x = index_box.left; x < index_box.width; x++) {
- world::sector_index_t index(x, y);
- world::sector_t *sector;
+ bbox.width = std::max({A.x, B.x, C.x, D.x}) - bbox.left;
+ bbox.height = std::max({A.y, B.y, C.y, D.y}) - bbox.top;
- sector = world.get_sector(index);
- sectors.push_back(sector);
- }
-
- for (auto *sector : sectors)
+ for (world::sector_t *sector : world.get_sectors(bbox))
draw_sector(window, sector);
- for (auto *sector : sectors)
- draw_sector_entities(window, sector);
+ for (world::entity_t *ent : world.get_entities(bbox))
+ ent->render(window);
}
void game::human_t::render(sf::RenderWindow *window)
diff --git a/src/world.cpp b/src/world.cpp
index 9d9b97d..9085b16 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -12,6 +12,12 @@ sector_index_t::sector_index_t (int64_t x_, int64_t y_)
y = y_;
}
+sector_index_t::sector_index_t (float x_, float y_)
+{
+ x = (int64_t)floor(x_ / SECTOR_SIZE);
+ y = (int64_t)floor(y_ / SECTOR_SIZE);
+}
+
bool sector_index_t::operator<(sector_index_t B) const
{
if (x < B.x)
@@ -29,31 +35,47 @@ world_t::world_t(void)
perlin.generate(&prng, 32);
}
+void world_t::generate_tile(ssize_t x, ssize_t y, tile_t *tile)
+{
+ float waterlevel, height;
+
+ waterlevel = perlin.get(x, y, 100.0f) * 0.3f +
+ perlin.get(x, y, 50.0f) * 0.1f;
+
+ height = perlin.get(x, y, 30.0f) * 0.6f +
+ perlin.get(x, y, 15.0f) * 0.25f +
+ perlin.get(x, y, 7.0f) * 0.1f +
+ perlin.get(x, y, 3.0f) * 0.05f;
+
+ if (height < waterlevel - 0.2f)
+ tile->type = -1;
+ else if (height < waterlevel)
+ tile->type = 0;
+ else if (height < waterlevel + 0.05f)
+ tile->type = 1;
+ else {
+ if (perlin.get(x, y, 5.0f) > 0.0f)
+ tile->type = 3;
+ else
+ tile->type = 2;
+ }
+}
+
void world_t::generate(sector_t *sector, sector_index_t index)
{
+ sector->index = index;
sector->bounds.left = index.x * SECTOR_SIZE;
sector->bounds.top = index.y * SECTOR_SIZE;
sector->bounds.width = SECTOR_SIZE;
sector->bounds.height = SECTOR_SIZE;
-
+
std::cout << "generating (" << index.x << ", " << index.y << ")\n";
for (ssize_t ly = 0; ly < SECTOR_SIZE; ly++)
- for (ssize_t lx = 0; lx < SECTOR_SIZE; lx++) {
- ssize_t x, y;
- float noise;
-
- x = index.x * SECTOR_SIZE + lx;
- y = index.y * SECTOR_SIZE + ly;
-
- noise = perlin.get(x, y, 30.0f) * 0.6f +
- perlin.get(x, y, 15.0f) * 0.25f +
- perlin.get(x, y, 7.0f) * 0.1f +
- perlin.get(x, y, 3.0f) * 0.05f;
-
- sector->tiles[ly * SECTOR_SIZE + lx].type =
- (noise + 1) * 100;
- }
+ for (ssize_t lx = 0; lx < SECTOR_SIZE; lx++)
+ generate_tile(index.x * SECTOR_SIZE + lx,
+ index.y * SECTOR_SIZE + ly,
+ sector->tiles + ly * SECTOR_SIZE + lx);
sector->empty = false;
}
@@ -83,9 +105,44 @@ tile_t *world_t::get_tile(ssize_t x, ssize_t y)
return sector->tiles + ty * SECTOR_SIZE + tx;
}
-static sector_index_t get_index(float x, float y)
+std::list<sector_t*> world_t::get_sectors(sf::FloatRect rect)
{
- return sector_index_t(floor(x), floor(y));
+ sector_index_t base(rect.left, rect.top),
+ upper(rect.left + rect.width, rect.top + rect.height);
+ std::list<sector_t*> list;
+
+ for (int64_t y = base.y; y <= upper.y; y++)
+ for (int64_t x = base.x; x <= upper.x; x++) {
+ sector_index_t index(x, y);
+ list.push_back(get_sector(index));
+ }
+
+ return list;
+}
+
+std::list<entity_t*> world_t::get_entities(sf::FloatRect rect)
+{
+ static size_t cookie = 0;
+ std::list<entity_t*> list;
+
+ cookie++;
+
+ for (sector_t *sector : get_sectors(rect))
+ for (entity_t *ent : sector->ents) {
+ if (ent->cookie == cookie)
+ continue;
+ ent->cookie = cookie;
+
+ list.push_back(ent);
+ }
+
+ return list;
+}
+
+void world_t::debug_point(sf::Vector2f point)
+{
+ sector_index_t index(point.x, point.y);
+ printf("sector (%zd, %zd)\n", index.x, index.y);
}
void entity_t::link_to_sector(sector_t *sector)
@@ -96,17 +153,36 @@ void entity_t::link_to_sector(sector_t *sector)
void entity_t::link(world_t *world)
{
+ float fx, fy;
sector_index_t base;
- sector_t *sector;
- ssize_t dx, dy;
+ float xlip, ylip;
+ size_t xsecs, ysecs;
+
+ fx = floor(bounds.left);
+ fy = floor(bounds.top);
+
+ base = sector_index_t(fx, fy);
+ xlip = bounds.left + bounds.width - (base.x + 1) * SECTOR_SIZE;
+ ylip = bounds.top + bounds.height - (base.y + 1) * SECTOR_SIZE;
- // An entity gets linked to at least one sector.
- base = get_index(bounds.left, bounds.top);
- sector = world->get_sector(base);
- link_to_sector(sector);
+ if (xlip > 0.0f)
+ xsecs = ceil(xlip / SECTOR_SIZE) + 1;
+ else
+ xsecs = 1;
- // There might be more, though.
- //for (dy = 0; dy <
+ if (ylip > 0.0f)
+ ysecs = ceil(ylip / SECTOR_SIZE) + 1;
+ else
+ ysecs = 1;
+
+ for (int64_t y = 0; y < (int64_t)ysecs; y++)
+ for (int64_t x = 0; x < (int64_t)xsecs; x++) {
+ sector_index_t index(base.x + x, base.y + y);
+ sector_t *sector;
+
+ sector = world->get_sector(index);
+ link_to_sector(sector);
+ }
}
void entity_t::unlink(void)