Skip to content

Commit

Permalink
make entity system more clear
Browse files Browse the repository at this point in the history
more purity

create simple update binary bat
  • Loading branch information
Philemon Benner authored and Philemon Benner committed Nov 13, 2024
1 parent e33a051 commit 1fb4ff9
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 111 deletions.
4 changes: 2 additions & 2 deletions .vscode/cmake-kits.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
{
"name": "Mingw Compiler",
"compilers": {
"C": "D:\\Program Files\\w64devkit\\bin\\gcc.exe",
"CXX": "D:\\Program Files\\w64devkit\\bin\\g++.exe"
"C": "D:\\ProgramFiles\\w64devkit\\bin\\gcc.exe",
"CXX": "D:\\ProgramFiles\\w64devkit\\bin\\g++.exe"
}
}
]
7 changes: 5 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"editor.formatOnSave": true,
"clang-format.executable": "D:\\Program Files\\clang-format.exe",
"clang-format.executable": "D:\\ProgramFiles\\clang-format.exe",
"files.associations": {
"ratio": "cpp",
"xmemory": "cpp",
Expand Down Expand Up @@ -80,6 +80,9 @@
"map": "cpp",
"set": "cpp",
"unordered_set": "cpp",
"xtree": "cpp"
"xtree": "cpp",
"iostream": "cpp",
"memory_resource": "cpp",
"regex": "cpp"
}
}
5 changes: 0 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ Once built (or using the prebuilt binary), you can run PathFindingCpp as follows

This command provides usage instructions and available command-line options.

### Additional Information

