Mostly working spatical map with 2 level collision/space structure. Not the best implementation but this is the idea.
This commit is contained in:
parent
fd53f92fe6
commit
d6326c9e41
7 changed files with 60 additions and 31 deletions
|
@ -31,7 +31,8 @@ namespace gui {
|
||||||
}
|
}
|
||||||
|
|
||||||
DinkyECS::Entity MainUI::camera_aim() {
|
DinkyECS::Entity MainUI::camera_aim() {
|
||||||
if($level.collision->occupied($rayview.aiming_at)) {
|
// what happens if there's two things at that spot
|
||||||
|
if($level.collision->something_there($rayview.aiming_at)) {
|
||||||
return $level.collision->get($rayview.aiming_at);
|
return $level.collision->get($rayview.aiming_at);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -85,7 +85,7 @@ DinkyECS::Entity LevelManager::spawn_enemy(std::string named) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
level.collision->insert(entity_pos.location, entity_id);
|
level.collision->insert(entity_pos.location, entity_id, true);
|
||||||
|
|
||||||
return entity_id;
|
return entity_id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,25 +5,43 @@ using namespace fmt;
|
||||||
|
|
||||||
using DinkyECS::Entity;
|
using DinkyECS::Entity;
|
||||||
|
|
||||||
void SpatialMap::insert(Point pos, Entity ent) {
|
void SpatialMap::insert(Point pos, Entity ent, bool has_collision) {
|
||||||
|
if(has_collision) {
|
||||||
yes_collision.insert_or_assign(pos, ent);
|
yes_collision.insert_or_assign(pos, ent);
|
||||||
|
} else {
|
||||||
|
no_collision.insert_or_assign(pos, ent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpatialMap::remove(Point pos) {
|
bool SpatialMap::remove(Point pos) {
|
||||||
|
if(yes_collision.contains(pos)) {
|
||||||
yes_collision.erase(pos);
|
yes_collision.erase(pos);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
no_collision.erase(pos);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpatialMap::move(Point from, Point to, Entity ent) {
|
void SpatialMap::move(Point from, Point to, Entity ent) {
|
||||||
remove(from);
|
bool has_collision = remove(from);
|
||||||
insert(to, ent);
|
insert(to, ent, has_collision);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpatialMap::occupied(Point at) const {
|
bool SpatialMap::occupied(Point at) const {
|
||||||
return yes_collision.contains(at);
|
return yes_collision.contains(at);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SpatialMap::something_there(Point at) const {
|
||||||
|
return yes_collision.contains(at) || no_collision.contains(at);
|
||||||
|
}
|
||||||
|
|
||||||
Entity SpatialMap::get(Point at) const {
|
Entity SpatialMap::get(Point at) const {
|
||||||
|
if(yes_collision.contains(at)) {
|
||||||
return yes_collision.at(at);
|
return yes_collision.at(at);
|
||||||
|
} else {
|
||||||
|
return no_collision.at(at);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -81,6 +99,7 @@ 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, yes_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<>());
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,14 @@ class SpatialMap {
|
||||||
public:
|
public:
|
||||||
SpatialMap() {}
|
SpatialMap() {}
|
||||||
PointEntityMap yes_collision;
|
PointEntityMap yes_collision;
|
||||||
|
PointEntityMap no_collision;
|
||||||
|
|
||||||
void insert(Point pos, DinkyECS::Entity obj);
|
void insert(Point pos, DinkyECS::Entity obj, bool has_collision);
|
||||||
void move(Point from, Point to, DinkyECS::Entity ent);
|
void move(Point from, Point to, DinkyECS::Entity ent);
|
||||||
void remove(Point pos);
|
// return value is whether the removed thing has collision
|
||||||
|
bool remove(Point pos);
|
||||||
bool occupied(Point pos) const;
|
bool occupied(Point pos) const;
|
||||||
|
bool something_there(Point at) const;
|
||||||
DinkyECS::Entity get(Point at) const;
|
DinkyECS::Entity get(Point at) const;
|
||||||
FoundEntities neighbors(Point position, bool diag=false) const;
|
FoundEntities neighbors(Point position, bool diag=false) const;
|
||||||
|
|
||||||
|
|
13
systems.cpp
13
systems.cpp
|
@ -163,11 +163,10 @@ void System::distribute_loot(GameLevel &level, Position target_pos) {
|
||||||
// BUG: inventory_count here isn't really used to remove it
|
// BUG: inventory_count here isn't really used to remove it
|
||||||
world.set<InventoryItem>(junk_entity, {inventory_count, entity_data});
|
world.set<InventoryItem>(junk_entity, {inventory_count, entity_data});
|
||||||
world.set<Position>(junk_entity, target_pos);
|
world.set<Position>(junk_entity, target_pos);
|
||||||
level.collision->insert(target_pos.location, junk_entity);
|
level.collision->insert(target_pos.location, junk_entity, false);
|
||||||
level.world->send<Events::GUI>(Events::GUI::ENTITY_SPAWN, junk_entity, {});
|
level.world->send<Events::GUI>(Events::GUI::ENTITY_SPAWN, junk_entity, {});
|
||||||
} else {
|
} else {
|
||||||
dbc::log("DEAD BODY NOT IMPLEMENTED, for now just removing enemy");
|
dbc::log("DEAD BODY NOT IMPLEMENTED, for now just removing enemy");
|
||||||
level.collision->remove(target_pos.location);
|
|
||||||
// BUG: should maybe add a component to the world for "dead thing no loot" that
|
// BUG: should maybe add a component to the world for "dead thing no loot" that
|
||||||
// has no collision or goes away after some kind of animation
|
// has no collision or goes away after some kind of animation
|
||||||
// Something like:
|
// Something like:
|
||||||
|
@ -213,9 +212,11 @@ void System::death(GameLevel &level) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pos = world.get<Position>(ent);
|
auto pos = world.get<Position>(ent);
|
||||||
// NOTE: distribute loot is responsible for either removing or replacing
|
|
||||||
// the collision for this entity. It has to do this since it's determining
|
// need to remove _after_ getting the position
|
||||||
// if a junkpile goes there or nothing
|
level.collision->remove(pos.location);
|
||||||
|
|
||||||
|
// distribute_loot is then responsible for putting something there
|
||||||
System::distribute_loot(level, pos);
|
System::distribute_loot(level, pos);
|
||||||
|
|
||||||
world.destroy(ent);
|
world.destroy(ent);
|
||||||
|
@ -454,7 +455,7 @@ bool System::drop_item(GameLevel& level, Entity item) {
|
||||||
|
|
||||||
if(map.can_move(pos.location) && !collision.occupied(pos.location)) {
|
if(map.can_move(pos.location) && !collision.occupied(pos.location)) {
|
||||||
world.set<Position>(item, pos);
|
world.set<Position>(item, pos);
|
||||||
collision.insert(pos.location, item);
|
collision.insert(pos.location, item, false);
|
||||||
// BUG: really there should be another system that handles loot->inv moves
|
// BUG: really there should be another system that handles loot->inv moves
|
||||||
if(player_inv.has(item)) player_inv.remove(item);
|
if(player_inv.has(item)) player_inv.remove(item);
|
||||||
level.world->send<Events::GUI>(Events::GUI::ENTITY_SPAWN, item, {});
|
level.world->send<Events::GUI>(Events::GUI::ENTITY_SPAWN, item, {});
|
||||||
|
|
|
@ -23,8 +23,8 @@ TEST_CASE("confirm basic collision operations", "[collision]") {
|
||||||
Entity enemy = world.entity();
|
Entity enemy = world.entity();
|
||||||
|
|
||||||
SpatialMap collider;
|
SpatialMap collider;
|
||||||
collider.insert({11,11}, player);
|
collider.insert({11,11}, player, true);
|
||||||
collider.insert({21,21}, enemy);
|
collider.insert({21,21}, enemy, true);
|
||||||
|
|
||||||
{ // not found
|
{ // not found
|
||||||
auto [found, nearby] = collider.neighbors({1,1});
|
auto [found, nearby] = collider.neighbors({1,1});
|
||||||
|
@ -43,7 +43,7 @@ TEST_CASE("confirm basic collision operations", "[collision]") {
|
||||||
REQUIRE(nearby.empty());
|
REQUIRE(nearby.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
collider.insert({11,11}, player); // setup for the move test
|
collider.insert({11,11}, player, true); // setup for the move test
|
||||||
{ // moving, not found
|
{ // moving, not found
|
||||||
collider.move({11,11}, {12, 12}, player);
|
collider.move({11,11}, {12, 12}, player);
|
||||||
auto [found, nearby] = collider.neighbors({10,10}, true);
|
auto [found, nearby] = collider.neighbors({10,10}, true);
|
||||||
|
@ -72,10 +72,10 @@ TEST_CASE("confirm multiple entities moving", "[collision]") {
|
||||||
Entity e3 = world.entity();
|
Entity e3 = world.entity();
|
||||||
|
|
||||||
SpatialMap collider;
|
SpatialMap collider;
|
||||||
collider.insert({11,11}, player);
|
collider.insert({11,11}, player, true);
|
||||||
collider.insert({10,10}, e2);
|
collider.insert({10,10}, e2, true);
|
||||||
collider.insert({11,10}, e3);
|
collider.insert({11,10}, e3, true);
|
||||||
collider.insert({21,21}, e1);
|
collider.insert({21,21}, e1, true);
|
||||||
|
|
||||||
EntityList 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);
|
||||||
|
@ -95,10 +95,10 @@ TEST_CASE("test edge cases that might crash", "[collision]") {
|
||||||
Entity enemy = world.entity();
|
Entity enemy = world.entity();
|
||||||
|
|
||||||
SpatialMap collider;
|
SpatialMap collider;
|
||||||
collider.insert({0,0}, player);
|
collider.insert({0,0}, player, true);
|
||||||
|
|
||||||
Point enemy_at = {1, 0};
|
Point enemy_at = {1, 0};
|
||||||
collider.insert(enemy_at, enemy);
|
collider.insert(enemy_at, enemy, true);
|
||||||
|
|
||||||
EntityList nearby = require_found(collider, {0,0}, true, 1);
|
EntityList nearby = require_found(collider, {0,0}, true, 1);
|
||||||
|
|
||||||
|
@ -118,10 +118,10 @@ TEST_CASE("check all diagonal works", "[collision]") {
|
||||||
|
|
||||||
SpatialMap collider;
|
SpatialMap collider;
|
||||||
Point player_at = {1,1};
|
Point player_at = {1,1};
|
||||||
collider.insert(player_at, player);
|
collider.insert(player_at, player, true);
|
||||||
|
|
||||||
Point enemy_at = {1, 0};
|
Point enemy_at = {1, 0};
|
||||||
collider.insert(enemy_at, enemy);
|
collider.insert(enemy_at, enemy, true);
|
||||||
|
|
||||||
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++) {
|
||||||
|
@ -150,7 +150,7 @@ TEST_CASE("confirm can iterate through all", "[spatialmap-sort]") {
|
||||||
size_t y = Random::uniform<size_t>(0, 251);
|
size_t y = Random::uniform<size_t>(0, 251);
|
||||||
|
|
||||||
Entity ent = world.entity();
|
Entity ent = world.entity();
|
||||||
collider.insert({x,y}, ent);
|
collider.insert({x,y}, ent, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sprite_distance = collider.distance_sorted(player, 1000);
|
auto sprite_distance = collider.distance_sorted(player, 1000);
|
||||||
|
|
|
@ -91,15 +91,20 @@ DinkyECS::Entity WorldBuilder::configure_entity_in_map(DinkyECS::World &world, j
|
||||||
// NOTE: aiming_at is set by the rayview since it knows that
|
// NOTE: aiming_at is set by the rayview since it knows that
|
||||||
world.set<Position>(item, {pos.x, pos.y});
|
world.set<Position>(item, {pos.x, pos.y});
|
||||||
|
|
||||||
if(entity_data["inventory_count"] > 0) {
|
// BUG: See #72, but this will change to a setting for collision
|
||||||
|
int inv_count = entity_data.contains("inventory_count") ? (int)entity_data["inventory_count"] : 0;
|
||||||
|
bool has_collision = true;
|
||||||
|
|
||||||
|
if(inv_count > 0) {
|
||||||
world.set<InventoryItem>(item, {entity_data["inventory_count"], entity_data});
|
world.set<InventoryItem>(item, {entity_data["inventory_count"], entity_data});
|
||||||
|
has_collision = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(entity_data.contains("components")) {
|
if(entity_data.contains("components")) {
|
||||||
components::configure_entity(world, item, entity_data["components"]);
|
components::configure_entity(world, item, entity_data["components"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$collision->insert(pos, item);
|
$collision->insert(pos, item, has_collision);
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue