feat(door): col·locació derivada de Map::door_col i caixa de col·lisió neta
This commit is contained in:
1 parent
b54f3fc622
commit
648a5932f8
3 files changed
+48
-10
No files matched your search
@@ -5,6 +5,14 @@ sprite:
|
||||
size: [48, 32]
|
||||
tile_size: [3, 2]
|
||||
collision:
|
||||
# Caixa de col·lisió: 16×24 centrada al sprite 48×32. Coincideix amb el
|
||||
# tile central transitable (els 16 px del passadís de sortida) i es
|
||||
# restringeix a la franja del mur trasser (24 px d'alçada). Així
|
||||
# `checkPlayerCollisions` només dispara `onPlayerContact` quan el
|
||||
# jugador entra al forat real, no als marcs flanquejants ni als 8 px
|
||||
# superiors que queden tapats pel HUD.
|
||||
size: [16, 24]
|
||||
offset: [16, 8]
|
||||
# Porta = mur infranquejable. Igual que el sarc, alçada efectiva
|
||||
# infinita per impedir que un jugador la salte per damunt.
|
||||
height: 999
|
||||
|
||||
@@ -129,7 +129,9 @@ entities:
|
||||
- type: sarcophagus
|
||||
sarc_position: [3, 4]
|
||||
- type: door
|
||||
position: [9, 1]
|
||||
# Sense `position`: la porta sempre viu al mur trasser. La columna
|
||||
# transitable la dicta `geometry.door_col`; el render i la caixa
|
||||
# de col·lisió es deriven d'aquesta dada al loadFromLevel.
|
||||
- type: mummy
|
||||
position: [10, 7]
|
||||
- type: mummy
|
||||
|
||||
@@ -291,6 +291,34 @@ namespace {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Col·loca la porta al mur trasser segons `Map::door_col`. La porta
|
||||
// viu sempre al `wall_north`; només la columna varia per nivell. El
|
||||
// sprite (típicament 48×32) es centra horitzontalment sobre la
|
||||
// columna transitable i s'alinea verticalment de manera que la seua
|
||||
// vora inferior coincideixi amb la base del strip del mur trasser
|
||||
// (= `playfield_y`). Amb sprite 48×32 i `back_wall_h = 24` això vol
|
||||
// dir que els 8 px superiors del sprite queden dins del HUD i hi
|
||||
// queden tapats — comportament intencional.
|
||||
auto placeDoor(EntityManager& manager, std::unique_ptr<Entity> entity, const SpriteInfo& sprite) -> bool {
|
||||
if (Map::door_col <= 0 || Map::tile_size <= 0) {
|
||||
std::cerr << "EntityManager: door requereix `geometry.door_col` definit al mapa\n";
|
||||
return false;
|
||||
}
|
||||
const float CENTER_X = static_cast<float>((Map::door_col * Map::tile_size) + Map::tilemap_origin_x) + (static_cast<float>(Map::tile_size) / 2.0F);
|
||||
const SDL_FRect RENDER{
|
||||
.x = CENTER_X - (sprite.width / 2.0F),
|
||||
.y = static_cast<float>(Map::playfield_y) - sprite.height,
|
||||
.w = sprite.width,
|
||||
.h = sprite.height,
|
||||
};
|
||||
entity->setPixelRect(RENDER);
|
||||
|
||||
auto* door_ptr = dynamic_cast<Door*>(entity.get());
|
||||
manager.add(std::move(entity));
|
||||
if (door_ptr != nullptr) { manager.setDoor(door_ptr); }
|
||||
return true;
|
||||
}
|
||||
|
||||
auto placeGeneric(EntityManager& manager, std::unique_ptr<Entity> entity, const std::string& type, const SpriteInfo& sprite, const std::string& anchor, const fkyaml::node& spawn) -> bool {
|
||||
if (!spawn.contains("position")) {
|
||||
std::cerr << "EntityManager: " << type << " sense position\n";
|
||||
@@ -322,13 +350,7 @@ namespace {
|
||||
}
|
||||
entity->setPixelRect({.x = rect_x, .y = rect_y, .w = sprite.width, .h = sprite.height});
|
||||
|
||||
if (type == "door") {
|
||||
auto* door_ptr = dynamic_cast<Door*>(entity.get());
|
||||
manager.add(std::move(entity));
|
||||
if (door_ptr != nullptr) { manager.setDoor(door_ptr); }
|
||||
} else {
|
||||
manager.add(std::move(entity));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
@@ -346,9 +368,15 @@ void EntityManager::loadFromLevel(const std::string& level_yaml_path) {
|
||||
auto entity = buildEntity(TYPE, sprite, anchor);
|
||||
if (entity == nullptr) { continue; }
|
||||
|
||||
const bool OK = (TYPE == "sarcophagus")
|
||||
? placeSarcophagus(*this, std::move(entity), sprite, spawn)
|
||||
: placeGeneric(*this, std::move(entity), TYPE, sprite, anchor, spawn);
|
||||
bool ok = false;
|
||||
if (TYPE == "sarcophagus") {
|
||||
ok = placeSarcophagus(*this, std::move(entity), sprite, spawn);
|
||||
} else if (TYPE == "door") {
|
||||
ok = placeDoor(*this, std::move(entity), sprite);
|
||||
} else {
|
||||
ok = placeGeneric(*this, std::move(entity), TYPE, sprite, anchor, spawn);
|
||||
}
|
||||
const bool OK = ok;
|
||||
if (OK) { ++loaded; }
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user