summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2017-10-17 16:39:13 +0200
committerPaweł Redman <pawel.redman@gmail.com>2017-10-17 16:39:13 +0200
commitf66cf28c8b4d80122896c87dba8af74ea1872eba (patch)
tree6d84c736463a3c210ba3791dc074df8565eb6559
parent672180b2ee3ed9b9ff984538a85e6eaf2e1c91bc (diff)
New vectors. Start refactoring to use it.
-rw-r--r--src/common.hpp19
-rw-r--r--src/game.cpp1
-rw-r--r--src/math.hpp231
-rw-r--r--src/procgen.cpp15
-rw-r--r--src/render.cpp4
-rw-r--r--src/world.cpp111
6 files changed, 309 insertions, 72 deletions
diff --git a/src/common.hpp b/src/common.hpp
index f458190..75dd17d 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -6,6 +6,7 @@
#include <list>
#include <unordered_set>
#include <SFML/Graphics.hpp>
+#include "math.hpp"
namespace procgen {
class prng_t {
@@ -29,7 +30,7 @@ namespace procgen {
~perlin_noise_t();
void generate(prng_t *prng, size_t size);
- float get(float x, float y, float scale);
+ float get(v2f_t x, float scale);
};
}
@@ -43,15 +44,8 @@ namespace world {
char type;
};
- class sector_index_t {
- public:
- int64_t x, y;
-
- 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;
- };
+ typedef vec_t<int64_t, 2> sector_index_t;
+ typedef vec_t<int64_t, 2> tile_index_t;
class entity_t;
@@ -70,7 +64,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_tile(tile_t *tile, tile_index_t index);
void generate(sector_t *sector, sector_index_t index);
public:
@@ -81,6 +75,7 @@ namespace world {
// 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);
+ std::list<entity_t*> get_render_entities(sf::FloatRect rect);
void render(sf::RenderWindow *window);
@@ -98,7 +93,7 @@ namespace world {
size_t cookie = 0;
public:
- sf::FloatRect bounds;
+ sf::FloatRect bounds, render_bounds;
void link(world_t *world);
void unlink();
diff --git a/src/game.cpp b/src/game.cpp
index 0b3e8d6..2af7736 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -34,6 +34,7 @@ void state_t::start(void)
human.bounds.top = 0;
human.bounds.width = 0.66f;
human.bounds.height = 1.0f;
+ human.render_bounds = human.bounds;
human.link(&world);
}
}
diff --git a/src/math.hpp b/src/math.hpp
new file mode 100644
index 0000000..b958092
--- /dev/null
+++ b/src/math.hpp
@@ -0,0 +1,231 @@
+template <typename T, size_t N>
+class vec_t {
+ template<size_t index, typename... U>
+ void load_from_args(void)
+ {
+ static_assert(index < N + 1, "too many elements in the initializer");
+ static_assert(index > N - 1, "too few elements in the initializer");
+ }
+
+ template<size_t index, typename... U>
+ void load_from_args(T first, U... rest)
+ {
+ v[index] = first;
+ load_from_args<index + 1>(rest...);
+ }
+
+public:
+ T v[N];
+
+ // Basic operations
+
+ vec_t() = default;
+
+ template<typename... U>
+ vec_t(T first, U... rest)
+ {
+ load_from_args<0>(first, rest...);
+ }
+
+ template<typename U>
+ vec_t(vec_t<U, N> b)
+ {
+ for (size_t i = 0; i < N; i++)
+ v[i] = (T)b[i];
+ }
+
+ T& operator[](size_t i)
+ {
+ return v[i];
+ }
+
+ const T& operator[](size_t i) const
+ {
+ return v[i];
+ }
+
+ // Comparison
+
+ friend bool operator==(const vec_t<T, N> &a, const vec_t<T, N> &b)
+ {
+ for (size_t i = 0; i < N; i++)
+ if (a[i] != b[i])
+ return false;
+
+ return true;
+ }
+
+ // Good enough for maps or sets.
+ friend bool operator<(const vec_t<T, N> &a, const vec_t<T, N> &b)
+ {
+ for (size_t i = 0; i < N; i++) {
+ if (a[i] < b[i])
+ return true;
+ else if (a[i] > b[i])
+ return false;
+ }
+
+ return false;
+ }
+
+ // Arithmetics
+
+ friend vec_t<T, N> operator+(const vec_t<T, N> &v)
+ {
+ return v;
+ }
+
+ friend vec_t<T, N> operator+(const vec_t<T, N> &a, const vec_t<T, N> &b)
+ {
+ vec_t<T, N> r;
+
+ for (size_t i = 0; i < N; i++)
+ r[i] = a[i] + b[i];
+
+ return r;
+ }
+
+ friend vec_t<T, N> &operator+=(vec_t<T, N> &v, const vec_t<T, N> &b)
+ {
+ for (size_t i = 0; i < N; i++)
+ v[i] += b[i];
+
+ return v;
+ }
+
+ friend vec_t<T, N> operator-(const vec_t<T, N> &v)
+ {
+ return -1 * v;
+ }
+
+ friend vec_t<T, N> operator-(const vec_t<T, N> &a, const vec_t<T, N> &b)
+ {
+ vec_t<T, N> r;
+
+ for (size_t i = 0; i < N; i++)
+ r[i] = a[i] - b[i];
+
+ return r;
+ }
+
+ friend vec_t<T, N> &operator-=(vec_t<T, N> &v, const vec_t<T, N> &b)
+ {
+ for (size_t i = 0; i < N; i++)
+ v[i] -= b[i];
+
+ return v;
+ }
+
+ friend T operator*(const vec_t<T, N> &a, const vec_t<T, N> &b)
+ {
+ T r = (T)0;
+
+ for (size_t i = 0; i < N; i++)
+ r += a[i] * b[i];
+
+ return r;
+ }
+
+ friend vec_t<T, N> operator*(const vec_t<T, N> &a, const T &b)
+ {
+ vec_t<T, N> r;
+
+ for (size_t i = 0; i < N; i++)
+ r[i] = a[i] * b;
+
+ return r;
+ }
+
+ friend vec_t<T, N> operator*(const T &b, const vec_t<T, N> &a)
+ {
+ return a * b;
+ }
+
+ friend vec_t<T, N> &operator*=(vec_t<T, N> &v, const T &b)
+ {
+ for (size_t i = 0; i < N; i++)
+ v[i] *= b;
+
+ return v;
+ }
+
+ friend vec_t<T, N> operator/(const vec_t<T, N> &a, const T &b)
+ {
+ vec_t<T, N> r;
+
+ for (size_t i = 0; i < N; i++)
+ r[i] = a[i] / b;
+
+ return r;
+ }
+
+ friend vec_t<T, N> operator/(const T &b, const vec_t<T, N> &a)
+ {
+ return a / b;
+ }
+
+ friend vec_t<T, N> &operator/=(vec_t<T, N> &v, const T &b)
+ {
+ for (size_t i = 0; i < N; i++)
+ v[i] /= b;
+
+ return v;
+ }
+
+ // Compatibility with SFML
+
+ template <typename U>
+ operator sf::Vector2<U>() const
+ {
+ static_assert(N == 2, "conversion of vec_t with N != 2 to sf::Vector2");
+ return sf::Vector2<U>((U)v[0], (U)v[1]);
+ }
+
+ template <typename U>
+ vec_t(sf::Vector2<U> b)
+ {
+ static_assert(N == 2, "conversion of sf::Vector2 to vec_t with N != 2");
+ v[0] = b.x;
+ v[1] = b.y;
+ }
+
+ // Compatibility with iostream
+
+ friend std::ostream& operator<<(std::ostream& stream, vec_t<T, N> v)
+ {
+ stream << "(";
+ for (size_t i = 0; i < N; i++) {
+ if (i)
+ stream << ", ";
+ stream << v.v[i];
+ }
+ stream << ")";
+
+ return stream;
+ }
+};
+
+// Shorthands
+typedef vec_t<float, 2> v2f_t;
+typedef vec_t<double, 2> v2d_t;
+
+template <typename T, size_t N>
+class rect_t {
+public:
+ vec_t<T, N> a, b;
+
+ rect_t() = default;
+
+ rect_t(vec_t<T, N> a_, vec_t<T, N> b_)
+ {
+ a = a_;
+ b = b_;
+ }
+
+ friend std::ostream& operator<<(std::ostream& stream, rect_t<T, N> r)
+ {
+ stream << "(" << r.a << ", " << r.b << ")";
+ return stream;
+ }
+};
+
diff --git a/src/procgen.cpp b/src/procgen.cpp
index b5e1d6f..bfff2c4 100644
--- a/src/procgen.cpp
+++ b/src/procgen.cpp
@@ -35,7 +35,7 @@ void prng_t::unit_vec(float out[2])
void perlin_noise_t::generate(prng_t *prng, size_t size_)
{
if (table)
- delete table;
+ delete[] table;
size = size_;
table = new float[size * size][2];
@@ -55,22 +55,21 @@ static float smooth_step(float x)
return 3 * x * x - 2 * x * x * x;
}
-float perlin_noise_t::get(float x, float y, float scale)
+float perlin_noise_t::get(v2f_t x, float scale)
{
size_t nx, ny, nx1, ny1;
float s, t, a, b, c, d;
x /= scale;
- y /= scale;
- nx = (ssize_t)floor(x) & (size - 1);
- ny = (ssize_t)floor(y) & (size - 1);
+ nx = (ssize_t)floor(x[0]) & (size - 1);
+ ny = (ssize_t)floor(x[1]) & (size - 1);
nx1 = (nx == size - 1 ? 0 : nx + 1);
ny1 = (ny == size - 1 ? 0 : ny + 1);
- s = smooth_step(x - floor(x));
- t = smooth_step(y - floor(y));
+ s = smooth_step(x[0] - floor(x[0]));
+ t = smooth_step(x[1] - floor(x[1]));
a = table_dot(nx, ny, -s, -t);
b = table_dot(nx1, ny, -s + 1.0f, -t);
@@ -82,7 +81,7 @@ float perlin_noise_t::get(float x, float y, float scale)
perlin_noise_t::~perlin_noise_t()
{
- delete table;
+ delete[] table;
}
} // namespace procgen
diff --git a/src/render.cpp b/src/render.cpp
index ee2e5b2..0353f97 100644
--- a/src/render.cpp
+++ b/src/render.cpp
@@ -45,12 +45,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);
- if ((sector->index.x & 2) ^ (sector->index.y & 2)) {
+ /*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 interface::state_t::render()
diff --git a/src/world.cpp b/src/world.cpp
index d340cc1..06369f6 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -2,31 +2,10 @@
namespace world {
-sector_index_t::sector_index_t ()
+sector_index_t sector_index_at(v2f_t x)
{
-}
-
-sector_index_t::sector_index_t (int64_t x_, int64_t y_)
-{
- x = x_;
- 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)
- return true;
- if (x > B.x)
- return false;
- if (y < B.y)
- return true;
- return false;
+ return sector_index_t(floor(x[0] / SECTOR_SIZE),
+ floor(x[1] / SECTOR_SIZE));
}
world_t::world_t(void)
@@ -35,17 +14,17 @@ world_t::world_t(void)
perlin.generate(&prng, 32);
}
-void world_t::generate_tile(ssize_t x, ssize_t y, tile_t *tile)
+void world_t::generate_tile(tile_t *tile, tile_index_t x)
{
float waterlevel, height;
- waterlevel = perlin.get(x, y, 1000.0f) * 0.3f +
- perlin.get(x, y, 500.0f) * 0.1f;
+ waterlevel = perlin.get(x, 1000.0f) * 0.3f +
+ perlin.get(x, 500.0f) * 0.1f;
- height = perlin.get(x, y, 60.0f) * 0.6f +
- perlin.get(x, y, 30.0f) * 0.25f +
- perlin.get(x, y, 14.0f) * 0.1f +
- perlin.get(x, y, 6.0f) * 0.05f;
+ height = perlin.get(x, 60.0f) * 0.6f +
+ perlin.get(x, 30.0f) * 0.25f +
+ perlin.get(x, 14.0f) * 0.1f +
+ perlin.get(x, 6.0f) * 0.05f;
if (height < waterlevel - 0.2f)
tile->type = -1;
@@ -54,7 +33,7 @@ void world_t::generate_tile(ssize_t x, ssize_t y, tile_t *tile)
else if (height < waterlevel + 0.05f)
tile->type = 1;
else {
- if (perlin.get(x, y, 5.0f) > 0.0f)
+ if (perlin.get(x, 5.0f) > 0.0f)
tile->type = 3;
else
tile->type = 2;
@@ -64,18 +43,18 @@ void world_t::generate_tile(ssize_t x, ssize_t y, tile_t *tile)
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.left = index[0] * SECTOR_SIZE;
+ sector->bounds.top = index[1] * SECTOR_SIZE;
sector->bounds.width = SECTOR_SIZE;
sector->bounds.height = SECTOR_SIZE;
- std::cout << "generating (" << index.x << ", " << index.y << ")\n";
+ std::cout << "generating " << index << "\n";
for (ssize_t ly = 0; ly < SECTOR_SIZE; ly++)
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);
+ generate_tile(sector->tiles + ly * SECTOR_SIZE + lx,
+ tile_index_t(index[0] * SECTOR_SIZE + lx,
+ index[1] * SECTOR_SIZE + ly));
sector->empty = false;
}
@@ -98,8 +77,8 @@ tile_t *world_t::get_tile(ssize_t x, ssize_t y)
sector_t *sector;
ssize_t tx, ty;
- index.x = divide_rmi(x, (ssize_t)SECTOR_SIZE, &tx);
- index.y = divide_rmi(y, (ssize_t)SECTOR_SIZE, &ty);
+ index[0] = divide_rmi(x, (ssize_t)SECTOR_SIZE, &tx);
+ index[1] = divide_rmi(y, (ssize_t)SECTOR_SIZE, &ty);
sector = get_sector(index);
return sector->tiles + ty * SECTOR_SIZE + tx;
@@ -107,12 +86,14 @@ tile_t *world_t::get_tile(ssize_t x, ssize_t y)
std::list<sector_t*> world_t::get_sectors(sf::FloatRect rect)
{
- sector_index_t base(rect.left, rect.top),
- upper(rect.left + rect.width, rect.top + rect.height);
+ sector_index_t base, upper;
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++) {
+ base = sector_index_at(v2f_t(rect.left, rect.top));
+ upper = sector_index_at(v2f_t(rect.left + rect.width, rect.top + rect.height));
+
+ for (int64_t y = base[1]; y <= upper[1]; y++)
+ for (int64_t x = base[0]; x <= upper[0]; x++) {
sector_index_t index(x, y);
list.push_back(get_sector(index));
}
@@ -120,6 +101,29 @@ std::list<sector_t*> world_t::get_sectors(sf::FloatRect rect)
return list;
}
+std::list<entity_t*> world_t::get_render_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;
+
+ if (!rect.intersects(ent->render_bounds))
+ continue;
+
+ ent->cookie = cookie;
+
+ list.push_back(ent);
+ }
+
+ return list;
+}
+
std::list<entity_t*> world_t::get_entities(sf::FloatRect rect)
{
static size_t cookie = 0;
@@ -145,8 +149,8 @@ std::list<entity_t*> world_t::get_entities(sf::FloatRect rect)
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);
+ sector_index_t index = sector_index_at(point);
+ printf("sector (%zd, %zd)\n", index[0], index[1]);
}
void entity_t::link_to_sector(sector_t *sector)
@@ -157,17 +161,24 @@ void entity_t::link_to_sector(sector_t *sector)
void entity_t::link(world_t *world)
{
+ //sf::FloatRect total_bounds;
float fx, fy;
sector_index_t base;
float xlip, ylip;
size_t xsecs, ysecs;
+ // TODO
+ //total.bounds.left = std::min(bounds.left, render_bounds.left);
+ //total.bounds.top = std::min(bounds.top, render_bounds.top);
+ //total.bounds.width = std::max(bounds.width, render_bounds.width);
+ //total.bounds.height = std::max(bounds.height, render_bounds.height);
+
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;
+ base = sector_index_at(v2f_t(fx, fy));
+ xlip = bounds.left + bounds.width - (base[0] + 1) * SECTOR_SIZE;
+ ylip = bounds.top + bounds.height - (base[1] + 1) * SECTOR_SIZE;
if (xlip > 0.0f)
xsecs = ceil(xlip / SECTOR_SIZE) + 1;
@@ -181,7 +192,7 @@ void entity_t::link(world_t *world)
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_index_t index = sector_index_at(v2f_t(base[0] + x, base[1] + y));
sector_t *sector;
sector = world->get_sector(index);