Refactor some code to have better naming and move Point and related point things into their own .hpp.

main
Zed A. Shaw 4 weeks ago
parent c19cd707d1
commit 5a123ae74c
  1. 14
      collider.cpp
  2. 14
      collider.hpp
  3. 4
      gui.cpp
  4. 11
      map.hpp
  5. 18
      point.hpp
  6. 6
      systems.cpp
  7. 18
      tests/collider.cpp

@ -5,20 +5,20 @@ using namespace fmt;
using DinkyECS::Entity; using DinkyECS::Entity;
void SpatialHashTable::insert(Point pos, Entity ent) { void spatial_map::insert(Point pos, Entity ent) {
table[pos] = ent; table[pos] = ent;
} }
void SpatialHashTable::remove(Point pos) { void spatial_map::remove(Point pos) {
table.erase(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); remove(from);
insert(to, ent); insert(to, ent);
} }
bool SpatialHashTable::occupied(Point at) const { bool spatial_map::occupied(Point at) const {
return table.contains(at); 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 * at.x or at.y is > 0. If either is 0 then there can't be
* a neighbor since that's out of bounds. * 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 // don't bother checking for cells out of bounds
if((dx < 0 && at.x <= 0) || (dy < 0 && at.y <= 0)) { if((dx < 0 && at.x <= 0) || (dy < 0 && at.y <= 0)) {
return; return;
@ -41,8 +41,8 @@ inline void find_neighbor(const PointEntityMap &table, FoundList &result, Point
} }
} }
std::tuple<bool, FoundList> SpatialHashTable::neighbors(Point cell, bool diag) const { std::tuple<bool, EntityList> spatial_map::neighbors(Point cell, bool diag) const {
FoundList result; EntityList result;
// just unroll the loop since we only check four directions // 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 // this also solves the problem that it was detecting that the cell was automatically included as a "neighbor" but it's not

@ -3,26 +3,22 @@
#include <unordered_map> #include <unordered_map>
#include "map.hpp" #include "map.hpp"
#include "dinkyecs.hpp" #include "dinkyecs.hpp"
#include "point.hpp"
#include <tuple> #include <tuple>
struct PointHash { typedef std::vector<DinkyECS::Entity> EntityList;
size_t operator()(const Point& p) const {
return std::hash<int>()(p.x) ^ std::hash<int>()(p.y);
}
};
typedef std::vector<DinkyECS::Entity> FoundList;
typedef std::unordered_map<Point, DinkyECS::Entity, PointHash> PointEntityMap; typedef std::unordered_map<Point, DinkyECS::Entity, PointHash> PointEntityMap;
class SpatialHashTable { class spatial_map {
public: public:
SpatialHashTable() {} spatial_map() {}
void insert(Point pos, DinkyECS::Entity obj); void insert(Point pos, DinkyECS::Entity obj);
void move(Point from, Point to, DinkyECS::Entity ent); void move(Point from, Point to, DinkyECS::Entity ent);
void remove(Point pos); void remove(Point pos);
bool occupied(Point pos) const; bool occupied(Point pos) const;
std::tuple<bool, FoundList> neighbors(Point position, bool diag=false) const; std::tuple<bool, EntityList> neighbors(Point position, bool diag=false) const;
private: private:
PointEntityMap table; PointEntityMap table;

@ -278,8 +278,8 @@ void GUI::configure_world() {
ActionLog log{{"Welcome to the game!"}}; ActionLog log{{"Welcome to the game!"}};
$world.set<ActionLog>(log); $world.set<ActionLog>(log);
SpatialHashTable collider; spatial_map collider;
$world.set<SpatialHashTable>(collider); $world.set<spatial_map>(collider);
$world.assign<Position>(player.entity, {$game_map.place_entity(0)}); $world.assign<Position>(player.entity, {$game_map.place_entity(0)});
$world.assign<Motion>(player.entity, {0, 0}); $world.assign<Motion>(player.entity, {0, 0});

@ -5,6 +5,7 @@
#include <random> #include <random>
#include <algorithm> #include <algorithm>
#include <fmt/core.h> #include <fmt/core.h>
#include "point.hpp"
#define INV_WALL 0 #define INV_WALL 0
#define INV_SPACE 1 #define INV_SPACE 1
@ -15,15 +16,6 @@
#define PLAYER_TILE "☺" #define PLAYER_TILE "☺"
#define ENEMY_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 { struct Room {
size_t x = 0; size_t x = 0;
size_t y = 0; size_t y = 0;
@ -33,7 +25,6 @@ struct Room {
Point exit; Point exit;
}; };
typedef std::vector<Point> PointList;
typedef std::vector<int> MatrixRow; typedef std::vector<int> MatrixRow;
typedef std::vector<MatrixRow> Matrix; typedef std::vector<MatrixRow> Matrix;

@ -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<Point> PointList;
struct PointHash {
size_t operator()(const Point& p) const {
return std::hash<int>()(p.x) ^ std::hash<int>()(p.y);
}
};

@ -26,7 +26,7 @@ void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player
} }
void System::init_positions(DinkyECS::World &world) { void System::init_positions(DinkyECS::World &world) {
auto &collider = world.get<SpatialHashTable>(); auto &collider = world.get<spatial_map>();
world.system<Position>([&](const auto &ent, auto &pos) { world.system<Position>([&](const auto &ent, auto &pos) {
collider.insert(pos.location, ent); 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) { void System::motion(DinkyECS::World &world, Map &game_map) {
auto &collider = world.get<SpatialHashTable>(); auto &collider = world.get<spatial_map>();
world.system<Position, Motion>([&](const auto &ent, auto &position, auto &motion) { world.system<Position, Motion>([&](const auto &ent, auto &position, auto &motion) {
// don't process entities that don't move // 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) { void System::combat(DinkyECS::World &world, Player &player) {
const auto& collider = world.get<SpatialHashTable>(); const auto& collider = world.get<spatial_map>();
const auto& player_position = world.component<Position>(player.entity); const auto& player_position = world.component<Position>(player.entity);
auto& player_combat = world.component<Combat>(player.entity); auto& player_combat = world.component<Combat>(player.entity);
auto& log = world.get<ActionLog>(); auto& log = world.get<ActionLog>();

@ -7,7 +7,7 @@
using DinkyECS::Entity; using DinkyECS::Entity;
using namespace fmt; 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); println("TEST require_found at={},{}", at.x, at.y);
auto [found, nearby] = collider.neighbors(at, diag); auto [found, nearby] = collider.neighbors(at, diag);
REQUIRE(found == true); REQUIRE(found == true);
@ -21,7 +21,7 @@ TEST_CASE("confirm basic collision operations", "[collision]") {
Entity player = world.entity(); Entity player = world.entity();
Entity enemy = world.entity(); Entity enemy = world.entity();
SpatialHashTable collider; spatial_map collider;
collider.insert({11,11}, player); collider.insert({11,11}, player);
collider.insert({21,21}, enemy); collider.insert({21,21}, enemy);
@ -32,7 +32,7 @@ TEST_CASE("confirm basic collision operations", "[collision]") {
} }
// found // found
FoundList nearby = require_found(collider, {10,10}, true, 1); EntityList nearby = require_found(collider, {10,10}, true, 1);
REQUIRE(nearby[0] == player); REQUIRE(nearby[0] == player);
{ // removed { // removed
@ -68,13 +68,13 @@ TEST_CASE("confirm multiple entities moving", "[collision]") {
Entity e2 = world.entity(); Entity e2 = world.entity();
Entity e3 = world.entity(); Entity e3 = world.entity();
SpatialHashTable collider; spatial_map collider;
collider.insert({11,11}, player); collider.insert({11,11}, player);
collider.insert({10,10}, e2); collider.insert({10,10}, e2);
collider.insert({11,10}, e3); collider.insert({11,10}, e3);
collider.insert({21,21}, e1); 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); REQUIRE(nearby[0] == e3);
nearby = require_found(collider, {11,11}, true, 2); 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 player = world.entity();
Entity enemy = world.entity(); Entity enemy = world.entity();
SpatialHashTable collider; spatial_map collider;
collider.insert({0,0}, player); collider.insert({0,0}, player);
Point enemy_at = {1, 0}; Point enemy_at = {1, 0};
collider.insert(enemy_at, enemy); 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); collider.move({1,0}, {1,1}, enemy);
nearby = require_found(collider, {0,0}, true, 1); nearby = require_found(collider, {0,0}, true, 1);
@ -113,7 +113,7 @@ TEST_CASE("check all diagonal works", "[collision]") {
Entity player = world.entity(); Entity player = world.entity();
Entity enemy = world.entity(); Entity enemy = world.entity();
SpatialHashTable collider; spatial_map collider;
Point player_at = {1,1}; Point player_at = {1,1};
collider.insert(player_at, player); 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 x = 0; x <= 2; x++) {
for(size_t y = 0; y <= 2; y++) { 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 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); REQUIRE(nearby[0] == enemy);
// move the enemy to a new spot around the player // move the enemy to a new spot around the player

Loading…
Cancel
Save