- Launch program from command line rather than directly invoking and pass `--height`
- Big thanks to [bshoshany](https://github.com/bshoshany) checkout his [threadpool](https://github.com/bshoshany/thread-pool) that i am using.

### Todo

- Fix too large height reported by `GetConsoleScreenBufferInfo`
Binary file modified bin/PathFinding.exe
Binary file not shown.
2 changes: 1 addition & 1 deletion bin/md5sum.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1ddd82a42d9b973ab16ac486011f2db2
3c15806bfbd628fa20ac4a01ad021ee2
127 changes: 71 additions & 56 deletions src/entity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,106 +7,121 @@
namespace st {
namespace {

static constexpr size_t kTrailSize = 20;
void UpdateMission(Mission &mission,
MissionIDX &mission_idx,
std::vector<Entity> &want_new_mission,
const Entity &entity,
const Point &position) {
if (mission.empty()) {
want_new_mission.push_back(entity);
return;
}

if (mission.back() == position) {
mission.clear();
mission_idx = 0;
want_new_mission.push_back(entity);
}
}

void UpdatePositon(Position &position, Mission &mission, MissionIDX &mission_idx, Trail &trail) {
if (mission.empty()) {
return;
}

trail.push_back(position);
position = mission[mission_idx];
mission_idx++;
}

void UpdateTrail(Trail &trail, std::vector<Position> &pending_removals) {
constexpr size_t kTrailSize = 20;

if (trail.size() == kTrailSize) {
pending_removals.push_back(trail.front());
trail.pop_front();
}
}

void DrawMission(Drawer *drawer, const Mission &mission, const Entity &mission_idx) {
// Skip if we already did draw the mission
if (mission_idx != 1) {
return;
}

void DrawMission(Drawer *drawer, const Mission &mission) {
for (const auto &item : mission) {
drawer->SetPixel(item, '~');
}
drawer->SetPixel(mission.back(), '?');
}

void DrawEntity(Drawer *drawer, const Point &position, const EntityShape &shape) {
void DrawPosition(Drawer *drawer, const Position &position, const Shape &shape) {
drawer->SetPixel(position, shape.look);
}

void DrawTrail(Drawer *drawer, const Trail &trail, const EntityShape &shape) {
void DrawTrail(Drawer *drawer, const Trail &trail, const Shape &shape) {
if (!trail.empty()) {
drawer->SetPixel(trail.back(), shape.trail);
}
}

} // namespace

void EntityRegistry::Reserve(size_t size) {
void EntitySystem::Reserve(size_t size) {
shapes_.reserve(size);
positions_.reserve(size);
missions_.reserve(size);
missions_idx_.reserve(size);
trails_.reserve(size);
}

auto EntityRegistry::Create(const Point &start_position, const EntityShape &shape) -> EntityID {
auto EntitySystem::Create(const Position &start, const Shape &shape) -> Entity {
shapes_.push_back(shape);
positions_.push_back(start_position);
positions_.push_back(start);
missions_.push_back({});
missions_idx_.push_back({});
trails_.push_back({});
EntityID id = num_entities_;
num_entities_++;
return num_entities_;
return positions_.size() - 1;
}

void EntityRegistry::AssignMission(EntityID id, Mission &&mission) {
assert(id < missions_.size() && "Uknown entitiy id passed");
assert(missions_[id].empty() && "Tried assigning mission to already active mission");
missions_[id] = std::forward<Mission>(mission);
void EntitySystem::AssignMission(Entity entity, Mission &&mission) {
assert(entity < missions_.size() && "Uknown entitiy passed");
assert(missions_[entity].empty() && "Tried assigning mission to already active mission");
missions_[entity] = std::forward<Mission>(mission);
}

auto EntityRegistry::Update() -> std::vector<EntityID> {
auto EntitySystem::Update() -> std::vector<Entity> {
pending_removals_.clear();

std::vector<EntityID> want_new_mission;
for (EntityID id = 0; id < positions_.size(); id++) {
auto &position = positions_[id];
auto &mission = missions_[id];
auto &mission_idx = missions_idx_[id];
auto &trail = trails_[id];

// Update position
if (!mission.empty()) {
trail.push_back(position);
position = mission[mission_idx];
mission_idx++;
}

// Update missions
if (!mission.empty()) {
if (mission.back() == position) {
mission.clear();
mission_idx = 0;
want_new_mission.push_back(id);
}
} else {
want_new_mission.push_back(id);
}

// Update trails
if (trail.size() == kTrailSize) {
pending_removals_.push_back(trail.front());
trail.pop_front();
}
}
std::vector<Entity> want_new_mission;
Entity entity{};
auto components = std::views::zip(positions_, shapes_, trails_, missions_, missions_idx_);
std::ranges::for_each(components, [&entity, &want_new_mission, &pd = pending_removals_](auto view) {
auto &[position, shape, trail, mission, mission_idx] = view;

UpdatePositon(position, mission, mission_idx, trail);
UpdateMission(mission, mission_idx, want_new_mission, entity, position);
UpdateTrail(trail, pd);
entity++;
});
return want_new_mission;
}

void EntityRegistry::Draw(Drawer *drawer) const {
auto zipped = std::views::zip(positions_, shapes_, trails_, missions_, missions_idx_);
std::ranges::for_each(zipped, [drawer](auto view) {
DrawEntity(drawer, std::get<0>(view), std::get<1>(view));
DrawTrail(drawer, std::get<2>(view), std::get<1>(view));
void EntitySystem::Draw(Drawer *drawer) const {
auto components = std::views::zip(positions_, shapes_, trails_, missions_, missions_idx_);
std::ranges::for_each(components, [drawer](auto view) {
auto &[position, shape, trail, mission, mission_idx] = view;

// If this is a new mission draw it
if (std::get<4>(view) == 1) {
DrawMission(drawer, std::get<3>(view));
}
DrawPosition(drawer, position, shape);
DrawTrail(drawer, trail, shape);
DrawMission(drawer, mission, mission_idx);
});

for (auto &removal : pending_removals_) {
drawer->ClearPixel(removal);
}
}

auto EntityRegistry::NumEntities() -> size_t const { return num_entities_; }
auto EntitySystem::NumEntities() -> size_t const { return positions_.size(); }

} // namespace st
52 changes: 28 additions & 24 deletions src/entity.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,64 @@

#include <deque>
#include <tuple>
#include <ranges>

#include "point.h"
#include "drawer.h"

namespace st {

struct EntityShape {
// Components
struct Shape {
char look;
char trail;
};

using Position = Point;
using Mission = std::vector<Point>;
using Trail = std::deque<Point>;
using EntityID = size_t;
using MissionIDX = size_t;

// Entity is just an index pointing to the position of the vector
using Entity = size_t;

class EntityRegistry {
class EntitySystem {
public:
EntityRegistry() = default;
EntitySystem() = default;

template <typename T>
constexpr T &GetComponent(EntityID id);
constexpr const T &View(Entity entity);

void Reserve(size_t size);
auto Create(const Point &start_position, const EntityShape &shape = EntityShape('O', '-')) -> EntityID;
void AssignMission(EntityID id, Mission &&mission);
// Update entities and return a vector of entites with ids that
auto Update() -> std::vector<EntityID>;
auto Create(const Position &start, const Shape &shape = Shape('O', '-')) -> Entity;
void AssignMission(Entity entity, Mission &&mission);
// Update entities and return a vector of entites that want a new mission
auto Update() -> std::vector<Entity>;
void Draw(Drawer *drawer) const;
auto NumEntities() -> size_t const;

private:
std::vector<EntityShape> shapes_;
std::vector<Shape> shapes_;
std::vector<Point> positions_;
std::vector<Mission> missions_;
std::vector<EntityID> missions_idx_;
std::vector<MissionIDX> missions_idx_;
std::vector<Trail> trails_;
std::vector<Point> pending_removals_;
size_t num_entities_{};
std::vector<Position> pending_removals_;
};

template <typename T>
constexpr T &EntityRegistry::GetComponent(EntityID id) {
if constexpr (std::is_same<T, EntityShape>()) {
return shapes_[id];
} else if constexpr (std::is_same<T, Point>()) {
return positions_[id];
constexpr const T &EntitySystem::View(Entity entity) {
if constexpr (std::is_same<T, Shape>()) {
return shapes_[entity];
} else if constexpr (std::is_same<T, Position>()) {
return positions_[entity];
} else if constexpr (std::is_same<T, Mission>()) {
return missions_[id];
} else if constexpr (std::is_same<T, EntityID>()) {
return missions_idx_[id];
return missions_[entity];
} else if constexpr (std::is_same<T, MissionIDX>()) {
return missions_idx_[entity];
} else if constexpr (std::is_same<T, Trail>()) {
return trails_[id];
return trails_[entity];
} else {
static_assert(false && "Failed to find component");
static_assert(false && "Uknown component");
}
}

Expand Down
Loading

0 comments on commit 1fb4ff9

Please sign in to comment.