refactor: extreure helpers per reduir complexitat cognitiva (tidy net)

This commit is contained in:
2026-05-16 16:13:57 +02:00
parent b984e6041e
commit e1bc1b597f
31 changed files with 1145 additions and 1332 deletions
+12 -12
View File
@@ -6,7 +6,7 @@
Bola::Bola(Jd8::Surface gfx, Prota* sam)
: Sprite(gfx) {
this->sam = sam;
this->sam_ = sam;
entitat.frames.reserve(2);
entitat.frames.push_back({30, 155, 15, 15});
@@ -17,28 +17,28 @@ Bola::Bola(Jd8::Surface gfx, Prota* sam)
this->cur_frame = 0;
this->o = 0;
this->cycles_per_frame = 4;
this->cycles_per_frame_ = 4;
this->x = 20;
this->y = 100;
this->contador = 0;
this->contador_ = 0;
}
void Bola::draw() {
if (this->contador == 0) {
if (this->contador_ == 0) {
Sprite::draw();
}
}
void Bola::update() {
if (this->contador == 0) {
if (this->contador_ == 0) {
// Augmentem la x
this->x++;
if (this->x == 280) {
this->contador = 200;
this->contador_ = 200;
}
// Augmentem el frame
if (Jg::getCycleCounter() % this->cycles_per_frame == 0) {
if (Jg::getCycleCounter() % this->cycles_per_frame_ == 0) {
this->cur_frame++;
if (this->cur_frame == entitat.animacions[this->o].frames.size()) {
this->cur_frame = 0;
@@ -46,16 +46,16 @@ void Bola::update() {
}
// Comprovem si ha tocat a Sam
if (this->x > (this->sam->x - 7) && this->x < (this->sam->x + 7) && this->y > (this->sam->y - 7) && this->y < (this->sam->y + 7)) {
this->contador = 200;
if (this->x > (this->sam_->x - 7) && this->x < (this->sam_->x + 7) && this->y > (this->sam_->y - 7) && this->y < (this->sam_->y + 7)) {
this->contador_ = 200;
Info::ctx.vida--;
if (Info::ctx.vida == 0) {
this->sam->o = 5;
this->sam_->o = 5;
}
}
} else {
this->contador--;
if (this->contador == 0) {
this->contador_--;
if (this->contador_ == 0) {
this->x = 20;
}
}
+2 -2
View File
@@ -12,6 +12,6 @@ class Bola : public Sprite {
void update();
protected:
Uint8 contador;
Prota* sam;
Uint8 contador_;
Prota* sam_;
};
+5 -5
View File
@@ -22,25 +22,25 @@ Engendro::Engendro(Jd8::Surface gfx, Uint16 x, Uint16 y)
entitat.animacions[0].frames = {0, 1, 2, 3, 2, 1};
this->cur_frame = 0;
this->vida = 18;
this->vida_ = 18;
this->x = x;
this->y = y;
this->o = 0;
this->cycles_per_frame = 30;
this->cycles_per_frame_ = 30;
}
auto Engendro::update() -> bool {
bool mort = false;
if (Jg::getCycleCounter() % this->cycles_per_frame == 0) {
if (Jg::getCycleCounter() % this->cycles_per_frame_ == 0) {
this->cur_frame++;
if (this->cur_frame == entitat.animacions[this->o].frames.size()) {
this->cur_frame = 0;
}
this->vida--;
this->vida_--;
}
if (vida == 0) {
if (vida_ == 0) {
mort = true;
}
+1 -1
View File
@@ -9,5 +9,5 @@ class Engendro : public Sprite {
auto update() -> bool;
protected:
Uint8 vida;
Uint8 vida_;
};
+1 -1
View File
@@ -247,7 +247,7 @@ void Mapa::comprovaCaixa(Uint8 num) {
}
// Si algun costat encara no està passat, no hi ha res que fer
if (std::any_of(std::begin(this->tombes[num].costat), std::end(this->tombes[num].costat), [](bool c) { return !c; })) {
if (std::ranges::any_of(this->tombes[num].costat, [](bool c) { return !c; })) {
return;
}
+16 -16
View File
@@ -1,8 +1,8 @@
#include "game/marcador.hpp"
Marcador::Marcador(Jd8::Surface gfx, Prota* sam) {
this->gfx = gfx;
this->sam = sam;
this->gfx_ = gfx;
this->sam_ = sam;
}
void Marcador::draw() {
@@ -15,47 +15,47 @@ void Marcador::draw() {
this->pintaNumero(156, 2, (Info::ctx.diners % 100) / 10);
this->pintaNumero(163, 2, Info::ctx.diners % 10);
if (this->sam->pergami) {
Jd8::blitCK(190, 1, this->gfx, 209, 185, 15, 14, 255);
if (this->sam_->pergami) {
Jd8::blitCK(190, 1, this->gfx_, 209, 185, 15, 14, 255);
}
Jd8::blitCK(271, 1, this->gfx, 0, 20, 15, Info::ctx.vida * 3, 255);
Jd8::blitCK(271, 1, this->gfx_, 0, 20, 15, Info::ctx.vida * 3, 255);
if (Info::ctx.vida < 5) {
Jd8::blitCK(271, 1 + (Info::ctx.vida * 3), this->gfx, 75, 20, 15, 15 - (Info::ctx.vida * 3), 255);
Jd8::blitCK(271, 1 + (Info::ctx.vida * 3), this->gfx_, 75, 20, 15, 15 - (Info::ctx.vida * 3), 255);
}
}
void Marcador::pintaNumero(Uint16 x, Uint16 y, Uint8 num) {
switch (num) {
case 0:
Jd8::blitCK(x, y, this->gfx, 141, 193, 10, 7, 255);
Jd8::blitCK(x, y, this->gfx_, 141, 193, 10, 7, 255);
break;
case 1:
Jd8::blitCK(x, y, this->gfx, 100, 185, 10, 7, 255);
Jd8::blitCK(x, y, this->gfx_, 100, 185, 10, 7, 255);
break;
case 2:
Jd8::blitCK(x, y, this->gfx, 110, 185, 10, 7, 255);
Jd8::blitCK(x, y, this->gfx_, 110, 185, 10, 7, 255);
break;
case 3:
Jd8::blitCK(x, y, this->gfx, 120, 185, 10, 7, 255);
Jd8::blitCK(x, y, this->gfx_, 120, 185, 10, 7, 255);
break;
case 4:
Jd8::blitCK(x, y, this->gfx, 130, 185, 10, 7, 255);
Jd8::blitCK(x, y, this->gfx_, 130, 185, 10, 7, 255);
break;
case 5:
Jd8::blitCK(x, y, this->gfx, 140, 185, 10, 7, 255);
Jd8::blitCK(x, y, this->gfx_, 140, 185, 10, 7, 255);
break;
case 6:
Jd8::blitCK(x, y, this->gfx, 101, 193, 10, 7, 255);
Jd8::blitCK(x, y, this->gfx_, 101, 193, 10, 7, 255);
break;
case 7:
Jd8::blitCK(x, y, this->gfx, 111, 193, 10, 7, 255);
Jd8::blitCK(x, y, this->gfx_, 111, 193, 10, 7, 255);
break;
case 8:
Jd8::blitCK(x, y, this->gfx, 121, 193, 10, 7, 255);
Jd8::blitCK(x, y, this->gfx_, 121, 193, 10, 7, 255);
break;
case 9:
Jd8::blitCK(x, y, this->gfx, 131, 193, 10, 7, 255);
Jd8::blitCK(x, y, this->gfx_, 131, 193, 10, 7, 255);
break;
default:
break;
+2 -2
View File
@@ -14,6 +14,6 @@ class Marcador {
protected:
void pintaNumero(Uint16 x, Uint16 y, Uint8 num);
Jd8::Surface gfx;
Prota* sam;
Jd8::Surface gfx_;
Prota* sam_;
};
+101 -88
View File
@@ -7,7 +7,7 @@
Momia::Momia(Jd8::Surface gfx, bool dimoni, Uint16 x, Uint16 y, Prota* sam)
: Sprite(gfx) {
this->dimoni = dimoni;
this->sam = sam;
this->sam_ = sam;
entitat.frames.reserve(20);
for (int row = 0; row < 4; row++) {
@@ -43,7 +43,7 @@ Momia::Momia(Jd8::Surface gfx, bool dimoni, Uint16 x, Uint16 y, Prota* sam)
this->cur_frame = 0;
this->o = rand() % 4;
this->cycles_per_frame = 4;
this->cycles_per_frame_ = 4;
if (this->dimoni) {
if (x == 0) {
@@ -52,7 +52,7 @@ Momia::Momia(Jd8::Surface gfx, bool dimoni, Uint16 x, Uint16 y, Prota* sam)
this->x = x;
}
if (y == 0) {
if (this->sam->y > 100) {
if (this->sam_->y > 100) {
this->y = 30;
} else {
this->y = 170;
@@ -60,7 +60,7 @@ Momia::Momia(Jd8::Surface gfx, bool dimoni, Uint16 x, Uint16 y, Prota* sam)
} else {
this->y = y;
}
this->engendro = std::make_unique<Engendro>(gfx, this->x, this->y);
this->engendro_ = std::make_unique<Engendro>(gfx, this->x, this->y);
} else {
this->x = x;
this->y = y;
@@ -68,104 +68,117 @@ Momia::Momia(Jd8::Surface gfx, bool dimoni, Uint16 x, Uint16 y, Prota* sam)
}
void Momia::draw() {
if (this->engendro) {
this->engendro->draw();
if (this->engendro_) {
this->engendro_->draw();
} else {
Sprite::draw();
if (Info::ctx.num_piramide == 4) {
if ((Jg::getCycleCounter() % 40) < 20) {
Jd8::blitCK(this->x, this->y, this->gfx, 220, 80, 15, 15, 255);
Jd8::blitCK(this->x, this->y, this->gfx_, 220, 80, 15, 15, 255);
} else {
Jd8::blitCK(this->x, this->y, this->gfx, 235, 80, 15, 15, 255);
Jd8::blitCK(this->x, this->y, this->gfx_, 235, 80, 15, 15, 255);
}
}
}
}
void Momia::pickHorizontalThenVertical() {
if (this->x > this->sam_->x) {
this->o = 3;
} else if (this->x < this->sam_->x) {
this->o = 2;
} else if (this->y < this->sam_->y) {
this->o = 0;
} else if (this->y > this->sam_->y) {
this->o = 1;
}
}
void Momia::pickVerticalThenHorizontal() {
if (this->y < this->sam_->y) {
this->o = 0;
} else if (this->y > this->sam_->y) {
this->o = 1;
} else if (this->x > this->sam_->x) {
this->o = 3;
} else if (this->x < this->sam_->x) {
this->o = 2;
}
}
void Momia::pickDirection() {
if (!this->dimoni) {
this->o = rand() % 4;
return;
}
if (rand() % 2 == 0) {
pickHorizontalThenVertical();
} else {
pickVerticalThenHorizontal();
}
}
void Momia::stepInDirection() {
switch (this->o) {
case 0:
if (y < 170) { this->y++; }
break;
case 1:
if (y > 30) { this->y--; }
break;
case 2:
if (x < 280) { this->x++; }
break;
case 3:
if (x > 20) { this->x--; }
break;
default:
break;
}
}
auto Momia::collidesWithSam() const -> bool {
return this->x > (this->sam_->x - 7) && this->x < (this->sam_->x + 7) &&
this->y > (this->sam_->y - 7) && this->y < (this->sam_->y + 7);
}
void Momia::applyCollisionWithSam() {
if (this->sam_->pergami) {
this->sam_->pergami = false;
return;
}
Info::ctx.vida--;
if (Info::ctx.vida == 0) {
this->sam_->o = 5;
}
}
auto Momia::update() -> bool {
bool morta = false;
if (this->engendro) {
if (this->engendro->update()) {
this->engendro.reset();
if (this->engendro_) {
if (this->engendro_->update()) {
this->engendro_.reset();
}
return morta;
return false;
}
if (this->sam->o < 4 && (this->dimoni || Info::ctx.num_piramide == 5 || Jg::getCycleCounter() % 2 == 0)) {
if ((this->x - 20) % 65 == 0 && (this->y - 30) % 35 == 0) {
if (this->dimoni) {
if (rand() % 2 == 0) {
if (this->x > this->sam->x) {
this->o = 3;
} else if (this->x < this->sam->x) {
this->o = 2;
} else if (this->y < this->sam->y) {
this->o = 0;
} else if (this->y > this->sam->y) {
this->o = 1;
}
} else {
if (this->y < this->sam->y) {
this->o = 0;
} else if (this->y > this->sam->y) {
this->o = 1;
} else if (this->x > this->sam->x) {
this->o = 3;
} else if (this->x < this->sam->x) {
this->o = 2;
}
}
} else {
this->o = rand() % 4;
}
}
switch (this->o) {
case 0:
if (y < 170) {
this->y++;
}
break;
case 1:
if (y > 30) {
this->y--;
}
break;
case 2:
if (x < 280) {
this->x++;
}
break;
case 3:
if (x > 20) {
this->x--;
}
break;
default:
break;
}
if (Jg::getCycleCounter() % this->cycles_per_frame == 0) {
this->cur_frame++;
if (this->cur_frame == entitat.animacions[this->o].frames.size()) {
this->cur_frame = 0;
}
}
if (this->x > (this->sam->x - 7) && this->x < (this->sam->x + 7) && this->y > (this->sam->y - 7) && this->y < (this->sam->y + 7)) {
morta = true;
if (this->sam->pergami) {
this->sam->pergami = false;
} else {
Info::ctx.vida--;
if (Info::ctx.vida == 0) {
this->sam->o = 5;
}
}
const bool SAM_ALIVE = this->sam_->o < 4;
const bool MAY_STEP = this->dimoni || Info::ctx.num_piramide == 5 || Jg::getCycleCounter() % 2 == 0;
if (!SAM_ALIVE || !MAY_STEP) {
return false;
}
if ((this->x - 20) % 65 == 0 && (this->y - 30) % 35 == 0) {
pickDirection();
}
stepInDirection();
if (Jg::getCycleCounter() % this->cycles_per_frame_ == 0) {
this->cur_frame++;
if (this->cur_frame == entitat.animacions[this->o].frames.size()) {
this->cur_frame = 0;
}
}
return morta;
if (collidesWithSam()) {
applyCollisionWithSam();
return true;
}
return false;
}
+9 -2
View File
@@ -17,6 +17,13 @@ class Momia : public Sprite {
bool dimoni;
protected:
Prota* sam;
std::unique_ptr<Engendro> engendro;
Prota* sam_;
std::unique_ptr<Engendro> engendro_;
void pickDirection();
void pickHorizontalThenVertical();
void pickVerticalThenHorizontal();
void stepInDirection();
[[nodiscard]] auto collidesWithSam() const -> bool;
void applyCollisionWithSam();
};
+27 -37
View File
@@ -437,7 +437,7 @@ namespace Options {
return true;
}
// --- Helper per a parsejar floats de YAML ---
// --- Helpers per a parsejar camps de YAML ---
static void parseFloatField(const fkyaml::node& node, const std::string& key, float& target) {
if (node.contains(key)) {
try {
@@ -448,6 +448,26 @@ namespace Options {
}
}
static void parseIntField(const fkyaml::node& node, const std::string& key, int& target) {
if (node.contains(key)) {
try {
target = node[key].get_value<int>();
} catch (...) {
// @INTENTIONAL: camp YAML no és int vàlid, mantenim valor per defecte.
}
}
}
static void parseBoolField(const fkyaml::node& node, const std::string& key, bool& target) {
if (node.contains(key)) {
try {
target = node[key].get_value<bool>();
} catch (...) {
// @INTENTIONAL: camp YAML no és bool vàlid, mantenim valor per defecte.
}
}
}
// --- Presets PostFX ---
void setPostFXFile(const std::string& path) { postfx_file_path = path; }
@@ -561,42 +581,12 @@ namespace Options {
parseFloatField(p, "mask_brightness", preset.mask_brightness);
parseFloatField(p, "curvature_x", preset.curvature_x);
parseFloatField(p, "curvature_y", preset.curvature_y);
if (p.contains("mask_type")) {
try {
preset.mask_type = p["mask_type"].get_value<int>();
} catch (...) { /* @INTENTIONAL: camp YAML invàlid, mantenim el valor per defecte. */
}
}
if (p.contains("enable_scanlines")) {
try {
preset.enable_scanlines = p["enable_scanlines"].get_value<bool>();
} catch (...) { /* @INTENTIONAL: camp YAML invàlid, mantenim el valor per defecte. */
}
}
if (p.contains("enable_multisample")) {
try {
preset.enable_multisample = p["enable_multisample"].get_value<bool>();
} catch (...) { /* @INTENTIONAL: camp YAML invàlid, mantenim el valor per defecte. */
}
}
if (p.contains("enable_gamma")) {
try {
preset.enable_gamma = p["enable_gamma"].get_value<bool>();
} catch (...) { /* @INTENTIONAL: camp YAML invàlid, mantenim el valor per defecte. */
}
}
if (p.contains("enable_curvature")) {
try {
preset.enable_curvature = p["enable_curvature"].get_value<bool>();
} catch (...) { /* @INTENTIONAL: camp YAML invàlid, mantenim el valor per defecte. */
}
}
if (p.contains("enable_sharper")) {
try {
preset.enable_sharper = p["enable_sharper"].get_value<bool>();
} catch (...) { /* @INTENTIONAL: camp YAML invàlid, mantenim el valor per defecte. */
}
}
parseIntField(p, "mask_type", preset.mask_type);
parseBoolField(p, "enable_scanlines", preset.enable_scanlines);
parseBoolField(p, "enable_multisample", preset.enable_multisample);
parseBoolField(p, "enable_gamma", preset.enable_gamma);
parseBoolField(p, "enable_curvature", preset.enable_curvature);
parseBoolField(p, "enable_sharper", preset.enable_sharper);
crtpi_presets.push_back(preset);
}
}
+132 -148
View File
@@ -5,84 +5,75 @@
#include "core/jail/jgame.hpp"
#include "core/jail/jinput.hpp"
Prota::Prota(Jd8::Surface gfx)
: Sprite(gfx) {
entitat.frames.reserve(82);
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 5; x++) {
Frame f;
f.w = 15;
f.h = 15;
if (Info::ctx.num_piramide == 4) {
f.h -= 5;
}
f.x = x * 15;
f.y = 20 + (y * 15);
entitat.frames.push_back(f);
}
namespace {
// Atura el frame.h a 10 quan piràmide 4 (sprite "petit" amb pijama de presoner).
auto adjustedHeight(int base_h) -> int {
return (Info::ctx.num_piramide == 4) ? base_h - 5 : base_h;
}
for (int y = 95; y < 185; y += 30) {
for (int x = 60; x < 315; x += 15) {
if (x != 300 || y != 155) {
Frame f;
f.w = 15;
f.h = 30;
if (Info::ctx.num_piramide == 4) {
f.h -= 5;
void addFrameGrid(Entitat& entitat, int x0, int x1, int x_step, int y0, int y1, int y_step, int w, int h, int skip_x = -1, int skip_y = -1) {
for (int yy = y0; yy < y1; yy += y_step) {
for (int xx = x0; xx < x1; xx += x_step) {
if (xx == skip_x && yy == skip_y) {
continue;
}
f.x = x;
f.y = y;
Frame f;
f.w = w;
f.h = adjustedHeight(h);
f.x = xx;
f.y = yy;
entitat.frames.push_back(f);
}
}
}
for (int y = 20; y < 50; y += 15) {
for (int x = 225; x < 315; x += 15) {
Frame f;
f.w = 15;
f.h = 15;
if (Info::ctx.num_piramide == 4) {
f.h -= 5;
}
f.x = x;
f.y = y;
entitat.frames.push_back(f);
void buildProtaFrames(Entitat& entitat) {
entitat.frames.reserve(82);
// Cara/quatre direccions (4×5 sprites de 15×15 a y=20..)
addFrameGrid(entitat, 0, 75, 15, 20, 80, 15, 15, 15);
// Animació de mort (15×30 a y=95..; salta x=300/y=155)
addFrameGrid(entitat, 60, 315, 15, 95, 185, 30, 15, 30, 300, 155);
// Animació de victòria (15×15 a y=20.., x=225..)
addFrameGrid(entitat, 225, 315, 15, 20, 50, 15, 15, 15);
}
void buildProtaAnimations(Entitat& entitat) {
entitat.animacions.resize(6);
for (int i = 0; i < 4; i++) {
entitat.animacions[i].frames = {
static_cast<Uint8>(0 + (i * 5)),
static_cast<Uint8>(1 + (i * 5)),
static_cast<Uint8>(2 + (i * 5)),
static_cast<Uint8>(1 + (i * 5)),
static_cast<Uint8>(0 + (i * 5)),
static_cast<Uint8>(3 + (i * 5)),
static_cast<Uint8>(4 + (i * 5)),
static_cast<Uint8>(3 + (i * 5)),
};
}
entitat.animacions[4].frames.resize(50);
for (int i = 0; i < 50; i++) {
entitat.animacions[4].frames[i] = i + 20;
}
entitat.animacions[5].frames.resize(48);
for (int i = 0; i < 12; i++) {
entitat.animacions[5].frames[i] = i + 70;
}
for (int i = 12; i < 48; i++) {
entitat.animacions[5].frames[i] = 81;
}
}
} // namespace
entitat.animacions.resize(6);
for (int i = 0; i < 4; i++) {
entitat.animacions[i].frames = {
static_cast<Uint8>(0 + (i * 5)),
static_cast<Uint8>(1 + (i * 5)),
static_cast<Uint8>(2 + (i * 5)),
static_cast<Uint8>(1 + (i * 5)),
static_cast<Uint8>(0 + (i * 5)),
static_cast<Uint8>(3 + (i * 5)),
static_cast<Uint8>(4 + (i * 5)),
static_cast<Uint8>(3 + (i * 5)),
};
}
entitat.animacions[4].frames.resize(50);
for (int i = 0; i < 50; i++) {
entitat.animacions[4].frames[i] = i + 20;
}
entitat.animacions[5].frames.resize(48);
for (int i = 0; i < 12; i++) {
entitat.animacions[5].frames[i] = i + 70;
}
for (int i = 12; i < 48; i++) {
entitat.animacions[5].frames[i] = 81;
}
Prota::Prota(Jd8::Surface gfx)
: Sprite(gfx) {
buildProtaFrames(entitat);
buildProtaAnimations(entitat);
cur_frame = 0;
x = 150;
y = 30;
o = 0;
cycles_per_frame = 4;
cycles_per_frame_ = 4;
pergami = false;
frame_pejades = 0;
}
@@ -92,94 +83,87 @@ void Prota::draw() {
if (Info::ctx.num_piramide == 4 && this->o != 4) {
if ((Jg::getCycleCounter() % 40) < 20) {
Jd8::blitCK(this->x, this->y, this->gfx, 220, 80, 15, 15, 255);
Jd8::blitCK(this->x, this->y, this->gfx_, 220, 80, 15, 15, 255);
} else {
Jd8::blitCK(this->x, this->y, this->gfx, 235, 80, 15, 15, 255);
Jd8::blitCK(this->x, this->y, this->gfx_, 235, 80, 15, 15, 255);
}
}
}
auto Prota::readDirection() -> Uint8 {
Uint8 dir = 4;
if (Ji::keyPressed(SDL_SCANCODE_DOWN)) {
if ((this->x - 20) % 65 == 0) { this->o = 0; }
dir = this->o;
}
if (Ji::keyPressed(SDL_SCANCODE_UP)) {
if ((this->x - 20) % 65 == 0) { this->o = 1; }
dir = this->o;
}
if (Ji::keyPressed(SDL_SCANCODE_RIGHT)) {
if ((this->y - 30) % 35 == 0) { this->o = 2; }
dir = this->o;
}
if (Ji::keyPressed(SDL_SCANCODE_LEFT)) {
if ((this->y - 30) % 35 == 0) { this->o = 3; }
dir = this->o;
}
return dir;
}
void Prota::stepInDirection(Uint8 dir) {
switch (dir) {
case 0:
if (this->y < 170) { this->y++; }
break;
case 1:
if (this->y > 30) { this->y--; }
break;
case 2:
if (this->x < 280) { this->x++; }
break;
case 3:
if (this->x > 20) { this->x--; }
break;
default:
break;
}
}
void Prota::advanceWalkingFrame(Uint8 dir) {
if (dir == 4) {
this->cur_frame = 0;
return;
}
this->frame_pejades++;
if (this->frame_pejades == 15) {
this->frame_pejades = 0;
}
if (Jg::getCycleCounter() % this->cycles_per_frame_ == 0) {
this->cur_frame++;
if (this->cur_frame == entitat.animacions[this->o].frames.size()) {
this->cur_frame = 0;
}
}
}
auto Prota::advanceFinalAnimation() -> Uint8 {
if (Jg::getCycleCounter() % this->cycles_per_frame_ != 0) {
return 0;
}
this->cur_frame++;
if (this->cur_frame != entitat.animacions[this->o].frames.size()) {
return 0;
}
return (this->o == 4) ? 1 : 2;
}
auto Prota::update() -> Uint8 {
Uint8 eixir = 0;
if (this->o < 4) {
Uint8 dir = 4;
if (Ji::keyPressed(SDL_SCANCODE_DOWN)) {
if ((this->x - 20) % 65 == 0) {
this->o = 0;
}
dir = this->o;
}
if (Ji::keyPressed(SDL_SCANCODE_UP)) {
if ((this->x - 20) % 65 == 0) {
this->o = 1;
}
dir = this->o;
}
if (Ji::keyPressed(SDL_SCANCODE_RIGHT)) {
if ((this->y - 30) % 35 == 0) {
this->o = 2;
}
dir = this->o;
}
if (Ji::keyPressed(SDL_SCANCODE_LEFT)) {
if ((this->y - 30) % 35 == 0) {
this->o = 3;
}
dir = this->o;
}
switch (dir) {
case 0:
if (this->y < 170) {
this->y++;
}
break;
case 1:
if (this->y > 30) {
this->y--;
}
break;
case 2:
if (this->x < 280) {
this->x++;
}
break;
case 3:
if (this->x > 20) {
this->x--;
}
break;
default:
break;
}
if (dir == 4) {
this->cur_frame = 0;
} else {
this->frame_pejades++;
if (this->frame_pejades == 15) {
this->frame_pejades = 0;
}
if (Jg::getCycleCounter() % this->cycles_per_frame == 0) {
this->cur_frame++;
if (this->cur_frame == entitat.animacions[this->o].frames.size()) {
this->cur_frame = 0;
}
}
}
eixir = 0U;
} else {
if (Jg::getCycleCounter() % this->cycles_per_frame == 0) {
this->cur_frame++;
if (this->cur_frame == entitat.animacions[this->o].frames.size()) {
if (this->o == 4) {
eixir = 1;
} else {
eixir = 2;
}
}
}
if (this->o >= 4) {
return advanceFinalAnimation();
}
return eixir;
const Uint8 DIR = readDirection();
stepInDirection(DIR);
advanceWalkingFrame(DIR);
return 0;
}
+4
View File
@@ -14,4 +14,8 @@ class Prota : public Sprite {
bool pergami;
protected:
auto readDirection() -> Uint8;
void stepInDirection(Uint8 dir);
void advanceWalkingFrame(Uint8 dir);
auto advanceFinalAnimation() -> Uint8;
};
+48 -53
View File
@@ -132,17 +132,59 @@ namespace Scenes {
}
}
void IntroNewLogoScene::advanceRevealing(int delta_ms) {
phase_acc_ms_ += delta_ms;
render();
if (phase_acc_ms_ < REVEAL_FRAME_MS) {
return;
}
phase_acc_ms_ = 0;
reveal_cursor_visible_ = !reveal_cursor_visible_;
if (!reveal_cursor_visible_) {
return;
}
++reveal_letter_;
if (reveal_letter_ >= 9) {
phase_ = Phase::FULL_LOGO_FLASH;
reveal_letter_ = 8;
}
}
void IntroNewLogoScene::advancePaletteStep(int delta_ms) {
phase_acc_ms_ += delta_ms;
while (phase_acc_ms_ >= PALETTE_CYCLE_STEP_MS && palette_step_ < PALETTE_CYCLE_STEPS) {
phase_acc_ms_ -= PALETTE_CYCLE_STEP_MS;
advancePaletteCycle();
++palette_step_;
}
render();
if (palette_step_ >= PALETTE_CYCLE_STEPS) {
phase_ = Phase::FINAL_WAIT;
phase_acc_ms_ = 0;
}
}
void IntroNewLogoScene::advanceSpritesPhase(int delta_ms) {
if (!sprites_scene_) {
sprites_scene_ = std::make_unique<IntroSpritesScene>(std::move(gfx_));
sprites_scene_->onEnter();
}
sprites_scene_->tick(delta_ms);
if (sprites_scene_->done()) {
Info::ctx.num_piramide = 0;
phase_ = Phase::DONE;
}
}
void IntroNewLogoScene::tick(int delta_ms) {
// Qualsevol tecla durant el revelat o el ciclo de paleta salta
// TOTA la intro (inclou saltar la fase de sprites). Durant SPRITES
// deixem que la sub-escena gestione el seu propi skip (que a més
// respecta la fase "final" no skippable de la variant 0).
// deixem que la sub-escena gestione el seu propi skip.
if (phase_ != Phase::SPRITES && phase_ != Phase::DONE && Ji::anyKey()) {
Info::ctx.num_piramide = 0;
phase_ = Phase::DONE;
return;
}
switch (phase_) {
case Phase::INITIAL:
phase_acc_ms_ += delta_ms;
@@ -152,25 +194,9 @@ namespace Scenes {
phase_acc_ms_ = 0;
}
break;
case Phase::REVEALING:
phase_acc_ms_ += delta_ms;
render();
if (phase_acc_ms_ >= REVEAL_FRAME_MS) {
phase_acc_ms_ = 0;
reveal_cursor_visible_ = !reveal_cursor_visible_;
// Quan acabem els dos frames d'una lletra (cursor on → off),
// passem a la següent lletra.
if (reveal_cursor_visible_) {
++reveal_letter_;
if (reveal_letter_ >= 9) {
phase_ = Phase::FULL_LOGO_FLASH;
reveal_letter_ = 8;
}
}
}
advanceRevealing(delta_ms);
break;
case Phase::FULL_LOGO_FLASH:
phase_acc_ms_ += delta_ms;
render();
@@ -179,24 +205,9 @@ namespace Scenes {
phase_acc_ms_ = 0;
}
break;
case Phase::PALETTE_CYCLE:
phase_acc_ms_ += delta_ms;
// Avancem passos de paleta cada 20 ms. Si el delta és gran,
// consumim múltiples passos en la mateixa crida.
while (phase_acc_ms_ >= PALETTE_CYCLE_STEP_MS &&
palette_step_ < PALETTE_CYCLE_STEPS) {
phase_acc_ms_ -= PALETTE_CYCLE_STEP_MS;
advancePaletteCycle();
++palette_step_;
}
render();
if (palette_step_ >= PALETTE_CYCLE_STEPS) {
phase_ = Phase::FINAL_WAIT;
phase_acc_ms_ = 0;
}
advancePaletteStep(delta_ms);
break;
case Phase::FINAL_WAIT:
phase_acc_ms_ += delta_ms;
render();
@@ -204,25 +215,9 @@ namespace Scenes {
phase_ = Phase::SPRITES;
}
break;
case Phase::SPRITES:
// Sub-escena construïda al primer tick. Transferim el gfx_
// per move — la sub-escena se n'ocupa fins que es destruix.
// Cada tick successiu delega l'animació dels sprites.
if (!sprites_scene_) {
sprites_scene_ = std::make_unique<IntroSpritesScene>(std::move(gfx_));
sprites_scene_->onEnter();
}
sprites_scene_->tick(delta_ms);
if (sprites_scene_->done()) {
// El vell `Go()` post-switch feia `num_piramide = 0`
// per passar al menú. Sense açò el while del fiber
// tornaria a crear IntroNewLogoScene infinitament.
Info::ctx.num_piramide = 0;
phase_ = Phase::DONE;
}
advanceSpritesPhase(delta_ms);
break;
case Phase::DONE:
break;
}
+9 -5
View File
@@ -41,17 +41,21 @@ namespace Scenes {
private:
enum class Phase : std::uint8_t {
INITIAL, // pantalla negra 1000 ms
REVEALING, // 9 × 2 frames × 150 ms cada un
INITIAL, // pantalla negra 1000 ms
REVEALING, // 9 × 2 frames × 150 ms cada un
FULL_LOGO_FLASH, // logo complet + cursor, 200 ms
PALETTE_CYCLE, // 256 passos × 20 ms modificant paleta
FINAL_WAIT, // 20 ms final
SPRITES, // tick delegat a IntroSpritesScene fins que acaba
PALETTE_CYCLE, // 256 passos × 20 ms modificant paleta
FINAL_WAIT, // 20 ms final
SPRITES, // tick delegat a IntroSpritesScene fins que acaba
DONE,
};
void render();
void advancePaletteCycle();
// Helpers per a `tick()` — extrets per reduir complexitat cognitiva.
void advanceRevealing(int delta_ms);
void advancePaletteStep(int delta_ms);
void advanceSpritesPhase(int delta_ms);
SurfaceHandle gfx_;
SurfaceHandle cursor_surf_;
+2 -2
View File
@@ -3,8 +3,8 @@
namespace Scenes {
auto SceneRegistry::instance() -> SceneRegistry& {
static SceneRegistry inst;
return inst;
static SceneRegistry instance_;
return instance_;
}
void SceneRegistry::registerScene(int state_key, Factory factory) {
+82 -75
View File
@@ -65,12 +65,12 @@ namespace Scenes {
next_state_ = 0;
}
void SlidesScene::drawSlide(int slide_idx, int POS_X) {
void SlidesScene::drawSlide(int slide_idx, int pos_x) {
const int SRC_Y = slide_idx * SLIDE_H;
// Clipping manual: translada un rect de 320×65 des de (POS_X, SLIDE_Y)
// a l'àrea visible (0..319, SLIDE_Y..SLIDE_Y+64).
int dst_x = POS_X;
int dst_x = pos_x;
int src_x = 0;
int w = 320;
@@ -99,99 +99,106 @@ namespace Scenes {
phase_ = Phase::FADE_FINAL;
}
void SlidesScene::tick(int delta_ms) {
// Skip: qualsevol tecla salta directament al fade final. Per fidelitat
// al vell doSlides, el skip NO atura la música explícitament — només
// el final natural crida Ja::fadeOutMusic (beginFinalFade() distingeix).
if (!skip_triggered_ && Ji::anyKey()) {
skip_triggered_ = true;
if (num_piramide_at_start_ != 7) {
Audio::get()->fadeOutMusic(250);
}
fade_.startFadeOut();
phase_ = Phase::FADE_FINAL;
void SlidesScene::triggerSkip() {
skip_triggered_ = true;
if (num_piramide_at_start_ != 7) {
Audio::get()->fadeOutMusic(250);
}
fade_.startFadeOut();
phase_ = Phase::FADE_FINAL;
}
void SlidesScene::tickSlideEnter(int delta_ms) {
phase_acc_ms_ += delta_ms;
int slide_idx = 2;
if (phase_ == Phase::SLIDE1_ENTER) {
slide_idx = 0;
} else if (phase_ == Phase::SLIDE2_ENTER) {
slide_idx = 1;
}
const float T = std::min(1.0F, static_cast<float>(phase_acc_ms_) / static_cast<float>(SCROLL_MS));
const float EASED = Easing::outCubic(T);
drawSlide(slide_idx, Easing::lerpInt(SLIDE_START_X[slide_idx], 0, EASED));
if (phase_acc_ms_ < SCROLL_MS) {
return;
}
drawSlide(slide_idx, 0);
switch (phase_) {
case Phase::SLIDE1_ENTER:
phase_ = Phase::SLIDE1_HOLD;
break;
case Phase::SLIDE2_ENTER:
phase_ = Phase::SLIDE2_HOLD;
break;
default:
phase_ = Phase::SLIDE3_HOLD;
break;
}
phase_acc_ms_ = 0;
}
void SlidesScene::tickHoldIntermediate(int delta_ms) {
phase_acc_ms_ += delta_ms;
if (phase_acc_ms_ < HOLD_MS) {
return;
}
fade_.startFadeOut();
phase_ = (phase_ == Phase::SLIDE1_HOLD) ? Phase::FADE_OUT1 : Phase::FADE_OUT2;
phase_acc_ms_ = 0;
}
void SlidesScene::tickFadeOutIntermediate(int delta_ms) {
fade_.tick(delta_ms);
if (!fade_.done()) {
return;
}
restorePalette();
Jd8::clearScreen(BG_COLOR_INDEX);
phase_ = (phase_ == Phase::FADE_OUT1) ? Phase::SLIDE2_ENTER : Phase::SLIDE3_ENTER;
phase_acc_ms_ = 0;
}
void SlidesScene::tickFinalFade(int delta_ms) {
fade_.tick(delta_ms);
if (!fade_.done()) {
return;
}
if (num_piramide_at_start_ == 7) {
Info::ctx.num_piramide = 8;
next_state_ = 1;
} else {
next_state_ = 0;
}
phase_ = Phase::DONE;
}
void SlidesScene::tick(int delta_ms) {
if (!skip_triggered_ && Ji::anyKey()) {
triggerSkip();
}
switch (phase_) {
case Phase::SLIDE1_ENTER:
case Phase::SLIDE2_ENTER:
case Phase::SLIDE3_ENTER: {
phase_acc_ms_ += delta_ms;
int slide_idx = 2;
if (phase_ == Phase::SLIDE1_ENTER) {
slide_idx = 0;
} else if (phase_ == Phase::SLIDE2_ENTER) {
slide_idx = 1;
}
const float T = std::min(1.0F, static_cast<float>(phase_acc_ms_) / static_cast<float>(SCROLL_MS));
const float EASED = Easing::outCubic(T);
const int POS_X = Easing::lerpInt(SLIDE_START_X[slide_idx], 0, EASED);
drawSlide(slide_idx, POS_X);
if (phase_acc_ms_ >= SCROLL_MS) {
// Garanteix posició final exacta (POS_X=0).
drawSlide(slide_idx, 0);
if (phase_ == Phase::SLIDE1_ENTER) {
phase_ = Phase::SLIDE1_HOLD;
} else if (phase_ == Phase::SLIDE2_ENTER) {
phase_ = Phase::SLIDE2_HOLD;
} else {
phase_ = Phase::SLIDE3_HOLD;
}
phase_acc_ms_ = 0;
}
case Phase::SLIDE3_ENTER:
tickSlideEnter(delta_ms);
break;
}
case Phase::SLIDE1_HOLD:
case Phase::SLIDE2_HOLD:
phase_acc_ms_ += delta_ms;
if (phase_acc_ms_ >= HOLD_MS) {
fade_.startFadeOut();
if (phase_ == Phase::SLIDE1_HOLD) {
phase_ = Phase::FADE_OUT1;
} else {
phase_ = Phase::FADE_OUT2;
}
phase_acc_ms_ = 0;
}
tickHoldIntermediate(delta_ms);
break;
case Phase::SLIDE3_HOLD:
phase_acc_ms_ += delta_ms;
if (phase_acc_ms_ >= HOLD_MS) {
beginFinalFade();
}
break;
case Phase::FADE_OUT1:
case Phase::FADE_OUT2:
fade_.tick(delta_ms);
if (fade_.done()) {
restorePalette();
Jd8::clearScreen(BG_COLOR_INDEX);
if (phase_ == Phase::FADE_OUT1) {
phase_ = Phase::SLIDE2_ENTER;
} else {
phase_ = Phase::SLIDE3_ENTER;
}
phase_acc_ms_ = 0;
}
tickFadeOutIntermediate(delta_ms);
break;
case Phase::FADE_FINAL:
fade_.tick(delta_ms);
if (fade_.done()) {
if (num_piramide_at_start_ == 7) {
Info::ctx.num_piramide = 8;
next_state_ = 1;
} else {
next_state_ = 0;
}
phase_ = Phase::DONE;
}
tickFinalFade(delta_ms);
break;
case Phase::DONE:
break;
}
+6
View File
@@ -65,6 +65,12 @@ namespace Scenes {
void drawSlide(int slide_idx, int pos_x);
void restorePalette();
void beginFinalFade();
// Helpers per a `tick()` — extrets per reduir complexitat cognitiva.
void triggerSkip();
void tickSlideEnter(int delta_ms);
void tickHoldIntermediate(int delta_ms);
void tickFadeOutIntermediate(int delta_ms);
void tickFinalFade(int delta_ms);
SurfaceHandle gfx_;
Jd8::Palette pal_aux_{nullptr}; // còpia "neta" que preservem
+2 -2
View File
@@ -63,9 +63,9 @@ namespace Scenes {
// Pot ser que el següent pas siga una cadena de one-shots.
flushOneShots();
} else if (s.continuous) {
const float p = static_cast<float>(elapsed_in_step_) /
const float P = static_cast<float>(elapsed_in_step_) /
static_cast<float>(std::max(1, s.duration_ms));
s.continuous(p);
s.continuous(P);
}
}
+2 -2
View File
@@ -1,9 +1,9 @@
#include "game/sprite.hpp"
Sprite::Sprite(Jd8::Surface gfx)
: gfx(gfx) {}
: gfx_(gfx) {}
void Sprite::draw() {
const Frame& f = entitat.frames[entitat.animacions[o].frames[cur_frame]];
Jd8::blitCK(x, y, gfx, f.x, f.y, f.w, f.h, 255);
Jd8::blitCK(x, y, gfx_, f.x, f.y, f.w, f.h, 255);
}
+2 -2
View File
@@ -34,6 +34,6 @@ class Sprite {
Uint16 o = 0;
protected:
Jd8::Surface gfx;
Uint8 cycles_per_frame = 1;
Jd8::Surface gfx_;
Uint8 cycles_per_frame_ = 1;
};