147 lines
4.8 KiB
C++
147 lines
4.8 KiB
C++
#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 gfx/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 ("music/final.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("music/final.ogg");
|
|
}
|
|
|
|
vaddr2_ = SurfaceHandle("gfx/final.gif");
|
|
vaddr3_ = SurfaceHandle("gfx/finals.gif");
|
|
|
|
JD8_Palette pal = JD8_LoadPalette("gfx/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
|