#include "collider.hpp" #include using namespace fmt; using DinkyECS::Entity; void SpatialHashTable::insert(Point pos, Entity ent) { table[pos] = ent; } void SpatialHashTable::remove(Point pos) { table.erase(pos); } void SpatialHashTable::move(Point from, Point to, Entity ent) { remove(from); insert(to, ent); } bool SpatialHashTable::occupied(Point at) const { return table.contains(at); } /* * Avoid doing work by using the dy,dx and confirming that * 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) { // don't bother checking for cells out of bounds if((dx < 0 && at.x <= 0) || (dy < 0 && at.y <= 0)) { return; } Point cell = {at.x + dx, at.y + dy}; auto it = table.find(cell); if (it != table.end()) { result.insert(result.end(), it->second); } } std::tuple SpatialHashTable::neighbors(Point cell, bool diag) const { FoundList 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 find_neighbor(table, result, cell, 0, 1); // north find_neighbor(table, result, cell, 0, -1); // south find_neighbor(table, result, cell, 1, 0); // east find_neighbor(table, result, cell, -1, 0); // west if(diag) { find_neighbor(table, result, cell, 1, -1); // south east find_neighbor(table, result, cell, -1, -1); // south west find_neighbor(table, result, cell, 1, 1); // north east find_neighbor(table, result, cell, -1, 1); // north west } return std::tuple(!result.empty(), result); }