Refactor some code to have better naming and move Point and related point things into their own .hpp.
This commit is contained in:
parent
c19cd707d1
commit
5a123ae74c
7 changed files with 45 additions and 40 deletions
14
collider.cpp
14
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
|
||||||
|
|
14
collider.hpp
14
collider.hpp
|
@ -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;
|
||||||
|
|
4
gui.cpp
4
gui.cpp
|
@ -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});
|
||||||
|
|
11
map.hpp
11
map.hpp
|
@ -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;
|
||||||
|
|
||||||
|
|
18
point.hpp
Normal file
18
point.hpp
Normal file
|
@ -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…
Add table
Add a link
Reference in a new issue