step 6: credits_scene substituix doCredits() (scroll vertical + parallax condicional)
This commit is contained in:
@@ -54,6 +54,7 @@ set(APP_SOURCES
|
|||||||
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
|
source/scenes/slides_scene.cpp
|
||||||
|
source/scenes/credits_scene.cpp
|
||||||
|
|
||||||
# Game
|
# Game
|
||||||
source/game/options.cpp
|
source/game/options.cpp
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "game/modulesequence.hpp"
|
#include "game/modulesequence.hpp"
|
||||||
#include "game/options.hpp"
|
#include "game/options.hpp"
|
||||||
#include "scenes/banner_scene.hpp"
|
#include "scenes/banner_scene.hpp"
|
||||||
|
#include "scenes/credits_scene.hpp"
|
||||||
#include "scenes/intro_new_logo_scene.hpp"
|
#include "scenes/intro_new_logo_scene.hpp"
|
||||||
#include "scenes/menu_scene.hpp"
|
#include "scenes/menu_scene.hpp"
|
||||||
#include "scenes/mort_scene.hpp"
|
#include "scenes/mort_scene.hpp"
|
||||||
@@ -43,7 +44,7 @@ void gameFiberEntry() {
|
|||||||
info::ctx.num_habitacio = Options::game.habitacio_inicial;
|
info::ctx.num_habitacio = Options::game.habitacio_inicial;
|
||||||
info::ctx.num_piramide = Options::game.piramide_inicial;
|
info::ctx.num_piramide = Options::game.piramide_inicial;
|
||||||
info::ctx.diners = 0;
|
info::ctx.diners = 0;
|
||||||
info::ctx.diamants = 0;
|
info::ctx.diamants = Options::game.diamants_inicial;
|
||||||
info::ctx.vida = Options::game.vides;
|
info::ctx.vida = Options::game.vides;
|
||||||
info::ctx.momies = 0;
|
info::ctx.momies = 0;
|
||||||
info::ctx.nou_personatge = false;
|
info::ctx.nou_personatge = false;
|
||||||
@@ -129,6 +130,7 @@ void Director::init() {
|
|||||||
// l'usuari no té prou diners per a la Secreta)
|
// l'usuari no té prou diners per a la Secreta)
|
||||||
registry.registerScene(1, [] { return std::make_unique<scenes::SlidesScene>(); });
|
registry.registerScene(1, [] { return std::make_unique<scenes::SlidesScene>(); });
|
||||||
registry.registerScene(7, [] { return std::make_unique<scenes::SlidesScene>(); });
|
registry.registerScene(7, [] { return std::make_unique<scenes::SlidesScene>(); });
|
||||||
|
registry.registerScene(8, [] { return std::make_unique<scenes::CreditsScene>(); });
|
||||||
// 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.
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ namespace Defaults::Game {
|
|||||||
constexpr int HABITACIO_INICIAL = 1;
|
constexpr int HABITACIO_INICIAL = 1;
|
||||||
constexpr int PIRAMIDE_INICIAL = 255;
|
constexpr int PIRAMIDE_INICIAL = 255;
|
||||||
constexpr int VIDES = 5;
|
constexpr int VIDES = 5;
|
||||||
|
constexpr int DIAMANTS_INICIAL = 0;
|
||||||
constexpr bool USE_NEW_LOGO = true;
|
constexpr bool USE_NEW_LOGO = true;
|
||||||
constexpr bool SHOW_TITLE_CREDITS = true;
|
constexpr bool SHOW_TITLE_CREDITS = true;
|
||||||
} // namespace Defaults::Game
|
} // namespace Defaults::Game
|
||||||
|
|||||||
@@ -44,9 +44,7 @@ int ModuleSequence::Go() {
|
|||||||
case 6: // Pre-Secreta
|
case 6: // Pre-Secreta
|
||||||
doSecreta();
|
doSecreta();
|
||||||
break;
|
break;
|
||||||
case 8: // Credits
|
// case 8 (Credits) → migrat a scenes::CreditsScene.
|
||||||
doCredits();
|
|
||||||
break;
|
|
||||||
// case 100 (Mort) → migrat a scenes::MortScene, dispatch via SceneRegistry.
|
// case 100 (Mort) → migrat a scenes::MortScene, dispatch via SceneRegistry.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -911,70 +909,6 @@ void ModuleSequence::doSecreta() {
|
|||||||
free(pal_aux);
|
free(pal_aux);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleSequence::doCredits() {
|
// doCredits() — migrat a scenes::CreditsScene (source/scenes/credits_scene.cpp)
|
||||||
struct {
|
|
||||||
Uint16 x, y;
|
|
||||||
} frames_coche[8] = {{214, 152}, {214, 104}, {214, 56}, {214, 104}, {214, 152}, {214, 8}, {108, 152}, {214, 8}};
|
|
||||||
const Uint32 n_frames_coche = 8;
|
|
||||||
const Uint32 velocitat_coche = 3;
|
|
||||||
|
|
||||||
JD8_Surface vaddr2 = JD8_LoadSurface("final.gif");
|
|
||||||
JD8_Surface vaddr3 = JD8_LoadSurface("finals.gif");
|
|
||||||
JD8_Palette pal = JD8_LoadPalette("final.gif");
|
|
||||||
JD8_SetScreenPalette(pal);
|
|
||||||
|
|
||||||
int contador = 0;
|
|
||||||
|
|
||||||
bool exit = false;
|
|
||||||
contador = 1;
|
|
||||||
while (!exit && !JG_Quitting()) {
|
|
||||||
if (JG_ShouldUpdate()) {
|
|
||||||
JI_Update();
|
|
||||||
|
|
||||||
if (JI_AnyKey() || contador >= 3100) {
|
|
||||||
exit = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
JD8_ClearScreen(255);
|
|
||||||
|
|
||||||
if (contador < 2750) {
|
|
||||||
JD8_BlitCKCut(115, 200 - (contador / 6), vaddr2, 0, 0, 80, 200, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((contador > 1200) && (contador < 2280)) {
|
|
||||||
JD8_BlitCKCut(100, 200 - ((contador - 1200) / 6), vaddr2, 85, 0, 120, 140, 0);
|
|
||||||
} else if (contador >= 2250) {
|
|
||||||
JD8_BlitCK(100, 20, vaddr2, 85, 0, 120, 140, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info::ctx.diamants == 16) {
|
|
||||||
// scroll_final_joc(vaddr3, vaddr, contador_final);
|
|
||||||
JD8_BlitCKScroll(50, vaddr3, ((contador >> 3) % 320) + 1, 0, 50, 255);
|
|
||||||
JD8_BlitCKScroll(50, vaddr3, ((contador >> 2) % 320) + 1, 50, 50, 255);
|
|
||||||
JD8_BlitCKScroll(50, vaddr3, ((contador >> 1) % 320) + 1, 100, 50, 255);
|
|
||||||
JD8_BlitCKScroll(50, vaddr3, (contador % 320) + 1, 150, 50, 255);
|
|
||||||
|
|
||||||
JD8_BlitCK(100, 50, vaddr2, frames_coche[(contador / velocitat_coche) % n_frames_coche].x, frames_coche[(contador / velocitat_coche) % n_frames_coche].y, 106, 48, 255);
|
|
||||||
} else {
|
|
||||||
JD8_BlitCK(0, 50, vaddr3, 0, 0, 320, 50, 255);
|
|
||||||
JD8_BlitCK(0, 50, vaddr3, 0, 50, 320, 50, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
JD8_FillSquare(0, 50, 255);
|
|
||||||
JD8_FillSquare(100, 10, 255);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
contador++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* ini = fopen("trick.ini", "wb");
|
|
||||||
fwrite("1", 1, 1, ini);
|
|
||||||
fclose(ini);
|
|
||||||
info::ctx.nou_personatge = true;
|
|
||||||
|
|
||||||
JD8_FreeSurface(vaddr3);
|
|
||||||
JD8_FreeSurface(vaddr2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// doMort() — migrat a scenes::MortScene (source/scenes/mort_scene.cpp)
|
// doMort() — migrat a scenes::MortScene (source/scenes/mort_scene.cpp)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class ModuleSequence {
|
|||||||
// doSlides() → migrat a scenes::SlidesScene
|
// doSlides() → migrat a scenes::SlidesScene
|
||||||
// doBanner() → migrat a scenes::BannerScene
|
// doBanner() → migrat a scenes::BannerScene
|
||||||
void doSecreta();
|
void doSecreta();
|
||||||
void doCredits();
|
// doCredits() → migrat a scenes::CreditsScene
|
||||||
// doMort() → migrat a scenes::MortScene
|
// doMort() → migrat a scenes::MortScene
|
||||||
|
|
||||||
int contador;
|
int contador;
|
||||||
|
|||||||
@@ -144,6 +144,8 @@ namespace Options {
|
|||||||
game.piramide_inicial = node["piramide_inicial"].get_value<int>();
|
game.piramide_inicial = node["piramide_inicial"].get_value<int>();
|
||||||
if (node.contains("vides"))
|
if (node.contains("vides"))
|
||||||
game.vides = node["vides"].get_value<int>();
|
game.vides = node["vides"].get_value<int>();
|
||||||
|
if (node.contains("diamants_inicial"))
|
||||||
|
game.diamants_inicial = node["diamants_inicial"].get_value<int>();
|
||||||
if (node.contains("use_new_logo"))
|
if (node.contains("use_new_logo"))
|
||||||
game.use_new_logo = node["use_new_logo"].get_value<bool>();
|
game.use_new_logo = node["use_new_logo"].get_value<bool>();
|
||||||
if (node.contains("show_title_credits"))
|
if (node.contains("show_title_credits"))
|
||||||
@@ -278,6 +280,7 @@ namespace Options {
|
|||||||
file << " habitacio_inicial: " << game.habitacio_inicial << "\n";
|
file << " habitacio_inicial: " << game.habitacio_inicial << "\n";
|
||||||
file << " piramide_inicial: " << game.piramide_inicial << "\n";
|
file << " piramide_inicial: " << game.piramide_inicial << "\n";
|
||||||
file << " vides: " << game.vides << "\n";
|
file << " vides: " << game.vides << "\n";
|
||||||
|
file << " diamants_inicial: " << game.diamants_inicial << "\n";
|
||||||
file << " use_new_logo: " << (game.use_new_logo ? "true" : "false") << "\n";
|
file << " use_new_logo: " << (game.use_new_logo ? "true" : "false") << "\n";
|
||||||
file << " show_title_credits: " << (game.show_title_credits ? "true" : "false") << "\n";
|
file << " show_title_credits: " << (game.show_title_credits ? "true" : "false") << "\n";
|
||||||
file << "\n";
|
file << "\n";
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ namespace Options {
|
|||||||
int habitacio_inicial{Defaults::Game::HABITACIO_INICIAL};
|
int habitacio_inicial{Defaults::Game::HABITACIO_INICIAL};
|
||||||
int piramide_inicial{Defaults::Game::PIRAMIDE_INICIAL};
|
int piramide_inicial{Defaults::Game::PIRAMIDE_INICIAL};
|
||||||
int vides{Defaults::Game::VIDES};
|
int vides{Defaults::Game::VIDES};
|
||||||
|
int diamants_inicial{Defaults::Game::DIAMANTS_INICIAL};
|
||||||
bool use_new_logo{Defaults::Game::USE_NEW_LOGO};
|
bool use_new_logo{Defaults::Game::USE_NEW_LOGO};
|
||||||
bool show_title_credits{Defaults::Game::SHOW_TITLE_CREDITS};
|
bool show_title_credits{Defaults::Game::SHOW_TITLE_CREDITS};
|
||||||
};
|
};
|
||||||
|
|||||||
139
source/scenes/credits_scene.cpp
Normal file
139
source/scenes/credits_scene.cpp
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
#include "scenes/credits_scene.hpp"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#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"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Frames del cotxe: 8 posicions dins del sprite sheet final.gif. El
|
||||||
|
// vell doCredits tenia aquesta taula inline — la reproduïm idèntica.
|
||||||
|
struct CocheFrame {
|
||||||
|
Uint16 x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr CocheFrame COCHE_FRAMES[8] = {
|
||||||
|
{214, 152}, {214, 104}, {214, 56}, {214, 104}, {214, 152}, {214, 8}, {108, 152}, {214, 8},
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr int CONTADOR_MAX = 3100; // ~62 s de crèdits a 20 ms/tick
|
||||||
|
constexpr int TICK_MS = 20; // JG_SetUpdateTicks heretat del doSlides previ
|
||||||
|
constexpr int BG_INDEX = 255;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace scenes {
|
||||||
|
|
||||||
|
CreditsScene::~CreditsScene() {
|
||||||
|
// No toquem la paleta activa: SetScreenPalette n'ha pres ownership.
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreditsScene::onEnter() {
|
||||||
|
// El vell doCredits no tocava música — heretava la del doSlides
|
||||||
|
// previ ("00000005.ogg"). Si l'escena s'arrenca directament (test
|
||||||
|
// amb piramide_inicial=8) no hi ha res que heretar, així que
|
||||||
|
// arranquem la mateixa pista només si no sona res. Inocu en el
|
||||||
|
// flux normal: JA_MUSIC_PLAYING fa que no la tornem a tocar.
|
||||||
|
if (JA_GetMusicState() != JA_MUSIC_PLAYING) {
|
||||||
|
playMusic("00000005.ogg");
|
||||||
|
}
|
||||||
|
|
||||||
|
vaddr2_ = SurfaceHandle("final.gif");
|
||||||
|
vaddr3_ = SurfaceHandle("finals.gif");
|
||||||
|
|
||||||
|
JD8_Palette pal = JD8_LoadPalette("final.gif");
|
||||||
|
JD8_SetScreenPalette(pal);
|
||||||
|
// `pal` passa a ser propietat de main_palette — no l'alliberem.
|
||||||
|
|
||||||
|
phase_ = Phase::Rolling;
|
||||||
|
contador_ = 1;
|
||||||
|
contador_acc_ms_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreditsScene::render() {
|
||||||
|
JD8_ClearScreen(BG_INDEX);
|
||||||
|
|
||||||
|
// Columna 1: scroll vertical del bloc (0,0,80,200) pujant des de
|
||||||
|
// y=200 fins que el contador supera 2750.
|
||||||
|
if (contador_ < 2750) {
|
||||||
|
JD8_BlitCKCut(115, 200 - (contador_ / 6), vaddr2_, 0, 0, 80, 200, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Columna 2: scroll vertical del bloc (85,0,120,140), arrenca
|
||||||
|
// a contador 1200 i s'atura (fix en y=20) a partir de 2250.
|
||||||
|
if ((contador_ > 1200) && (contador_ < 2280)) {
|
||||||
|
JD8_BlitCKCut(100, 200 - ((contador_ - 1200) / 6), vaddr2_, 85, 0, 120, 140, 0);
|
||||||
|
} else if (contador_ >= 2250) {
|
||||||
|
JD8_BlitCK(100, 20, vaddr2_, 85, 0, 120, 140, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fons: 4 capes parallax + cotxe només si l'usuari ha aconseguit
|
||||||
|
// tots els diamants (final "bo"). Altrament fons estàtic.
|
||||||
|
if (info::ctx.diamants == 16) {
|
||||||
|
JD8_BlitCKScroll(50, vaddr3_, ((contador_ >> 3) % 320) + 1, 0, 50, 255);
|
||||||
|
JD8_BlitCKScroll(50, vaddr3_, ((contador_ >> 2) % 320) + 1, 50, 50, 255);
|
||||||
|
JD8_BlitCKScroll(50, vaddr3_, ((contador_ >> 1) % 320) + 1, 100, 50, 255);
|
||||||
|
JD8_BlitCKScroll(50, vaddr3_, (contador_ % 320) + 1, 150, 50, 255);
|
||||||
|
|
||||||
|
const CocheFrame& cf = COCHE_FRAMES[coche_.frame()];
|
||||||
|
JD8_BlitCK(100, 50, vaddr2_, cf.x, cf.y, 106, 48, 255);
|
||||||
|
} else {
|
||||||
|
JD8_BlitCK(0, 50, vaddr3_, 0, 0, 320, 50, 255);
|
||||||
|
JD8_BlitCK(0, 50, vaddr3_, 0, 50, 320, 50, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Barres de marc que cobreixen els extrems del scroll vertical.
|
||||||
|
JD8_FillSquare(0, 50, BG_INDEX);
|
||||||
|
JD8_FillSquare(100, 10, BG_INDEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreditsScene::writeTrickIni() {
|
||||||
|
FILE* ini = std::fopen("trick.ini", "wb");
|
||||||
|
if (ini) {
|
||||||
|
std::fwrite("1", 1, 1, ini);
|
||||||
|
std::fclose(ini);
|
||||||
|
}
|
||||||
|
info::ctx.nou_personatge = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreditsScene::tick(int delta_ms) {
|
||||||
|
switch (phase_) {
|
||||||
|
case Phase::Rolling: {
|
||||||
|
// Avancem el contador en passos discrets de 20 ms, igual
|
||||||
|
// que feia JG_ShouldUpdate(20) al vell doCredits.
|
||||||
|
contador_acc_ms_ += delta_ms;
|
||||||
|
while (contador_acc_ms_ >= TICK_MS) {
|
||||||
|
contador_acc_ms_ -= TICK_MS;
|
||||||
|
++contador_;
|
||||||
|
}
|
||||||
|
|
||||||
|
coche_.tick(delta_ms);
|
||||||
|
render();
|
||||||
|
|
||||||
|
if (JI_AnyKey() || contador_ >= CONTADOR_MAX) {
|
||||||
|
writeTrickIni();
|
||||||
|
fade_.startFadeOut();
|
||||||
|
phase_ = Phase::FadingOut;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Phase::FadingOut:
|
||||||
|
fade_.tick(delta_ms);
|
||||||
|
if (fade_.done()) {
|
||||||
|
info::ctx.num_piramide = 255;
|
||||||
|
phase_ = Phase::Done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Phase::Done:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace scenes
|
||||||
52
source/scenes/credits_scene.hpp
Normal file
52
source/scenes/credits_scene.hpp
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/jail/jdraw8.hpp"
|
||||||
|
#include "scenes/frame_animator.hpp"
|
||||||
|
#include "scenes/palette_fade.hpp"
|
||||||
|
#include "scenes/scene.hpp"
|
||||||
|
#include "scenes/surface_handle.hpp"
|
||||||
|
|
||||||
|
namespace scenes {
|
||||||
|
|
||||||
|
// Crèdits finals del joc. Reemplaça `ModuleSequence::doCredits()`.
|
||||||
|
//
|
||||||
|
// Flux:
|
||||||
|
// 1. Carrega final.gif (sprites de crèdits) i finals.gif (fons).
|
||||||
|
// 2. Mostra els crèdits amb scroll vertical de 2 columnes durant
|
||||||
|
// ~62 segons (contador 0..3100 × 20 ms).
|
||||||
|
// 3. Si `info::ctx.diamants == 16`, pinta addicionalment un parallax
|
||||||
|
// de 4 capes amb cotxe animat (8 frames). Si no, 2 blits fixos.
|
||||||
|
// 4. Al acabar (per tecla o per contador), crea el fitxer `trick.ini`
|
||||||
|
// i activa `info::ctx.nou_personatge`.
|
||||||
|
// 5. Fade-out de paleta. Torna a la intro (num_piramide = 255).
|
||||||
|
//
|
||||||
|
// Registrada al SceneRegistry amb state_key = 8.
|
||||||
|
class CreditsScene : public Scene {
|
||||||
|
public:
|
||||||
|
CreditsScene() = default;
|
||||||
|
~CreditsScene() override;
|
||||||
|
|
||||||
|
void onEnter() override;
|
||||||
|
void tick(int delta_ms) override;
|
||||||
|
bool done() const override { return phase_ == Phase::Done; }
|
||||||
|
int nextState() const override { return 1; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class Phase { Rolling,
|
||||||
|
FadingOut,
|
||||||
|
Done };
|
||||||
|
|
||||||
|
void render();
|
||||||
|
void writeTrickIni();
|
||||||
|
|
||||||
|
SurfaceHandle vaddr2_; // final.gif (sprites i coches)
|
||||||
|
SurfaceHandle vaddr3_; // finals.gif (fons / parallax)
|
||||||
|
PaletteFade fade_;
|
||||||
|
FrameAnimator coche_{8, 60, true}; // 8 frames × 60 ms (~3 × 20 ms tick vell)
|
||||||
|
|
||||||
|
Phase phase_{Phase::Rolling};
|
||||||
|
int contador_{1};
|
||||||
|
int contador_acc_ms_{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace scenes
|
||||||
Reference in New Issue
Block a user