feat(player): animacions direccionals i stand automàtic en col·lisió; v0.18.0
This commit is contained in:
1 parent
13ae4a51a4
commit
a3592d6c73
4 files changed
+135
-10
No files matched your search
@@ -66,24 +66,38 @@ void Player::update(float delta_time) {
|
||||
setVelX(vx);
|
||||
setVelY(vy);
|
||||
|
||||
// El sprite original mira a la dreta; flipem només si es mou a l'esquerra
|
||||
// i restaurem si torna a la dreta. Moviments purament verticals conserven
|
||||
// l'últim flip perquè el jugador no "gire" sense motiu.
|
||||
if (vx < 0.0F) {
|
||||
setFlip(SDL_FLIP_HORIZONTAL);
|
||||
} else if (vx > 0.0F) {
|
||||
// Tria de facing amb prevalença lateral: si hi ha component horitzontal
|
||||
// (inclòs el diagonal), l'animació és lateral i el flip segueix el signe
|
||||
// de `vx`. Només en moviment purament vertical passem a UP/DOWN, i en
|
||||
// aquest cas el flip es força a NONE perquè els sprites frontals no
|
||||
// s'han d'espillar segons l'últim lateral. En aturar-se conservem
|
||||
// `facing_` per a l'animació stand corresponent.
|
||||
if (vx != 0.0F) {
|
||||
facing_ = Facing::SIDE;
|
||||
setFlip(vx < 0.0F ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE);
|
||||
} else if (vy < 0.0F) {
|
||||
facing_ = Facing::UP;
|
||||
setFlip(SDL_FLIP_NONE);
|
||||
} else if (vy > 0.0F) {
|
||||
facing_ = Facing::DOWN;
|
||||
setFlip(SDL_FLIP_NONE);
|
||||
}
|
||||
|
||||
const bool MOVING = vx != 0.0F || vy != 0.0F;
|
||||
setCurrentAnimation(MOVING ? "walk" : "stand");
|
||||
|
||||
// Snap al passadís: si només hi ha moviment horitzontal (o vertical) i
|
||||
// la caixa està prou prop d'una lane perpendicular (≤ mitja caixa), la
|
||||
// Y (o X) es corregeix gradualment per enfilar el passadís. Amb
|
||||
// moviment diagonal no es fa snap — l'usuari pilota manualment.
|
||||
const bool ONLY_H = (vx != 0.0F) && (vy == 0.0F);
|
||||
const bool ONLY_V = (vy != 0.0F) && (vx == 0.0F);
|
||||
|
||||
// Pos d'inici de frame (abans de snap i integració): si en acabar el
|
||||
// frame coincideix amb la posició final, el jugador no s'ha mogut
|
||||
// realment (ni per input, ni per snap, ni ha superat la col·lisió) i cal
|
||||
// forçar l'animació `stand` corresponent al facing — així s'atura el
|
||||
// caminat quan xoca contra un mur o un sarcòfag.
|
||||
const float FRAME_START_X = getPosX();
|
||||
const float FRAME_START_Y = getPosY();
|
||||
|
||||
if (ONLY_H) {
|
||||
snapToHorizontalLane(delta_time);
|
||||
} else if (ONLY_V) {
|
||||
@@ -109,6 +123,12 @@ void Player::update(float delta_time) {
|
||||
|
||||
clampToPlayfield();
|
||||
|
||||
// Animació basada en moviment real: si la col·lisió (o l'absència
|
||||
// d'input) ha deixat el jugador al mateix lloc que al principi del
|
||||
// frame, queda en `stand` del facing actual.
|
||||
const bool MOVED = (getPosX() != FRAME_START_X) || (getPosY() != FRAME_START_Y);
|
||||
setCurrentAnimation(animationName(MOVED));
|
||||
|
||||
// Detecció de canvi de tile. Es calcula *després* del clamp i de les
|
||||
// col·lisions perquè la posició aquí ja és la definitiva del frame;
|
||||
// així els sarcòfags no reben falsos positius mentre el Player rellisca
|
||||
@@ -124,6 +144,18 @@ void Player::update(float delta_time) {
|
||||
}
|
||||
}
|
||||
|
||||
auto Player::animationName(bool moving) const -> const char* {
|
||||
switch (facing_) {
|
||||
case Facing::UP:
|
||||
return moving ? "walk_up" : "stand_up";
|
||||
case Facing::DOWN:
|
||||
return moving ? "walk_down" : "stand_down";
|
||||
case Facing::SIDE:
|
||||
break;
|
||||
}
|
||||
return moving ? "walk" : "stand";
|
||||
}
|
||||
|
||||
auto Player::getCurrentTile() const -> std::pair<int, int> {
|
||||
// El grid del tilemap és de `Map::tile_size` píxels i està 16-alineat
|
||||
// respecte a l'origen del tilemap (pot ser negatiu per overscan). El
|
||||
|
||||
Reference in new issue
Block a user