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,3 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include "graphics/textures.hpp"
|
||||
#include "algos/dinkyecs.hpp"
|
||||
#include "game/config.hpp"
|
||||
|
|
@ -10,160 +9,176 @@
|
|||
#include "graphics/animation.hpp"
|
||||
#include "game/sound.hpp"
|
||||
#include "game/components.hpp"
|
||||
#include <fuc2/testing.hpp>
|
||||
|
||||
using namespace components;
|
||||
using namespace textures;
|
||||
using namespace std::chrono_literals;
|
||||
using namespace animation;
|
||||
using namespace fuc2;
|
||||
|
||||
Animation load_animation(const string& name) {
|
||||
auto anim = animation::load("assets/animation.json", "rat_king_boss");
|
||||
anim.set_form("attack");
|
||||
namespace animation_tests {
|
||||
Animation load_animation(const string& name) {
|
||||
auto anim = animation::load("assets/animation.json", "rat_king_boss");
|
||||
anim.set_form("attack");
|
||||
|
||||
anim.transform.looped = false;
|
||||
anim.transform.looped = false;
|
||||
|
||||
for(size_t i = 0; i < anim.sequence.durations.size(); i++) {
|
||||
anim.sequence.durations[i] = Random::uniform(1, 5);
|
||||
}
|
||||
|
||||
return anim;
|
||||
}
|
||||
|
||||
void FAKE_RENDER() {
|
||||
std::this_thread::sleep_for(Random::milliseconds(5, 32));
|
||||
}
|
||||
|
||||
void PLAY_TEST(Animation &anim) {
|
||||
REQUIRE(anim.transform.looped == false);
|
||||
anim.play();
|
||||
|
||||
while(anim.playing) {
|
||||
anim.update();
|
||||
FAKE_RENDER();
|
||||
}
|
||||
|
||||
REQUIRE(anim.playing == false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Animation is a Sheet + Sequence + Transform.
|
||||
*
|
||||
* A Sheet is just a grid of images with a predefined size for each cell. Arbitrary sized cells not supported.
|
||||
*
|
||||
* A Sequence is a list of Sheet cells _in any order_. See https://github.com/yottahmd/ganim8-lib. Sequences have a timing element for the cells, possibly a list of durations or a single duration.
|
||||
*
|
||||
* A Transform is combinations of scale and/or position easing/motion, shader effects, and things like if it's looped or toggled.
|
||||
*
|
||||
* I like the ganim8 onLoop concept, just a callback that says what to do when the animation has looped.
|
||||
*/
|
||||
TEST_CASE("new animation system", "[animation-new]") {
|
||||
textures::init();
|
||||
sound::init();
|
||||
sound::mute(true);
|
||||
|
||||
auto anim = load_animation("rat_king_boss");
|
||||
PLAY_TEST(anim);
|
||||
|
||||
// test that toggled works
|
||||
anim.transform.toggled = true;
|
||||
PLAY_TEST(anim);
|
||||
REQUIRE(anim.sequence.current == anim.sequence.frames.size() - 1);
|
||||
anim.transform.toggled = false;
|
||||
|
||||
bool onLoop_ran = false;
|
||||
anim.onLoop = [&](auto& seq, auto& tr) -> bool {
|
||||
seq.current = 0;
|
||||
onLoop_ran = true;
|
||||
return tr.looped;
|
||||
};
|
||||
|
||||
PLAY_TEST(anim);
|
||||
REQUIRE(onLoop_ran == true);
|
||||
|
||||
// only runs twice
|
||||
anim.onLoop = [](auto& seq, auto& tr) -> bool {
|
||||
if(seq.loop_count == 2) {
|
||||
seq.current = 0;
|
||||
return false;
|
||||
} else {
|
||||
seq.current = seq.current % seq.frame_count;
|
||||
return true;
|
||||
for(size_t i = 0; i < anim.sequence.durations.size(); i++) {
|
||||
anim.sequence.durations[i] = Random::uniform(1, 5);
|
||||
}
|
||||
};
|
||||
|
||||
PLAY_TEST(anim);
|
||||
REQUIRE(anim.sequence.loop_count == 2);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("confirm frame sequencing works", "[animation-new]") {
|
||||
textures::init();
|
||||
sound::init();
|
||||
sound::mute(true);
|
||||
|
||||
auto anim = load_animation("rat_king_boss");
|
||||
|
||||
auto boss = textures::get_sprite("rat_king_boss");
|
||||
sf::IntRect init_rect{{0,0}, {anim.sheet.frame_width, anim.sheet.frame_height}};
|
||||
|
||||
anim.play();
|
||||
bool loop_ran = false;
|
||||
|
||||
// this will check that it moved to the next frame
|
||||
anim.onLoop = [&](auto& seq, auto& tr) -> bool {
|
||||
seq.current = 0;
|
||||
loop_ran = true;
|
||||
return false;
|
||||
};
|
||||
|
||||
anim.onFrame = [&](){
|
||||
anim.apply(*boss.sprite);
|
||||
};
|
||||
|
||||
while(anim.playing) {
|
||||
anim.update();
|
||||
FAKE_RENDER();
|
||||
return anim;
|
||||
}
|
||||
|
||||
REQUIRE(loop_ran == true);
|
||||
REQUIRE(anim.playing == false);
|
||||
}
|
||||
|
||||
TEST_CASE("confirm transition changes work", "[animation-new]") {
|
||||
textures::init();
|
||||
sound::init();
|
||||
sound::mute(true);
|
||||
|
||||
auto sprite = *textures::get_sprite("rat_king_boss").sprite;
|
||||
sf::Vector2f pos{100,100};
|
||||
sprite.setPosition(pos);
|
||||
auto scale = sprite.getScale();
|
||||
auto anim = load_animation("rat_king_boss");
|
||||
|
||||
// also testing that onFrame being null means it's not run
|
||||
REQUIRE(anim.onFrame == nullptr);
|
||||
|
||||
anim.play();
|
||||
REQUIRE(anim.playing == true);
|
||||
|
||||
while(anim.playing) {
|
||||
anim.update();
|
||||
anim.motion(sprite, pos, scale);
|
||||
FAKE_RENDER();
|
||||
void FAKE_RENDER() {
|
||||
std::this_thread::sleep_for(Random::milliseconds(5, 32));
|
||||
}
|
||||
|
||||
REQUIRE(anim.playing == false);
|
||||
REQUIRE(pos == sf::Vector2f{100, 100});
|
||||
REQUIRE(scale != sf::Vector2f{0,0});
|
||||
}
|
||||
void PLAY_TEST(Animation &anim) {
|
||||
CHECK(anim.transform.looped == false);
|
||||
anim.play();
|
||||
|
||||
TEST_CASE("playing with delta time", "[animation-new]") {
|
||||
animation::Timer timer;
|
||||
timer.start();
|
||||
while(anim.playing) {
|
||||
anim.update();
|
||||
FAKE_RENDER();
|
||||
}
|
||||
|
||||
for(int i = 0; i < 20; i++) {
|
||||
FAKE_RENDER();
|
||||
auto [tick_count, alpha] = timer.commit();
|
||||
// fmt::println("tick: {}, alpha: {}", tick_count, alpha);
|
||||
CHECK(anim.playing == false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Animation is a Sheet + Sequence + Transform.
|
||||
*
|
||||
* A Sheet is just a grid of images with a predefined size for each cell. Arbitrary sized cells not supported.
|
||||
*
|
||||
* A Sequence is a list of Sheet cells _in any order_. See https://github.com/yottahmd/ganim8-lib. Sequences have a timing element for the cells, possibly a list of durations or a single duration.
|
||||
*
|
||||
* A Transform is combinations of scale and/or position easing/motion, shader effects, and things like if it's looped or toggled.
|
||||
*
|
||||
* I like the ganim8 onLoop concept, just a callback that says what to do when the animation has looped.
|
||||
*/
|
||||
void test_new_animation_system() {
|
||||
textures::init();
|
||||
sound::init();
|
||||
sound::mute(true);
|
||||
|
||||
auto anim = load_animation("rat_king_boss");
|
||||
PLAY_TEST(anim);
|
||||
|
||||
// test that toggled works
|
||||
anim.transform.toggled = true;
|
||||
PLAY_TEST(anim);
|
||||
CHECK(anim.sequence.current == anim.sequence.frames.size() - 1);
|
||||
anim.transform.toggled = false;
|
||||
|
||||
bool onLoop_ran = false;
|
||||
anim.onLoop = [&](auto& seq, auto& tr) -> bool {
|
||||
seq.current = 0;
|
||||
onLoop_ran = true;
|
||||
return tr.looped;
|
||||
};
|
||||
|
||||
PLAY_TEST(anim);
|
||||
CHECK(onLoop_ran == true);
|
||||
|
||||
// only runs twice
|
||||
anim.onLoop = [](auto& seq, auto& tr) -> bool {
|
||||
if(seq.loop_count == 2) {
|
||||
seq.current = 0;
|
||||
return false;
|
||||
} else {
|
||||
seq.current = seq.current % seq.frame_count;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
PLAY_TEST(anim);
|
||||
CHECK(anim.sequence.loop_count == 2);
|
||||
}
|
||||
|
||||
|
||||
void test_confirm_frame_sequencing_works() {
|
||||
textures::init();
|
||||
sound::init();
|
||||
sound::mute(true);
|
||||
|
||||
auto anim = load_animation("rat_king_boss");
|
||||
|
||||
auto boss = textures::get_sprite("rat_king_boss");
|
||||
sf::IntRect init_rect{{0,0}, {anim.sheet.frame_width, anim.sheet.frame_height}};
|
||||
|
||||
anim.play();
|
||||
bool loop_ran = false;
|
||||
|
||||
// this will check that it moved to the next frame
|
||||
anim.onLoop = [&](auto& seq, auto& tr) -> bool {
|
||||
seq.current = 0;
|
||||
loop_ran = true;
|
||||
return false;
|
||||
};
|
||||
|
||||
anim.onFrame = [&](){
|
||||
anim.apply(*boss.sprite);
|
||||
};
|
||||
|
||||
while(anim.playing) {
|
||||
anim.update();
|
||||
FAKE_RENDER();
|
||||
}
|
||||
|
||||
CHECK(loop_ran == true);
|
||||
CHECK(anim.playing == false);
|
||||
}
|
||||
|
||||
void test_confirm_transition_changes_work() {
|
||||
textures::init();
|
||||
sound::init();
|
||||
sound::mute(true);
|
||||
|
||||
auto sprite = *textures::get_sprite("rat_king_boss").sprite;
|
||||
sf::Vector2f pos{100,100};
|
||||
sprite.setPosition(pos);
|
||||
auto scale = sprite.getScale();
|
||||
auto anim = load_animation("rat_king_boss");
|
||||
|
||||
// also testing that onFrame being null means it's not run
|
||||
CHECK(anim.onFrame == nullptr);
|
||||
|
||||
anim.play();
|
||||
CHECK(anim.playing == true);
|
||||
|
||||
while(anim.playing) {
|
||||
anim.update();
|
||||
anim.motion(sprite, pos, scale);
|
||||
FAKE_RENDER();
|
||||
}
|
||||
|
||||
CHECK(anim.playing == false);
|
||||
CHECK(pos == sf::Vector2f{100, 100});
|
||||
CHECK(scale != sf::Vector2f{0,0});
|
||||
}
|
||||
|
||||
void test_playing_with_delta_time() {
|
||||
animation::Timer timer;
|
||||
timer.start();
|
||||
|
||||
for(int i = 0; i < 20; i++) {
|
||||
FAKE_RENDER();
|
||||
auto [tick_count, alpha] = timer.commit();
|
||||
// fmt::println("tick: {}, alpha: {}", tick_count, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fuc2::Set TESTS{
|
||||
.name="ai functionality",
|
||||
.tests={
|
||||
TEST(test_new_animation_system),
|
||||
TEST(test_confirm_frame_sequencing_works),
|
||||
TEST(test_confirm_transition_changes_work),
|
||||
TEST(test_playing_with_delta_time),
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,18 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <string>
|
||||
#include <fuc2/testing.hpp>
|
||||
|
||||
using namespace fmt;
|
||||
using namespace fuc2;
|
||||
|
||||
TEST_CASE("base test", "[base]") {
|
||||
REQUIRE(1 == 1);
|
||||
namespace base_tests {
|
||||
void test_base_test() {
|
||||
CHECK(1 == 1);
|
||||
}
|
||||
|
||||
fuc2::Set TESTS{
|
||||
.name="base template",
|
||||
.tests={
|
||||
TEST(test_base_test),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
203
tests/battle.cpp
203
tests/battle.cpp
|
|
@ -1,4 +1,3 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include "game/rituals.hpp"
|
||||
|
|
@ -11,134 +10,146 @@
|
|||
#include "game/components.hpp"
|
||||
#include "ai/ai.hpp"
|
||||
#include "graphics/palette.hpp"
|
||||
#include <fuc2/testing.hpp>
|
||||
|
||||
using namespace combat;
|
||||
using namespace boss;
|
||||
using namespace components;
|
||||
using namespace fuc2;
|
||||
|
||||
TEST_CASE("battle operations fantasy", "[fail]") {
|
||||
ai::reset();
|
||||
ai::init("ai");
|
||||
namespace battle_tests {
|
||||
void test_battle_operations_fantasy() {
|
||||
ai::reset();
|
||||
ai::init("ai");
|
||||
|
||||
auto ai_start = ai::load_state("Enemy::initial_state");
|
||||
auto ai_goal = ai::load_state("Enemy::final_state");
|
||||
auto host_start = ai::load_state("Host::initial_state");
|
||||
auto host_goal = ai::load_state("Host::final_state");
|
||||
BattleEngine battle;
|
||||
auto ai_start = ai::load_state("Enemy::initial_state");
|
||||
auto ai_goal = ai::load_state("Enemy::final_state");
|
||||
auto host_start = ai::load_state("Host::initial_state");
|
||||
auto host_goal = ai::load_state("Host::final_state");
|
||||
BattleEngine battle;
|
||||
|
||||
DinkyECS::Entity host = 0;
|
||||
ai::EntityAI host_ai("Host::actions", host_start, host_goal);
|
||||
components::Combat host_combat{
|
||||
.hp=100, .max_hp=100, .ap_delta=6, .max_ap=12, .damage=20};
|
||||
battle.add_enemy({host, &host_ai, &host_combat, true});
|
||||
DinkyECS::Entity host = 0;
|
||||
ai::EntityAI host_ai("Host::actions", host_start, host_goal);
|
||||
components::Combat host_combat{
|
||||
.hp=100, .max_hp=100, .ap_delta=6, .max_ap=12, .damage=20};
|
||||
battle.add_enemy({host, &host_ai, &host_combat, true});
|
||||
|
||||
DinkyECS::Entity axe_ranger = 1;
|
||||
ai::EntityAI axe_ai("Enemy::actions", ai_start, ai_goal);
|
||||
components::Combat axe_combat{
|
||||
.hp=20, .max_hp=20, .ap_delta=8, .max_ap=12, .damage=20};
|
||||
battle.add_enemy({axe_ranger, &axe_ai, &axe_combat});
|
||||
DinkyECS::Entity axe_ranger = 1;
|
||||
ai::EntityAI axe_ai("Enemy::actions", ai_start, ai_goal);
|
||||
components::Combat axe_combat{
|
||||
.hp=20, .max_hp=20, .ap_delta=8, .max_ap=12, .damage=20};
|
||||
battle.add_enemy({axe_ranger, &axe_ai, &axe_combat});
|
||||
|
||||
DinkyECS::Entity rat = 2;
|
||||
ai::EntityAI rat_ai("Enemy::actions", ai_start, ai_goal);
|
||||
components::Combat rat_combat{
|
||||
.hp=10, .max_hp=10, .ap_delta=2, .max_ap=10, .damage=10};
|
||||
battle.add_enemy({rat, &rat_ai, &rat_combat});
|
||||
DinkyECS::Entity rat = 2;
|
||||
ai::EntityAI rat_ai("Enemy::actions", ai_start, ai_goal);
|
||||
components::Combat rat_combat{
|
||||
.hp=10, .max_hp=10, .ap_delta=2, .max_ap=10, .damage=10};
|
||||
battle.add_enemy({rat, &rat_ai, &rat_combat});
|
||||
|
||||
battle.set_all("enemy_found", true);
|
||||
battle.set_all("in_combat", true);
|
||||
battle.set_all("tough_personality", true);
|
||||
battle.set_all("health_good", true);
|
||||
battle.set_all("enemy_found", true);
|
||||
battle.set_all("in_combat", true);
|
||||
battle.set_all("tough_personality", true);
|
||||
battle.set_all("health_good", true);
|
||||
|
||||
battle.set(rat, "tough_personality", false);
|
||||
battle.set(host, "have_healing", false);
|
||||
battle.set(host, "tough_personality", false);
|
||||
battle.set(rat, "tough_personality", false);
|
||||
battle.set(host, "have_healing", false);
|
||||
battle.set(host, "tough_personality", false);
|
||||
|
||||
int host_combat_loop = 0;
|
||||
for(host_combat_loop = 0; host_combat_loop < 1000; host_combat_loop++) {
|
||||
if(host_combat.is_dead()) break;
|
||||
battle.set(host, "health_good", host_combat.hp > 20);
|
||||
int host_combat_loop = 0;
|
||||
for(host_combat_loop = 0; host_combat_loop < 1000; host_combat_loop++) {
|
||||
if(host_combat.is_dead()) break;
|
||||
battle.set(host, "health_good", host_combat.hp > 20);
|
||||
|
||||
battle.player_request("use_healing");
|
||||
battle.player_request("kill_enemy");
|
||||
battle.player_request("use_healing");
|
||||
battle.player_request("kill_enemy");
|
||||
|
||||
battle.ap_refresh();
|
||||
battle.plan();
|
||||
int battle_count = 0;
|
||||
battle.ap_refresh();
|
||||
battle.plan();
|
||||
int battle_count = 0;
|
||||
|
||||
for(int battle_count = 0; battle_count < 1000; battle_count++) {
|
||||
auto act = battle.next();
|
||||
if(!act) break;
|
||||
for(int battle_count = 0; battle_count < 1000; battle_count++) {
|
||||
auto act = battle.next();
|
||||
if(!act) break;
|
||||
|
||||
auto& [enemy, wants_to, cost, enemy_state] = *act;
|
||||
auto& [enemy, wants_to, cost, enemy_state] = *act;
|
||||
|
||||
// fmt::println(">>>>> entity: {} wants to {} cost={}; has {} HP; {} ap",
|
||||
// enemy.entity, wants_to,
|
||||
// cost, enemy.combat->hp,
|
||||
// enemy.combat->ap);
|
||||
// fmt::println(">>>>> entity: {} wants to {} cost={}; has {} HP; {} ap",
|
||||
// enemy.entity, wants_to,
|
||||
// cost, enemy.combat->hp,
|
||||
// enemy.combat->ap);
|
||||
|
||||
switch(enemy_state) {
|
||||
case BattleHostState::agree:
|
||||
// fmt::println("HOST and PLAYER requests match {}, doing it.", wants_to);
|
||||
break;
|
||||
case BattleHostState::disagree:
|
||||
// fmt::println("REBELIOUS ACT: {}", wants_to);
|
||||
battle.clear_requests();
|
||||
REQUIRE(battle.$player_requests.size() == 0);
|
||||
break;
|
||||
case BattleHostState::not_host:
|
||||
if(wants_to == "kill_enemy") {
|
||||
enemy.combat->attack(host_combat);
|
||||
}
|
||||
break;
|
||||
case BattleHostState::out_of_ap:
|
||||
// fmt::println("ENEMY OUT OF AP");
|
||||
break;
|
||||
switch(enemy_state) {
|
||||
case BattleHostState::agree:
|
||||
// fmt::println("HOST and PLAYER requests match {}, doing it.", wants_to);
|
||||
break;
|
||||
case BattleHostState::disagree:
|
||||
// fmt::println("REBELIOUS ACT: {}", wants_to);
|
||||
battle.clear_requests();
|
||||
CHECK(battle.$player_requests.size() == 0);
|
||||
break;
|
||||
case BattleHostState::not_host:
|
||||
if(wants_to == "kill_enemy") {
|
||||
enemy.combat->attack(host_combat);
|
||||
}
|
||||
break;
|
||||
case BattleHostState::out_of_ap:
|
||||
// fmt::println("ENEMY OUT OF AP");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(!battle.next());
|
||||
dbc::check(battle_count < 1000, "infinite battle loop");
|
||||
}
|
||||
|
||||
REQUIRE(!battle.next());
|
||||
dbc::check(battle_count < 1000, "infinite battle loop");
|
||||
dbc::check(host_combat_loop < 1000, "infinite host combat loop, host won't die!");
|
||||
}
|
||||
|
||||
dbc::check(host_combat_loop < 1000, "infinite host combat loop, host won't die!");
|
||||
}
|
||||
void test_boss_systems_work() {
|
||||
components::init();
|
||||
gui::Backend backend;
|
||||
guecs::init(&backend);
|
||||
|
||||
TEST_CASE("boss/systems.cpp works", "[combat-battle]") {
|
||||
components::init();
|
||||
gui::Backend backend;
|
||||
guecs::init(&backend);
|
||||
ai::reset();
|
||||
ai::init("ai");
|
||||
GameDB::init();
|
||||
cinematic::init();
|
||||
auto host = GameDB::the_player();
|
||||
|
||||
ai::reset();
|
||||
ai::init("ai");
|
||||
GameDB::init();
|
||||
cinematic::init();
|
||||
auto host = GameDB::the_player();
|
||||
auto fight = System::create_bossfight();
|
||||
auto battle = System::create_battle(fight->$world, fight->$boss_id);
|
||||
auto& host_combat = fight->$world->get<Combat>(host);
|
||||
|
||||
auto fight = System::create_bossfight();
|
||||
auto battle = System::create_battle(fight->$world, fight->$boss_id);
|
||||
auto& host_combat = fight->$world->get<Combat>(host);
|
||||
System::initialize_actor_ai(*fight->$world, fight->$boss_id);
|
||||
|
||||
System::initialize_actor_ai(*fight->$world, fight->$boss_id);
|
||||
// NEED UPDATE STATE
|
||||
battle.set_all("enemy_found", true);
|
||||
battle.set_all("in_combat", true);
|
||||
battle.set_all("tough_personality", true);
|
||||
battle.set_all("health_good", true);
|
||||
|
||||
// NEED UPDATE STATE
|
||||
battle.set_all("enemy_found", true);
|
||||
battle.set_all("in_combat", true);
|
||||
battle.set_all("tough_personality", true);
|
||||
battle.set_all("health_good", true);
|
||||
battle.ap_refresh();
|
||||
|
||||
battle.ap_refresh();
|
||||
battle.player_request("kill_enemy");
|
||||
int pending_ap = battle.player_pending_ap();
|
||||
|
||||
battle.player_request("kill_enemy");
|
||||
int pending_ap = battle.player_pending_ap();
|
||||
CHECK(pending_ap < host_combat.ap);
|
||||
|
||||
REQUIRE(pending_ap < host_combat.ap);
|
||||
System::plan_battle(battle, fight->$world, fight->$boss_id);
|
||||
|
||||
System::plan_battle(battle, fight->$world, fight->$boss_id);
|
||||
while(auto action = battle.next()) {
|
||||
dbc::log("ACTION!");
|
||||
System::combat(*action, fight->$world, fight->$boss_id, 0);
|
||||
}
|
||||
|
||||
while(auto action = battle.next()) {
|
||||
dbc::log("ACTION!");
|
||||
System::combat(*action, fight->$world, fight->$boss_id, 0);
|
||||
CHECK(host_combat.ap == pending_ap);
|
||||
}
|
||||
|
||||
REQUIRE(host_combat.ap == pending_ap);
|
||||
fuc2::Set TESTS{
|
||||
.name="battle tests",
|
||||
.tests={
|
||||
TEST(test_battle_operations_fantasy),
|
||||
TEST(test_boss_systems_work),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,17 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <fuc2/testing.hpp>
|
||||
|
||||
TEST_CASE("view based camera system", "[camera]") {
|
||||
REQUIRE(1 == 1);
|
||||
using namespace fuc2;
|
||||
|
||||
namespace camera_tests {
|
||||
void test_view_based_camera_system() {
|
||||
CHECK(1 == 1);
|
||||
}
|
||||
|
||||
fuc2::Set TESTS{
|
||||
.name="camera tests (EMPTY!)",
|
||||
.tests={
|
||||
TEST(test_view_based_camera_system),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fuc2/testing.hpp>
|
||||
#include "game/components.hpp"
|
||||
#include "algos/dinkyecs.hpp"
|
||||
#include "game/config.hpp"
|
||||
|
|
@ -7,44 +7,56 @@
|
|||
using namespace components;
|
||||
using namespace DinkyECS;
|
||||
|
||||
TEST_CASE("confirm component loading works", "[components]") {
|
||||
std::vector<std::string> test_list{
|
||||
"assets/enemies.json", "assets/items.json", "assets/devices.json"};
|
||||
using namespace fuc2;
|
||||
|
||||
components::init();
|
||||
DinkyECS::World world;
|
||||
namespace component_tests {
|
||||
void test_confirm_component_loading_works() {
|
||||
std::vector<std::string> test_list{
|
||||
"assets/enemies.json", "assets/items.json", "assets/devices.json"};
|
||||
|
||||
for(auto test_data : test_list) {
|
||||
auto config = settings::get(test_data);
|
||||
auto data_list = config.json();
|
||||
components::init();
|
||||
DinkyECS::World world;
|
||||
|
||||
for(auto& [key, data] : data_list.items()) {
|
||||
auto& components = data["components"];
|
||||
fmt::println("TEST COMPONENT: {} from file {}", key, test_data);
|
||||
auto ent = world.entity();
|
||||
components::configure_entity(world, ent, components);
|
||||
auto tile = components::get<Tile>(components[0]);
|
||||
REQUIRE(tile.display != L' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
for(auto test_data : test_list) {
|
||||
auto config = settings::get(test_data);
|
||||
auto data_list = config.json();
|
||||
|
||||
TEST_CASE("make sure json_mods works", "[components]") {
|
||||
auto config = settings::get("bosses");
|
||||
// this confirms that loading something with an optional
|
||||
// field works with the json conversions in json_mods.hpp
|
||||
for(auto& comp_data : config["RAT_KING"]["components"]) {
|
||||
if(comp_data["_type"] == "AnimatedScene") {
|
||||
auto comp = components::convert<components::AnimatedScene>(comp_data);
|
||||
for(auto& [key, data] : data_list.items()) {
|
||||
auto& components = data["components"];
|
||||
fmt::println("TEST COMPONENT: {} from file {}", key, test_data);
|
||||
auto ent = world.entity();
|
||||
components::configure_entity(world, ent, components);
|
||||
auto tile = components::get<Tile>(components[0]);
|
||||
CHECK(tile.display != L' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this then confirms everything else about the json conversion
|
||||
components::init();
|
||||
void test_make_sure_json_mods_works() {
|
||||
auto config = settings::get("bosses");
|
||||
// this confirms that loading something with an optional
|
||||
// field works with the json conversions in json_mods.hpp
|
||||
for(auto& comp_data : config["RAT_KING"]["components"]) {
|
||||
if(comp_data["_type"] == "AnimatedScene") {
|
||||
auto comp = components::convert<components::AnimatedScene>(comp_data);
|
||||
}
|
||||
}
|
||||
|
||||
DinkyECS::World world;
|
||||
auto rat_king = world.entity();
|
||||
// this then confirms everything else about the json conversion
|
||||
components::init();
|
||||
|
||||
components::configure_entity(world, rat_king, config["RAT_KING"]["components"]);
|
||||
auto boss = world.get<AnimatedScene>(rat_king);
|
||||
DinkyECS::World world;
|
||||
auto rat_king = world.entity();
|
||||
|
||||
components::configure_entity(world, rat_king, config["RAT_KING"]["components"]);
|
||||
auto boss = world.get<AnimatedScene>(rat_king);
|
||||
}
|
||||
|
||||
fuc2::Set TESTS{
|
||||
.name="components",
|
||||
.tests={
|
||||
TEST(test_make_sure_json_mods_works),
|
||||
TEST(test_confirm_component_loading_works),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,40 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fuc2/testing.hpp>
|
||||
#include "game/config.hpp"
|
||||
#include <iostream>
|
||||
|
||||
TEST_CASE("confirm basic config loader ops", "[config]") {
|
||||
settings::Config::set_base_dir("./");
|
||||
auto config = settings::get("devices");
|
||||
auto data_list = config.json();
|
||||
auto the_keys = config.keys();
|
||||
using namespace fuc2;
|
||||
|
||||
REQUIRE(the_keys.size() > 0);
|
||||
namespace config_tests {
|
||||
void test_confirm_basic_config_loader_ops() {
|
||||
settings::Config::set_base_dir("./");
|
||||
auto config = settings::get("devices");
|
||||
auto data_list = config.json();
|
||||
auto the_keys = config.keys();
|
||||
|
||||
for(auto& [key, data] : data_list.items()) {
|
||||
auto wide1 = config.wstring(key, "name");
|
||||
auto& comps = data["components"];
|
||||
CHECK(the_keys.size() > 0);
|
||||
|
||||
for(auto& comp_data : comps) {
|
||||
REQUIRE(comp_data.contains("_type"));
|
||||
for(auto& [key, data] : data_list.items()) {
|
||||
auto wide1 = config.wstring(key, "name");
|
||||
auto& comps = data["components"];
|
||||
|
||||
for(auto& comp_data : comps) {
|
||||
CHECK(comp_data.contains("_type"));
|
||||
}
|
||||
}
|
||||
|
||||
auto indexed = settings::get("tests/config_test.json");
|
||||
auto& test_0 = indexed[0];
|
||||
CHECK(test_0["test"] == 0);
|
||||
|
||||
auto& test_1 = indexed[1];
|
||||
CHECK(test_1["test"] == 1);
|
||||
}
|
||||
|
||||
auto indexed = settings::get("tests/config_test.json");
|
||||
auto& test_0 = indexed[0];
|
||||
REQUIRE(test_0["test"] == 0);
|
||||
fuc2::Set TESTS{
|
||||
.name="config",
|
||||
.tests={
|
||||
TEST(test_confirm_basic_config_loader_ops),
|
||||
}
|
||||
};
|
||||
|
||||
auto& test_1 = indexed[1];
|
||||
REQUIRE(test_1["test"] == 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,28 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fuc2/testing.hpp>
|
||||
#include "dbc.hpp"
|
||||
|
||||
using namespace dbc;
|
||||
|
||||
TEST_CASE("basic feature tests", "[dbc]") {
|
||||
log("Logging a message.");
|
||||
namespace dbc_tests {
|
||||
void test_basic_dbc_features() {
|
||||
log("Logging a message.");
|
||||
|
||||
pre("confirm positive cases work", 1 == 1);
|
||||
pre("confirm positive cases work", 1 == 1);
|
||||
|
||||
pre("confirm positive lambda", [&]{ return 1 == 1;});
|
||||
pre("confirm positive lambda", [&]{ return 1 == 1;});
|
||||
|
||||
post("confirm positive post", 1 == 1);
|
||||
post("confirm positive post", 1 == 1);
|
||||
|
||||
post("confirm postitive post with lamdba", [&]{ return 1 == 1;});
|
||||
post("confirm postitive post with lamdba", [&]{ return 1 == 1;});
|
||||
|
||||
check(1 == 1, "one equals 1");
|
||||
}
|
||||
|
||||
fuc2::Set TESTS{
|
||||
.name="dbc",
|
||||
.tests={
|
||||
TEST(test_basic_dbc_features),
|
||||
}
|
||||
};
|
||||
|
||||
check(1 == 1, "one equals 1");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
25
tests/main.cpp
Normal file
25
tests/main.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#include <fuc2/run.hpp>
|
||||
|
||||
using namespace fuc2;
|
||||
|
||||
TEST_SET(ai_tests);
|
||||
TEST_SET(animation_tests);
|
||||
TEST_SET(base_tests);
|
||||
TEST_SET(battle_tests);
|
||||
TEST_SET(camera_tests);
|
||||
TEST_SET(component_tests);
|
||||
TEST_SET(config_tests);
|
||||
TEST_SET(dbc_tests);
|
||||
TEST_SET(dinkyecs_tests);
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
run(ai_tests::TESTS);
|
||||
run(animation_tests::TESTS);
|
||||
run(base_tests::TESTS);
|
||||
run(battle_tests::TESTS);
|
||||
run(camera_tests::TESTS);
|
||||
run(component_tests::TESTS);
|
||||
run(config_tests::TESTS);
|
||||
run(dbc_tests::TESTS);
|
||||
run(dinkyecs_tests::TESTS);
|
||||
}
|
||||
|
|
@ -1,12 +1,4 @@
|
|||
tests = files(
|
||||
'animation.cpp',
|
||||
'base.cpp',
|
||||
'battle.cpp',
|
||||
'camera.cpp',
|
||||
'components.cpp',
|
||||
'config.cpp',
|
||||
'dbc.cpp',
|
||||
'dinkyecs.cpp',
|
||||
'event_router.cpp',
|
||||
'fsm.cpp',
|
||||
'inventory.cpp',
|
||||
|
|
@ -27,6 +19,14 @@ tests = files(
|
|||
)
|
||||
|
||||
fuc2_tests = files(
|
||||
'dinkyecs.cpp',
|
||||
'dbc.cpp',
|
||||
'ai.cpp',
|
||||
'animation.cpp',
|
||||
'base.cpp',
|
||||
'battle.cpp',
|
||||
'camera.cpp',
|
||||
'components.cpp',
|
||||
'config.cpp',
|
||||
'main.cpp'
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue