|
|
|
@ -1,5 +1,5 @@ |
|
|
|
|
#include <catch2/catch_test_macros.hpp> |
|
|
|
|
#include "dinkyecs.hpp" |
|
|
|
|
|
|
|
|
|
#include <iostream> |
|
|
|
|
#include <fmt/core.h> |
|
|
|
|
|
|
|
|
@ -23,6 +23,10 @@ struct Gravity { |
|
|
|
|
double level; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct DaGUI { |
|
|
|
|
int event; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Using a function catches instances where I'm not copying |
|
|
|
|
* the data into the world. |
|
|
|
@ -35,7 +39,7 @@ void configure(DinkyECS::World &world, Entity &test) { |
|
|
|
|
world.set<Velocity>(test, {1,2}); |
|
|
|
|
|
|
|
|
|
world.set<Position>(test2, {1,1}); |
|
|
|
|
world.set<Velocity>(test2, {10,20}); |
|
|
|
|
world.set<Velocity>(test2, {9,19}); |
|
|
|
|
|
|
|
|
|
println("---- Setting up the player as a fact in the system."); |
|
|
|
|
|
|
|
|
@ -55,62 +59,91 @@ void configure(DinkyECS::World &world, Entity &test) { |
|
|
|
|
world.set_the<Gravity>({0.9}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int main() { |
|
|
|
|
TEST_CASE("confirm ECS system works", "[ecs]") { |
|
|
|
|
DinkyECS::World world; |
|
|
|
|
Entity test = world.entity(); |
|
|
|
|
|
|
|
|
|
configure(world, test); |
|
|
|
|
|
|
|
|
|
Position &pos = world.get<Position>(test); |
|
|
|
|
println("GOT POS x={}, y={}", pos.x, pos.y); |
|
|
|
|
REQUIRE(pos.x == 10); |
|
|
|
|
REQUIRE(pos.y == 20); |
|
|
|
|
|
|
|
|
|
Velocity &vel = world.get<Velocity>(test); |
|
|
|
|
println("GOT VELOCITY x={}, y={}", vel.x, vel.y); |
|
|
|
|
REQUIRE(vel.x == 1); |
|
|
|
|
REQUIRE(vel.y == 2); |
|
|
|
|
|
|
|
|
|
println("--- Position only system:"); |
|
|
|
|
world.query<Position>([](const auto &ent, auto &pos) { |
|
|
|
|
println("entity={}, pos.x={}, pos.y={}", ent, pos.x, pos.y); |
|
|
|
|
REQUIRE(ent > 0); |
|
|
|
|
REQUIRE(pos.x >= 0); |
|
|
|
|
REQUIRE(pos.y >= 0); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
println("--- Velocity only system:"); |
|
|
|
|
world.query<Velocity>([](const auto &, auto &vel) { |
|
|
|
|
println("vel.x={}, vel.y={}", vel.x, vel.y); |
|
|
|
|
world.query<Velocity>([](const auto &ent, auto &vel) { |
|
|
|
|
REQUIRE(ent > 0); |
|
|
|
|
REQUIRE(vel.x >= 0); |
|
|
|
|
REQUIRE(vel.y >= 0); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
println("--- Manually get the velocity in position system:"); |
|
|
|
|
world.query<Position>([&](const auto &ent, auto &pos) { |
|
|
|
|
Velocity &vel = world.get<Velocity>(ent); |
|
|
|
|
println("entity={}, vel.x, vel.y, pos.x={}, pos.y={}", ent, vel.x, vel.y, pos.x, pos.y); |
|
|
|
|
|
|
|
|
|
REQUIRE(ent > 0); |
|
|
|
|
REQUIRE(pos.x >= 0); |
|
|
|
|
REQUIRE(pos.y >= 0); |
|
|
|
|
REQUIRE(ent > 0); |
|
|
|
|
REQUIRE(vel.x >= 0); |
|
|
|
|
REQUIRE(vel.y >= 0); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
println("--- Query only entities with Position and Velocity:"); |
|
|
|
|
world.query<Position, Velocity>([&](const auto &ent, auto &pos, auto &vel) { |
|
|
|
|
Gravity &grav = world.get_the<Gravity>(); |
|
|
|
|
println("grav={}, entity={}, vel.x, vel.y, pos.x={}, pos.y={}", grav.level, ent, vel.x, vel.y, pos.x, pos.y); |
|
|
|
|
REQUIRE(grav.level <= 1.0f); |
|
|
|
|
REQUIRE(grav.level > 0.5f); |
|
|
|
|
REQUIRE(ent > 0); |
|
|
|
|
REQUIRE(pos.x >= 0); |
|
|
|
|
REQUIRE(pos.y >= 0); |
|
|
|
|
REQUIRE(ent > 0); |
|
|
|
|
REQUIRE(vel.x >= 0); |
|
|
|
|
REQUIRE(vel.y >= 0); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// now remove Velocity
|
|
|
|
|
world.remove<Velocity>(test); |
|
|
|
|
REQUIRE_THROWS(world.get<Velocity>(test)); |
|
|
|
|
|
|
|
|
|
println("--- After remove test, should only result in test2:"); |
|
|
|
|
world.query<Position, Velocity>([&](const auto &ent, auto &pos, auto &vel) { |
|
|
|
|
println("entity={}, vel.x, vel.y, pos.x={}, pos.y={}", ent, vel.x, vel.y, pos.x, pos.y); |
|
|
|
|
REQUIRE(pos.x >= 0); |
|
|
|
|
REQUIRE(pos.y >= 0); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// to avoid repeatedly getting the player just make a closure with it
|
|
|
|
|
// QUESTION: could I just capture it and not have the double function wrapping?
|
|
|
|
|
auto playerVsEnemies = [&]() { |
|
|
|
|
auto& player = world.get_the<Player>(); // grabbed it
|
|
|
|
|
world.query<Position>([&](const auto &ent, auto &pos) { |
|
|
|
|
if(player.eid != ent) { |
|
|
|
|
println("{} is enemy attacking player {}", ent, player.name); |
|
|
|
|
} else { |
|
|
|
|
println("{} is player", player.name); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
enum FakeEvent { |
|
|
|
|
HIT_EVENT, MISS_EVENT |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
playerVsEnemies(); |
|
|
|
|
TEST_CASE("confirm that the event system works", "[ecs]") { |
|
|
|
|
DinkyECS::World world; |
|
|
|
|
DinkyECS::Entity gui_ent = world.entity(); |
|
|
|
|
DinkyECS::Entity player = world.entity(); |
|
|
|
|
DaGUI gui{384}; |
|
|
|
|
|
|
|
|
|
world.set<DaGUI>(gui_ent, gui); |
|
|
|
|
DaGUI &gui_test = world.get<DaGUI>(gui_ent); |
|
|
|
|
REQUIRE(gui.event == gui_test.event); |
|
|
|
|
|
|
|
|
|
world.send<DaGUI>(FakeEvent::HIT_EVENT, player); |
|
|
|
|
|
|
|
|
|
bool ready = world.has_event<DaGUI>(); |
|
|
|
|
REQUIRE(ready == true); |
|
|
|
|
|
|
|
|
|
auto [event, entity] = world.recv<DaGUI>(); |
|
|
|
|
REQUIRE(event == FakeEvent::HIT_EVENT); |
|
|
|
|
REQUIRE(entity == player); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
ready = world.has_event<DaGUI>(); |
|
|
|
|
REQUIRE(ready == false); |
|
|
|
|
} |
|
|
|
|