Started to convert from catch2 to fuc2.
This commit is contained in:
parent
4deda37665
commit
b8b42d5681
10 changed files with 615 additions and 493 deletions
|
|
@ -1,4 +1,4 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fuc2/testing.hpp>
|
||||
#include "algos/dinkyecs.hpp"
|
||||
#include <iostream>
|
||||
#include <fmt/core.h>
|
||||
|
|
@ -6,207 +6,224 @@
|
|||
using namespace fmt;
|
||||
using DinkyECS::Entity;
|
||||
using std::string;
|
||||
using namespace fuc2;
|
||||
|
||||
struct Point {
|
||||
size_t x;
|
||||
size_t y;
|
||||
};
|
||||
namespace dinkyecs_tests {
|
||||
struct Point {
|
||||
size_t x;
|
||||
size_t y;
|
||||
};
|
||||
|
||||
struct Player {
|
||||
string name;
|
||||
Entity eid;
|
||||
};
|
||||
struct Player {
|
||||
string name;
|
||||
Entity eid;
|
||||
};
|
||||
|
||||
struct Position {
|
||||
Point location;
|
||||
};
|
||||
struct Position {
|
||||
Point location;
|
||||
};
|
||||
|
||||
struct Motion {
|
||||
int dx;
|
||||
int dy;
|
||||
bool random=false;
|
||||
};
|
||||
struct Motion {
|
||||
int dx;
|
||||
int dy;
|
||||
bool random=false;
|
||||
};
|
||||
|
||||
struct Velocity {
|
||||
double x, y;
|
||||
};
|
||||
struct Velocity {
|
||||
double x, y;
|
||||
};
|
||||
|
||||
struct Gravity {
|
||||
double level;
|
||||
};
|
||||
struct Gravity {
|
||||
double level;
|
||||
};
|
||||
|
||||
struct DaGUI {
|
||||
int event;
|
||||
};
|
||||
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();
|
||||
/*
|
||||
* 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<Position>(test, {10,20});
|
||||
world.set<Velocity>(test, {1,2});
|
||||
world.set<Position>(test, {10,20});
|
||||
world.set<Velocity>(test, {1,2});
|
||||
|
||||
world.set<Position>(test2, {1,1});
|
||||
world.set<Velocity>(test2, {9,19});
|
||||
world.set<Position>(test2, {1,1});
|
||||
world.set<Velocity>(test2, {9,19});
|
||||
|
||||
println("---- Setting up the player as a fact in the system.");
|
||||
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>(player_info);
|
||||
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>(player_info);
|
||||
|
||||
world.set<Velocity>(player_eid, {0,0});
|
||||
world.set<Position>(player_eid, {0,0});
|
||||
world.set<Velocity>(player_eid, {0,0});
|
||||
world.set<Position>(player_eid, {0,0});
|
||||
|
||||
auto enemy = world.entity();
|
||||
world.set<Velocity>(enemy, {0,0});
|
||||
world.set<Position>(enemy, {0,0});
|
||||
auto enemy = world.entity();
|
||||
world.set<Velocity>(enemy, {0,0});
|
||||
world.set<Position>(enemy, {0,0});
|
||||
|
||||
println("--- Creating facts (singletons)");
|
||||
world.set_the<Gravity>({0.9});
|
||||
}
|
||||
|
||||
TEST_CASE("confirm ECS system works", "[ecs]") {
|
||||
DinkyECS::World world;
|
||||
Entity test = world.entity();
|
||||
|
||||
configure(world, test);
|
||||
|
||||
Position &pos = world.get<Position>(test);
|
||||
REQUIRE(pos.location.x == 10);
|
||||
REQUIRE(pos.location.y == 20);
|
||||
|
||||
Velocity &vel = world.get<Velocity>(test);
|
||||
REQUIRE(vel.x == 1);
|
||||
REQUIRE(vel.y == 2);
|
||||
|
||||
world.query<Position>([](const auto &ent, auto &pos) {
|
||||
REQUIRE(ent > 0);
|
||||
REQUIRE(pos.location.x >= 0);
|
||||
REQUIRE(pos.location.y >= 0);
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
REQUIRE(ent > 0);
|
||||
REQUIRE(pos.location.x >= 0);
|
||||
REQUIRE(pos.location.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>();
|
||||
REQUIRE(grav.level <= 1.0f);
|
||||
REQUIRE(grav.level > 0.5f);
|
||||
REQUIRE(ent > 0);
|
||||
REQUIRE(pos.location.x >= 0);
|
||||
REQUIRE(pos.location.y >= 0);
|
||||
REQUIRE(ent > 0);
|
||||
REQUIRE(vel.x >= 0);
|
||||
REQUIRE(vel.y >= 0);
|
||||
});
|
||||
|
||||
// now remove Velocity
|
||||
REQUIRE(world.has<Velocity>(test));
|
||||
world.remove<Velocity>(test);
|
||||
REQUIRE_THROWS(world.get<Velocity>(test));
|
||||
REQUIRE(!world.has<Velocity>(test));
|
||||
|
||||
println("--- After remove test, should only result in test2:");
|
||||
world.query<Position, Velocity>([&](const auto &ent, auto &pos, auto &vel) {
|
||||
auto &in_position = world.get<Position>(ent);
|
||||
auto &in_velocity = world.get<Velocity>(ent);
|
||||
REQUIRE(pos.location.x >= 0);
|
||||
REQUIRE(pos.location.y >= 0);
|
||||
REQUIRE(in_position.location.x == pos.location.x);
|
||||
REQUIRE(in_position.location.y == pos.location.y);
|
||||
REQUIRE(in_velocity.x == vel.x);
|
||||
REQUIRE(in_velocity.y == vel.y);
|
||||
});
|
||||
}
|
||||
|
||||
enum GUIEvent {
|
||||
HIT, MISS
|
||||
};
|
||||
|
||||
TEST_CASE("confirm that the event system works", "[ecs]") {
|
||||
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>(GUIEvent::HIT, player, string{"hello"});
|
||||
println("--- Creating facts (singletons)");
|
||||
world.set_the<Gravity>({0.9});
|
||||
}
|
||||
|
||||
// just count down and should get the same number
|
||||
while(world.has_event<GUIEvent>()) {
|
||||
auto [event, entity, data] = world.recv<GUIEvent>();
|
||||
REQUIRE(event == GUIEvent::HIT);
|
||||
REQUIRE(entity == player);
|
||||
auto &str_data = std::any_cast<string&>(data);
|
||||
REQUIRE(string{"hello"} == str_data);
|
||||
i--;
|
||||
void test_confirm_ECS_system_works() {
|
||||
DinkyECS::World world;
|
||||
Entity test = world.entity();
|
||||
|
||||
configure(world, test);
|
||||
|
||||
Position &pos = world.get<Position>(test);
|
||||
CHECK(pos.location.x == 10);
|
||||
CHECK(pos.location.y == 20);
|
||||
|
||||
Velocity &vel = world.get<Velocity>(test);
|
||||
CHECK(vel.x == 1);
|
||||
CHECK(vel.y == 2);
|
||||
|
||||
world.query<Position>([](const auto &ent, auto &pos) {
|
||||
CHECK(ent > 0);
|
||||
CHECK(pos.location.x >= 0);
|
||||
CHECK(pos.location.y >= 0);
|
||||
});
|
||||
|
||||
world.query<Velocity>([](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<Position>([&](const auto &ent, auto &pos) {
|
||||
Velocity &vel = world.get<Velocity>(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<Position, Velocity>([&](const auto &ent, auto &pos, auto &vel) {
|
||||
Gravity &grav = world.get_the<Gravity>();
|
||||
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<Velocity>(test));
|
||||
world.remove<Velocity>(test);
|
||||
|
||||
BLOWS_UP([&]() {
|
||||
world.get<Velocity>(test);
|
||||
});
|
||||
|
||||
CHECK(!world.has<Velocity>(test));
|
||||
|
||||
println("--- After remove test, should only result in test2:");
|
||||
world.query<Position, Velocity>([&](const auto &ent, auto &pos, auto &vel) {
|
||||
auto &in_position = world.get<Position>(ent);
|
||||
auto &in_velocity = world.get<Velocity>(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);
|
||||
});
|
||||
}
|
||||
|
||||
REQUIRE(i == 0);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("confirm copying and constants", "[ecs-constants]") {
|
||||
DinkyECS::World world1;
|
||||
|
||||
Player player_info{"Zed", world1.entity()};
|
||||
world1.set_the<Player>(player_info);
|
||||
|
||||
world1.set<Position>(player_info.eid, {10,10});
|
||||
world1.make_constant(player_info.eid);
|
||||
|
||||
DinkyECS::World world2;
|
||||
world1.clone_into(world2);
|
||||
|
||||
auto &test1 = world1.get<Position>(player_info.eid);
|
||||
auto &test2 = world2.get<Position>(player_info.eid);
|
||||
|
||||
REQUIRE(test2.location.x == test1.location.x);
|
||||
REQUIRE(test2.location.y == test1.location.y);
|
||||
|
||||
// check for accidental reference
|
||||
test1.location.x = 100;
|
||||
REQUIRE(test2.location.x != test1.location.x);
|
||||
|
||||
// test the facts copy over
|
||||
auto &player2 = world2.get_the<Player>();
|
||||
REQUIRE(player2.eid == player_info.eid);
|
||||
}
|
||||
|
||||
TEST_CASE("can destroy all entity", "[ecs-destroy]") {
|
||||
DinkyECS::World world;
|
||||
auto entity = world.entity();
|
||||
|
||||
world.set<Velocity>(entity, {10,10});
|
||||
world.set<Gravity>(entity, {1});
|
||||
world.set<Motion>(entity, {0,0});
|
||||
|
||||
world.destroy(entity);
|
||||
|
||||
REQUIRE(!world.has<Velocity>(entity));
|
||||
REQUIRE(!world.has<Gravity>(entity));
|
||||
REQUIRE(!world.has<Motion>(entity));
|
||||
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>(GUIEvent::HIT, player, string{"hello"});
|
||||
}
|
||||
|
||||
// just count down and should get the same number
|
||||
while(world.has_event<GUIEvent>()) {
|
||||
auto [event, entity, data] = world.recv<GUIEvent>();
|
||||
CHECK(event == GUIEvent::HIT);
|
||||
CHECK(entity == player);
|
||||
auto &str_data = std::any_cast<string&>(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>(player_info);
|
||||
|
||||
world1.set<Position>(player_info.eid, {10,10});
|
||||
world1.make_constant(player_info.eid);
|
||||
|
||||
DinkyECS::World world2;
|
||||
world1.clone_into(world2);
|
||||
|
||||
auto &test1 = world1.get<Position>(player_info.eid);
|
||||
auto &test2 = world2.get<Position>(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<Player>();
|
||||
CHECK(player2.eid == player_info.eid);
|
||||
}
|
||||
|
||||
void test_can_destroy_all_entity() {
|
||||
DinkyECS::World world;
|
||||
auto entity = world.entity();
|
||||
|
||||
world.set<Velocity>(entity, {10,10});
|
||||
world.set<Gravity>(entity, {1});
|
||||
world.set<Motion>(entity, {0,0});
|
||||
|
||||
world.destroy(entity);
|
||||
|
||||
CHECK(!world.has<Velocity>(entity));
|
||||
CHECK(!world.has<Gravity>(entity));
|
||||
CHECK(!world.has<Motion>(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),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue