feat(entities): clipping per frame, falsa perspectiva del sarcòfag i piràmide amb 20 sarcs
This commit is contained in:
1 parent
7191a08618
commit
1af5ef861f
11 files changed
+162
-25
No files matched your search
@@ -11,6 +11,9 @@
|
||||
// T6 animation — 3 frames @ 10 fps, `tick(0.15)` → frame índex == 1.
|
||||
// T7 plantilles — carrega els 7 YAML d'entitat sense excepcions.
|
||||
// T8 decoration — Torch no col·lisiona ni és interactable.
|
||||
// T10 torch anim — Torch llegeix 4 frames del YAML i el tick avança frame.
|
||||
// T11 sarcofag — tile_size [3,1] llegit; perímetre 8; falsa perspectiva:
|
||||
// el sprite.height no canvia la caixa lògica 48×16.
|
||||
//
|
||||
// Execució (des de la ruta del repo):
|
||||
// make build && cd build && ctest --output-on-failure
|
||||
@@ -268,9 +271,12 @@ namespace {
|
||||
REQUIRE(Map::tilemap_origin_x == -8);
|
||||
REQUIRE(Map::tilemap_origin_y == 0);
|
||||
|
||||
// 2) El pyramid.yaml conté 5 spawns amb els tipus esperats.
|
||||
// 2) El pyramid.yaml conté spawns dels tipus esperats. Comptem al
|
||||
// menys un de cada tipus que el nivell ha de tenir sí o sí (no
|
||||
// fixem quants torches exactes perquè és decoratiu i pot
|
||||
// variar). Així afegir decoració al YAML no trenca el smoke.
|
||||
const auto SPAWNS = EntityLoader::readSpawns("data/maps/pyramid.yaml");
|
||||
REQUIRE(SPAWNS.size() == 5);
|
||||
REQUIRE(!SPAWNS.empty());
|
||||
int torches = 0;
|
||||
int sarcs = 0;
|
||||
int doors = 0;
|
||||
@@ -282,10 +288,10 @@ namespace {
|
||||
else if (T == "door") { ++doors; }
|
||||
else if (T == "mummy") { ++mummies; }
|
||||
}
|
||||
REQUIRE(torches == 1);
|
||||
REQUIRE(sarcs == 2);
|
||||
REQUIRE(doors == 1);
|
||||
REQUIRE(mummies == 1);
|
||||
REQUIRE(torches >= 1);
|
||||
REQUIRE(sarcs >= 1);
|
||||
REQUIRE(doors >= 1);
|
||||
REQUIRE(mummies >= 1);
|
||||
|
||||
// 3) La conversió sarc-grid (0,0) → tile anchor (3,4) (i.e. la
|
||||
// fórmula que usa loadFromLevel). Sarc rect = (40, 64, 48, 16).
|
||||
@@ -316,6 +322,48 @@ namespace {
|
||||
REQUIRE(sarc_raw->getState() == Sarcophagus::State::OPENING);
|
||||
}
|
||||
|
||||
void testSarcophagusYaml() {
|
||||
std::cout << "[T11] sarcofag YAML + falsa perspectiva\n";
|
||||
// El template ha de declarar tile_size [3,1]: el footprint lògic
|
||||
// són els 48×16 inferiors del sprite, encara que el sprite sencer
|
||||
// fa 48×32 (16 px de "alçada" per damunt, sense col·lisió).
|
||||
fkyaml::node tmpl = EntityLoader::loadTemplate("sarcophagus");
|
||||
REQUIRE(tmpl.contains("tile_size"));
|
||||
REQUIRE(tmpl["tile_size"][0].get_value<int>() == 3);
|
||||
REQUIRE(tmpl["tile_size"][1].get_value<int>() == 1);
|
||||
REQUIRE(tmpl["sprite"]["size"][0].get_value<int>() == 48);
|
||||
REQUIRE(tmpl["sprite"]["size"][1].get_value<int>() == 32);
|
||||
|
||||
// Amb tile_size [3,1], un sarc a ancoratge (3,4) conserva els 8
|
||||
// tiles de perímetre (no es converteix en 10 per culpa del [3,2]
|
||||
// antic). Això blinda la geometria contra regressions al YAML.
|
||||
auto sarc = std::make_unique<Sarcophagus>(tmpl);
|
||||
sarc->place(3, 4, {});
|
||||
REQUIRE(sarc->getPerimeterSize() == 8);
|
||||
}
|
||||
|
||||
void testTorchAnimation() {
|
||||
std::cout << "[T10] torch animation wired from yaml\n";
|
||||
// Regressió: el torch.yaml declarava `frames: [0]` i el render no
|
||||
// consultava `currentFrame()`, així que una antorxa animada no es
|
||||
// veia viva. Ara el YAML ha de portar 4 frames i l'Entity::update
|
||||
// ha d'avançar el frame via el component d'animació.
|
||||
fkyaml::node tmpl = EntityLoader::loadTemplate("torch");
|
||||
Torch torch(tmpl);
|
||||
const auto& ANIM = torch.getAnimation();
|
||||
REQUIRE(ANIM.has_value());
|
||||
REQUIRE(ANIM->frameCount() == 4);
|
||||
REQUIRE(ANIM->currentFrame() == 0);
|
||||
|
||||
// Amb fps=8, el pas entre frames és 0.125s. Un tick d'aquest valor
|
||||
// ha de fer saltar current_ a 1 (i, com que `frames: [0..3]`, el
|
||||
// valor retornat pel currentFrame coincideix amb l'índex).
|
||||
torch.update(0.125F);
|
||||
REQUIRE(torch.getAnimation()->currentFrame() == 1);
|
||||
torch.update(0.125F);
|
||||
REQUIRE(torch.getAnimation()->currentFrame() == 2);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto main() -> int {
|
||||
@@ -330,6 +378,8 @@ auto main() -> int {
|
||||
testAllTemplatesLoad();
|
||||
testDecorationFlags();
|
||||
testLoadFromLevel();
|
||||
testSarcophagusYaml();
|
||||
testTorchAnimation();
|
||||
|
||||
if (g_failures == 0) {
|
||||
std::cout << "ALL OK\n";
|
||||
|
||||
Reference in new issue
Block a user