208 lines
6.3 KiB
C++
208 lines
6.3 KiB
C++
#include "game/scenes/slides_scene.hpp"
|
||
|
||
#include <algorithm>
|
||
#include <cstdlib>
|
||
#include <cstring>
|
||
|
||
#include "core/audio/audio.hpp"
|
||
#include "core/jail/jdraw8.hpp"
|
||
#include "core/jail/jinput.hpp"
|
||
#include "game/info.hpp"
|
||
#include "game/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() {
|
||
delete[] 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("final.ogg", 1)`.
|
||
playMusic("music/final.ogg", 1);
|
||
arxiu = (Info::ctx.diners < 200) ? "gfx/intro2.gif" : "gfx/intro3.gif";
|
||
} else {
|
||
arxiu = "gfx/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_ = new Color[256];
|
||
std::memcpy(pal_active_, pal_aux_, 768);
|
||
Jd8::setScreenPalette(pal_active_);
|
||
|
||
Jd8::clearScreen(BG_COLOR_INDEX);
|
||
|
||
phase_ = Phase::SLIDE1_ENTER;
|
||
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) {
|
||
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:
|
||
tickSlideEnter(delta_ms);
|
||
break;
|
||
case Phase::SLIDE1_HOLD:
|
||
case Phase::SLIDE2_HOLD:
|
||
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:
|
||
tickFadeOutIntermediate(delta_ms);
|
||
break;
|
||
case Phase::FADE_FINAL:
|
||
tickFinalFade(delta_ms);
|
||
break;
|
||
case Phase::DONE:
|
||
break;
|
||
}
|
||
}
|
||
|
||
} // namespace Scenes
|