The next little game in the series where I make a fancy rogue game.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
roguish/tests/dinkyecs.cpp

149 lines
3.5 KiB

#include <catch2/catch_test_macros.hpp>
#include "dinkyecs.hpp"
#include <iostream>
#include <fmt/core.h>
using namespace fmt;
using DinkyECS::Entity;
using std::string;
struct Player {
string name;
Entity eid;
};
struct Position {
double x, y;
};
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<Position>(test, {10,20});
world.set<Velocity>(test, {1,2});
world.set<Position>(test2, {1,1});
world.set<Velocity>(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>(player_info);
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});
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.x == 10);
REQUIRE(pos.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.x >= 0);
REQUIRE(pos.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.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>();
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
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) {
REQUIRE(pos.x >= 0);
REQUIRE(pos.y >= 0);
});
}
enum GUIEvent {
HIT, MISS
};
TEST_CASE("confirm that the event system works", "[ecs]") {
DinkyECS::World world;
DinkyECS::Entity player = world.entity();
world.send<GUIEvent>(GUIEvent::HIT, player, string{"hello"});
bool ready = world.has_event<GUIEvent>();
REQUIRE(ready == true);
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);
ready = world.has_event<GUIEvent>();
REQUIRE(ready == false);
}