feat(anim): cardinal WEST i flip totalment governat pel motor d'animació
This commit is contained in:
1 parent
9dc7ff0da3
commit
72384c3113
15 files changed
+183
-182
No files matched your search
@@ -203,22 +203,21 @@ void Player::readWhipBlock(const fkyaml::node& yaml) {
|
||||
}
|
||||
|
||||
void Player::applyCardinal(Cardinal c) {
|
||||
// El flip del sprite el governa l'animació al motor: només cal posar
|
||||
// el `facing_` que tocaria; `animationName()` ja resol el sufix
|
||||
// (`_west` per Cardinal::WEST) i el YAML hi declara `flip_h: true`.
|
||||
switch (c) {
|
||||
case Cardinal::NORTH:
|
||||
facing_ = Facing::NORTH;
|
||||
setFlip(SDL_FLIP_NONE);
|
||||
break;
|
||||
case Cardinal::SOUTH:
|
||||
facing_ = Facing::SOUTH;
|
||||
setFlip(SDL_FLIP_NONE);
|
||||
break;
|
||||
case Cardinal::EAST:
|
||||
facing_ = Facing::EAST;
|
||||
setFlip(SDL_FLIP_NONE);
|
||||
break;
|
||||
case Cardinal::WEST:
|
||||
facing_ = Facing::EAST;
|
||||
setFlip(SDL_FLIP_HORIZONTAL);
|
||||
facing_ = Facing::WEST;
|
||||
break;
|
||||
case Cardinal::NONE:
|
||||
break;
|
||||
@@ -313,17 +312,14 @@ void Player::updateFacingAndTurn(float delta_time, float vx, float vy) {
|
||||
turning_remaining_ms_ = static_cast<float>(turn_config.duration_ms);
|
||||
applyCardinal(intermediate_cardinal_);
|
||||
} else if (vx != 0.0F) {
|
||||
// Tria de facing original: prevalença lateral, flip segons el
|
||||
// signe de vx; verticals purs van a NORTH/SOUTH amb flip NONE;
|
||||
// en aturar-se conservem `facing_` per a l'animació stand.
|
||||
facing_ = Facing::EAST;
|
||||
setFlip(vx < 0.0F ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE);
|
||||
// Tria de facing: prevalença lateral, EAST/WEST segons el signe
|
||||
// de vx; verticals purs van a NORTH/SOUTH. En aturar-se
|
||||
// conservem `facing_` per a l'animació stand.
|
||||
facing_ = (vx < 0.0F) ? Facing::WEST : Facing::EAST;
|
||||
} else if (vy < 0.0F) {
|
||||
facing_ = Facing::NORTH;
|
||||
setFlip(SDL_FLIP_NONE);
|
||||
} else if (vy > 0.0F) {
|
||||
facing_ = Facing::SOUTH;
|
||||
setFlip(SDL_FLIP_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -655,11 +651,11 @@ auto Player::currentFacingCardinal() const -> Cardinal {
|
||||
case Facing::SOUTH:
|
||||
return Cardinal::SOUTH;
|
||||
case Facing::EAST:
|
||||
break;
|
||||
return Cardinal::EAST;
|
||||
case Facing::WEST:
|
||||
return Cardinal::WEST;
|
||||
}
|
||||
// Lateral: el flip discrimina E/W. Sense flip = mira a la dreta
|
||||
// (convenció estable a tots els assets actuals).
|
||||
return (getFlip() == SDL_FLIP_HORIZONTAL) ? Cardinal::WEST : Cardinal::EAST;
|
||||
return Cardinal::EAST;
|
||||
}
|
||||
|
||||
void Player::enterAttacking(Cardinal facing) {
|
||||
@@ -1106,89 +1102,48 @@ void Player::renderShadow() const {
|
||||
Screen::get().blendRect(SX, SY, SHADOW_W, SHADOW_H, SHADOW_ARGB, SHADOW_ALPHA);
|
||||
}
|
||||
|
||||
auto Player::animationName(bool moving) const -> const char* {
|
||||
// En l'aire forcem la variant `jump_*` (per direcció), independent de
|
||||
// si hi ha velocitat horitzontal: per al jugador, l'estat visual del
|
||||
// salt és per direcció, no per velocitat.
|
||||
if (state_ == State::AIRBORNE) {
|
||||
switch (facing_) {
|
||||
case Facing::NORTH:
|
||||
return "jump_north";
|
||||
case Facing::SOUTH:
|
||||
return "jump_south";
|
||||
case Facing::EAST:
|
||||
break;
|
||||
}
|
||||
return "jump_east";
|
||||
}
|
||||
// En LANDING_STUN, `stun_*` (per direcció): mostrem el frame
|
||||
// d'aterratge fins que s'esgota el timer. La direcció ve fixada del
|
||||
// moment del despegue (no es canvia mentre estem en l'aire).
|
||||
if (state_ == State::LANDING_STUN) {
|
||||
switch (facing_) {
|
||||
case Facing::NORTH:
|
||||
return "stun_north";
|
||||
case Facing::SOUTH:
|
||||
return "stun_south";
|
||||
case Facing::EAST:
|
||||
break;
|
||||
}
|
||||
return "stun_east";
|
||||
}
|
||||
// En HURT, `hurt_*` (per direcció): el jugador llisca sense
|
||||
// control en la direcció triada per `enterHurt`. Mateixa estructura
|
||||
// que walk per facilitat (ara mateix els frames són clons).
|
||||
if (state_ == State::HURT) {
|
||||
switch (facing_) {
|
||||
case Facing::NORTH:
|
||||
return "hurt_north";
|
||||
case Facing::SOUTH:
|
||||
return "hurt_south";
|
||||
case Facing::EAST:
|
||||
break;
|
||||
}
|
||||
return "hurt_east";
|
||||
}
|
||||
// ATTACKING té dues sub-fases: durant `swing_ms` el sprite és
|
||||
// `attack_*` (animació del braç llançant el látigo); durant
|
||||
// `cooldown_ms` posterior canviem a `recover_*` per a frames
|
||||
// pròpis de recuperació. Mentre l'art no estiga dibuixat, els
|
||||
// YAMLs apunten `recover_*` als mateixos frames que `stand_*` —
|
||||
// visualment és idèntic, però la separació deixa l'arquitectura
|
||||
// preparada perquè en afegir frames reals només calga tocar el
|
||||
// YAML, no el codi.
|
||||
if (state_ == State::ATTACKING) {
|
||||
const bool IN_SWING = (attacking_remaining_ms_ > static_cast<float>(whip_config.cooldown_ms));
|
||||
if (IN_SWING) {
|
||||
switch (facing_) {
|
||||
case Facing::NORTH:
|
||||
return "attack_north";
|
||||
case Facing::SOUTH:
|
||||
return "attack_south";
|
||||
case Facing::EAST:
|
||||
break;
|
||||
}
|
||||
return "attack_east";
|
||||
}
|
||||
switch (facing_) {
|
||||
case Facing::NORTH:
|
||||
return "recover_north";
|
||||
case Facing::SOUTH:
|
||||
return "recover_south";
|
||||
case Facing::EAST:
|
||||
break;
|
||||
}
|
||||
return "recover_east";
|
||||
}
|
||||
switch (facing_) {
|
||||
// Sufix d'animació per cardinal — empat 1:1 amb l'enum `Facing` i el
|
||||
// sufix declarat als YAMLs de jugador (sam.yaml, morcus.yaml).
|
||||
auto Player::facingSuffix(Facing facing) -> const char* {
|
||||
switch (facing) {
|
||||
case Facing::NORTH:
|
||||
return moving ? "walk_north" : "stand_north";
|
||||
return "_north";
|
||||
case Facing::SOUTH:
|
||||
return moving ? "walk_south" : "stand_south";
|
||||
return "_south";
|
||||
case Facing::EAST:
|
||||
return "_east";
|
||||
case Facing::WEST:
|
||||
return "_west";
|
||||
}
|
||||
return "_east";
|
||||
}
|
||||
|
||||
// Prefix d'animació per estat. ATTACKING té dues sub-fases: durant
|
||||
// `swing_ms` és `attack_*` (animació del braç llançant el látigo); durant
|
||||
// `cooldown_ms` posterior, `recover_*`. A AIRBORNE/LANDING_STUN/HURT, la
|
||||
// variant és per direcció, no per velocitat: l'estat bloqueja el `moving`
|
||||
// argument i no fa servir walk/stand.
|
||||
auto Player::statePrefix(State state, bool moving, bool in_attack_swing) -> const char* {
|
||||
switch (state) {
|
||||
case State::AIRBORNE:
|
||||
return "jump";
|
||||
case State::LANDING_STUN:
|
||||
return "stun";
|
||||
case State::HURT:
|
||||
return "hurt";
|
||||
case State::ATTACKING:
|
||||
return in_attack_swing ? "attack" : "recover";
|
||||
case State::GROUNDED:
|
||||
case State::EXITED:
|
||||
case State::DISABLED:
|
||||
break;
|
||||
}
|
||||
return moving ? "walk_east" : "stand_east";
|
||||
return moving ? "walk" : "stand";
|
||||
}
|
||||
|
||||
auto Player::animationName(bool moving) const -> std::string {
|
||||
const bool IN_ATTACK_SWING = (attacking_remaining_ms_ > static_cast<float>(whip_config.cooldown_ms));
|
||||
return std::string(statePrefix(state_, moving, IN_ATTACK_SWING)) + facingSuffix(facing_);
|
||||
}
|
||||
|
||||
auto Player::getCurrentTile() const -> std::pair<int, int> {
|
||||
@@ -1252,7 +1207,6 @@ void Player::respawn(float x, float y) {
|
||||
// sense això, un EXITED que entrava per la porta amb facing NORTH
|
||||
// re-aparix d'esquena al pròxim cicle. Mateixa lògica que el ctor.
|
||||
facing_ = Facing::SOUTH;
|
||||
setFlip(SDL_FLIP_NONE);
|
||||
setCurrentAnimation("stand_south");
|
||||
setPosX(x);
|
||||
setPosY(y);
|
||||
|
||||
Reference in new issue
Block a user