step 5: slides_scene amb wipe suau per easing (substituix doSlides)
This commit is contained in:
@@ -53,6 +53,7 @@ set(APP_SOURCES
|
|||||||
source/scenes/banner_scene.cpp
|
source/scenes/banner_scene.cpp
|
||||||
source/scenes/menu_scene.cpp
|
source/scenes/menu_scene.cpp
|
||||||
source/scenes/intro_new_logo_scene.cpp
|
source/scenes/intro_new_logo_scene.cpp
|
||||||
|
source/scenes/slides_scene.cpp
|
||||||
|
|
||||||
# Game
|
# Game
|
||||||
source/game/options.cpp
|
source/game/options.cpp
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "scenes/mort_scene.hpp"
|
#include "scenes/mort_scene.hpp"
|
||||||
#include "scenes/scene.hpp"
|
#include "scenes/scene.hpp"
|
||||||
#include "scenes/scene_registry.hpp"
|
#include "scenes/scene_registry.hpp"
|
||||||
|
#include "scenes/slides_scene.hpp"
|
||||||
|
|
||||||
// Cheats del joc original — declarats a jinput.cpp
|
// Cheats del joc original — declarats a jinput.cpp
|
||||||
extern void JI_moveCheats(Uint8 new_key);
|
extern void JI_moveCheats(Uint8 new_key);
|
||||||
@@ -61,6 +62,16 @@ void gameFiberEntry() {
|
|||||||
// amb un mini-loop tick-based. El codi de la Scene no toca
|
// amb un mini-loop tick-based. El codi de la Scene no toca
|
||||||
// fibers; el JD8_Flip() entre ticks és el que cedeix al Director.
|
// fibers; el JD8_Flip() entre ticks és el que cedeix al Director.
|
||||||
if (gameState == 1) {
|
if (gameState == 1) {
|
||||||
|
// Replica del redirect que el `ModuleSequence::Go()` vell feia
|
||||||
|
// al principi: si el jugador arriba a la piràmide Secreta (6)
|
||||||
|
// sense prou diners, salta directament als slides de fracàs (7).
|
||||||
|
// Cal fer-ho ací perquè el SceneRegistry consulta num_piramide
|
||||||
|
// abans del fallback legacy; mentres doSecreta no estiga migrada
|
||||||
|
// també continuarà al Go() vell amb num_piramide ja corregida.
|
||||||
|
if (info::ctx.num_piramide == 6 && info::ctx.diners < 200) {
|
||||||
|
info::ctx.num_piramide = 7;
|
||||||
|
}
|
||||||
|
|
||||||
if (auto scene = scenes::SceneRegistry::instance().tryCreate(info::ctx.num_piramide)) {
|
if (auto scene = scenes::SceneRegistry::instance().tryCreate(info::ctx.num_piramide)) {
|
||||||
scene->onEnter();
|
scene->onEnter();
|
||||||
Uint32 last = SDL_GetTicks();
|
Uint32 last = SDL_GetTicks();
|
||||||
@@ -112,6 +123,12 @@ void Director::init() {
|
|||||||
for (int p = 2; p <= 5; ++p) {
|
for (int p = 2; p <= 5; ++p) {
|
||||||
registry.registerScene(p, [] { return std::make_unique<scenes::BannerScene>(); });
|
registry.registerScene(p, [] { return std::make_unique<scenes::BannerScene>(); });
|
||||||
}
|
}
|
||||||
|
// SlidesScene cobreix els dos states on el vell `doSlides` s'invocava:
|
||||||
|
// - num_piramide == 1: slides narratius inicials (entrada al joc)
|
||||||
|
// - num_piramide == 7: slides de fracàs (ve del redirect 6→7 quan
|
||||||
|
// l'usuari no té prou diners per a la Secreta)
|
||||||
|
registry.registerScene(1, [] { return std::make_unique<scenes::SlidesScene>(); });
|
||||||
|
registry.registerScene(7, [] { return std::make_unique<scenes::SlidesScene>(); });
|
||||||
// IntroNewLogoScene només es registra quan `use_new_logo` està actiu;
|
// IntroNewLogoScene només es registra quan `use_new_logo` està actiu;
|
||||||
// si no, la factory retorna nullptr i el gameFiberEntry cau al vell
|
// si no, la factory retorna nullptr i el gameFiberEntry cau al vell
|
||||||
// ModuleSequence::doIntro() legacy que no ha sigut migrat encara.
|
// ModuleSequence::doIntro() legacy que no ha sigut migrat encara.
|
||||||
|
|||||||
@@ -39,10 +39,7 @@ int ModuleSequence::Go() {
|
|||||||
doIntro();
|
doIntro();
|
||||||
break;
|
break;
|
||||||
// case 0 (Menú) → migrat a scenes::MenuScene.
|
// case 0 (Menú) → migrat a scenes::MenuScene.
|
||||||
case 1: // Slides
|
// case 1 i 7 (Slides) → migrat a scenes::SlidesScene.
|
||||||
case 7:
|
|
||||||
doSlides();
|
|
||||||
break;
|
|
||||||
// case 2..5 (Pre-piràmide) → migrat a scenes::BannerScene.
|
// case 2..5 (Pre-piràmide) → migrat a scenes::BannerScene.
|
||||||
case 6: // Pre-Secreta
|
case 6: // Pre-Secreta
|
||||||
doSecreta();
|
doSecreta();
|
||||||
@@ -823,85 +820,7 @@ void ModuleSequence::doIntroSprites(JD8_Surface gfx) {
|
|||||||
|
|
||||||
// doMenu() — migrat a scenes::MenuScene (source/scenes/menu_scene.cpp)
|
// doMenu() — migrat a scenes::MenuScene (source/scenes/menu_scene.cpp)
|
||||||
|
|
||||||
void ModuleSequence::doSlides() {
|
// doSlides() — migrat a scenes::SlidesScene (source/scenes/slides_scene.cpp)
|
||||||
JG_SetUpdateTicks(20);
|
|
||||||
|
|
||||||
const char* arxiu;
|
|
||||||
if (info::ctx.num_piramide == 7) {
|
|
||||||
play_music("00000005.ogg", 1);
|
|
||||||
if (info::ctx.diners < 200) {
|
|
||||||
arxiu = "intro2.gif";
|
|
||||||
} else {
|
|
||||||
arxiu = "intro3.gif";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
arxiu = "intro.gif";
|
|
||||||
}
|
|
||||||
|
|
||||||
JD8_Surface gfx = JD8_LoadSurface(arxiu);
|
|
||||||
JD8_Palette pal_aux = JD8_LoadPalette(arxiu);
|
|
||||||
JD8_Palette pal = (JD8_Palette)malloc(768);
|
|
||||||
memcpy(pal, pal_aux, 768);
|
|
||||||
JD8_ClearScreen(255);
|
|
||||||
JD8_SetScreenPalette(pal);
|
|
||||||
|
|
||||||
bool exit = false;
|
|
||||||
int step = 0;
|
|
||||||
contador = 1;
|
|
||||||
while (!exit && !JG_Quitting()) {
|
|
||||||
if (JG_ShouldUpdate()) {
|
|
||||||
JI_Update();
|
|
||||||
|
|
||||||
if (JI_AnyKey()) {
|
|
||||||
exit = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (step) {
|
|
||||||
case 0:
|
|
||||||
JD8_Blit(320 - (contador * 4), 65, gfx, 0, 0, contador * 4, 65);
|
|
||||||
JD8_Flip();
|
|
||||||
contador++;
|
|
||||||
if (contador == 80) step++;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
JD8_Blit(0, 65, gfx, 320 - (contador * 4), 65, contador * 4, 65);
|
|
||||||
JD8_Flip();
|
|
||||||
contador++;
|
|
||||||
if (contador == 80) step++;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
JD8_Blit(320 - (contador * 4), 65, gfx, 0, 130, contador * 4, 65);
|
|
||||||
JD8_Flip();
|
|
||||||
contador++;
|
|
||||||
if (contador == 80) step++;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
case 4:
|
|
||||||
case 7:
|
|
||||||
contador--;
|
|
||||||
if (contador == -150) {
|
|
||||||
contador = 0;
|
|
||||||
step++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
case 5:
|
|
||||||
JD8_FadeOut();
|
|
||||||
memcpy(pal, pal_aux, 768);
|
|
||||||
JD8_ClearScreen(255);
|
|
||||||
step++;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
if (info::ctx.num_piramide != 7) JA_FadeOutMusic(250);
|
|
||||||
exit = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
free(pal_aux);
|
|
||||||
}
|
|
||||||
|
|
||||||
// doBanner() — migrat a scenes::BannerScene (source/scenes/banner_scene.cpp)
|
// doBanner() — migrat a scenes::BannerScene (source/scenes/banner_scene.cpp)
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class ModuleSequence {
|
|||||||
void doIntro();
|
void doIntro();
|
||||||
void doIntroNewLogo();
|
void doIntroNewLogo();
|
||||||
// doMenu() → migrat a scenes::MenuScene
|
// doMenu() → migrat a scenes::MenuScene
|
||||||
void doSlides();
|
// doSlides() → migrat a scenes::SlidesScene
|
||||||
// doBanner() → migrat a scenes::BannerScene
|
// doBanner() → migrat a scenes::BannerScene
|
||||||
void doSecreta();
|
void doSecreta();
|
||||||
void doCredits();
|
void doCredits();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "core/jail/jdraw8.hpp"
|
#include "core/jail/jdraw8.hpp"
|
||||||
#include "core/jail/jinput.hpp"
|
#include "core/jail/jinput.hpp"
|
||||||
|
#include "game/info.hpp"
|
||||||
#include "game/modulesequence.hpp"
|
#include "game/modulesequence.hpp"
|
||||||
#include "scenes/scene_utils.hpp"
|
#include "scenes/scene_utils.hpp"
|
||||||
|
|
||||||
@@ -120,11 +121,14 @@ void IntroNewLogoScene::advancePaletteCycle() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IntroNewLogoScene::tick(int delta_ms) {
|
void IntroNewLogoScene::tick(int delta_ms) {
|
||||||
// Qualsevol tecla salta tota la intro del logo i va directament
|
// Qualsevol tecla durant el revelat o el ciclo de paleta salta
|
||||||
// a la delegació final — el mini-while del fiber no ha pintat
|
// TOTA la intro (inclou saltar doIntroSprites). Aquest era el
|
||||||
// res encara, però doIntroSprites fa la seua pròpia intro.
|
// comportament del vell `doIntroNewLogo`: a cada `waitTick()`
|
||||||
if (JI_AnyKey()) {
|
// retornava abans de cridar `doIntroSprites`.
|
||||||
phase_ = Phase::Delegate;
|
if (phase_ != Phase::Delegate && phase_ != Phase::Done && JI_AnyKey()) {
|
||||||
|
info::ctx.num_piramide = 0;
|
||||||
|
phase_ = Phase::Done;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (phase_) {
|
switch (phase_) {
|
||||||
@@ -192,13 +196,18 @@ void IntroNewLogoScene::tick(int delta_ms) {
|
|||||||
case Phase::Delegate: {
|
case Phase::Delegate: {
|
||||||
// Delegació temporal al codi legacy: crea un ModuleSequence
|
// Delegació temporal al codi legacy: crea un ModuleSequence
|
||||||
// instància i li crida `doIntroSprites(gfx)`. La funció
|
// instància i li crida `doIntroSprites(gfx)`. La funció
|
||||||
// legacy fa els seus propis `JD8_Flip()` (que cedeixen al
|
// legacy *sempre* allibera `gfx` ella mateixa (al final o en
|
||||||
// Director via GameFiber::yield) i torna quan la cinemàtica
|
// els paths de skip amb JI_AnyKey), així que necessitem
|
||||||
// de sprites ha acabat. Step 9 d'aquesta migració la
|
// transferir-li ownership via `release()` per evitar un
|
||||||
// reescriurà com a scenes::IntroSpritesScene i aquesta
|
// double free al destructor de SurfaceHandle. Step 9
|
||||||
// delegació desapareixerà.
|
// d'aquesta migració la reescriurà com a IntroSpritesScene
|
||||||
|
// i la delegació desapareixerà.
|
||||||
ModuleSequence legacy;
|
ModuleSequence legacy;
|
||||||
legacy.doIntroSprites(gfx_.get());
|
legacy.doIntroSprites(gfx_.release());
|
||||||
|
// El vell `Go()` post-switch feia `num_piramide = 0` per a
|
||||||
|
// passar al menú. Ho reproduïm ací — si no, el while extern
|
||||||
|
// del fiber tornaria a crear IntroNewLogoScene infinitament.
|
||||||
|
info::ctx.num_piramide = 0;
|
||||||
phase_ = Phase::Done;
|
phase_ = Phase::Done;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
void playMusic(const char* filename) {
|
void playMusic(const char* filename, int loop) {
|
||||||
if (!filename) return;
|
if (!filename) return;
|
||||||
int size = 0;
|
int size = 0;
|
||||||
char* buffer = file_getfilebuffer(filename, size);
|
char* buffer = file_getfilebuffer(filename, size);
|
||||||
@@ -15,7 +15,7 @@ void playMusic(const char* filename) {
|
|||||||
// JA_LoadMusic fa una còpia del OGG comprimit (SDL_malloc), així que
|
// JA_LoadMusic fa una còpia del OGG comprimit (SDL_malloc), així que
|
||||||
// el `buffer` original es queda huérfano. Leak conegut heredat del
|
// el `buffer` original es queda huérfano. Leak conegut heredat del
|
||||||
// codi original — es tractarà quan jfile tinga una API std::vector.
|
// codi original — es tractarà quan jfile tinga una API std::vector.
|
||||||
JA_PlayMusic(JA_LoadMusic(reinterpret_cast<Uint8*>(buffer), size, filename));
|
JA_PlayMusic(JA_LoadMusic(reinterpret_cast<Uint8*>(buffer), size, filename), loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace scenes {
|
|||||||
|
|
||||||
// Carrega un OGG de `data/` i arranca'l com a música de fons. Substituïx
|
// Carrega un OGG de `data/` i arranca'l com a música de fons. Substituïx
|
||||||
// el `play_music()` repetit en tots els doX() del vell modulesequence.
|
// el `play_music()` repetit en tots els doX() del vell modulesequence.
|
||||||
void playMusic(const char* filename);
|
// `loop`: -1 = infinit (per defecte), 0 = una sola vegada, N = N+1 passades.
|
||||||
|
void playMusic(const char* filename, int loop = -1);
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
186
source/scenes/slides_scene.cpp
Normal file
186
source/scenes/slides_scene.cpp
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
#include "scenes/slides_scene.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "core/jail/jail_audio.hpp"
|
||||||
|
#include "core/jail/jdraw8.hpp"
|
||||||
|
#include "core/jail/jinput.hpp"
|
||||||
|
#include "game/info.hpp"
|
||||||
|
#include "scenes/scene_utils.hpp"
|
||||||
|
#include "utils/easing.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr int SCROLL_MS = 1600; // 80 iters × 20 ms del vell doSlides
|
||||||
|
constexpr int HOLD_MS = 4600; // 230 iters × 20 ms (80 + 150) del vell
|
||||||
|
constexpr int SLIDE_Y = 65;
|
||||||
|
constexpr int SLIDE_H = 65;
|
||||||
|
constexpr int BG_COLOR_INDEX = 255;
|
||||||
|
|
||||||
|
// Desplaçament inicial del slide segons direcció del wipe.
|
||||||
|
// Slide 1 i 3: "scroll in from right" (pos_x va de 320 → 0).
|
||||||
|
// Slide 2: "wipe reverse" (pos_x va de -320 → 0), el mateix efecte
|
||||||
|
// estrany del doSlides vell on la imatge es desplaça des de l'esquerra
|
||||||
|
// però revela primer el lateral dret del src.
|
||||||
|
constexpr int SLIDE_START_X[3] = {320, -320, 320};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace scenes {
|
||||||
|
|
||||||
|
SlidesScene::~SlidesScene() {
|
||||||
|
if (pal_aux_) std::free(pal_aux_);
|
||||||
|
// pal_active_ NO s'allibera: propietat de main_palette via SetScreenPalette.
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlidesScene::onEnter() {
|
||||||
|
num_piramide_at_start_ = info::ctx.num_piramide;
|
||||||
|
|
||||||
|
const char* arxiu = nullptr;
|
||||||
|
if (num_piramide_at_start_ == 7) {
|
||||||
|
// loop=1 per replicar el vell `play_music("00000005.ogg", 1)`.
|
||||||
|
playMusic("00000005.ogg", 1);
|
||||||
|
arxiu = (info::ctx.diners < 200) ? "intro2.gif" : "intro3.gif";
|
||||||
|
} else {
|
||||||
|
arxiu = "intro.gif";
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx_ = SurfaceHandle(arxiu);
|
||||||
|
pal_aux_ = JD8_LoadPalette(arxiu);
|
||||||
|
|
||||||
|
// Còpia editable de la paleta. `pal_active_` comparteix memòria amb
|
||||||
|
// main_palette després del SetScreenPalette — modificar-la modifica
|
||||||
|
// main_palette directament. `pal_aux_` es manté intacte per a poder
|
||||||
|
// restaurar després de cada fade-out intermedi.
|
||||||
|
pal_active_ = static_cast<JD8_Palette>(std::malloc(768));
|
||||||
|
std::memcpy(pal_active_, pal_aux_, 768);
|
||||||
|
JD8_SetScreenPalette(pal_active_);
|
||||||
|
|
||||||
|
JD8_ClearScreen(BG_COLOR_INDEX);
|
||||||
|
|
||||||
|
phase_ = Phase::Slide1Enter;
|
||||||
|
phase_acc_ms_ = 0;
|
||||||
|
next_state_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 src_x = 0;
|
||||||
|
int w = 320;
|
||||||
|
|
||||||
|
if (dst_x < 0) {
|
||||||
|
src_x = -dst_x;
|
||||||
|
w = 320 + dst_x;
|
||||||
|
dst_x = 0;
|
||||||
|
} else if (dst_x > 0) {
|
||||||
|
w = 320 - dst_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w > 0) {
|
||||||
|
JD8_Blit(dst_x, SLIDE_Y, gfx_, src_x, src_y, w, SLIDE_H);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlidesScene::restorePalette() {
|
||||||
|
std::memcpy(pal_active_, pal_aux_, 768);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlidesScene::beginFinalFade() {
|
||||||
|
if (num_piramide_at_start_ != 7) {
|
||||||
|
JA_FadeOutMusic(250);
|
||||||
|
}
|
||||||
|
fade_.startFadeOut();
|
||||||
|
phase_ = Phase::FadeFinal;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) JA_FadeOutMusic(250);
|
||||||
|
fade_.startFadeOut();
|
||||||
|
phase_ = Phase::FadeFinal;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (phase_) {
|
||||||
|
case Phase::Slide1Enter:
|
||||||
|
case Phase::Slide2Enter:
|
||||||
|
case Phase::Slide3Enter: {
|
||||||
|
phase_acc_ms_ += delta_ms;
|
||||||
|
const int slide_idx = (phase_ == Phase::Slide1Enter ? 0
|
||||||
|
: phase_ == Phase::Slide2Enter ? 1
|
||||||
|
: 2);
|
||||||
|
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::Slide1Enter) phase_ = Phase::Slide1Hold;
|
||||||
|
else if (phase_ == Phase::Slide2Enter) phase_ = Phase::Slide2Hold;
|
||||||
|
else phase_ = Phase::Slide3Hold;
|
||||||
|
phase_acc_ms_ = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Phase::Slide1Hold:
|
||||||
|
case Phase::Slide2Hold:
|
||||||
|
phase_acc_ms_ += delta_ms;
|
||||||
|
if (phase_acc_ms_ >= HOLD_MS) {
|
||||||
|
fade_.startFadeOut();
|
||||||
|
if (phase_ == Phase::Slide1Hold) phase_ = Phase::FadeOut1;
|
||||||
|
else phase_ = Phase::FadeOut2;
|
||||||
|
phase_acc_ms_ = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Phase::Slide3Hold:
|
||||||
|
phase_acc_ms_ += delta_ms;
|
||||||
|
if (phase_acc_ms_ >= HOLD_MS) {
|
||||||
|
beginFinalFade();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Phase::FadeOut1:
|
||||||
|
case Phase::FadeOut2:
|
||||||
|
fade_.tick(delta_ms);
|
||||||
|
if (fade_.done()) {
|
||||||
|
restorePalette();
|
||||||
|
JD8_ClearScreen(BG_COLOR_INDEX);
|
||||||
|
if (phase_ == Phase::FadeOut1) phase_ = Phase::Slide2Enter;
|
||||||
|
else phase_ = Phase::Slide3Enter;
|
||||||
|
phase_acc_ms_ = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Phase::FadeFinal:
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Phase::Done:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace scenes
|
||||||
79
source/scenes/slides_scene.hpp
Normal file
79
source/scenes/slides_scene.hpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/jail/jdraw8.hpp"
|
||||||
|
#include "scenes/palette_fade.hpp"
|
||||||
|
#include "scenes/scene.hpp"
|
||||||
|
#include "scenes/surface_handle.hpp"
|
||||||
|
|
||||||
|
namespace scenes {
|
||||||
|
|
||||||
|
// 3 slides narratius amb scroll d'entrada + espera + transició amb
|
||||||
|
// fade-out. Reemplaça `ModuleSequence::doSlides()`.
|
||||||
|
//
|
||||||
|
// Tria d'asset segons context:
|
||||||
|
// - num_piramide == 7 i diners < 200: intro2.gif + música "00000005.ogg"
|
||||||
|
// - num_piramide == 7 i diners >= 200: intro3.gif + música "00000005.ogg"
|
||||||
|
// - altre cas (num_piramide == 1): intro.gif, sense música nova
|
||||||
|
//
|
||||||
|
// Flux:
|
||||||
|
// Slide1Enter (1600 ms scroll dreta→centre, easing outCubic)
|
||||||
|
// → Slide1Hold (4600 ms)
|
||||||
|
// → FadeOut1 + clear + reset paleta
|
||||||
|
// → Slide2Enter (1600 ms scroll esquerra→centre)
|
||||||
|
// → Slide2Hold (4600 ms)
|
||||||
|
// → FadeOut2 + clear + reset paleta
|
||||||
|
// → Slide3Enter (1600 ms scroll dreta→centre)
|
||||||
|
// → Slide3Hold (4600 ms)
|
||||||
|
// → FadeFinal (JA_FadeOutMusic si num_piramide != 7 + fade paleta)
|
||||||
|
// → Done
|
||||||
|
//
|
||||||
|
// Qualsevol tecla salta directament a FadeFinal (sense cortar la música
|
||||||
|
// si hem entrat per num_piramide==7, per fidelitat al vell).
|
||||||
|
//
|
||||||
|
// NextState:
|
||||||
|
// - num_piramide==7 al entrar → num_piramide=8 + return 1 (a Credits)
|
||||||
|
// - altre cas → return 0 (entra al ModuleGame)
|
||||||
|
class SlidesScene : public Scene {
|
||||||
|
public:
|
||||||
|
SlidesScene() = default;
|
||||||
|
~SlidesScene() override;
|
||||||
|
|
||||||
|
void onEnter() override;
|
||||||
|
void tick(int delta_ms) override;
|
||||||
|
bool done() const override { return phase_ == Phase::Done; }
|
||||||
|
int nextState() const override { return next_state_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class Phase {
|
||||||
|
Slide1Enter,
|
||||||
|
Slide1Hold,
|
||||||
|
FadeOut1,
|
||||||
|
Slide2Enter,
|
||||||
|
Slide2Hold,
|
||||||
|
FadeOut2,
|
||||||
|
Slide3Enter,
|
||||||
|
Slide3Hold,
|
||||||
|
FadeFinal,
|
||||||
|
Done,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pinta un slide amb desplaçament horitzontal. `slide_idx` = 0..2
|
||||||
|
// (correspon a la franja 65x65 a y = 0, 65, 130 dins de gfx_).
|
||||||
|
// `pos_x` = desplaçament, amb clipping manual quan surt de pantalla.
|
||||||
|
void drawSlide(int slide_idx, int pos_x);
|
||||||
|
void restorePalette();
|
||||||
|
void beginFinalFade();
|
||||||
|
|
||||||
|
SurfaceHandle gfx_;
|
||||||
|
JD8_Palette pal_aux_{nullptr}; // còpia "neta" que preservem
|
||||||
|
JD8_Palette pal_active_{nullptr}; // propietat transferida a main_palette
|
||||||
|
PaletteFade fade_;
|
||||||
|
|
||||||
|
Phase phase_{Phase::Slide1Enter};
|
||||||
|
int phase_acc_ms_{0};
|
||||||
|
int num_piramide_at_start_{1};
|
||||||
|
int next_state_{0};
|
||||||
|
bool skip_triggered_{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace scenes
|
||||||
@@ -33,4 +33,10 @@ void SurfaceHandle::adopt(JD8_Surface raw) {
|
|||||||
surface_ = raw;
|
surface_ = raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JD8_Surface SurfaceHandle::release() {
|
||||||
|
JD8_Surface r = surface_;
|
||||||
|
surface_ = nullptr;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -29,6 +29,13 @@ class SurfaceHandle {
|
|||||||
// — la surface adoptada s'allibera al destructor o al següent reset/adopt.
|
// — la surface adoptada s'allibera al destructor o al següent reset/adopt.
|
||||||
void adopt(JD8_Surface raw);
|
void adopt(JD8_Surface raw);
|
||||||
|
|
||||||
|
// Allibera ownership sense destruir la surface. Retorna el pointer cru;
|
||||||
|
// el caller passa a ser responsable d'alliberar-lo (o de passar-lo a un
|
||||||
|
// altre propietari). Usat quan una escena delega a codi legacy que
|
||||||
|
// també allibera la mateixa surface — cal "soltar" el ownership per
|
||||||
|
// evitar double free.
|
||||||
|
[[nodiscard]] JD8_Surface release();
|
||||||
|
|
||||||
// Conversió implícita per al confort d'ús: JD8_Blit(handle)
|
// Conversió implícita per al confort d'ús: JD8_Blit(handle)
|
||||||
// en lloc de JD8_Blit(handle.get()).
|
// en lloc de JD8_Blit(handle.get()).
|
||||||
operator JD8_Surface() const { return surface_; }
|
operator JD8_Surface() const { return surface_; }
|
||||||
|
|||||||
Reference in New Issue
Block a user