feat(player): clamp permet pujar al passadís + porta tancada bloqueja via Map::collides
This commit is contained in:
1 parent
648a5932f8
commit
377e5d0b97
3 files changed
+37
-2
No files matched your search
@@ -6,6 +6,7 @@
|
|||||||
#include "game/entities/entity_factory.hpp"
|
#include "game/entities/entity_factory.hpp"
|
||||||
#include "game/entities/event_bus.hpp"
|
#include "game/entities/event_bus.hpp"
|
||||||
#include "game/entities/player.hpp"
|
#include "game/entities/player.hpp"
|
||||||
|
#include "game/map/map.hpp"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -80,6 +81,12 @@ void Door::open() {
|
|||||||
if (state_ != State::CLOSED) { return; }
|
if (state_ != State::CLOSED) { return; }
|
||||||
state_ = State::OPENING;
|
state_ = State::OPENING;
|
||||||
setAnimation(anim_opening_);
|
setAnimation(anim_opening_);
|
||||||
|
// Marquem el passadís com a transitable: a partir d'aquest tic
|
||||||
|
// `Map::collides` deixa de bloquejar el rect del passadís. La
|
||||||
|
// transició d'animació OPENING → OPEN encara dura el seu temps,
|
||||||
|
// però la geometria ja és permeable — coherent amb el feel de
|
||||||
|
// "la porta s'obri i el jugador pot avançar al moment".
|
||||||
|
Map::door_open = true;
|
||||||
// Edge case: si `opening` té ≤1 frame i és loop=true, mai es
|
// Edge case: si `opening` té ≤1 frame i és loop=true, mai es
|
||||||
// completarà. Per força, forcem loop=false del frame únic aquí. Els
|
// completarà. Per força, forcem loop=false del frame únic aquí. Els
|
||||||
// placeholders defineixen `loop: false` explícitament al YAML, així
|
// placeholders defineixen `loop: false` explícitament al YAML, així
|
||||||
|
|||||||
@@ -987,11 +987,27 @@ void Player::clampToPlayfield() {
|
|||||||
const auto MIN_X = static_cast<float>(map_.playfield_x - collision_x_offset);
|
const auto MIN_X = static_cast<float>(map_.playfield_x - collision_x_offset);
|
||||||
const auto MAX_X = static_cast<float>(
|
const auto MAX_X = static_cast<float>(
|
||||||
map_.playfield_x + map_.playfield_w - collision_x_offset - collision_size);
|
map_.playfield_x + map_.playfield_w - collision_x_offset - collision_size);
|
||||||
const auto MIN_Y = static_cast<float>(map_.playfield_y - collision_y_offset);
|
auto min_y = static_cast<float>(map_.playfield_y - collision_y_offset);
|
||||||
const auto MAX_Y = static_cast<float>(
|
const auto MAX_Y = static_cast<float>(
|
||||||
map_.playfield_y + map_.playfield_h - collision_y_offset - collision_size);
|
map_.playfield_y + map_.playfield_h - collision_y_offset - collision_size);
|
||||||
|
|
||||||
|
// Passadís de sortida: si la base box queda enterament dins del rang
|
||||||
|
// X del passadís de la porta, deixem que pugi al strip del mur trasser
|
||||||
|
// (fins a `door_corridor.y`). Fora del rang, MIN_Y es queda al
|
||||||
|
// playfield. La regla "enterament dins" exigeix alinear-se al passadís
|
||||||
|
// abans de pujar — la base box (12 px) hi cap amb 4 px de marge.
|
||||||
|
if (map_.door_corridor_w > 0) {
|
||||||
|
const float BASE_X = getPosX() + static_cast<float>(collision_x_offset);
|
||||||
|
const float BASE_RIGHT = BASE_X + static_cast<float>(collision_size);
|
||||||
|
const auto CORRIDOR_LEFT = static_cast<float>(map_.door_corridor_x);
|
||||||
|
const auto CORRIDOR_RIGHT = static_cast<float>(map_.door_corridor_x + map_.door_corridor_w);
|
||||||
|
if (BASE_X >= CORRIDOR_LEFT && BASE_RIGHT <= CORRIDOR_RIGHT) {
|
||||||
|
min_y = static_cast<float>(map_.door_corridor_y - collision_y_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setPosX(std::clamp(getPosX(), MIN_X, MAX_X));
|
setPosX(std::clamp(getPosX(), MIN_X, MAX_X));
|
||||||
setPosY(std::clamp(getPosY(), MIN_Y, MAX_Y));
|
setPosY(std::clamp(getPosY(), min_y, MAX_Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Player::getBaseBox() const -> SDL_FRect {
|
auto Player::getBaseBox() const -> SDL_FRect {
|
||||||
|
|||||||
@@ -114,6 +114,18 @@ namespace Map {
|
|||||||
if (overlapStrict(base_box, getSarcRect(col, row))) { return true; }
|
if (overlapStrict(base_box, getSarcRect(col, row))) { return true; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Porta tancada: el passadís de sortida actua com a paret. Quan la
|
||||||
|
// porta passa a OPEN, l'entitat Door posa `door_open = true` i
|
||||||
|
// aquesta clàusula deixa de bloquejar — el jugador pot creuar.
|
||||||
|
if (!door_open && door_corridor_w > 0 && door_corridor_h > 0) {
|
||||||
|
const SDL_FRect CORRIDOR{
|
||||||
|
.x = static_cast<float>(door_corridor_x),
|
||||||
|
.y = static_cast<float>(door_corridor_y),
|
||||||
|
.w = static_cast<float>(door_corridor_w),
|
||||||
|
.h = static_cast<float>(door_corridor_h),
|
||||||
|
};
|
||||||
|
if (overlapStrict(base_box, CORRIDOR)) { return true; }
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user