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

main
Zed A. Shaw 10 months 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;
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<bool, FoundList> SpatialHashTable::neighbors(Point cell, bool diag) const {
FoundList result;
std::tuple<bool, EntityList> 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

@ -3,26 +3,22 @@
#include <unordered_map>
#include "map.hpp"
#include "dinkyecs.hpp"
#include "point.hpp"
#include <tuple>
struct PointHash {
size_t operator()(const Point& p) const {
return std::hash<int>()(p.x) ^ std::hash<int>()(p.y);
}
};
typedef std::vector<DinkyECS::Entity> EntityList;
typedef std::vector<DinkyECS::Entity> FoundList;
typedef std::unordered_map<Point, DinkyECS::Entity, PointHash> 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<bool, FoundList> neighbors(Point position, bool diag=false) const;
std::tuple<bool, EntityList> neighbors(Point position, bool diag=false) const;
private:
PointEntityMap table;

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

@ -5,6 +5,7 @@
#include <random>
#include <algorithm>
#include <fmt/core.h>
#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<Point> PointList;
typedef std::vector<int> MatrixRow;
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) {
auto &collider = world.get<SpatialHashTable>();
auto &collider = world.get<spatial_map>();
world.system<Position>([&](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<SpatialHashTable>();
auto &collider = world.get<spatial_map>();
world.system<Position, Motion>([&](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<SpatialHashTable>();
const auto& collider = world.get<spatial_map>();
const auto& player_position = world.component<Position>(player.entity);
auto& player_combat = world.component<Combat>(player.entity);
auto& log = world.get<ActionLog>();

@ -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

Loading…
Cancel
Save