Now using a simple collision map to track entities and then determine if they're near the player for attacking.

This commit is contained in:
Zed A. Shaw 2024-10-26 04:33:23 -04:00
parent 743f906bc7
commit ec1ed23c52
6 changed files with 72 additions and 48 deletions

View file

@ -3,6 +3,7 @@
#include <string>
#include <cmath>
#include "rand.hpp"
#include "collider.hpp"
using std::string;
using namespace fmt;
@ -24,8 +25,17 @@ void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player
game_map.clear_target(player_position.location);
}
void System::init_positions(DinkyECS::World &world) {
auto &collider = world.get<SpatialHashTable>();
world.system<Position>([&](const auto &ent, auto &pos) {
collider.insert(pos.location, ent);
});
}
void System::motion(DinkyECS::World &world, Map &game_map) {
auto &collider = world.get<SpatialHashTable>();
world.system<Position, Motion>([&](const auto &ent, auto &position, auto &motion) {
// don't process entities that don't move
if(motion.dx != 0 || motion.dy != 0) {
@ -36,8 +46,10 @@ void System::motion(DinkyECS::World &world, Map &game_map) {
motion = {0,0}; // clear it after getting it
if(game_map.inmap(move_to.x, move_to.y) &&
!game_map.iswall(move_to.x,move_to.y))
!game_map.iswall(move_to.x, move_to.y) &&
!collider.occupied(move_to))
{
collider.move(position.location, move_to, ent);
position.location = move_to;
}
}
@ -46,25 +58,27 @@ 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& player_position = world.component<Position>(player.entity);
auto& player_combat = world.component<Combat>(player.entity);
auto& log = world.get<ActionLog>();
world.system<Position, Combat>([&](const auto &ent, auto &pos, auto &combat) {
if(ent != player.entity) {
int dx = std::abs(int(pos.location.x) - int(player_position.location.x));
int dy = std::abs(int(pos.location.y) - int(player_position.location.y));
// this is guaranteed to not return the given position
auto [found, nearby] = collider.neighbors(player_position.location);
if(dx <= 1 && dy <= 1) {
if(player_combat.hp > -1) {
int dmg = Random::uniform<int>(1, combat.damage);
player_combat.hp -= dmg;
log.log(format("HIT! You took {} damage.", dmg));
}
}
if(found) {
for(auto entity : nearby) {
int attack = Random::uniform<int>(0,1);
if(attack) {
const auto& enemy_dmg = world.component<Combat>(entity);
int dmg = Random::uniform<int>(1, enemy_dmg.damage);
player_combat.hp -= dmg;
log.log(format("HIT! You took {} damage.", dmg));
} else {
log.log("You dodged! Run!");
}
});
}
}
};
void System::draw_entities(DinkyECS::World &world, Map &game_map, ftxui::Canvas &canvas, const Point &cam_orig, size_t view_x, size_t view_y) {