diff options
author | Paweł Redman <pawel.redman@gmail.com> | 2017-10-21 11:20:34 +0200 |
---|---|---|
committer | Paweł Redman <pawel.redman@gmail.com> | 2017-10-21 13:12:42 +0200 |
commit | 20b189455545db5688ed4f14d2966380137ee2db (patch) | |
tree | 7504e059147cfae54fa466b8a4c0073ecbbc582c /src/world.cpp | |
parent | 29d124b93125d7c9de762c45876f69df3acd549d (diff) |
Start working on path finding.
Diffstat (limited to 'src/world.cpp')
-rw-r--r-- | src/world.cpp | 145 |
1 files changed, 142 insertions, 3 deletions
diff --git a/src/world.cpp b/src/world.cpp index d2fc2bb..818c024 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -1,11 +1,17 @@ #include "common.hpp" +#include <stack> +#include <sstream> namespace world { sector_index_t sector_index_at(v2f_t x) { - return sector_index_t(floor(x[0] / SECTOR_SIZE), - floor(x[1] / SECTOR_SIZE)); + return sector_index_t((x / SECTOR_SIZE).floor()); +} + +tile_index_t tile_index_at(v2f_t x) +{ + return sector_index_t(x.floor()); } world_t::world_t(void) @@ -45,7 +51,7 @@ void world_t::generate(sector_t *sector, sector_index_t index) sector->index = index; sector->bounds.v[0] = (v2f_t)index * SECTOR_SIZE; - sector->bounds.v[1].broadcast(SECTOR_SIZE); + sector->bounds.v[1] = sector->bounds.v[0] + v2f_t(SECTOR_SIZE, SECTOR_SIZE); std::cout << "generating " << index << "\n"; @@ -58,6 +64,139 @@ void world_t::generate(sector_t *sector, sector_index_t index) sector->empty = false; } +typedef struct { + bool accessible; + float dist; +} path_node_t; + +static const v2f_t path_margin(5, 5); +static const tile_index_t path_offsets[8] = { + {+1, 0}, {+1, +1}, {0, +1}, {-1, +1}, + {-1, 0}, {-1, -1}, {0, -1}, {+1, -1} +}; + +class path_finder_t { +public: + v2f_t src, dst; + path_node_t *nodes; + size_t width, height; + tile_index_t base; + std::stack<v2f_t> current_path, shortest_path; + + ~path_finder_t() + { + delete nodes; + } + + void setup_nodes(v2f_t src_, v2f_t dst_) + { + rectf_t src_margin, dst_margin, bounds; + tile_index_t end; + + src = src_; + dst = dst_; + + src_margin[0] = src - path_margin; + src_margin[1] = src + path_margin; + dst_margin[0] = dst - path_margin; + dst_margin[1] = dst + path_margin; + bounds = src_margin + dst_margin; + + base = tile_index_at(bounds[0]); + end = tile_index_at(bounds[1]); + + width = end[0] - base[0] + 1; + height = end[1] - base[1] + 1; + + nodes = new path_node_t[width * height]; + for (size_t i = 0; i < width * height; i++) + nodes[i].dist = INFINITY; + } + + void find_r(tile_index_t index, float dist) + { + path_node_t *node; + + node = nodes + index[1] * width + index[0]; + + if (!node->accessible) + return; + if (node->dist <= dist) + return; + + node->dist = dist; + + for (size_t i = 0; i < 8; i++) { + tile_index_t offset, next; + + offset = path_offsets[i]; + next = index + offset; + + if (next[0] < 0 || next[1] < 0 || + next[0] >= (int64_t)width || next[1] >= (int64_t)height) + continue; + + find_r(next, dist + v2f_t(offset).len()); + } + } + + void find(void) + { + tile_index_t start; + + start = tile_index_at(src) - base; + nodes[start[1] * width + start[0]].accessible = false; + + for (size_t i = 0; i < 8; i++) { + tile_index_t next; + v2f_t offset; + + next = start + path_offsets[i]; + offset = src - v2f_t(base) - v2f_t(next); + + if (next[0] < 0 || next[1] < 0 || + next[0] >= (int64_t)width || next[1] >= (int64_t)height) + continue; + + find_r(next, v2f_t(offset).len()); + } + } +}; + +bool world_t::find_path(v2f_t src, v2f_t dst, rectf_t size, + std::list<v2f_t> *path) +{ + path_finder_t finder; + + finder.setup_nodes(src, dst); + + for (size_t y = 0; y < finder.height; y++) + for (size_t x = 0; x < finder.width; x++) { + path_node_t *node = finder.nodes + y * finder.width + x; + tile_index_t index; + + index = finder.base + tile_index_t(x, y); + node->accessible = (get_tile(index)->type >= 1); + } + + finder.find(); + + debug.clear(); + + for (size_t y = 0; y < finder.height; y++) + for (size_t x = 0; x < finder.width; x++) { + path_node_t *node = finder.nodes + y * finder.width + x; + std::stringstream ss; + + ss << finder.base + tile_index_t(x, y) << "\n"; + ss << node->dist; + + debug.push_back((debug_t){finder.base + tile_index_t(x, y), ss.str()}); + } + + return false; +} + sector_t *world_t::get_sector(sector_index_t index) { sector_t *sector; |