|
|
@ -6,46 +6,49 @@ using namespace fmt; |
|
|
|
using DinkyECS::Entity; |
|
|
|
using DinkyECS::Entity; |
|
|
|
|
|
|
|
|
|
|
|
void SpatialMap::insert(Point pos, Entity ent, bool has_collision) { |
|
|
|
void SpatialMap::insert(Point pos, Entity ent, bool has_collision) { |
|
|
|
if(has_collision) { |
|
|
|
dbc::check(!occupied(pos), "attempt to insert an entity with collision in space with collision"); |
|
|
|
dbc::check(!yes_collision.contains(pos), "YES_collision already has entity"); |
|
|
|
|
|
|
|
yes_collision.insert_or_assign(pos, ent); |
|
|
|
$collision.emplace(pos, CollisionData{ent, has_collision}); |
|
|
|
} else { |
|
|
|
|
|
|
|
dbc::check(!no_collision.contains(pos), "no_collision already has entity"); |
|
|
|
|
|
|
|
no_collision.insert_or_assign(pos, ent); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool SpatialMap::remove(Point pos) { |
|
|
|
CollisionData SpatialMap::remove(Point pos, Entity ent) { |
|
|
|
if(yes_collision.contains(pos)) { |
|
|
|
auto [begin, end] = $collision.equal_range(pos); |
|
|
|
yes_collision.erase(pos); |
|
|
|
for(auto it = begin; it != end; ++it) { |
|
|
|
return true; |
|
|
|
if(it->second.entity == ent) { |
|
|
|
} else { |
|
|
|
// does the it->second go invalid after erase?
|
|
|
|
dbc::check(no_collision.contains(pos), "remove of entity that's not in no_collision"); |
|
|
|
auto copy = it->second; |
|
|
|
no_collision.erase(pos); |
|
|
|
$collision.erase(it); |
|
|
|
return false; |
|
|
|
return copy; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dbc::sentinel("failed to find entity to remove"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void SpatialMap::move(Point from, Point to, Entity ent) { |
|
|
|
void SpatialMap::move(Point from, Point to, Entity ent) { |
|
|
|
dbc::check(!occupied(to), "attempt to move to point with an existing entity"); |
|
|
|
auto data = remove(from, ent); |
|
|
|
bool has_collision = remove(from); |
|
|
|
insert(to, ent, data.collision); |
|
|
|
insert(to, ent, has_collision); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool SpatialMap::occupied(Point at) const { |
|
|
|
bool SpatialMap::occupied(Point at) const { |
|
|
|
return yes_collision.contains(at); |
|
|
|
auto [begin, end] = $collision.equal_range(at); |
|
|
|
|
|
|
|
for(auto it = begin; it != end; ++it) { |
|
|
|
|
|
|
|
if(it->second.collision) { |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool SpatialMap::something_there(Point at) const { |
|
|
|
bool SpatialMap::something_there(Point at) const { |
|
|
|
return yes_collision.contains(at) || no_collision.contains(at); |
|
|
|
return $collision.count(at) > 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Entity SpatialMap::get(Point at) const { |
|
|
|
Entity SpatialMap::get(Point at) const { |
|
|
|
if(yes_collision.contains(at)) { |
|
|
|
dbc::check($collision.contains(at), "attempt to get entity when none there"); |
|
|
|
return yes_collision.at(at); |
|
|
|
auto [begin, end] = $collision.equal_range(at); |
|
|
|
} else { |
|
|
|
return begin->second.entity; |
|
|
|
return no_collision.at(at); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -63,7 +66,7 @@ inline void find_neighbor(const PointEntityMap &table, EntityList &result, Point |
|
|
|
|
|
|
|
|
|
|
|
auto it = table.find(cell); |
|
|
|
auto it = table.find(cell); |
|
|
|
if (it != table.end()) { |
|
|
|
if (it != table.end()) { |
|
|
|
result.insert(result.end(), it->second); |
|
|
|
result.insert(result.end(), it->second.entity); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -72,16 +75,16 @@ FoundEntities SpatialMap::neighbors(Point cell, bool diag) const { |
|
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
find_neighbor(yes_collision, result, cell, 0, 1); // north
|
|
|
|
find_neighbor($collision, result, cell, 0, 1); // north
|
|
|
|
find_neighbor(yes_collision, result, cell, 0, -1); // south
|
|
|
|
find_neighbor($collision, result, cell, 0, -1); // south
|
|
|
|
find_neighbor(yes_collision, result, cell, 1, 0); // east
|
|
|
|
find_neighbor($collision, result, cell, 1, 0); // east
|
|
|
|
find_neighbor(yes_collision, result, cell, -1, 0); // west
|
|
|
|
find_neighbor($collision, result, cell, -1, 0); // west
|
|
|
|
|
|
|
|
|
|
|
|
if(diag) { |
|
|
|
if(diag) { |
|
|
|
find_neighbor(yes_collision, result, cell, 1, -1); // south east
|
|
|
|
find_neighbor($collision, result, cell, 1, -1); // south east
|
|
|
|
find_neighbor(yes_collision, result, cell, -1, -1); // south west
|
|
|
|
find_neighbor($collision, result, cell, -1, -1); // south west
|
|
|
|
find_neighbor(yes_collision, result, cell, 1, 1); // north east
|
|
|
|
find_neighbor($collision, result, cell, 1, 1); // north east
|
|
|
|
find_neighbor(yes_collision, result, cell, -1, 1); // north west
|
|
|
|
find_neighbor($collision, result, cell, -1, 1); // north west
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return {!result.empty(), result}; |
|
|
|
return {!result.empty(), result}; |
|
|
@ -94,7 +97,7 @@ inline void update_sorted(SortedEntities& sprite_distance, PointEntityMap& table |
|
|
|
(from.y - sprite.y) * (from.y - sprite.y); |
|
|
|
(from.y - sprite.y) * (from.y - sprite.y); |
|
|
|
|
|
|
|
|
|
|
|
if(inside < max_dist) { |
|
|
|
if(inside < max_dist) { |
|
|
|
sprite_distance.push_back({inside, rec.second}); |
|
|
|
sprite_distance.push_back({inside, rec.second.entity}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -102,8 +105,7 @@ inline void update_sorted(SortedEntities& sprite_distance, PointEntityMap& table |
|
|
|
SortedEntities SpatialMap::distance_sorted(Point from, int max_dist) { |
|
|
|
SortedEntities SpatialMap::distance_sorted(Point from, int max_dist) { |
|
|
|
SortedEntities sprite_distance; |
|
|
|
SortedEntities sprite_distance; |
|
|
|
|
|
|
|
|
|
|
|
update_sorted(sprite_distance, yes_collision, from, max_dist); |
|
|
|
update_sorted(sprite_distance, $collision, from, max_dist); |
|
|
|
update_sorted(sprite_distance, no_collision, from, max_dist); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::sort(sprite_distance.begin(), sprite_distance.end(), std::greater<>()); |
|
|
|
std::sort(sprite_distance.begin(), sprite_distance.end(), std::greater<>()); |
|
|
|
|
|
|
|
|
|
|
|