refactor(anim): direccions cardinals (north/south/east) en YAML i codi
This commit is contained in:
1 parent
1d43a77800
commit
9dc7ff0da3
9 files changed
+189
-240
No files matched your search
@@ -23,18 +23,18 @@ flags:
|
|||||||
collides: true
|
collides: true
|
||||||
interactable: false
|
interactable: false
|
||||||
# Strip de 12 frames en graella 4×3 (mateix esquema que el jugador):
|
# Strip de 12 frames en graella 4×3 (mateix esquema que el jugador):
|
||||||
# 0..3 → walk_down (cara avall)
|
# 0..3 → walk_south (cara avall)
|
||||||
# 4..7 → walk_up (cara amunt)
|
# 4..7 → walk_north (cara amunt)
|
||||||
# 8..11 → walk (lateral; flip horitzontal segons el sentit)
|
# 8..11 → walk_east (lateral; flip horitzontal segons el sentit)
|
||||||
# La momia no té variants `stand_*` perquè mai no para.
|
# La momia no té variants `stand_*` perquè mai no para.
|
||||||
animations:
|
animations:
|
||||||
walk_down: { frames: [0, 1, 2, 3], fps: 8, loop: true }
|
walk_south: { frames: [0, 1, 2, 3], fps: 8, loop: true }
|
||||||
walk_up: { frames: [4, 5, 6, 7], fps: 8, loop: true }
|
walk_north: { frames: [4, 5, 6, 7], fps: 8, loop: true }
|
||||||
walk: { frames: [8, 9, 10, 11], fps: 8, loop: true }
|
walk_east: { frames: [8, 9, 10, 11], fps: 8, loop: true }
|
||||||
ai:
|
ai:
|
||||||
type: corridor_wanderer
|
type: corridor_wanderer
|
||||||
direction_choice: random
|
direction_choice: random
|
||||||
initial_direction: right
|
initial_direction: east
|
||||||
stats:
|
stats:
|
||||||
speed: 30
|
speed: 30
|
||||||
damage: 1
|
damage: 1
|
||||||
|
|||||||
+23
-50
@@ -12,60 +12,33 @@ collision:
|
|||||||
height: 12
|
height: 12
|
||||||
|
|
||||||
animations:
|
animations:
|
||||||
stand_down: { frames: [0] }
|
stand_south: { frames: [0] }
|
||||||
stand_up: { frames: [4] }
|
stand_north: { frames: [4] }
|
||||||
stand: { frames: [8] }
|
stand_east: { frames: [8] }
|
||||||
jump_down: { frames: [12] }
|
|
||||||
jump_up: { frames: [13] }
|
|
||||||
jump: { frames: [14] }
|
|
||||||
stun_down: { frames: [16] }
|
|
||||||
stun_up: { frames: [17] }
|
|
||||||
stun: { frames: [18] }
|
|
||||||
|
|
||||||
walk_down:
|
jump_south: { frames: [12] }
|
||||||
frames: [0, 1, 2, 3]
|
jump_north: { frames: [13] }
|
||||||
frame_ms: 100
|
jump_east: { frames: [14] }
|
||||||
|
|
||||||
walk_up:
|
stun_south: { frames: [16] }
|
||||||
frames: [4, 5, 6, 7]
|
stun_north: { frames: [17] }
|
||||||
frame_ms: 100
|
stun_east: { frames: [18] }
|
||||||
|
|
||||||
walk:
|
walk_south: { frames: [0, 1, 2, 3], frame_ms: 100 }
|
||||||
frames: [8, 9, 10, 11]
|
walk_north: { frames: [4, 5, 6, 7], frame_ms: 100 }
|
||||||
frame_ms: 100
|
walk_east: { frames: [8, 9, 10, 11], frame_ms: 100 }
|
||||||
|
|
||||||
hurt_down:
|
hurt_south: { frames: [0, 1, 2, 3], frame_ms: 100 }
|
||||||
frames: [0, 1, 2, 3]
|
hurt_north: { frames: [4, 5, 6, 7], frame_ms: 100 }
|
||||||
frame_ms: 100
|
hurt_east: { frames: [8, 9, 10, 11], frame_ms: 100 }
|
||||||
|
|
||||||
hurt_up:
|
attack_south: { frames: [20, 21, 22, 23], frame_ms: 50 }
|
||||||
frames: [4, 5, 6, 7]
|
attack_north: { frames: [24, 25, 26, 27], frame_ms: 50 }
|
||||||
frame_ms: 100
|
attack_east: { frames: [28, 29, 30, 31], frame_ms: 50 }
|
||||||
|
|
||||||
hurt:
|
recover_south: { frames: [23] }
|
||||||
frames: [8, 9, 10, 11]
|
recover_north: { frames: [27] }
|
||||||
frame_ms: 100
|
recover_east: { frames: [31] }
|
||||||
|
|
||||||
attack_down:
|
|
||||||
frames: [20, 21, 22, 23]
|
|
||||||
frame_ms: 50
|
|
||||||
|
|
||||||
attack_up:
|
|
||||||
frames: [24, 25, 26, 27]
|
|
||||||
frame_ms: 50
|
|
||||||
|
|
||||||
attack:
|
|
||||||
frames: [28, 29, 30, 31]
|
|
||||||
frame_ms: 50
|
|
||||||
|
|
||||||
recover_down:
|
|
||||||
frames: [23]
|
|
||||||
|
|
||||||
recover_up:
|
|
||||||
frames: [27]
|
|
||||||
|
|
||||||
recover:
|
|
||||||
frames: [31]
|
|
||||||
|
|
||||||
# Inèrcia de frenada en soltar la direcció. `threshold_ms` filtra
|
# Inèrcia de frenada en soltar la direcció. `threshold_ms` filtra
|
||||||
# tocs curts (passets d'un tile sense rellisquera).
|
# tocs curts (passets d'un tile sense rellisquera).
|
||||||
@@ -78,8 +51,8 @@ inertia:
|
|||||||
turn:
|
turn:
|
||||||
duration_ms: 80
|
duration_ms: 80
|
||||||
transitions:
|
transitions:
|
||||||
west_to_east: down
|
west_to_east: south
|
||||||
east_to_west: up
|
east_to_west: north
|
||||||
north_to_south: east
|
north_to_south: east
|
||||||
south_to_north: west
|
south_to_north: west
|
||||||
|
|
||||||
|
|||||||
+23
-50
@@ -12,60 +12,33 @@ collision:
|
|||||||
height: 12
|
height: 12
|
||||||
|
|
||||||
animations:
|
animations:
|
||||||
stand_down: { frames: [0] }
|
stand_south: { frames: [0] }
|
||||||
stand_up: { frames: [4] }
|
stand_north: { frames: [4] }
|
||||||
stand: { frames: [8] }
|
stand_east: { frames: [8] }
|
||||||
jump_down: { frames: [12] }
|
|
||||||
jump_up: { frames: [13] }
|
|
||||||
jump: { frames: [14] }
|
|
||||||
stun_down: { frames: [16] }
|
|
||||||
stun_up: { frames: [17] }
|
|
||||||
stun: { frames: [18] }
|
|
||||||
|
|
||||||
walk_down:
|
jump_south: { frames: [12] }
|
||||||
frames: [0, 1, 2, 3]
|
jump_north: { frames: [13] }
|
||||||
frame_ms: 100
|
jump_east: { frames: [14] }
|
||||||
|
|
||||||
walk_up:
|
stun_south: { frames: [16] }
|
||||||
frames: [4, 5, 6, 7]
|
stun_north: { frames: [17] }
|
||||||
frame_ms: 100
|
stun_east: { frames: [18] }
|
||||||
|
|
||||||
walk:
|
walk_south: { frames: [0, 1, 2, 3], frame_ms: 100 }
|
||||||
frames: [8, 9, 10, 11]
|
walk_north: { frames: [4, 5, 6, 7], frame_ms: 100 }
|
||||||
frame_ms: 100
|
walk_east: { frames: [8, 9, 10, 11], frame_ms: 100 }
|
||||||
|
|
||||||
hurt_down:
|
hurt_south: { frames: [0, 1, 2, 3], frame_ms: 100 }
|
||||||
frames: [0, 1, 2, 3]
|
hurt_north: { frames: [4, 5, 6, 7], frame_ms: 100 }
|
||||||
frame_ms: 100
|
hurt_east: { frames: [8, 9, 10, 11], frame_ms: 100 }
|
||||||
|
|
||||||
hurt_up:
|
attack_south: { frames: [20, 21, 22, 23], frame_ms: 50 }
|
||||||
frames: [4, 5, 6, 7]
|
attack_north: { frames: [24, 25, 26, 27], frame_ms: 50 }
|
||||||
frame_ms: 100
|
attack_east: { frames: [28, 29, 30, 31], frame_ms: 50 }
|
||||||
|
|
||||||
hurt:
|
recover_south: { frames: [23] }
|
||||||
frames: [8, 9, 10, 11]
|
recover_north: { frames: [27] }
|
||||||
frame_ms: 100
|
recover_east: { frames: [31] }
|
||||||
|
|
||||||
attack_down:
|
|
||||||
frames: [20, 21, 22, 23]
|
|
||||||
frame_ms: 50
|
|
||||||
|
|
||||||
attack_up:
|
|
||||||
frames: [24, 25, 26, 27]
|
|
||||||
frame_ms: 50
|
|
||||||
|
|
||||||
attack:
|
|
||||||
frames: [28, 29, 30, 31]
|
|
||||||
frame_ms: 50
|
|
||||||
|
|
||||||
recover_down:
|
|
||||||
frames: [23]
|
|
||||||
|
|
||||||
recover_up:
|
|
||||||
frames: [27]
|
|
||||||
|
|
||||||
recover:
|
|
||||||
frames: [31]
|
|
||||||
|
|
||||||
# Inèrcia de frenada en soltar la direcció. `threshold_ms` filtra
|
# Inèrcia de frenada en soltar la direcció. `threshold_ms` filtra
|
||||||
# tocs curts (passets d'un tile sense rellisquera).
|
# tocs curts (passets d'un tile sense rellisquera).
|
||||||
@@ -78,8 +51,8 @@ inertia:
|
|||||||
turn:
|
turn:
|
||||||
duration_ms: 80
|
duration_ms: 80
|
||||||
transitions:
|
transitions:
|
||||||
west_to_east: down
|
west_to_east: south
|
||||||
east_to_west: up
|
east_to_west: north
|
||||||
north_to_south: east
|
north_to_south: east
|
||||||
south_to_north: west
|
south_to_north: west
|
||||||
|
|
||||||
|
|||||||
@@ -73,9 +73,9 @@ namespace {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Mummy::Mummy(const fkyaml::node& yaml)
|
Mummy::Mummy(const fkyaml::node& yaml)
|
||||||
: anim_walk_down_(buildAnimation(yaml, "walk_down")),
|
: anim_walk_south_(buildAnimation(yaml, "walk_south")),
|
||||||
anim_walk_up_(buildAnimation(yaml, "walk_up")),
|
anim_walk_north_(buildAnimation(yaml, "walk_north")),
|
||||||
anim_walk_lateral_(buildAnimation(yaml, "walk")) {
|
anim_walk_east_(buildAnimation(yaml, "walk_east")) {
|
||||||
name_ = yaml.contains("name") ? yaml["name"].get_value<std::string>() : std::string("mummy");
|
name_ = yaml.contains("name") ? yaml["name"].get_value<std::string>() : std::string("mummy");
|
||||||
collides_ = true;
|
collides_ = true;
|
||||||
interactable_ = false;
|
interactable_ = false;
|
||||||
@@ -87,21 +87,22 @@ Mummy::Mummy(const fkyaml::node& yaml)
|
|||||||
if (s.contains("damage")) { setDamage(s["damage"].get_value<int>()); }
|
if (s.contains("damage")) { setDamage(s["damage"].get_value<int>()); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Direcció inicial llegida del bloc `ai:`. Per defecte dreta, per
|
// Direcció inicial llegida del bloc `ai:`. Per defecte est, per
|
||||||
// coherència amb el que fa RollingRock. Valors acceptats: right, left,
|
// coherència amb el que fa RollingRock. Valors acceptats:
|
||||||
// up, down. Qualsevol altre s'interpreta com a "sense direcció" (la
|
// east, west, north, south. Qualsevol altre s'interpreta com a
|
||||||
// momia no es mou fins que step() no triï una direcció).
|
// "sense direcció" (la momia no es mou fins que step() no triï una
|
||||||
std::string initial = "right";
|
// direcció).
|
||||||
|
std::string initial = "east";
|
||||||
if (yaml.contains("ai") && yaml["ai"].contains("initial_direction")) {
|
if (yaml.contains("ai") && yaml["ai"].contains("initial_direction")) {
|
||||||
initial = yaml["ai"]["initial_direction"].get_value<std::string>();
|
initial = yaml["ai"]["initial_direction"].get_value<std::string>();
|
||||||
}
|
}
|
||||||
if (initial == "right") {
|
if (initial == "east") {
|
||||||
changeDirection(1.0F, 0.0F);
|
changeDirection(1.0F, 0.0F);
|
||||||
} else if (initial == "left") {
|
} else if (initial == "west") {
|
||||||
changeDirection(-1.0F, 0.0F);
|
changeDirection(-1.0F, 0.0F);
|
||||||
} else if (initial == "up") {
|
} else if (initial == "north") {
|
||||||
changeDirection(0.0F, -1.0F);
|
changeDirection(0.0F, -1.0F);
|
||||||
} else if (initial == "down") {
|
} else if (initial == "south") {
|
||||||
changeDirection(0.0F, 1.0F);
|
changeDirection(0.0F, 1.0F);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,18 +126,18 @@ Mummy::Mummy(const fkyaml::node& yaml)
|
|||||||
void Mummy::changeDirection(float dx, float dy) {
|
void Mummy::changeDirection(float dx, float dy) {
|
||||||
setDirection(dx, dy);
|
setDirection(dx, dy);
|
||||||
// Prevalença lateral: si hi ha component horitzontal s'usa l'anim
|
// Prevalença lateral: si hi ha component horitzontal s'usa l'anim
|
||||||
// lateral + flip segons el signe. Només direccions purament verticals
|
// est + flip segons el signe. Només direccions purament verticals
|
||||||
// disparen walk_up/walk_down. Quan la direcció queda (0,0) (cul-de-sac
|
// disparen walk_north/walk_south. Quan la direcció queda (0,0)
|
||||||
// amb NONE) no toquem l'animació: la momia es quedarà al frame actual
|
// (cul-de-sac amb NONE) no toquem l'animació: la momia es quedarà al
|
||||||
// fins que step() li torni a assignar direcció.
|
// frame actual fins que step() li torni a assignar direcció.
|
||||||
if (dx != 0.0F) {
|
if (dx != 0.0F) {
|
||||||
anim_ = anim_walk_lateral_;
|
anim_ = anim_walk_east_;
|
||||||
flip_ = (dx < 0.0F) ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
|
flip_ = (dx < 0.0F) ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
|
||||||
} else if (dy < 0.0F) {
|
} else if (dy < 0.0F) {
|
||||||
anim_ = anim_walk_up_;
|
anim_ = anim_walk_north_;
|
||||||
flip_ = SDL_FLIP_NONE;
|
flip_ = SDL_FLIP_NONE;
|
||||||
} else if (dy > 0.0F) {
|
} else if (dy > 0.0F) {
|
||||||
anim_ = anim_walk_down_;
|
anim_ = anim_walk_south_;
|
||||||
flip_ = SDL_FLIP_NONE;
|
flip_ = SDL_FLIP_NONE;
|
||||||
}
|
}
|
||||||
if (anim_.has_value()) { anim_->reset(); }
|
if (anim_.has_value()) { anim_->reset(); }
|
||||||
@@ -234,10 +235,10 @@ auto Mummy::detectLaneCrossing(float dx, float dy) const -> std::optional<float>
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto Mummy::currentDirection() const -> Direction {
|
auto Mummy::currentDirection() const -> Direction {
|
||||||
if (dir_x_ > 0.0F) { return Direction::RIGHT; }
|
if (dir_x_ > 0.0F) { return Direction::EAST; }
|
||||||
if (dir_x_ < 0.0F) { return Direction::LEFT; }
|
if (dir_x_ < 0.0F) { return Direction::WEST; }
|
||||||
if (dir_y_ > 0.0F) { return Direction::DOWN; }
|
if (dir_y_ > 0.0F) { return Direction::SOUTH; }
|
||||||
if (dir_y_ < 0.0F) { return Direction::UP; }
|
if (dir_y_ < 0.0F) { return Direction::NORTH; }
|
||||||
return Direction::NONE;
|
return Direction::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,10 +269,10 @@ auto Mummy::collectDirectionPools(float step) const -> DirectionPools {
|
|||||||
Direction dir;
|
Direction dir;
|
||||||
};
|
};
|
||||||
const std::array<Candidate, 4> ALL{{
|
const std::array<Candidate, 4> ALL{{
|
||||||
{.dx = step, .dy = 0.0F, .dir = Direction::RIGHT},
|
{.dx = step, .dy = 0.0F, .dir = Direction::EAST},
|
||||||
{.dx = -step, .dy = 0.0F, .dir = Direction::LEFT},
|
{.dx = -step, .dy = 0.0F, .dir = Direction::WEST},
|
||||||
{.dx = 0.0F, .dy = -step, .dir = Direction::UP},
|
{.dx = 0.0F, .dy = -step, .dir = Direction::NORTH},
|
||||||
{.dx = 0.0F, .dy = step, .dir = Direction::DOWN},
|
{.dx = 0.0F, .dy = step, .dir = Direction::SOUTH},
|
||||||
}};
|
}};
|
||||||
DirectionPools pools;
|
DirectionPools pools;
|
||||||
for (const auto& c : ALL) {
|
for (const auto& c : ALL) {
|
||||||
@@ -293,16 +294,16 @@ auto Mummy::collectDirectionPools(float step) const -> DirectionPools {
|
|||||||
|
|
||||||
void Mummy::applyChoice(Direction dir) {
|
void Mummy::applyChoice(Direction dir) {
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case Direction::UP:
|
case Direction::NORTH:
|
||||||
changeDirection(0.0F, -1.0F);
|
changeDirection(0.0F, -1.0F);
|
||||||
break;
|
break;
|
||||||
case Direction::DOWN:
|
case Direction::SOUTH:
|
||||||
changeDirection(0.0F, 1.0F);
|
changeDirection(0.0F, 1.0F);
|
||||||
break;
|
break;
|
||||||
case Direction::LEFT:
|
case Direction::WEST:
|
||||||
changeDirection(-1.0F, 0.0F);
|
changeDirection(-1.0F, 0.0F);
|
||||||
break;
|
break;
|
||||||
case Direction::RIGHT:
|
case Direction::EAST:
|
||||||
changeDirection(1.0F, 0.0F);
|
changeDirection(1.0F, 0.0F);
|
||||||
break;
|
break;
|
||||||
case Direction::NONE:
|
case Direction::NONE:
|
||||||
@@ -347,16 +348,16 @@ auto Mummy::chooseHurtDirection(Direction preferred) const -> Direction {
|
|||||||
float dx = 0.0F;
|
float dx = 0.0F;
|
||||||
float dy = 0.0F;
|
float dy = 0.0F;
|
||||||
switch (d) {
|
switch (d) {
|
||||||
case Direction::UP:
|
case Direction::NORTH:
|
||||||
dy = -STEP;
|
dy = -STEP;
|
||||||
break;
|
break;
|
||||||
case Direction::DOWN:
|
case Direction::SOUTH:
|
||||||
dy = STEP;
|
dy = STEP;
|
||||||
break;
|
break;
|
||||||
case Direction::LEFT:
|
case Direction::WEST:
|
||||||
dx = -STEP;
|
dx = -STEP;
|
||||||
break;
|
break;
|
||||||
case Direction::RIGHT:
|
case Direction::EAST:
|
||||||
dx = STEP;
|
dx = STEP;
|
||||||
break;
|
break;
|
||||||
case Direction::NONE:
|
case Direction::NONE:
|
||||||
@@ -373,21 +374,21 @@ auto Mummy::chooseHurtDirection(Direction preferred) const -> Direction {
|
|||||||
Direction left = Direction::NONE;
|
Direction left = Direction::NONE;
|
||||||
Direction right = Direction::NONE;
|
Direction right = Direction::NONE;
|
||||||
switch (preferred) {
|
switch (preferred) {
|
||||||
case Direction::UP:
|
case Direction::NORTH:
|
||||||
left = Direction::LEFT;
|
left = Direction::WEST;
|
||||||
right = Direction::RIGHT;
|
right = Direction::EAST;
|
||||||
break;
|
break;
|
||||||
case Direction::DOWN:
|
case Direction::SOUTH:
|
||||||
left = Direction::RIGHT;
|
left = Direction::EAST;
|
||||||
right = Direction::LEFT;
|
right = Direction::WEST;
|
||||||
break;
|
break;
|
||||||
case Direction::LEFT:
|
case Direction::WEST:
|
||||||
left = Direction::DOWN;
|
left = Direction::SOUTH;
|
||||||
right = Direction::UP;
|
right = Direction::NORTH;
|
||||||
break;
|
break;
|
||||||
case Direction::RIGHT:
|
case Direction::EAST:
|
||||||
left = Direction::UP;
|
left = Direction::NORTH;
|
||||||
right = Direction::DOWN;
|
right = Direction::SOUTH;
|
||||||
break;
|
break;
|
||||||
case Direction::NONE:
|
case Direction::NONE:
|
||||||
return Direction::NONE;
|
return Direction::NONE;
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
class Mummy : public DynamicHazard {
|
class Mummy : public DynamicHazard {
|
||||||
public:
|
public:
|
||||||
enum class Direction : std::uint8_t { NONE,
|
enum class Direction : std::uint8_t { NONE,
|
||||||
UP,
|
NORTH,
|
||||||
DOWN,
|
SOUTH,
|
||||||
LEFT,
|
WEST,
|
||||||
RIGHT };
|
EAST };
|
||||||
|
|
||||||
// Estat d'alt nivell. ROAMING = IA normal (corridor_wanderer); HURT =
|
// Estat d'alt nivell. ROAMING = IA normal (corridor_wanderer); HURT =
|
||||||
// post-fuetada, fugint en línia recta durant `hurt_config_.duration_s`.
|
// post-fuetada, fugint en línia recta durant `hurt_config_.duration_s`.
|
||||||
@@ -129,10 +129,10 @@ class Mummy : public DynamicHazard {
|
|||||||
[[nodiscard]] auto chooseHurtDirection(Direction preferred) const -> Direction;
|
[[nodiscard]] auto chooseHurtDirection(Direction preferred) const -> Direction;
|
||||||
|
|
||||||
// Animacions carregades del YAML, una per cada facing. Per a horitzontal
|
// Animacions carregades del YAML, una per cada facing. Per a horitzontal
|
||||||
// només en cal una (`walk`) i el flip ja diferencia esquerra/dreta.
|
// només en cal una (`walk_east`) i el flip ja diferencia esquerra/dreta.
|
||||||
AnimationComponent anim_walk_down_;
|
AnimationComponent anim_walk_south_;
|
||||||
AnimationComponent anim_walk_up_;
|
AnimationComponent anim_walk_north_;
|
||||||
AnimationComponent anim_walk_lateral_;
|
AnimationComponent anim_walk_east_;
|
||||||
|
|
||||||
// Estat HURT i la seua configuració. `hurt_speed_` és l'efectiva
|
// Estat HURT i la seua configuració. `hurt_speed_` és l'efectiva
|
||||||
// (resultat d'aplicar el `speed` del bloc `hurt:` o, si val 0, la
|
// (resultat d'aplicar el `speed` del bloc `hurt:` o, si val 0, la
|
||||||
|
|||||||
@@ -255,13 +255,13 @@ namespace {
|
|||||||
auto whipDirToMummyDir(WhipAttack::Direction d) -> Mummy::Direction {
|
auto whipDirToMummyDir(WhipAttack::Direction d) -> Mummy::Direction {
|
||||||
switch (d) {
|
switch (d) {
|
||||||
case WhipAttack::Direction::NORTH:
|
case WhipAttack::Direction::NORTH:
|
||||||
return Mummy::Direction::UP;
|
return Mummy::Direction::NORTH;
|
||||||
case WhipAttack::Direction::SOUTH:
|
case WhipAttack::Direction::SOUTH:
|
||||||
return Mummy::Direction::DOWN;
|
return Mummy::Direction::SOUTH;
|
||||||
case WhipAttack::Direction::EAST:
|
case WhipAttack::Direction::EAST:
|
||||||
return Mummy::Direction::RIGHT;
|
return Mummy::Direction::EAST;
|
||||||
case WhipAttack::Direction::WEST:
|
case WhipAttack::Direction::WEST:
|
||||||
return Mummy::Direction::LEFT;
|
return Mummy::Direction::WEST;
|
||||||
}
|
}
|
||||||
return Mummy::Direction::NONE;
|
return Mummy::Direction::NONE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,19 +205,19 @@ void Player::readWhipBlock(const fkyaml::node& yaml) {
|
|||||||
void Player::applyCardinal(Cardinal c) {
|
void Player::applyCardinal(Cardinal c) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case Cardinal::NORTH:
|
case Cardinal::NORTH:
|
||||||
facing_ = Facing::UP;
|
facing_ = Facing::NORTH;
|
||||||
setFlip(SDL_FLIP_NONE);
|
setFlip(SDL_FLIP_NONE);
|
||||||
break;
|
break;
|
||||||
case Cardinal::SOUTH:
|
case Cardinal::SOUTH:
|
||||||
facing_ = Facing::DOWN;
|
facing_ = Facing::SOUTH;
|
||||||
setFlip(SDL_FLIP_NONE);
|
setFlip(SDL_FLIP_NONE);
|
||||||
break;
|
break;
|
||||||
case Cardinal::EAST:
|
case Cardinal::EAST:
|
||||||
facing_ = Facing::SIDE;
|
facing_ = Facing::EAST;
|
||||||
setFlip(SDL_FLIP_NONE);
|
setFlip(SDL_FLIP_NONE);
|
||||||
break;
|
break;
|
||||||
case Cardinal::WEST:
|
case Cardinal::WEST:
|
||||||
facing_ = Facing::SIDE;
|
facing_ = Facing::EAST;
|
||||||
setFlip(SDL_FLIP_HORIZONTAL);
|
setFlip(SDL_FLIP_HORIZONTAL);
|
||||||
break;
|
break;
|
||||||
case Cardinal::NONE:
|
case Cardinal::NONE:
|
||||||
@@ -236,10 +236,10 @@ auto Player::cardinalFromInput(float vx, float vy) -> Cardinal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto Player::cardinalFromString(const std::string& s) -> Cardinal {
|
auto Player::cardinalFromString(const std::string& s) -> Cardinal {
|
||||||
if (s == "north" || s == "up") { return Cardinal::NORTH; }
|
if (s == "north") { return Cardinal::NORTH; }
|
||||||
if (s == "south" || s == "down") { return Cardinal::SOUTH; }
|
if (s == "south") { return Cardinal::SOUTH; }
|
||||||
if (s == "east" || s == "right") { return Cardinal::EAST; }
|
if (s == "east") { return Cardinal::EAST; }
|
||||||
if (s == "west" || s == "left") { return Cardinal::WEST; }
|
if (s == "west") { return Cardinal::WEST; }
|
||||||
throw std::runtime_error("Player: cardinal desconegut '" + s + "' al bloc turn.transitions");
|
throw std::runtime_error("Player: cardinal desconegut '" + s + "' al bloc turn.transitions");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,15 +314,15 @@ void Player::updateFacingAndTurn(float delta_time, float vx, float vy) {
|
|||||||
applyCardinal(intermediate_cardinal_);
|
applyCardinal(intermediate_cardinal_);
|
||||||
} else if (vx != 0.0F) {
|
} else if (vx != 0.0F) {
|
||||||
// Tria de facing original: prevalença lateral, flip segons el
|
// Tria de facing original: prevalença lateral, flip segons el
|
||||||
// signe de vx; verticals purs van a UP/DOWN amb flip NONE; en
|
// signe de vx; verticals purs van a NORTH/SOUTH amb flip NONE;
|
||||||
// aturar-se conservem `facing_` per a l'animació stand.
|
// en aturar-se conservem `facing_` per a l'animació stand.
|
||||||
facing_ = Facing::SIDE;
|
facing_ = Facing::EAST;
|
||||||
setFlip(vx < 0.0F ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE);
|
setFlip(vx < 0.0F ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE);
|
||||||
} else if (vy < 0.0F) {
|
} else if (vy < 0.0F) {
|
||||||
facing_ = Facing::UP;
|
facing_ = Facing::NORTH;
|
||||||
setFlip(SDL_FLIP_NONE);
|
setFlip(SDL_FLIP_NONE);
|
||||||
} else if (vy > 0.0F) {
|
} else if (vy > 0.0F) {
|
||||||
facing_ = Facing::DOWN;
|
facing_ = Facing::SOUTH;
|
||||||
setFlip(SDL_FLIP_NONE);
|
setFlip(SDL_FLIP_NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -342,11 +342,11 @@ Player::Player(const std::string& anim_key, int id, float x, float y, const Cont
|
|||||||
paint_tile_index_(paint_tile_index) {
|
paint_tile_index_(paint_tile_index) {
|
||||||
setPos(x, y);
|
setPos(x, y);
|
||||||
// Postura inicial mirant cap al jugador (cara avall), no de costat:
|
// Postura inicial mirant cap al jugador (cara avall), no de costat:
|
||||||
// forcem facing_ a DOWN i l'animació `stand_down` abans del primer
|
// forcem facing_ a SOUTH i l'animació `stand_south` abans del primer
|
||||||
// frame d'input — el primer `update` la preservarà si l'usuari no
|
// frame d'input — el primer `update` la preservarà si l'usuari no
|
||||||
// prem cap tecla.
|
// prem cap tecla.
|
||||||
facing_ = Facing::DOWN;
|
facing_ = Facing::SOUTH;
|
||||||
setCurrentAnimation("stand_down");
|
setCurrentAnimation("stand_south");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::update(float delta_time) {
|
void Player::update(float delta_time) {
|
||||||
@@ -650,11 +650,11 @@ auto Player::consumeAttackEdge() -> bool {
|
|||||||
|
|
||||||
auto Player::currentFacingCardinal() const -> Cardinal {
|
auto Player::currentFacingCardinal() const -> Cardinal {
|
||||||
switch (facing_) {
|
switch (facing_) {
|
||||||
case Facing::UP:
|
case Facing::NORTH:
|
||||||
return Cardinal::NORTH;
|
return Cardinal::NORTH;
|
||||||
case Facing::DOWN:
|
case Facing::SOUTH:
|
||||||
return Cardinal::SOUTH;
|
return Cardinal::SOUTH;
|
||||||
case Facing::SIDE:
|
case Facing::EAST:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Lateral: el flip discrimina E/W. Sense flip = mira a la dreta
|
// Lateral: el flip discrimina E/W. Sense flip = mira a la dreta
|
||||||
@@ -725,7 +725,7 @@ void Player::startJump() {
|
|||||||
// Un gir de 180° en curs es compromet immediatament: si l'usuari
|
// Un gir de 180° en curs es compromet immediatament: si l'usuari
|
||||||
// ha disparat un giro (oest→est, p.ex.) i salta abans que s'esgote
|
// ha disparat un giro (oest→est, p.ex.) i salta abans que s'esgote
|
||||||
// el timer, l'animació del salt ha de mostrar la direcció final
|
// el timer, l'animació del salt ha de mostrar la direcció final
|
||||||
// (jump lateral), no la intermèdia (jump_down). Aplem el pending
|
// (jump lateral), no la intermèdia (jump_south). Aplem el pending
|
||||||
// ara mateix i resetem l'estat del gir. Si no hi havia gir en
|
// ara mateix i resetem l'estat del gir. Si no hi havia gir en
|
||||||
// curs, és no-op.
|
// curs, és no-op.
|
||||||
if (turning_remaining_ms_ > 0.0F) {
|
if (turning_remaining_ms_ > 0.0F) {
|
||||||
@@ -1112,42 +1112,42 @@ auto Player::animationName(bool moving) const -> const char* {
|
|||||||
// salt és per direcció, no per velocitat.
|
// salt és per direcció, no per velocitat.
|
||||||
if (state_ == State::AIRBORNE) {
|
if (state_ == State::AIRBORNE) {
|
||||||
switch (facing_) {
|
switch (facing_) {
|
||||||
case Facing::UP:
|
case Facing::NORTH:
|
||||||
return "jump_up";
|
return "jump_north";
|
||||||
case Facing::DOWN:
|
case Facing::SOUTH:
|
||||||
return "jump_down";
|
return "jump_south";
|
||||||
case Facing::SIDE:
|
case Facing::EAST:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return "jump";
|
return "jump_east";
|
||||||
}
|
}
|
||||||
// En LANDING_STUN, `stun_*` (per direcció): mostrem el frame
|
// En LANDING_STUN, `stun_*` (per direcció): mostrem el frame
|
||||||
// d'aterratge fins que s'esgota el timer. La direcció ve fixada del
|
// d'aterratge fins que s'esgota el timer. La direcció ve fixada del
|
||||||
// moment del despegue (no es canvia mentre estem en l'aire).
|
// moment del despegue (no es canvia mentre estem en l'aire).
|
||||||
if (state_ == State::LANDING_STUN) {
|
if (state_ == State::LANDING_STUN) {
|
||||||
switch (facing_) {
|
switch (facing_) {
|
||||||
case Facing::UP:
|
case Facing::NORTH:
|
||||||
return "stun_up";
|
return "stun_north";
|
||||||
case Facing::DOWN:
|
case Facing::SOUTH:
|
||||||
return "stun_down";
|
return "stun_south";
|
||||||
case Facing::SIDE:
|
case Facing::EAST:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return "stun";
|
return "stun_east";
|
||||||
}
|
}
|
||||||
// En HURT, `hurt_*` (per direcció): el jugador llisca sense
|
// En HURT, `hurt_*` (per direcció): el jugador llisca sense
|
||||||
// control en la direcció triada per `enterHurt`. Mateixa estructura
|
// control en la direcció triada per `enterHurt`. Mateixa estructura
|
||||||
// que walk per facilitat (ara mateix els frames són clons).
|
// que walk per facilitat (ara mateix els frames són clons).
|
||||||
if (state_ == State::HURT) {
|
if (state_ == State::HURT) {
|
||||||
switch (facing_) {
|
switch (facing_) {
|
||||||
case Facing::UP:
|
case Facing::NORTH:
|
||||||
return "hurt_up";
|
return "hurt_north";
|
||||||
case Facing::DOWN:
|
case Facing::SOUTH:
|
||||||
return "hurt_down";
|
return "hurt_south";
|
||||||
case Facing::SIDE:
|
case Facing::EAST:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return "hurt";
|
return "hurt_east";
|
||||||
}
|
}
|
||||||
// ATTACKING té dues sub-fases: durant `swing_ms` el sprite és
|
// ATTACKING té dues sub-fases: durant `swing_ms` el sprite és
|
||||||
// `attack_*` (animació del braç llançant el látigo); durant
|
// `attack_*` (animació del braç llançant el látigo); durant
|
||||||
@@ -1161,34 +1161,34 @@ auto Player::animationName(bool moving) const -> const char* {
|
|||||||
const bool IN_SWING = (attacking_remaining_ms_ > static_cast<float>(whip_config.cooldown_ms));
|
const bool IN_SWING = (attacking_remaining_ms_ > static_cast<float>(whip_config.cooldown_ms));
|
||||||
if (IN_SWING) {
|
if (IN_SWING) {
|
||||||
switch (facing_) {
|
switch (facing_) {
|
||||||
case Facing::UP:
|
case Facing::NORTH:
|
||||||
return "attack_up";
|
return "attack_north";
|
||||||
case Facing::DOWN:
|
case Facing::SOUTH:
|
||||||
return "attack_down";
|
return "attack_south";
|
||||||
case Facing::SIDE:
|
case Facing::EAST:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return "attack";
|
return "attack_east";
|
||||||
}
|
}
|
||||||
switch (facing_) {
|
switch (facing_) {
|
||||||
case Facing::UP:
|
case Facing::NORTH:
|
||||||
return "recover_up";
|
return "recover_north";
|
||||||
case Facing::DOWN:
|
case Facing::SOUTH:
|
||||||
return "recover_down";
|
return "recover_south";
|
||||||
case Facing::SIDE:
|
case Facing::EAST:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return "recover";
|
return "recover_east";
|
||||||
}
|
}
|
||||||
switch (facing_) {
|
switch (facing_) {
|
||||||
case Facing::UP:
|
case Facing::NORTH:
|
||||||
return moving ? "walk_up" : "stand_up";
|
return moving ? "walk_north" : "stand_north";
|
||||||
case Facing::DOWN:
|
case Facing::SOUTH:
|
||||||
return moving ? "walk_down" : "stand_down";
|
return moving ? "walk_south" : "stand_south";
|
||||||
case Facing::SIDE:
|
case Facing::EAST:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return moving ? "walk" : "stand";
|
return moving ? "walk_east" : "stand_east";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Player::getCurrentTile() const -> std::pair<int, int> {
|
auto Player::getCurrentTile() const -> std::pair<int, int> {
|
||||||
@@ -1249,11 +1249,11 @@ void Player::respawn(float x, float y) {
|
|||||||
intermediate_cardinal_ = Cardinal::NONE;
|
intermediate_cardinal_ = Cardinal::NONE;
|
||||||
last_input_cardinal_ = Cardinal::NONE;
|
last_input_cardinal_ = Cardinal::NONE;
|
||||||
// Reseteig del facing al d'spawn original (mirant cap a la càmera):
|
// Reseteig del facing al d'spawn original (mirant cap a la càmera):
|
||||||
// sense això, un EXITED que entrava per la porta amb facing UP
|
// 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.
|
// re-aparix d'esquena al pròxim cicle. Mateixa lògica que el ctor.
|
||||||
facing_ = Facing::DOWN;
|
facing_ = Facing::SOUTH;
|
||||||
setFlip(SDL_FLIP_NONE);
|
setFlip(SDL_FLIP_NONE);
|
||||||
setCurrentAnimation("stand_down");
|
setCurrentAnimation("stand_south");
|
||||||
setPosX(x);
|
setPosX(x);
|
||||||
setPosY(y);
|
setPosY(y);
|
||||||
}
|
}
|
||||||
@@ -1300,10 +1300,10 @@ void Player::spawnFromAir(float x, float y) {
|
|||||||
intended_vy_ = 0.0F;
|
intended_vy_ = 0.0F;
|
||||||
|
|
||||||
// Mirant cap avall durant la caiguda — `animationName(AIRBORNE)` amb
|
// Mirant cap avall durant la caiguda — `animationName(AIRBORNE)` amb
|
||||||
// facing DOWN ja resol a `jump_down`. `respawn` ja ha posat facing a
|
// facing SOUTH ja resol a `jump_south`. `respawn` ja ha posat facing a
|
||||||
// DOWN; ho deixem explícit ací per claredat de la cinemàtica.
|
// SOUTH; ho deixem explícit ací per claredat de la cinemàtica.
|
||||||
facing_ = Facing::DOWN;
|
facing_ = Facing::SOUTH;
|
||||||
setCurrentAnimation("jump_down");
|
setCurrentAnimation("jump_south");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Player::getBaseBox() const -> SDL_FRect {
|
auto Player::getBaseBox() const -> SDL_FRect {
|
||||||
|
|||||||
@@ -430,13 +430,15 @@ class Player : public AnimatedSprite {
|
|||||||
|
|
||||||
// Direcció "cap on mira" el jugador. Governa quin conjunt d'animacions
|
// Direcció "cap on mira" el jugador. Governa quin conjunt d'animacions
|
||||||
// s'aplica (lateral, amunt, avall) i si el sprite es flipeja o no. Els
|
// s'aplica (lateral, amunt, avall) i si el sprite es flipeja o no. Els
|
||||||
// moviments purament horitzontals o diagonals prenen `SIDE` (prevalença
|
// moviments purament horitzontals o diagonals prenen `EAST` (prevalença
|
||||||
// lateral), els purament verticals fan `UP`/`DOWN`. En aturar-se es
|
// lateral; el flip horitzontal converteix l'animació EAST en la
|
||||||
// preserva l'última orientació perquè la versió stand coincideixi.
|
// simètrica oest), els purament verticals fan `NORTH`/`SOUTH`. En
|
||||||
enum class Facing : std::uint8_t { SIDE,
|
// aturar-se es preserva l'última orientació perquè la versió stand
|
||||||
UP,
|
// coincideixi.
|
||||||
DOWN };
|
enum class Facing : std::uint8_t { EAST,
|
||||||
Facing facing_{Facing::SIDE};
|
NORTH,
|
||||||
|
SOUTH };
|
||||||
|
Facing facing_{Facing::EAST};
|
||||||
|
|
||||||
// Cardinal complet (N/S/E/W) usat per a la detecció de girs de 180°.
|
// Cardinal complet (N/S/E/W) usat per a la detecció de girs de 180°.
|
||||||
// El parell (Facing, flip) només té 3+1 estats; aquesta enum n'afegeix
|
// El parell (Facing, flip) només té 3+1 estats; aquesta enum n'afegeix
|
||||||
@@ -553,8 +555,8 @@ class Player : public AnimatedSprite {
|
|||||||
void enterAttacking(Cardinal facing);
|
void enterAttacking(Cardinal facing);
|
||||||
|
|
||||||
// Cardinal que correspon al `(facing_, flip_)` actual del sprite —
|
// Cardinal que correspon al `(facing_, flip_)` actual del sprite —
|
||||||
// la direcció cap on mira el jugador. Si `facing_ == SIDE` el
|
// la direcció cap on mira el jugador. Si `facing_ == EAST` el
|
||||||
// resultat depèn del flip; UP/DOWN són trivials. Mai retorna NONE.
|
// resultat depèn del flip; NORTH/SOUTH són trivials. Mai retorna NONE.
|
||||||
[[nodiscard]] auto currentFacingCardinal() const -> Cardinal;
|
[[nodiscard]] auto currentFacingCardinal() const -> Cardinal;
|
||||||
|
|
||||||
// Activa l'estat HURT: el jugador queda projectat amb velocitat
|
// Activa l'estat HURT: el jugador queda projectat amb velocitat
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ namespace {
|
|||||||
|
|
||||||
// Direcció preferida: dreta. Mòmia ha d'entrar en HURT i avançar
|
// Direcció preferida: dreta. Mòmia ha d'entrar en HURT i avançar
|
||||||
// a la dreta (la velocitat de hurt és més alta que la base).
|
// a la dreta (la velocitat de hurt és més alta que la base).
|
||||||
mummy.enterHurt(Mummy::Direction::RIGHT);
|
mummy.enterHurt(Mummy::Direction::EAST);
|
||||||
REQUIRE(mummy.getState() == Mummy::State::HURT);
|
REQUIRE(mummy.getState() == Mummy::State::HURT);
|
||||||
REQUIRE(mummy.getDirX() > 0.0F);
|
REQUIRE(mummy.getDirX() > 0.0F);
|
||||||
|
|
||||||
@@ -488,7 +488,7 @@ namespace {
|
|||||||
// timer. Aquesta variant del test NO comprova la sortida
|
// timer. Aquesta variant del test NO comprova la sortida
|
||||||
// per col·lisió; només verifica que entrar a HURT a la
|
// per col·lisió; només verifica que entrar a HURT a la
|
||||||
// paret no peta.
|
// paret no peta.
|
||||||
mummy.enterHurt(Mummy::Direction::RIGHT);
|
mummy.enterHurt(Mummy::Direction::EAST);
|
||||||
REQUIRE(mummy.getState() == Mummy::State::HURT);
|
REQUIRE(mummy.getState() == Mummy::State::HURT);
|
||||||
// Update llarg → expira el timer i torna a ROAMING.
|
// Update llarg → expira el timer i torna a ROAMING.
|
||||||
mummy.update(1.0F);
|
mummy.update(1.0F);
|
||||||
|
|||||||
Reference in new issue
Block a user