diff --git a/collider.cpp b/collider.cpp index dcc8be0..c7f7f2a 100644 --- a/collider.cpp +++ b/collider.cpp @@ -5,20 +5,20 @@ using namespace fmt; using DinkyECS::Entity; -void SpatialHashTable::insert(Point pos, Entity ent) { +void spatial_map::insert(Point pos, Entity ent) { table[pos] = ent; } -void SpatialHashTable::remove(Point pos) { +void spatial_map::remove(Point pos) { table.erase(pos); } -void SpatialHashTable::move(Point from, Point to, Entity ent) { +void spatial_map::move(Point from, Point to, Entity ent) { remove(from); insert(to, ent); } -bool SpatialHashTable::occupied(Point at) const { +bool spatial_map::occupied(Point at) const { return table.contains(at); } @@ -27,7 +27,7 @@ bool SpatialHashTable::occupied(Point at) const { * at.x or at.y is > 0. If either is 0 then there can't be * a neighbor since that's out of bounds. */ -inline void find_neighbor(const PointEntityMap &table, FoundList &result, Point at, int dy, int dx) { +inline void find_neighbor(const PointEntityMap &table, EntityList &result, Point at, int dy, int dx) { // don't bother checking for cells out of bounds if((dx < 0 && at.x <= 0) || (dy < 0 && at.y <= 0)) { return; @@ -41,8 +41,8 @@ inline void find_neighbor(const PointEntityMap &table, FoundList &result, Point } } -std::tuple SpatialHashTable::neighbors(Point cell, bool diag) const { - FoundList result; +std::tuple spatial_map::neighbors(Point cell, bool diag) const { + EntityList result; // just unroll the loop since we only check four directions // this also solves the problem that it was detecting that the cell was automatically included as a "neighbor" but it's not diff --git a/collider.hpp b/collider.hpp index 12d8e57..2a4f502 100644 --- a/collider.hpp +++ b/collider.hpp @@ -3,26 +3,22 @@ #include #include "map.hpp" #include "dinkyecs.hpp" +#include "point.hpp" #include -struct PointHash { - size_t operator()(const Point& p) const { - return std::hash()(p.x) ^ std::hash()(p.y); - } -}; +typedef std::vector EntityList; -typedef std::vector FoundList; typedef std::unordered_map PointEntityMap; -class SpatialHashTable { +class spatial_map { public: - SpatialHashTable() {} + spatial_map() {} void insert(Point pos, DinkyECS::Entity obj); void move(Point from, Point to, DinkyECS::Entity ent); void remove(Point pos); bool occupied(Point pos) const; - std::tuple neighbors(Point position, bool diag=false) const; + std::tuple neighbors(Point position, bool diag=false) const; private: PointEntityMap table; diff --git a/gui.cpp b/gui.cpp index fcdd7fa..7936825 100644 --- a/gui.cpp +++ b/gui.cpp @@ -278,8 +278,8 @@ void GUI::configure_world() { ActionLog log{{"Welcome to the game!"}}; $world.set(log); - SpatialHashTable collider; - $world.set(collider); + spatial_map collider; + $world.set(collider); $world.assign(player.entity, {$game_map.place_entity(0)}); $world.assign(player.entity, {0, 0}); diff --git a/map.hpp b/map.hpp index 3453505..e263ae0 100644 --- a/map.hpp +++ b/map.hpp @@ -5,6 +5,7 @@ #include #include #include +#include "point.hpp" #define INV_WALL 0 #define INV_SPACE 1 @@ -15,15 +16,6 @@ #define PLAYER_TILE "☺" #define ENEMY_TILE "Ω" -struct Point { - size_t x = 0; - size_t y = 0; - - bool operator==(const Point& other) const { - return other.x == x && other.y == y; - } -}; - struct Room { size_t x = 0; size_t y = 0; @@ -33,7 +25,6 @@ struct Room { Point exit; }; -typedef std::vector PointList; typedef std::vector MatrixRow; typedef std::vector Matrix; diff --git a/point.hpp b/point.hpp new file mode 100644 index 0000000..7d2a5da --- /dev/null +++ b/point.hpp @@ -0,0 +1,18 @@ +#pragma once + +struct Point { + size_t x = 0; + size_t y = 0; + + bool operator==(const Point& other) const { + return other.x == x && other.y == y; + } +}; + +typedef std::vector PointList; + +struct PointHash { + size_t operator()(const Point& p) const { + return std::hash()(p.x) ^ std::hash()(p.y); + } +}; diff --git a/systems.cpp b/systems.cpp index 7d11975..f5a45e6 100644 --- a/systems.cpp +++ b/systems.cpp @@ -26,7 +26,7 @@ void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player } void System::init_positions(DinkyECS::World &world) { - auto &collider = world.get(); + auto &collider = world.get(); world.system([&](const auto &ent, auto &pos) { collider.insert(pos.location, ent); @@ -34,7 +34,7 @@ void System::init_positions(DinkyECS::World &world) { } void System::motion(DinkyECS::World &world, Map &game_map) { - auto &collider = world.get(); + auto &collider = world.get(); world.system([&](const auto &ent, auto &position, auto &motion) { // don't process entities that don't move @@ -58,7 +58,7 @@ void System::motion(DinkyECS::World &world, Map &game_map) { void System::combat(DinkyECS::World &world, Player &player) { - const auto& collider = world.get(); + const auto& collider = world.get(); const auto& player_position = world.component(player.entity); auto& player_combat = world.component(player.entity); auto& log = world.get(); diff --git a/tests/collider.cpp b/tests/collider.cpp index 7432756..9a6dc1d 100644 --- a/tests/collider.cpp +++ b/tests/collider.cpp @@ -7,7 +7,7 @@ using DinkyECS::Entity; using namespace fmt; -FoundList require_found(const SpatialHashTable& collider, Point at, bool diag, size_t expect_size) { +EntityList require_found(const spatial_map& collider, Point at, bool diag, size_t expect_size) { println("TEST require_found at={},{}", at.x, at.y); auto [found, nearby] = collider.neighbors(at, diag); REQUIRE(found == true); @@ -21,7 +21,7 @@ TEST_CASE("confirm basic collision operations", "[collision]") { Entity player = world.entity(); Entity enemy = world.entity(); - SpatialHashTable collider; + spatial_map collider; collider.insert({11,11}, player); collider.insert({21,21}, enemy); @@ -32,7 +32,7 @@ TEST_CASE("confirm basic collision operations", "[collision]") { } // found - FoundList nearby = require_found(collider, {10,10}, true, 1); + EntityList nearby = require_found(collider, {10,10}, true, 1); REQUIRE(nearby[0] == player); { // removed @@ -68,13 +68,13 @@ TEST_CASE("confirm multiple entities moving", "[collision]") { Entity e2 = world.entity(); Entity e3 = world.entity(); - SpatialHashTable collider; + spatial_map collider; collider.insert({11,11}, player); collider.insert({10,10}, e2); collider.insert({11,10}, e3); collider.insert({21,21}, e1); - FoundList nearby = require_found(collider, {11,11}, false, 1); + EntityList nearby = require_found(collider, {11,11}, false, 1); REQUIRE(nearby[0] == e3); nearby = require_found(collider, {11,11}, true, 2); @@ -91,13 +91,13 @@ TEST_CASE("test edge cases that might crash", "[collision]") { Entity player = world.entity(); Entity enemy = world.entity(); - SpatialHashTable collider; + spatial_map collider; collider.insert({0,0}, player); Point enemy_at = {1, 0}; collider.insert(enemy_at, enemy); - FoundList nearby = require_found(collider, {0,0}, true, 1); + EntityList nearby = require_found(collider, {0,0}, true, 1); collider.move({1,0}, {1,1}, enemy); nearby = require_found(collider, {0,0}, true, 1); @@ -113,7 +113,7 @@ TEST_CASE("check all diagonal works", "[collision]") { Entity player = world.entity(); Entity enemy = world.entity(); - SpatialHashTable collider; + spatial_map collider; Point player_at = {1,1}; collider.insert(player_at, player); @@ -123,7 +123,7 @@ TEST_CASE("check all diagonal works", "[collision]") { for(size_t x = 0; x <= 2; x++) { for(size_t y = 0; y <= 2; y++) { if(enemy_at.x == player_at.x && enemy_at.y == player_at.y) continue; // skip player spot - FoundList nearby = require_found(collider, player_at, true, 1); + EntityList nearby = require_found(collider, player_at, true, 1); REQUIRE(nearby[0] == enemy); // move the enemy to a new spot around the player