#include #include "algos/dinkyecs.hpp" #include #include using namespace fmt; using DinkyECS::Entity; using std::string; using namespace fuc2; namespace dinkyecs_tests { struct Point { size_t x; size_t y; }; struct Player { string name; Entity eid; }; struct Position { Point location; }; struct Motion { int dx; int dy; bool random=false; }; struct Velocity { double x, y; }; struct Gravity { double level; }; struct DaGUI { int event; }; /* * Using a function catches instances where I'm not copying * the data into the world. */ void configure(DinkyECS::World &world, Entity &test) { println("---Configuring the base system."); Entity test2 = world.entity(); world.set(test, {10,20}); world.set(test, {1,2}); world.set(test2, {1,1}); world.set(test2, {9,19}); println("---- Setting up the player as a fact in the system."); auto player_eid = world.entity(); Player player_info{"Zed", player_eid}; // just set some player info as a fact with the entity id world.set_the(player_info); world.set(player_eid, {0,0}); world.set(player_eid, {0,0}); auto enemy = world.entity(); world.set(enemy, {0,0}); world.set(enemy, {0,0}); println("--- Creating facts (singletons)"); world.set_the({0.9}); } void test_confirm_ECS_system_works() { DinkyECS::World world; Entity test = world.entity(); configure(world, test); Position &pos = world.get(test); CHECK(pos.location.x == 10); CHECK(pos.location.y == 20); Velocity &vel = world.get(test); CHECK(vel.x == 1); CHECK(vel.y == 2); world.query([](const auto &ent, auto &pos) { CHECK(ent > 0); CHECK(pos.location.x >= 0); CHECK(pos.location.y >= 0); }); world.query([](const auto &ent, auto &vel) { CHECK(ent > 0); CHECK(vel.x >= 0); CHECK(vel.y >= 0); }); println("--- Manually get the velocity in position system:"); world.query([&](const auto &ent, auto &pos) { Velocity &vel = world.get(ent); CHECK(ent > 0); CHECK(pos.location.x >= 0); CHECK(pos.location.y >= 0); CHECK(ent > 0); CHECK(vel.x >= 0); CHECK(vel.y >= 0); }); println("--- Query only entities with Position and Velocity:"); world.query([&](const auto &ent, auto &pos, auto &vel) { Gravity &grav = world.get_the(); CHECK(grav.level <= 1.0f); CHECK(grav.level > 0.5f); CHECK(ent > 0); CHECK(pos.location.x >= 0); CHECK(pos.location.y >= 0); CHECK(ent > 0); CHECK(vel.x >= 0); CHECK(vel.y >= 0); }); // now remove Velocity CHECK(world.has(test)); world.remove(test); BLOWS_UP([&]() { world.get(test); }); CHECK(!world.has(test)); println("--- After remove test, should only result in test2:"); world.query([&](const auto &ent, auto &pos, auto &vel) { auto &in_position = world.get(ent); auto &in_velocity = world.get(ent); CHECK(pos.location.x >= 0); CHECK(pos.location.y >= 0); CHECK(in_position.location.x == pos.location.x); CHECK(in_position.location.y == pos.location.y); CHECK(in_velocity.x == vel.x); CHECK(in_velocity.y == vel.y); }); } enum GUIEvent { HIT, MISS }; void test_confirm_that_the_event_system_works() { DinkyECS::World world; DinkyECS::Entity player = world.entity(); // this confirms we can send these in a for-loop and get them out int i = 0; for(; i < 10; i++) { world.send(GUIEvent::HIT, player, string{"hello"}); } // just count down and should get the same number while(world.has_event()) { auto [event, entity, data] = world.recv(); CHECK(event == GUIEvent::HIT); CHECK(entity == player); auto &str_data = std::any_cast(data); CHECK(string{"hello"} == str_data); i--; } CHECK(i == 0); } void test_confirm_copying_and_constants() { DinkyECS::World world1; Player player_info{"Zed", world1.entity()}; world1.set_the(player_info); world1.set(player_info.eid, {10,10}); world1.make_constant(player_info.eid); DinkyECS::World world2; world1.clone_into(world2); auto &test1 = world1.get(player_info.eid); auto &test2 = world2.get(player_info.eid); CHECK(test2.location.x == test1.location.x); CHECK(test2.location.y == test1.location.y); // check for accidental reference test1.location.x = 100; CHECK(test2.location.x != test1.location.x); // test the facts copy over auto &player2 = world2.get_the(); CHECK(player2.eid == player_info.eid); } void test_can_destroy_all_entity() { DinkyECS::World world; auto entity = world.entity(); world.set(entity, {10,10}); world.set(entity, {1}); world.set(entity, {0,0}); world.destroy(entity); CHECK(!world.has(entity)); CHECK(!world.has(entity)); CHECK(!world.has(entity)); } fuc2::Set TESTS{ .name="dinkyecs", .tests={ TEST(test_confirm_ECS_system_works), TEST(test_confirm_that_the_event_system_works), TEST(test_confirm_copying_and_constants), TEST(test_can_destroy_all_entity), } }; }