From 7471347839f30a85e985891b945a721967fcfb86 Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Tue, 7 Nov 2017 12:06:19 +0100 Subject: Avoid walking into walls. --- src/common.hpp | 2 +- src/game.cpp | 36 +++++++++++++++++++++++++++++------- src/render.cpp | 8 +++++--- src/world.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 11 deletions(-) diff --git a/src/common.hpp b/src/common.hpp index 10fafcf..a301881 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -113,7 +113,7 @@ namespace world { std::list get_entities(rectf_t rect, cflags_t cflags); std::list get_render_entities(rectf_t rect); - bool test_rect(rectf_t rect, cflags_t cflags); + bool test_rect(const cmodel_t *cmodel, const entity_t *ignore); void debug_point(sf::Vector2f point); }; diff --git a/src/game.cpp b/src/game.cpp index a2f4bbc..e8c179a 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -5,10 +5,19 @@ namespace game { class unit_t : public world::entity_t { world::world_t *world; + world::cmodel_t make_cmodel(v2f_t at) + { + world::cmodel_t cmodel; + + cmodel.bounds[0] = at + size[0]; + cmodel.bounds[1] = at + size[1]; + cmodel.cflags = cflags; + + return cmodel; + } + void compute_bounds() { - cmodel.bounds[0] = x + size[0]; - cmodel.bounds[1] = x + size[1]; render_bounds[0] = x + render_size[0]; render_bounds[1] = x + render_size[1]; } @@ -16,6 +25,7 @@ class unit_t : public world::entity_t { public: v2f_t x; rectf_t size, render_size; + world::cflags_t cflags; struct { bool moving = false; @@ -30,9 +40,10 @@ public: world = world_; x = x_; move.moving = false; - cmodel.cflags = 1; + cflags = 1; unlink(); + cmodel = make_cmodel(x); compute_bounds(); link(world); } @@ -47,7 +58,8 @@ public: time = 0.15; while (time > 0.0f) { - v2f_t delta, next; + v2f_t delta, next, x_new; + world::cmodel_t cmodel_next; if (!move.path.size()) { move.moving = false; @@ -59,15 +71,25 @@ public: move.angle = delta.angle(); if (delta.len() >= time) { - x += delta * time / delta.len(); - break; + x_new = x + delta * time / delta.len(); + time -= delta.len(); } else { - x = next; + x_new = next; time -= delta.len(); move.path.pop_front(); } + + cmodel_next = make_cmodel(x_new); + if (world->test_rect(&cmodel_next, this)) { + move.moving = false; + break; + } + + x = x_new; + cmodel = cmodel_next; } + unlink(); compute_bounds(); link(world); diff --git a/src/render.cpp b/src/render.cpp index 9fb1625..313bc4d 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -5,7 +5,8 @@ static sf::RectangleShape wot_rect; static sf::Font font; -static void draw_tile(sf::RenderWindow *window, v2f_t x, world::tile_t *tile) +static void draw_tile(sf::RenderWindow *window, v2f_t x, world::tile_t *tile, + world::tile_index_t local) { sf::Texture *texture; @@ -30,7 +31,7 @@ static void draw_tile(sf::RenderWindow *window, v2f_t x, world::tile_t *tile) window->draw(wot_rect); std::stringstream ss; - ss << tile->type << ":" << tile->neighbors; + ss << "L=" << local; sf::Text text(ss.str(), font, 20); text.setPosition(x); text.setScale(0.005, 0.005); @@ -42,7 +43,8 @@ static void draw_sector(sf::RenderWindow *window, world::sector_t *sector) for (ssize_t y = 0; y < SECTOR_SIZE; y++) for (ssize_t x = 0; x < SECTOR_SIZE; x++) draw_tile(window, sector->bounds.v[0] + v2f_t(x, y), - sector->tiles + y * SECTOR_SIZE + x); + sector->tiles + y * SECTOR_SIZE + x, + world::tile_index_t(x, y)); } void interface::state_t::render() diff --git a/src/world.cpp b/src/world.cpp index 778e463..2339dbf 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -230,6 +230,59 @@ std::list world_t::get_render_entities(rectf_t rect) return list; } +bool world_t::test_rect(const cmodel_t *cmodel, const entity_t *ignore) +{ + static size_t cookie = 0; + + cookie++; + + for (sector_t *sector : get_sectors(cmodel->bounds)) { + rect_t bounds; + tile_index_t index; + + bounds[0] = (cmodel->bounds[0] - sector->bounds[0]).floor(); + bounds[1] = (cmodel->bounds[1] - sector->bounds[0]).floor(); + + if (bounds[0][0] < 0) + bounds[0][0] = 0; + if (bounds[0][1] < 0) + bounds[0][1] = 0; + if (bounds[1][0] >= (coord_t)SECTOR_SIZE) + bounds[1][0] = SECTOR_SIZE - 1; + if (bounds[1][1] >= (coord_t)SECTOR_SIZE) + bounds[1][1] = SECTOR_SIZE - 1; + + for (index[1] = bounds[0][1]; index[1] <= bounds[1][1]; index[1]++) + for (index[0] = bounds[0][0]; index[0] <= bounds[1][0]; index[0]++) { + tile_t *tile; + + tile = sector->tiles + index[1] * SECTOR_SIZE + index[0]; + if (tile->type != TILE_DIRT) + return true; + } + + for (entity_t *ent : sector->ents) { + if (ent == ignore) + continue; + + if (ent->cookie == cookie) + continue; + + ent->cookie = cookie; + + if (!(ent->cmodel.cflags & cmodel->cflags)) + continue; + + if (!(cmodel->bounds && ent->cmodel.bounds)) + continue; + + return true; + } + } + + return false; +} + void world_t::debug_point(sf::Vector2f point) { sector_index_t index = sector_index_at(point); -- cgit