Compare commits
5 Commits
6125277d70
...
4e18f83ec5
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e18f83ec5 | |||
| f9346add79 | |||
| b3ff620c81 | |||
| d343e719ca | |||
| e18b7321eb |
@@ -58,7 +58,7 @@ The scenes layer itself lives in [source/scenes/](source/scenes/): `scene.hpp` (
|
|||||||
- Collision detection, scoring, lives, level progression
|
- Collision detection, scoring, lives, level progression
|
||||||
- Visible animation cadence (once translated to ms, must look identical)
|
- Visible animation cadence (once translated to ms, must look identical)
|
||||||
- Difficulty curves and cinematic timings
|
- Difficulty curves and cinematic timings
|
||||||
- Cheat codes (`reviu`, `alone`, `obert`) — currently broken, should be restored
|
- Cheat codes (`reviu`, `alone`, `obert`)
|
||||||
- Original palettes, fades, music cues
|
- Original palettes, fades, music cues
|
||||||
|
|
||||||
**Free to change** (internal representation):
|
**Free to change** (internal representation):
|
||||||
@@ -235,10 +235,10 @@ JD8_Flip produces ABGR byte order: `0xFF000000 + R + (G<<8) + (B<<16)`. SDL text
|
|||||||
### Known Issues & Technical Debt
|
### Known Issues & Technical Debt
|
||||||
|
|
||||||
1. **gif.h cannot be included twice**: Functions are not `static` or `inline`, causing multiple definition errors. Text class uses `extern` forward declarations as workaround
|
1. **gif.h cannot be included twice**: Functions are not `static` or `inline`, causing multiple definition errors. Text class uses `extern` forward declarations as workaround
|
||||||
2. **Cheats are broken (`reviu`, `alone`, `obert`)**: `JI_CheatActivated` in [jinput.cpp:46](source/core/jail/jinput.cpp#L46) compares `SDL_Scancode` values (e.g. `SDL_SCANCODE_R`=21) against ASCII chars (`'r'`=114). They never match. Regression from SDL3 migration. **Now fixable** — scheduled for Phase 1 of modernization since jail is no longer off-limits.
|
2. ~~**Cheats are broken (`reviu`, `alone`, `obert`)**~~: Fixed. `JI_moveCheats` tradueix `SDL_Scancode` → ASCII via `scancode_to_ascii` abans de ficar-los al buffer ([jinput.cpp:32-37, 55-61](source/core/jail/jinput.cpp#L32-L61)), i `JI_CheatActivated` compara ASCII amb ASCII.
|
||||||
3. **No sound effects in game**: Game code never calls `JA_PlaySound*`/`JA_LoadSound` — only music via `JA_PlayMusic`/`JA_FadeOutMusic`. The SONS and VOL SONS menu items control volume of an empty channel pool. Infrastructure ready for future SFX.
|
3. **No sound effects in game**: Game code never calls `JA_PlaySound*`/`JA_LoadSound` — only music via `JA_PlayMusic`/`JA_FadeOutMusic`. The SONS and VOL SONS menu items control volume of an empty channel pool. Infrastructure ready for future SFX.
|
||||||
4. **Raw `malloc`/`free` in gameplay structs**: `Sprite`/`Entitat` use `malloc` for `Frame[]` and `Animacio[]`; `jfile.cpp` uses a global `scratch[255]` buffer (UB under concurrent calls); `jail_audio.cpp` mixes `new`/`malloc`/`SDL_malloc`. Scheduled for Phase 1 (RAII pass).
|
4. ~~**Raw `malloc`/`free` in gameplay structs**~~: Majoritàriament arreglat. `Sprite`/`Entitat` usen `std::vector<Frame>` i `std::vector<Animacio>` ([sprite.hpp](source/game/sprite.hpp)). `jfile.cpp` ja no té el global `scratch[255]` (substituït per `thread_local std::string`). L'API `file_getfilebuffer` (que tornava raw `char*` amb `malloc`) s'ha substituït per `file_readfile` que retorna `std::vector<char>` RAII — elimina els leaks silenciosos que hi havia a `JD8_LoadPalette`, `ModuleGame::Go()` i `scenes::playMusic`. Queda `jail_audio.hpp` barrejant `new`/`malloc`/`SDL_malloc` de forma pairada i correcta (no leak), pendent de polir amb `std::unique_ptr` quan toque.
|
||||||
5. **Blocking loops in cinematics and fades**: `ModuleSequence::doIntro()` has 15+ `while(!JG_ShouldUpdate())` spin-waits; `JD8_FadeOut`/`JD8_FadeToPal` run 32 internal iterations calling `JD8_Flip`. Incompatible with `SDL_AppIterate`. Scheduled for Phase 2 (state-machine refactor).
|
5. ~~**Blocking loops in cinematics and fades**~~: Fixed. La migració completa de `ModuleSequence::do*()` a la capa `scenes::` (Steps 1–9) ha eliminat tots els `while(!JG_ShouldUpdate())` i `wait_frame_or_skip()`. Les cinemàtiques ara són tick-based amb acumuladors ms. `JD8_FadeOut`/`JD8_FadeToPal` encara tenen el seu bucle intern de 32 passos (usat per a transicions fora d'escena com al final de `ModuleGame`); el wrapper tick-based `scenes::PaletteFade` el consumeix un pas per tick quan es crida des d'una escena.
|
||||||
6. ~~**`SDL_AddTimer` in audio**~~: Fixed in Phase 3. `jail_audio` is now a header-only `inline` module (single `.cpp` stub only hosts the `stb_vorbis` implementation to avoid multiple definitions). Music uses true streaming via `stb_vorbis_open_memory` + `JA_PumpMusic` with a 0.5s low-water-mark instead of decoding the whole OGG into RAM. Mixing/fade update runs manually via `JA_Update()` called once per frame from `Director::run()`. Ported from the `jaildoctors_dilemma` codebase.
|
6. ~~**`SDL_AddTimer` in audio**~~: Fixed in Phase 3. `jail_audio` is now a header-only `inline` module (single `.cpp` stub only hosts the `stb_vorbis` implementation to avoid multiple definitions). Music uses true streaming via `stb_vorbis_open_memory` + `JA_PumpMusic` with a 0.5s low-water-mark instead of decoding the whole OGG into RAM. Mixing/fade update runs manually via `JA_Update()` called once per frame from `Director::run()`. Ported from the `jaildoctors_dilemma` codebase.
|
||||||
7. ~~**Game thread + `publishFrame` mutex/cv**~~: Fixed in Phase 4+5. Replaced by a cooperative `GameFiber` (ucontext on POSIX, Fibers API on Windows). `JD8_Flip()` calls `GameFiber::yield()`, Director calls `GameFiber::resume()` once per frame. Zero threads, zero mutexes. Emscripten fiber backend still pending for Phase 7.
|
7. ~~**Game thread + `publishFrame` mutex/cv**~~: Fixed in Phase 4+5. Replaced by a cooperative `GameFiber` (ucontext on POSIX, Fibers API on Windows). `JD8_Flip()` calls `GameFiber::yield()`, Director calls `GameFiber::resume()` once per frame. Zero threads, zero mutexes. Emscripten fiber backend still pending for Phase 7.
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ 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/intro_scene.cpp
|
||||||
|
source/scenes/intro_sprites_scene.cpp
|
||||||
source/scenes/slides_scene.cpp
|
source/scenes/slides_scene.cpp
|
||||||
source/scenes/credits_scene.cpp
|
source/scenes/credits_scene.cpp
|
||||||
source/scenes/secreta_scene.cpp
|
source/scenes/secreta_scene.cpp
|
||||||
@@ -65,7 +67,6 @@ set(APP_SOURCES
|
|||||||
source/game/mapa.cpp
|
source/game/mapa.cpp
|
||||||
source/game/marcador.cpp
|
source/game/marcador.cpp
|
||||||
source/game/modulegame.cpp
|
source/game/modulegame.cpp
|
||||||
source/game/modulesequence.cpp
|
|
||||||
source/game/momia.cpp
|
source/game/momia.cpp
|
||||||
source/game/prota.cpp
|
source/game/prota.cpp
|
||||||
source/game/sprite.cpp
|
source/game/sprite.cpp
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#define STB_VORBIS_HEADER_ONLY
|
#define STB_VORBIS_HEADER_ONLY
|
||||||
#include "external/stb_vorbis.h"
|
#include "external/stb_vorbis.h"
|
||||||
|
|
||||||
@@ -48,13 +51,15 @@ struct JA_Channel_t {
|
|||||||
struct JA_Music_t {
|
struct JA_Music_t {
|
||||||
SDL_AudioSpec spec{SDL_AUDIO_S16, 2, 48000};
|
SDL_AudioSpec spec{SDL_AUDIO_S16, 2, 48000};
|
||||||
|
|
||||||
// OGG comprimit en memòria. Propietat nostra; es copia des del fitxer una
|
// OGG comprimit en memòria. Propietat nostra; es copia des del buffer
|
||||||
// sola vegada en JA_LoadMusic i es descomprimix en chunks per streaming.
|
// d'entrada una sola vegada en JA_LoadMusic i es descomprimix en chunks
|
||||||
Uint8* ogg_data{nullptr};
|
// per streaming. Com que stb_vorbis guarda un punter persistent al
|
||||||
Uint32 ogg_length{0};
|
// `.data()` d'aquest vector, no el podem resize'jar un cop establert
|
||||||
|
// (una reallocation invalidaria el punter que el decoder conserva).
|
||||||
|
std::vector<Uint8> ogg_data;
|
||||||
stb_vorbis* vorbis{nullptr}; // handle del decoder, viu tot el cicle del JA_Music_t
|
stb_vorbis* vorbis{nullptr}; // handle del decoder, viu tot el cicle del JA_Music_t
|
||||||
|
|
||||||
char* filename{nullptr};
|
std::string filename;
|
||||||
|
|
||||||
int times{0}; // loops restants (-1 = infinit, 0 = un sol play)
|
int times{0}; // loops restants (-1 = infinit, 0 = un sol play)
|
||||||
SDL_AudioStream* stream{nullptr};
|
SDL_AudioStream* stream{nullptr};
|
||||||
@@ -200,26 +205,23 @@ inline void JA_Quit() {
|
|||||||
inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) {
|
inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) {
|
||||||
if (!buffer || length == 0) return nullptr;
|
if (!buffer || length == 0) return nullptr;
|
||||||
|
|
||||||
// Còpia del OGG comprimit: stb_vorbis llig de forma persistent aquesta
|
// Allocem el JA_Music_t primer per aprofitar el seu `std::vector<Uint8>`
|
||||||
// memòria mentre el handle estiga viu, així que hem de posseir-la nosaltres.
|
// com a propietari del OGG comprimit. stb_vorbis guarda un punter
|
||||||
Uint8* ogg_copy = static_cast<Uint8*>(SDL_malloc(length));
|
// persistent al buffer; com que ací no el resize'jem, el .data() és
|
||||||
if (!ogg_copy) return nullptr;
|
// estable durant tot el cicle de vida del music.
|
||||||
SDL_memcpy(ogg_copy, buffer, length);
|
auto* music = new JA_Music_t();
|
||||||
|
music->ogg_data.assign(buffer, buffer + length);
|
||||||
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
stb_vorbis* vorbis = stb_vorbis_open_memory(ogg_copy, static_cast<int>(length), &error, nullptr);
|
music->vorbis = stb_vorbis_open_memory(music->ogg_data.data(),
|
||||||
if (!vorbis) {
|
static_cast<int>(length), &error, nullptr);
|
||||||
SDL_free(ogg_copy);
|
if (!music->vorbis) {
|
||||||
SDL_Log("JA_LoadMusic: stb_vorbis_open_memory failed (error %d)", error);
|
SDL_Log("JA_LoadMusic: stb_vorbis_open_memory failed (error %d)", error);
|
||||||
|
delete music;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* music = new JA_Music_t();
|
const stb_vorbis_info info = stb_vorbis_get_info(music->vorbis);
|
||||||
music->ogg_data = ogg_copy;
|
|
||||||
music->ogg_length = length;
|
|
||||||
music->vorbis = vorbis;
|
|
||||||
|
|
||||||
const stb_vorbis_info info = stb_vorbis_get_info(vorbis);
|
|
||||||
music->spec.channels = info.channels;
|
music->spec.channels = info.channels;
|
||||||
music->spec.freq = static_cast<int>(info.sample_rate);
|
music->spec.freq = static_cast<int>(info.sample_rate);
|
||||||
music->spec.format = SDL_AUDIO_S16;
|
music->spec.format = SDL_AUDIO_S16;
|
||||||
@@ -228,38 +230,11 @@ inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) {
|
|||||||
return music;
|
return music;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overload de compatibilitat: accepta filename per a no trencar els call
|
// Overload amb filename — els callers l'usen per poder comparar la música
|
||||||
// sites existents que passaven el nom del fitxer junt amb el buffer.
|
// en curs amb JA_GetMusicFilename() i no rearrancar-la si ja és la mateixa.
|
||||||
inline JA_Music_t* JA_LoadMusic(Uint8* buffer, Uint32 length, const char* filename) {
|
inline JA_Music_t* JA_LoadMusic(Uint8* buffer, Uint32 length, const char* filename) {
|
||||||
JA_Music_t* music = JA_LoadMusic(static_cast<const Uint8*>(buffer), length);
|
JA_Music_t* music = JA_LoadMusic(static_cast<const Uint8*>(buffer), length);
|
||||||
if (music && filename) {
|
if (music && filename) music->filename = filename;
|
||||||
music->filename = static_cast<char*>(malloc(strlen(filename) + 1));
|
|
||||||
if (music->filename) strcpy(music->filename, filename);
|
|
||||||
}
|
|
||||||
return music;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline JA_Music_t* JA_LoadMusic(const char* filename) {
|
|
||||||
FILE* f = fopen(filename, "rb");
|
|
||||||
if (!f) return nullptr;
|
|
||||||
fseek(f, 0, SEEK_END);
|
|
||||||
long fsize = ftell(f);
|
|
||||||
fseek(f, 0, SEEK_SET);
|
|
||||||
auto* buffer = static_cast<Uint8*>(malloc(fsize + 1));
|
|
||||||
if (!buffer) {
|
|
||||||
fclose(f);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (fread(buffer, fsize, 1, f) != 1) {
|
|
||||||
fclose(f);
|
|
||||||
free(buffer);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
JA_Music_t* music = JA_LoadMusic(buffer, static_cast<Uint32>(fsize), filename);
|
|
||||||
free(buffer);
|
|
||||||
|
|
||||||
return music;
|
return music;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,10 +265,10 @@ inline void JA_PlayMusic(JA_Music_t* music, const int loop = -1) {
|
|||||||
if (!SDL_BindAudioStream(sdlAudioDevice, current_music->stream)) printf("[ERROR] SDL_BindAudioStream failed!\n");
|
if (!SDL_BindAudioStream(sdlAudioDevice, current_music->stream)) printf("[ERROR] SDL_BindAudioStream failed!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* JA_GetMusicFilename(JA_Music_t* music = nullptr) {
|
inline const char* JA_GetMusicFilename(JA_Music_t* music = nullptr) {
|
||||||
if (!music) music = current_music;
|
if (!music) music = current_music;
|
||||||
if (!music) return nullptr;
|
if (!music || music->filename.empty()) return nullptr;
|
||||||
return music->filename;
|
return music->filename.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void JA_PauseMusic() {
|
inline void JA_PauseMusic() {
|
||||||
@@ -352,8 +327,8 @@ inline void JA_DeleteMusic(JA_Music_t* music) {
|
|||||||
}
|
}
|
||||||
if (music->stream) SDL_DestroyAudioStream(music->stream);
|
if (music->stream) SDL_DestroyAudioStream(music->stream);
|
||||||
if (music->vorbis) stb_vorbis_close(music->vorbis);
|
if (music->vorbis) stb_vorbis_close(music->vorbis);
|
||||||
SDL_free(music->ogg_data);
|
// ogg_data (std::vector) i filename (std::string) s'alliberen sols
|
||||||
free(music->filename);
|
// al destructor de JA_Music_t.
|
||||||
delete music;
|
delete music;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,13 +45,10 @@ JD8_Surface JD8_NewSurface() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JD8_Surface JD8_LoadSurface(const char* file) {
|
JD8_Surface JD8_LoadSurface(const char* file) {
|
||||||
int filesize = 0;
|
auto buffer = file_readfile(file);
|
||||||
char* buffer = file_getfilebuffer(file, filesize);
|
|
||||||
|
|
||||||
unsigned short w, h;
|
unsigned short w, h;
|
||||||
Uint8* pixels = LoadGif((unsigned char*)buffer, &w, &h);
|
Uint8* pixels = LoadGif(reinterpret_cast<unsigned char*>(buffer.data()), &w, &h);
|
||||||
|
|
||||||
free(buffer);
|
|
||||||
|
|
||||||
if (pixels == NULL) {
|
if (pixels == NULL) {
|
||||||
printf("Unable to load bitmap: %s\n", SDL_GetError());
|
printf("Unable to load bitmap: %s\n", SDL_GetError());
|
||||||
@@ -66,13 +63,8 @@ JD8_Surface JD8_LoadSurface(const char* file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JD8_Palette JD8_LoadPalette(const char* file) {
|
JD8_Palette JD8_LoadPalette(const char* file) {
|
||||||
int filesize = 0;
|
auto buffer = file_readfile(file);
|
||||||
char* buffer = NULL;
|
return (JD8_Palette)LoadPalette(reinterpret_cast<unsigned char*>(buffer.data()));
|
||||||
buffer = file_getfilebuffer(file, filesize);
|
|
||||||
|
|
||||||
JD8_Palette palette = (JD8_Palette)LoadPalette((unsigned char*)buffer);
|
|
||||||
|
|
||||||
return palette;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JD8_SetScreenPalette(JD8_Palette palette) {
|
void JD8_SetScreenPalette(JD8_Palette palette) {
|
||||||
|
|||||||
@@ -147,12 +147,12 @@ FILE* file_getfilepointer(const char* resourcename, int& filesize, const bool bi
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* file_getfilebuffer(const char* resourcename, int& filesize, const bool zero_terminate) {
|
std::vector<char> file_readfile(const char* resourcename) {
|
||||||
|
int filesize = 0;
|
||||||
FILE* f = file_getfilepointer(resourcename, filesize, true);
|
FILE* f = file_getfilepointer(resourcename, filesize, true);
|
||||||
if (!f) return nullptr;
|
if (!f) return {};
|
||||||
char* buffer = static_cast<char*>(malloc(zero_terminate ? filesize + 1 : filesize));
|
std::vector<char> buffer(filesize);
|
||||||
fread(buffer, filesize, 1, f);
|
fread(buffer.data(), filesize, 1, f);
|
||||||
if (zero_terminate) buffer[filesize] = 0;
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#define SOURCE_FILE 0
|
#define SOURCE_FILE 0
|
||||||
#define SOURCE_FOLDER 1
|
#define SOURCE_FOLDER 1
|
||||||
|
|
||||||
@@ -12,7 +14,12 @@ void file_setresourcefolder(const char* str);
|
|||||||
void file_setsource(const int src);
|
void file_setsource(const int src);
|
||||||
|
|
||||||
FILE* file_getfilepointer(const char* resourcename, int& filesize, const bool binary = false);
|
FILE* file_getfilepointer(const char* resourcename, int& filesize, const bool binary = false);
|
||||||
char* file_getfilebuffer(const char* resourcename, int& filesize, const bool zero_terminate = false);
|
|
||||||
|
// Llig tot el contingut d'un recurs (fitxer solt o entrada del .jrf).
|
||||||
|
// Retorna un vector buit si el recurs no existeix. El vector es destrueix
|
||||||
|
// automàticament en eixir d'àmbit — no fa falta cap free() manual. Mida =
|
||||||
|
// bytes llegits (el buffer no està null-terminated).
|
||||||
|
std::vector<char> file_readfile(const char* resourcename);
|
||||||
|
|
||||||
const char* file_getconfigvalue(const char* key);
|
const char* file_getconfigvalue(const char* key);
|
||||||
void file_setconfigvalue(const char* key, const char* value);
|
void file_setconfigvalue(const char* key, const char* value);
|
||||||
|
|||||||
@@ -27,14 +27,12 @@ namespace Locale {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool load(const char* filename) {
|
bool load(const char* filename) {
|
||||||
int size = 0;
|
auto buffer = file_readfile(filename);
|
||||||
char* buffer = file_getfilebuffer(filename, size, true);
|
if (buffer.empty()) {
|
||||||
if (!buffer || size <= 0) {
|
|
||||||
std::cerr << "Locale: unable to load " << filename << '\n';
|
std::cerr << "Locale: unable to load " << filename << '\n';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::string content(buffer, size);
|
std::string content(buffer.data(), buffer.size());
|
||||||
free(buffer);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto yaml = fkyaml::node::deserialize(content);
|
auto yaml = fkyaml::node::deserialize(content);
|
||||||
|
|||||||
@@ -62,15 +62,13 @@ auto Text::nextCodepoint(const char*& ptr) -> uint32_t {
|
|||||||
// --- Càrrega de font ---
|
// --- Càrrega de font ---
|
||||||
|
|
||||||
void Text::loadFont(const char* fnt_file) {
|
void Text::loadFont(const char* fnt_file) {
|
||||||
int filesize = 0;
|
auto buffer = file_readfile(fnt_file);
|
||||||
char* buffer = file_getfilebuffer(fnt_file, filesize, true);
|
if (buffer.empty()) {
|
||||||
if (!buffer) {
|
|
||||||
std::cerr << "Text: unable to load font file: " << fnt_file << '\n';
|
std::cerr << "Text: unable to load font file: " << fnt_file << '\n';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::istringstream stream(std::string(buffer, filesize));
|
std::istringstream stream(std::string(buffer.data(), buffer.size()));
|
||||||
free(buffer);
|
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
int glyph_index = 0;
|
int glyph_index = 0;
|
||||||
@@ -128,15 +126,14 @@ void Text::loadFont(const char* fnt_file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Text::loadBitmap(const char* gif_file) {
|
void Text::loadBitmap(const char* gif_file) {
|
||||||
int filesize = 0;
|
auto buffer = file_readfile(gif_file);
|
||||||
char* buffer = file_getfilebuffer(gif_file, filesize);
|
if (buffer.empty()) {
|
||||||
if (!buffer) {
|
|
||||||
std::cerr << "Text: unable to load bitmap: " << gif_file << '\n';
|
std::cerr << "Text: unable to load bitmap: " << gif_file << '\n';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extrau dimensions del header GIF (bytes 6-7 = width, 8-9 = height, little-endian)
|
// Extrau dimensions del header GIF (bytes 6-7 = width, 8-9 = height, little-endian)
|
||||||
auto* raw = reinterpret_cast<unsigned char*>(buffer);
|
auto* raw = reinterpret_cast<unsigned char*>(buffer.data());
|
||||||
int w = raw[6] | (raw[7] << 8);
|
int w = raw[6] | (raw[7] << 8);
|
||||||
int h = raw[8] | (raw[9] << 8);
|
int h = raw[8] | (raw[9] << 8);
|
||||||
|
|
||||||
@@ -144,7 +141,6 @@ void Text::loadBitmap(const char* gif_file) {
|
|||||||
Uint8* pixels = LoadGif(raw, &gw, &gh);
|
Uint8* pixels = LoadGif(raw, &gw, &gh);
|
||||||
if (!pixels) {
|
if (!pixels) {
|
||||||
std::cerr << "Text: unable to decode GIF: " << gif_file << '\n';
|
std::cerr << "Text: unable to decode GIF: " << gif_file << '\n';
|
||||||
free(buffer);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +148,6 @@ void Text::loadBitmap(const char* gif_file) {
|
|||||||
bitmap_height_ = h;
|
bitmap_height_ = h;
|
||||||
bitmap_ = pixels;
|
bitmap_ = pixels;
|
||||||
|
|
||||||
free(buffer);
|
|
||||||
std::cout << "Text: bitmap loaded " << w << "x" << h << '\n';
|
std::cout << "Text: bitmap loaded " << w << "x" << h << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,11 @@
|
|||||||
#include "core/system/fiber.hpp"
|
#include "core/system/fiber.hpp"
|
||||||
#include "game/info.hpp"
|
#include "game/info.hpp"
|
||||||
#include "game/modulegame.hpp"
|
#include "game/modulegame.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/credits_scene.hpp"
|
||||||
#include "scenes/intro_new_logo_scene.hpp"
|
#include "scenes/intro_new_logo_scene.hpp"
|
||||||
|
#include "scenes/intro_scene.hpp"
|
||||||
#include "scenes/menu_scene.hpp"
|
#include "scenes/menu_scene.hpp"
|
||||||
#include "scenes/mort_scene.hpp"
|
#include "scenes/mort_scene.hpp"
|
||||||
#include "scenes/scene.hpp"
|
#include "scenes/scene.hpp"
|
||||||
@@ -37,10 +37,11 @@ Director* Director::instance_ = nullptr;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Entry del fiber del joc. Executa la màquina d'estats que alterna entre
|
// Entry del fiber del joc. Dispatcha a una escena segons l'estat actual:
|
||||||
// ModuleSequence (state=1) i ModuleGame (state=0) fins que el joc demana
|
// `gameState == 0` → ModuleGame (gameplay), `gameState == 1` → una
|
||||||
// eixir. Quan el joc crida JD8_Flip() des de dins d'aquest fiber, el
|
// `scenes::Scene` del registry triada per `info::ctx.num_piramide`. Cada
|
||||||
// control torna automàticament al Director.
|
// escena és tick-based; el JD8_Flip() entre ticks cedeix al Director
|
||||||
|
// via `GameFiber::yield()`.
|
||||||
void gameFiberEntry() {
|
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;
|
||||||
@@ -59,51 +60,39 @@ void gameFiberEntry() {
|
|||||||
|
|
||||||
int gameState = 1;
|
int gameState = 1;
|
||||||
while (gameState != -1 && !JG_Quitting()) {
|
while (gameState != -1 && !JG_Quitting()) {
|
||||||
// Mode "Scene nova": si el state actual és de seqüència i el
|
std::unique_ptr<scenes::Scene> scene;
|
||||||
// registry té una escena migrada per al num_piramide, l'executem
|
|
||||||
// amb un mini-loop tick-based. El codi de la Scene no toca
|
if (gameState == 0) {
|
||||||
// fibers; el JD8_Flip() entre ticks és el que cedeix al Director.
|
// Gameplay. ModuleGame és una scenes::Scene des de Phase A de
|
||||||
if (gameState == 1) {
|
// la migració — mateix mini-loop tick+flip que la resta.
|
||||||
// Replica del redirect que el `ModuleSequence::Go()` vell feia
|
scene = std::make_unique<ModuleGame>();
|
||||||
// al principi: si el jugador arriba a la piràmide Secreta (6)
|
} else {
|
||||||
// sense prou diners, salta directament als slides de fracàs (7).
|
// gameState == 1: dispatch al registry per num_piramide. El
|
||||||
// Cal fer-ho ací perquè el SceneRegistry consulta num_piramide
|
// vell ModuleSequence::Go() feia aquest redirect al principi:
|
||||||
// abans del fallback legacy; mentres doSecreta no estiga migrada
|
// si el jugador arriba a la Secreta (6) sense prou diners,
|
||||||
// també continuarà al Go() vell amb num_piramide ja corregida.
|
// salta als slides de fracàs (7) abans de buscar l'escena.
|
||||||
if (info::ctx.num_piramide == 6 && info::ctx.diners < 200) {
|
if (info::ctx.num_piramide == 6 && info::ctx.diners < 200) {
|
||||||
info::ctx.num_piramide = 7;
|
info::ctx.num_piramide = 7;
|
||||||
}
|
}
|
||||||
|
scene = scenes::SceneRegistry::instance().tryCreate(info::ctx.num_piramide);
|
||||||
if (auto scene = scenes::SceneRegistry::instance().tryCreate(info::ctx.num_piramide)) {
|
|
||||||
scene->onEnter();
|
|
||||||
Uint32 last = SDL_GetTicks();
|
|
||||||
while (!scene->done() && !JG_Quitting()) {
|
|
||||||
JI_Update(); // refresca key_pressed/any_key per a les escenes
|
|
||||||
const Uint32 now = SDL_GetTicks();
|
|
||||||
scene->tick(static_cast<int>(now - last));
|
|
||||||
last = now;
|
|
||||||
JD8_Flip(); // presenta i cedix al Director
|
|
||||||
}
|
|
||||||
gameState = scene->nextState();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback al codi legacy (encara no migrat a Scene).
|
if (!scene) {
|
||||||
switch (gameState) {
|
// State no registrat — indica un bug del dispatcher o del
|
||||||
case 0: {
|
// registre d'escenes. Eixim ordenadament en lloc de cremar CPU.
|
||||||
auto* moduleGame = new ModuleGame();
|
break;
|
||||||
gameState = moduleGame->Go();
|
|
||||||
delete moduleGame;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: {
|
|
||||||
auto* moduleSequence = new ModuleSequence();
|
|
||||||
gameState = moduleSequence->Go();
|
|
||||||
delete moduleSequence;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scene->onEnter();
|
||||||
|
Uint32 last = SDL_GetTicks();
|
||||||
|
while (!scene->done() && !JG_Quitting()) {
|
||||||
|
JI_Update(); // refresca key_pressed/any_key per a les escenes
|
||||||
|
const Uint32 now = SDL_GetTicks();
|
||||||
|
scene->tick(static_cast<int>(now - last));
|
||||||
|
last = now;
|
||||||
|
JD8_Flip(); // presenta i cedix al Director
|
||||||
|
}
|
||||||
|
gameState = scene->nextState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,10 +102,10 @@ void Director::init() {
|
|||||||
instance_ = new Director();
|
instance_ = new Director();
|
||||||
Gamepad::init();
|
Gamepad::init();
|
||||||
|
|
||||||
// Registre d'escenes migrades. Cada entrada = una funció del vell
|
// Registre d'escenes. Cada entrada = un state_key (`num_piramide`)
|
||||||
// ModuleSequence reescrita com a `scenes::*Scene`. Mentre vagen
|
// amb una factory de `scenes::Scene`. El gameFiberEntry consulta
|
||||||
// caient, el fallback al switch legacy de gameFiberEntry deixa de
|
// aquest registry per a tots els states de seqüència; si una clau
|
||||||
// rebre aquests states.
|
// no apareix ací, el fiber eixirà del loop.
|
||||||
auto& registry = scenes::SceneRegistry::instance();
|
auto& registry = scenes::SceneRegistry::instance();
|
||||||
registry.registerScene(0, [] { return std::make_unique<scenes::MenuScene>(); });
|
registry.registerScene(0, [] { return std::make_unique<scenes::MenuScene>(); });
|
||||||
registry.registerScene(100, [] { return std::make_unique<scenes::MortScene>(); });
|
registry.registerScene(100, [] { return std::make_unique<scenes::MortScene>(); });
|
||||||
@@ -133,14 +122,15 @@ void Director::init() {
|
|||||||
registry.registerScene(7, [] { return std::make_unique<scenes::SlidesScene>(); });
|
registry.registerScene(7, [] { return std::make_unique<scenes::SlidesScene>(); });
|
||||||
registry.registerScene(6, [] { return std::make_unique<scenes::SecretaScene>(); });
|
registry.registerScene(6, [] { return std::make_unique<scenes::SecretaScene>(); });
|
||||||
registry.registerScene(8, [] { return std::make_unique<scenes::CreditsScene>(); });
|
registry.registerScene(8, [] { return std::make_unique<scenes::CreditsScene>(); });
|
||||||
// IntroNewLogoScene només es registra quan `use_new_logo` està actiu;
|
// State 255 (intro): dues variants segons `Options::game.use_new_logo`.
|
||||||
// si no, la factory retorna nullptr i el gameFiberEntry cau al vell
|
// La factory tria a runtime — així es pot togglar des del menú sense
|
||||||
// ModuleSequence::doIntro() legacy que no ha sigut migrat encara.
|
// re-registrar. Les dues escenes construeixen una IntroSpritesScene
|
||||||
|
// com a sub-escena per a la part d'animacions de sprites.
|
||||||
registry.registerScene(255, []() -> std::unique_ptr<scenes::Scene> {
|
registry.registerScene(255, []() -> std::unique_ptr<scenes::Scene> {
|
||||||
if (Options::game.use_new_logo) {
|
if (Options::game.use_new_logo) {
|
||||||
return std::make_unique<scenes::IntroNewLogoScene>();
|
return std::make_unique<scenes::IntroNewLogoScene>();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return std::make_unique<scenes::IntroScene>();
|
||||||
});
|
});
|
||||||
|
|
||||||
GameFiber::init(gameFiberEntry);
|
GameFiber::init(gameFiberEntry);
|
||||||
|
|||||||
@@ -1,165 +1,204 @@
|
|||||||
#include "game/modulegame.hpp"
|
#include "game/modulegame.hpp"
|
||||||
|
|
||||||
#include "core/jail/jail_audio.hpp"
|
#include "core/jail/jail_audio.hpp"
|
||||||
#include "core/jail/jdraw8.hpp"
|
#include "core/jail/jdraw8.hpp"
|
||||||
#include "core/jail/jfile.hpp"
|
#include "core/jail/jfile.hpp"
|
||||||
#include "core/jail/jgame.hpp"
|
#include "core/jail/jgame.hpp"
|
||||||
#include "core/jail/jinput.hpp"
|
#include "core/jail/jinput.hpp"
|
||||||
|
|
||||||
ModuleGame::ModuleGame() {
|
ModuleGame::ModuleGame() {
|
||||||
this->gfx = JD8_LoadSurface(info::ctx.pepe_activat ? "frames2.gif" : "frames.gif");
|
this->gfx = JD8_LoadSurface(info::ctx.pepe_activat ? "frames2.gif" : "frames.gif");
|
||||||
JG_SetUpdateTicks(10);
|
JG_SetUpdateTicks(10);
|
||||||
|
|
||||||
this->sam = new Prota(this->gfx);
|
this->sam = new Prota(this->gfx);
|
||||||
this->mapa = new Mapa(this->gfx, this->sam);
|
this->mapa = new Mapa(this->gfx, this->sam);
|
||||||
this->marcador = new Marcador(this->gfx, this->sam);
|
this->marcador = new Marcador(this->gfx, this->sam);
|
||||||
if (info::ctx.num_piramide == 2) {
|
if (info::ctx.num_piramide == 2) {
|
||||||
this->bola = new Bola(this->gfx, this->sam);
|
this->bola = new Bola(this->gfx, this->sam);
|
||||||
} else {
|
} else {
|
||||||
this->bola = NULL;
|
this->bola = nullptr;
|
||||||
}
|
}
|
||||||
this->momies = NULL;
|
this->momies = nullptr;
|
||||||
|
|
||||||
this->final = 0;
|
this->iniciarMomies();
|
||||||
this->iniciarMomies();
|
}
|
||||||
}
|
|
||||||
|
ModuleGame::~ModuleGame() {
|
||||||
ModuleGame::~ModuleGame(void) {
|
if (this->bola != nullptr) delete this->bola;
|
||||||
JD8_FadeOut();
|
if (this->momies != nullptr) {
|
||||||
|
this->momies->clear();
|
||||||
if (this->bola != NULL) delete this->bola;
|
delete this->momies;
|
||||||
if (this->momies != NULL) {
|
}
|
||||||
this->momies->clear();
|
delete this->marcador;
|
||||||
delete this->momies;
|
delete this->mapa;
|
||||||
}
|
delete this->sam;
|
||||||
delete this->marcador;
|
|
||||||
delete this->mapa;
|
JD8_FreeSurface(this->gfx);
|
||||||
delete this->sam;
|
}
|
||||||
|
|
||||||
JD8_FreeSurface(this->gfx);
|
void ModuleGame::onEnter() {
|
||||||
}
|
// Primera Draw per omplir `screen` amb el contingut del gameplay
|
||||||
|
// abans que el fade-in arranque. Si no, les primeres iteracions del
|
||||||
int ModuleGame::Go() {
|
// fade interpolarien cap a una paleta amb pantalla buida.
|
||||||
this->Draw();
|
this->Draw();
|
||||||
|
|
||||||
const char* music = info::ctx.num_piramide == 3 ? "00000008.ogg" : (info::ctx.num_piramide == 2 ? "00000007.ogg" : (info::ctx.num_piramide == 6 ? "00000002.ogg" : "00000006.ogg"));
|
const char* music = info::ctx.num_piramide == 3 ? "00000008.ogg"
|
||||||
const char* current_music = JA_GetMusicFilename();
|
: info::ctx.num_piramide == 2 ? "00000007.ogg"
|
||||||
if ((JA_GetMusicState() != JA_MUSIC_PLAYING) || !(strcmp(music, current_music) == 0)) {
|
: info::ctx.num_piramide == 6 ? "00000002.ogg"
|
||||||
int size;
|
: "00000006.ogg";
|
||||||
char* buffer = file_getfilebuffer(music, size);
|
const char* current_music = JA_GetMusicFilename();
|
||||||
JA_PlayMusic(JA_LoadMusic((Uint8*)buffer, size, music));
|
if ((JA_GetMusicState() != JA_MUSIC_PLAYING) || !current_music ||
|
||||||
}
|
strcmp(music, current_music) != 0) {
|
||||||
|
auto buffer = file_readfile(music);
|
||||||
JD8_FadeToPal(JD8_LoadPalette(info::ctx.pepe_activat ? "frames2.gif" : "frames.gif"));
|
JA_PlayMusic(JA_LoadMusic(reinterpret_cast<Uint8*>(buffer.data()),
|
||||||
|
static_cast<Uint32>(buffer.size()), music));
|
||||||
while (this->final == 0 && !JG_Quitting()) {
|
}
|
||||||
this->Draw();
|
|
||||||
this->Update();
|
// Arranca el fade-in tick-based. El `PaletteFade` avança un pas (de
|
||||||
}
|
// 32) per cada tick; durant aquesta fase el gameplay no corre,
|
||||||
|
// només Draw+fade. Substituïx la crida bloquejant `JD8_FadeToPal`.
|
||||||
// JS_FadeOutMusic();
|
fade_.startFadeTo(JD8_LoadPalette(info::ctx.pepe_activat ? "frames2.gif" : "frames.gif"));
|
||||||
|
phase_ = Phase::FadingIn;
|
||||||
if (this->final == 1) {
|
}
|
||||||
info::ctx.num_habitacio++;
|
|
||||||
if (info::ctx.num_habitacio == 6) {
|
void ModuleGame::tick(int delta_ms) {
|
||||||
info::ctx.num_habitacio = 1;
|
switch (phase_) {
|
||||||
info::ctx.num_piramide++;
|
case Phase::FadingIn:
|
||||||
}
|
// No redibuixem durant el fade: el `screen` ja va ser omplit
|
||||||
if (info::ctx.num_piramide == 6 && info::ctx.num_habitacio == 2) info::ctx.num_piramide++;
|
// per la Draw() d'onEnter. Només el JD8_Flip del caller muta
|
||||||
} else if (this->final == 2) {
|
// pixel_data segons la paleta que avança pas a pas.
|
||||||
info::ctx.num_piramide = 100;
|
fade_.tick(delta_ms);
|
||||||
}
|
if (fade_.done()) phase_ = Phase::Playing;
|
||||||
|
break;
|
||||||
if (JG_Quitting()) {
|
|
||||||
return -1;
|
case Phase::Playing:
|
||||||
} else {
|
this->Draw();
|
||||||
if (info::ctx.num_habitacio == 1 || info::ctx.num_piramide == 100 || info::ctx.num_piramide == 7) {
|
this->Update();
|
||||||
return 1;
|
if (this->final_ != 0) {
|
||||||
} else {
|
this->applyFinalTransitions();
|
||||||
return 0;
|
fade_.startFadeOut();
|
||||||
}
|
phase_ = Phase::FadingOut;
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
|
|
||||||
void ModuleGame::Draw() {
|
case Phase::FadingOut:
|
||||||
this->mapa->draw();
|
// No redibuixem: el `screen` té l'últim frame pintat per la
|
||||||
this->marcador->draw();
|
// fase Playing (just abans que Update() setegés `final_`).
|
||||||
this->sam->draw();
|
// El vell `JD8_FadeOut` feia exactament això — flips amb
|
||||||
if (this->momies != NULL) this->momies->draw();
|
// paleta fading però sense tocar el buffer. Redibuixar ací
|
||||||
if (this->bola != NULL) this->bola->draw();
|
// mostraria l'estat post-Update del sprite (p.ex. el prota
|
||||||
|
// "tornant" davant la porta després d'haver eixit).
|
||||||
JD8_Flip();
|
fade_.tick(delta_ms);
|
||||||
}
|
if (fade_.done()) phase_ = Phase::Done;
|
||||||
|
break;
|
||||||
void ModuleGame::Update() {
|
|
||||||
if (JG_ShouldUpdate()) {
|
case Phase::Done:
|
||||||
JI_Update();
|
break;
|
||||||
|
}
|
||||||
this->final = this->sam->update();
|
}
|
||||||
if (this->momies != NULL && this->momies->update()) {
|
|
||||||
Momia* seguent = this->momies->next;
|
int ModuleGame::nextState() const {
|
||||||
delete this->momies;
|
if (JG_Quitting()) return -1;
|
||||||
this->momies = seguent;
|
if (info::ctx.num_habitacio == 1 ||
|
||||||
info::ctx.momies--;
|
info::ctx.num_piramide == 100 ||
|
||||||
}
|
info::ctx.num_piramide == 7) {
|
||||||
if (this->bola != NULL) this->bola->update();
|
return 1;
|
||||||
this->mapa->update();
|
}
|
||||||
if (this->mapa->novaMomia()) {
|
return 0;
|
||||||
if (this->momies != NULL) {
|
}
|
||||||
this->momies->insertar(new Momia(this->gfx, true, 0, 0, this->sam));
|
|
||||||
info::ctx.momies++;
|
void ModuleGame::applyFinalTransitions() {
|
||||||
} else {
|
if (this->final_ == 1) {
|
||||||
this->momies = new Momia(this->gfx, true, 0, 0, this->sam);
|
info::ctx.num_habitacio++;
|
||||||
info::ctx.momies++;
|
if (info::ctx.num_habitacio == 6) {
|
||||||
}
|
info::ctx.num_habitacio = 1;
|
||||||
}
|
info::ctx.num_piramide++;
|
||||||
|
}
|
||||||
if (JI_CheatActivated("reviu")) info::ctx.vida = 5;
|
if (info::ctx.num_piramide == 6 && info::ctx.num_habitacio == 2) info::ctx.num_piramide++;
|
||||||
if (JI_CheatActivated("alone")) {
|
} else if (this->final_ == 2) {
|
||||||
if (this->momies != NULL) {
|
info::ctx.num_piramide = 100;
|
||||||
this->momies->clear();
|
}
|
||||||
delete this->momies;
|
}
|
||||||
this->momies = NULL;
|
|
||||||
info::ctx.momies = 0;
|
void ModuleGame::Draw() {
|
||||||
}
|
// No crida JD8_Flip — el caller (mini-loop del fiber, o Director a
|
||||||
}
|
// Phase B.2) ho fa després de cada tick.
|
||||||
if (JI_CheatActivated("obert")) {
|
this->mapa->draw();
|
||||||
for (int i = 0; i < 16; i++) {
|
this->marcador->draw();
|
||||||
this->mapa->tombes[i].costat[0] = true;
|
this->sam->draw();
|
||||||
this->mapa->tombes[i].costat[1] = true;
|
if (this->momies != nullptr) this->momies->draw();
|
||||||
this->mapa->tombes[i].costat[2] = true;
|
if (this->bola != nullptr) this->bola->draw();
|
||||||
this->mapa->tombes[i].costat[3] = true;
|
}
|
||||||
this->mapa->comprovaCaixa(i);
|
|
||||||
}
|
void ModuleGame::Update() {
|
||||||
}
|
if (JG_ShouldUpdate()) {
|
||||||
|
JI_Update();
|
||||||
if (JI_KeyPressed(SDL_SCANCODE_ESCAPE)) {
|
|
||||||
JG_QuitSignal();
|
this->final_ = this->sam->update();
|
||||||
}
|
if (this->momies != nullptr && this->momies->update()) {
|
||||||
}
|
Momia* seguent = this->momies->next;
|
||||||
}
|
delete this->momies;
|
||||||
|
this->momies = seguent;
|
||||||
void ModuleGame::iniciarMomies() {
|
info::ctx.momies--;
|
||||||
if (info::ctx.num_habitacio == 1) {
|
}
|
||||||
info::ctx.momies = 1;
|
if (this->bola != nullptr) this->bola->update();
|
||||||
} else {
|
this->mapa->update();
|
||||||
info::ctx.momies++;
|
if (this->mapa->novaMomia()) {
|
||||||
}
|
if (this->momies != nullptr) {
|
||||||
if (info::ctx.num_piramide == 6) info::ctx.momies = 8;
|
this->momies->insertar(new Momia(this->gfx, true, 0, 0, this->sam));
|
||||||
|
info::ctx.momies++;
|
||||||
int x = 20;
|
} else {
|
||||||
int y = 170;
|
this->momies = new Momia(this->gfx, true, 0, 0, this->sam);
|
||||||
bool dimonis = info::ctx.num_piramide == 6;
|
info::ctx.momies++;
|
||||||
for (int i = 0; i < info::ctx.momies; i++) {
|
}
|
||||||
if (this->momies == NULL) {
|
}
|
||||||
this->momies = new Momia(this->gfx, dimonis, x, y, this->sam);
|
|
||||||
} else {
|
if (JI_CheatActivated("reviu")) info::ctx.vida = 5;
|
||||||
this->momies->insertar(new Momia(this->gfx, dimonis, x, y, this->sam));
|
if (JI_CheatActivated("alone")) {
|
||||||
}
|
if (this->momies != nullptr) {
|
||||||
x += 65;
|
this->momies->clear();
|
||||||
if (x == 345) {
|
delete this->momies;
|
||||||
x = 20;
|
this->momies = nullptr;
|
||||||
y -= 35;
|
info::ctx.momies = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (JI_CheatActivated("obert")) {
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
this->mapa->tombes[i].costat[0] = true;
|
||||||
|
this->mapa->tombes[i].costat[1] = true;
|
||||||
|
this->mapa->tombes[i].costat[2] = true;
|
||||||
|
this->mapa->tombes[i].costat[3] = true;
|
||||||
|
this->mapa->comprovaCaixa(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JI_KeyPressed(SDL_SCANCODE_ESCAPE)) {
|
||||||
|
JG_QuitSignal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModuleGame::iniciarMomies() {
|
||||||
|
if (info::ctx.num_habitacio == 1) {
|
||||||
|
info::ctx.momies = 1;
|
||||||
|
} else {
|
||||||
|
info::ctx.momies++;
|
||||||
|
}
|
||||||
|
if (info::ctx.num_piramide == 6) info::ctx.momies = 8;
|
||||||
|
|
||||||
|
int x = 20;
|
||||||
|
int y = 170;
|
||||||
|
bool dimonis = info::ctx.num_piramide == 6;
|
||||||
|
for (int i = 0; i < info::ctx.momies; i++) {
|
||||||
|
if (this->momies == nullptr) {
|
||||||
|
this->momies = new Momia(this->gfx, dimonis, x, y, this->sam);
|
||||||
|
} else {
|
||||||
|
this->momies->insertar(new Momia(this->gfx, dimonis, x, y, this->sam));
|
||||||
|
}
|
||||||
|
x += 65;
|
||||||
|
if (x == 345) {
|
||||||
|
x = 20;
|
||||||
|
y -= 35;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,31 +1,60 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "game/bola.hpp"
|
#include "game/bola.hpp"
|
||||||
#include "game/info.hpp"
|
#include "game/info.hpp"
|
||||||
#include "game/mapa.hpp"
|
#include "game/mapa.hpp"
|
||||||
#include "game/marcador.hpp"
|
#include "game/marcador.hpp"
|
||||||
#include "game/momia.hpp"
|
#include "game/momia.hpp"
|
||||||
#include "game/prota.hpp"
|
#include "game/prota.hpp"
|
||||||
|
#include "scenes/palette_fade.hpp"
|
||||||
class ModuleGame {
|
#include "scenes/scene.hpp"
|
||||||
public:
|
|
||||||
ModuleGame();
|
// Escena de gameplay pur. Reemplaça el vell `Go()` bloquejant amb
|
||||||
~ModuleGame(void);
|
// l'interfície `scenes::Scene` tick-based: `onEnter()` arranca la
|
||||||
|
// música i un fade-in, el `tick()` avança un frame (Draw + Update
|
||||||
int Go();
|
// gated per JG_ShouldUpdate), i quan la partida acaba fa un fade-out
|
||||||
|
// abans de retornar el next state.
|
||||||
private:
|
//
|
||||||
void Draw();
|
// Tres fases internes:
|
||||||
void Update();
|
// 1. FadingIn — fade-in 32 passos mentre el render segueix viu.
|
||||||
|
// 2. Playing — gameplay normal; `final_` es setja quan el prota mor
|
||||||
void iniciarMomies();
|
// o canvia de sala. `Update()` només avança cada 10 ms
|
||||||
|
// via `JG_ShouldUpdate` (ticker fix del jail).
|
||||||
Uint8 final;
|
// 3. FadingOut — fade-out 32 passos mantenint l'últim frame visible
|
||||||
JD8_Surface gfx;
|
// (substituïx el `JD8_FadeOut` bloquejant que feia el
|
||||||
|
// destructor legacy).
|
||||||
Mapa* mapa;
|
class ModuleGame : public scenes::Scene {
|
||||||
Prota* sam;
|
public:
|
||||||
Marcador* marcador;
|
ModuleGame();
|
||||||
Momia* momies;
|
~ModuleGame() override;
|
||||||
Bola* bola;
|
|
||||||
};
|
void onEnter() override;
|
||||||
|
void tick(int delta_ms) override;
|
||||||
|
bool done() const override { return phase_ == Phase::Done; }
|
||||||
|
int nextState() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class Phase {
|
||||||
|
FadingIn,
|
||||||
|
Playing,
|
||||||
|
FadingOut,
|
||||||
|
Done,
|
||||||
|
};
|
||||||
|
|
||||||
|
void Draw(); // render a `screen`; no crida JD8_Flip (ho fa el caller)
|
||||||
|
void Update(); // gated per JG_ShouldUpdate
|
||||||
|
|
||||||
|
void iniciarMomies();
|
||||||
|
void applyFinalTransitions(); // muta info::ctx quan final_ passa a !=0
|
||||||
|
|
||||||
|
Phase phase_{Phase::FadingIn};
|
||||||
|
scenes::PaletteFade fade_;
|
||||||
|
Uint8 final_{0};
|
||||||
|
JD8_Surface gfx{nullptr};
|
||||||
|
|
||||||
|
Mapa* mapa{nullptr};
|
||||||
|
Prota* sam{nullptr};
|
||||||
|
Marcador* marcador{nullptr};
|
||||||
|
Momia* momies{nullptr};
|
||||||
|
Bola* bola{nullptr};
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,827 +0,0 @@
|
|||||||
#include "game/modulesequence.hpp"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "core/jail/jail_audio.hpp"
|
|
||||||
#include "core/jail/jdraw8.hpp"
|
|
||||||
#include "core/jail/jfile.hpp"
|
|
||||||
#include "core/jail/jgame.hpp"
|
|
||||||
#include "core/jail/jinput.hpp"
|
|
||||||
#include "game/options.hpp"
|
|
||||||
|
|
||||||
ModuleSequence::ModuleSequence() {
|
|
||||||
}
|
|
||||||
|
|
||||||
ModuleSequence::~ModuleSequence(void) {
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
// Espera fins que passe el tick de JG_ShouldUpdate o fins que el jugador
|
|
||||||
// polse qualsevol tecla. Torna `true` si la seqüència s'ha de cancel·lar.
|
|
||||||
// Centralitza el patró repetit de les cinemàtiques; a la Fase 5 (quan
|
|
||||||
// eliminem el game thread) passarà a ser un pas de màquina d'estats real.
|
|
||||||
bool wait_frame_or_skip() {
|
|
||||||
while (!JG_ShouldUpdate()) {
|
|
||||||
JI_Update();
|
|
||||||
if (JI_AnyKey() || JG_Quitting()) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
int ModuleSequence::Go() {
|
|
||||||
if (info::ctx.num_piramide == 6 && info::ctx.diners < 200) info::ctx.num_piramide = 7;
|
|
||||||
|
|
||||||
switch (info::ctx.num_piramide) {
|
|
||||||
case 255: // Intro
|
|
||||||
doIntro();
|
|
||||||
break;
|
|
||||||
// case 0 (Menú) → migrat a scenes::MenuScene.
|
|
||||||
// case 1 i 7 (Slides) → migrat a scenes::SlidesScene.
|
|
||||||
// case 2..5 (Pre-piràmide) → migrat a scenes::BannerScene.
|
|
||||||
// case 6 (Pre-Secreta) → migrat a scenes::SecretaScene.
|
|
||||||
// case 8 (Credits) → migrat a scenes::CreditsScene.
|
|
||||||
// case 100 (Mort) → migrat a scenes::MortScene, dispatch via SceneRegistry.
|
|
||||||
}
|
|
||||||
|
|
||||||
JD8_FadeOut();
|
|
||||||
|
|
||||||
if (JG_Quitting()) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
if (info::ctx.num_piramide == 255) {
|
|
||||||
info::ctx.num_piramide = 0;
|
|
||||||
return 1;
|
|
||||||
} else if (info::ctx.num_piramide == 0) {
|
|
||||||
info::ctx.num_piramide = 1;
|
|
||||||
// info::ctx.num_piramide = 6;
|
|
||||||
// info::ctx.diners = 200;
|
|
||||||
return 1;
|
|
||||||
} else if (info::ctx.num_piramide == 7) {
|
|
||||||
info::ctx.num_piramide = 8;
|
|
||||||
return 1;
|
|
||||||
} else if (info::ctx.num_piramide == 8) {
|
|
||||||
info::ctx.num_piramide = 255;
|
|
||||||
return 1;
|
|
||||||
} else if (info::ctx.num_piramide == 100) {
|
|
||||||
info::ctx.num_piramide = 0;
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int minim(const int a, const int b) {
|
|
||||||
if (b < a) {
|
|
||||||
return b;
|
|
||||||
} else {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pinta el wordmark JAILGAMES/Jailgames en el mateix lloc (y=78) durant les
|
|
||||||
// animacions de sprites de l'intro. Branqueja entre logo vell i nou segons
|
|
||||||
// Options::game.use_new_logo.
|
|
||||||
static void drawIntroWordmark(JD8_Surface gfx) {
|
|
||||||
if (Options::game.use_new_logo) {
|
|
||||||
JD8_Blit(60, 78, gfx, 60, 158, 188, 28);
|
|
||||||
} else {
|
|
||||||
JD8_Blit(43, 78, gfx, 43, 155, 231, 45);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void play_music(const char* music, bool loop = -1) {
|
|
||||||
int size;
|
|
||||||
char* buffer = file_getfilebuffer(music, size);
|
|
||||||
JA_PlayMusic(JA_LoadMusic((Uint8*)buffer, size, music), loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModuleSequence::doIntro() {
|
|
||||||
// Branca `if (use_new_logo)` eliminada: scenes::IntroNewLogoScene
|
|
||||||
// agafa eixe camí via el SceneRegistry. Aquest `doIntro()` legacy
|
|
||||||
// només s'executa quan `use_new_logo == false`.
|
|
||||||
|
|
||||||
JG_SetUpdateTicks(1000);
|
|
||||||
|
|
||||||
play_music("00000003.ogg");
|
|
||||||
|
|
||||||
JD8_Surface gfx = JD8_LoadSurface("logo.gif");
|
|
||||||
JD8_Palette pal = JD8_LoadPalette("logo.gif");
|
|
||||||
JD8_SetScreenPalette(pal);
|
|
||||||
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
JG_SetUpdateTicks(100);
|
|
||||||
|
|
||||||
JD8_Blit(43, 78, gfx, 43, 155, 27, 45);
|
|
||||||
JD8_Blit(68, 78, gfx, 274, 155, 27, 45);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
JD8_Blit(43, 78, gfx, 43, 155, 53, 45);
|
|
||||||
JD8_Blit(96, 78, gfx, 274, 155, 27, 45);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
JD8_Blit(43, 78, gfx, 43, 155, 66, 45);
|
|
||||||
JD8_Blit(109, 78, gfx, 274, 155, 27, 45);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
JG_SetUpdateTicks(200);
|
|
||||||
|
|
||||||
JD8_Blit(43, 78, gfx, 43, 155, 92, 45);
|
|
||||||
JD8_Blit(136, 78, gfx, 274, 155, 27, 45);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
JD8_Blit(43, 78, gfx, 43, 155, 92, 45);
|
|
||||||
// JD8_Blit( 136, 78, gfx, 274, 155, 27, 45 );
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
JG_SetUpdateTicks(100);
|
|
||||||
|
|
||||||
JD8_Blit(43, 78, gfx, 43, 155, 118, 45);
|
|
||||||
JD8_Blit(160, 78, gfx, 274, 155, 27, 45);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
JD8_Blit(43, 78, gfx, 43, 155, 145, 45);
|
|
||||||
JD8_Blit(188, 78, gfx, 274, 155, 27, 45);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
JD8_Blit(43, 78, gfx, 43, 155, 178, 45);
|
|
||||||
JD8_Blit(221, 78, gfx, 274, 155, 27, 45);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
JD8_Blit(43, 78, gfx, 43, 155, 205, 45);
|
|
||||||
JD8_Blit(248, 78, gfx, 274, 155, 27, 45);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
JG_SetUpdateTicks(200);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
JD8_Blit(274, 78, gfx, 274, 155, 27, 45);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
JD8_Blit(274, 78, gfx, 274, 155, 27, 45);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
JD8_Blit(274, 78, gfx, 274, 155, 27, 45);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < 256; j++) {
|
|
||||||
for (int i = 16; i < 32; i++) {
|
|
||||||
if (i == 17) {
|
|
||||||
if (pal[i].r < 255) pal[i].r++;
|
|
||||||
if (pal[i].g < 255) pal[i].g++;
|
|
||||||
if (pal[i].b < 255) pal[i].b++;
|
|
||||||
}
|
|
||||||
if (pal[i].b < pal[i].g) pal[i].b++;
|
|
||||||
if (pal[i].b > pal[i].g) pal[i].b--;
|
|
||||||
if (pal[i].r < pal[i].g) pal[i].r++;
|
|
||||||
if (pal[i].r > pal[i].g) pal[i].r--;
|
|
||||||
}
|
|
||||||
JD8_Flip();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
doIntroSprites(gfx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModuleSequence::doIntroSprites(JD8_Surface gfx) {
|
|
||||||
JG_SetUpdateTicks(20);
|
|
||||||
|
|
||||||
Uint16 fr1 = 13;
|
|
||||||
Uint16 fr2 = fr1;
|
|
||||||
Uint16 fr3 = 11;
|
|
||||||
Uint16 fr4 = fr3;
|
|
||||||
Uint16 fr5 = 20;
|
|
||||||
Uint16 fr6 = 8;
|
|
||||||
Uint16 fr7 = 29;
|
|
||||||
Uint16 fr8 = 4;
|
|
||||||
Uint16 fr9 = 16;
|
|
||||||
Uint16 fr10 = fr9;
|
|
||||||
Uint16 fr11 = 6;
|
|
||||||
Uint16 creu = 75;
|
|
||||||
Uint16 interrogant = 90;
|
|
||||||
|
|
||||||
Uint16 fr_ani_1[13]; // camina dreta
|
|
||||||
Uint16 fr_ani_2[13]; // camina esquerra
|
|
||||||
Uint16 fr_ani_3[11]; // trau el mapa DRETA
|
|
||||||
Uint16 fr_ani_4[11]; // trau el mapa ESQUERRA
|
|
||||||
Uint16 fr_ani_5[20]; // bot de susto
|
|
||||||
Uint16 fr_ani_6[8]; // momia
|
|
||||||
Uint16 fr_ani_7[29]; // deixa caure el PAPER i SOMBRA
|
|
||||||
Uint16 fr_ani_8[4]; // PEDRA
|
|
||||||
Uint16 fr_ani_9[16]; // prota BALL
|
|
||||||
Uint16 fr_ani_10[16]; // momia BALL
|
|
||||||
Uint16 fr_ani_11[6]; // altaveu
|
|
||||||
|
|
||||||
for (int i = 0; i < fr1; i++) fr_ani_1[i] = i * 15;
|
|
||||||
for (int i = 0; i < fr2; i++) fr_ani_2[i] = i * 15; // 15
|
|
||||||
for (int i = 0; i < fr3; i++) fr_ani_3[i] = i * 15; // 30
|
|
||||||
for (int i = 0; i < fr4; i++) fr_ani_4[i] = i * 15; // 45
|
|
||||||
for (int i = 0; i <= 9; i++) fr_ani_5[i] = (i + 11) * 15; // 45
|
|
||||||
for (int i = 10; i <= 19; i++) fr_ani_5[i] = fr_ani_5[19 - i];
|
|
||||||
for (int i = 0; i < fr6; i++) fr_ani_6[i] = i * 15; // 60
|
|
||||||
for (int i = 0; i <= 13; i++) fr_ani_7[i] = (i + 5) * 15; // 75
|
|
||||||
for (int i = 14; i < fr7; i++) fr_ani_7[i] = (i - 14) * 15; // 105
|
|
||||||
for (int i = 0; i < fr8; i++) fr_ani_8[i] = (i + 1) * 15; // 75
|
|
||||||
for (int i = 0; i < fr9; i++) fr_ani_9[i] = i * 15; // 120
|
|
||||||
for (int i = 0; i < fr10; i++) fr_ani_10[i] = i * 15; // 135
|
|
||||||
for (int i = 0; i < fr11; i++) fr_ani_11[i] = (i + 1) * 15; // 90
|
|
||||||
fr_ani_11[fr11 - 1] = fr_ani_11[3];
|
|
||||||
|
|
||||||
switch (rand() % 3) {
|
|
||||||
case 0:
|
|
||||||
|
|
||||||
// camina cap a la DRETA }
|
|
||||||
for (int i = 0; i <= 200; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_1[(i div 5) mod fr1],15,15,i,150);
|
|
||||||
JD8_BlitCK(i, 150, gfx, fr_ani_1[(i / 5) % fr1], 0, 15, 15, 0);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// trau el MAPA DRETA }
|
|
||||||
|
|
||||||
for (int i = 0; i <= 200; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_3[minim((i div 5),fr3-1)],15,15,200,150);
|
|
||||||
JD8_BlitCK(200, 150, gfx, fr_ani_3[minim((i / 5), fr3 - 1)], 30, 15, 15, 0);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// guarda el MAPA }
|
|
||||||
|
|
||||||
for (int i = 200; i >= 0; i--) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_3[minim((i div 5),fr3-1)],15,15,200,150);
|
|
||||||
JD8_BlitCK(200, 150, gfx, fr_ani_3[minim((i / 5), fr3 - 1)], 30, 15, 15, 0);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// camina cap a la ESQUERRA }
|
|
||||||
|
|
||||||
for (int i = 200; i >= 80; i--) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_2[(i div 5) mod fr2],15,15,i,150);
|
|
||||||
JD8_BlitCK(i, 150, gfx, fr_ani_2[(i / 5) % fr2], 15, 15, 15, 0);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// trau el MAPA ESQUERRA }
|
|
||||||
|
|
||||||
for (int i = 0; i <= 200; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_4[minim((i div 5),fr4-1)],15,15,80,150);
|
|
||||||
JD8_BlitCK(80, 150, gfx, fr_ani_4[minim((i / 5), fr4 - 1)], 45, 15, 15, 0);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// momia cap a la ESQUERRA }
|
|
||||||
|
|
||||||
for (int i = 300; i >= 95; i--) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_6[(i div 10) mod fr6],15,15,i,150);
|
|
||||||
JD8_BlitCK(i, 150, gfx, fr_ani_6[(i / 5) % fr6], 60, 15, 15, 0);
|
|
||||||
// Put_sprite(from,where,fr_ani_4[fr4-1],15,15,80,150);
|
|
||||||
JD8_BlitCK(80, 150, gfx, fr_ani_4[fr4 - 1], 45, 15, 15, 0);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// girar-se }
|
|
||||||
|
|
||||||
for (int i = 0; i <= 50; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_1[1],15,15,80,150);
|
|
||||||
JD8_BlitCK(80, 150, gfx, fr_ani_1[1], 0, 15, 15, 0);
|
|
||||||
// Put_sprite(from,where,fr_ani_6[4],15,15,95,150);
|
|
||||||
JD8_BlitCK(95, 150, gfx, fr_ani_6[4], 60, 15, 15, 0);
|
|
||||||
// Put_sprite(from,where,interrogant,15,15,80,133);
|
|
||||||
JD8_BlitCK(80, 133, gfx, 0, interrogant, 15, 15, 0);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// bot de SUSTO }
|
|
||||||
|
|
||||||
for (int i = 0; i <= 49; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_5[minim((i div 5),fr5-1)],15,15,80,150-((i mod 50) div 5));
|
|
||||||
JD8_BlitCK(80, 150 - ((i % 50) / 5), gfx, fr_ani_5[minim(i / 5, fr5 - 1)], 45, 15, 15, 0);
|
|
||||||
// Put_sprite(from,where,fr_ani_6[4],15,15,95,150);
|
|
||||||
JD8_BlitCK(95, 150, gfx, fr_ani_6[4], 60, 15, 15, 0);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// bot de SUSTO }
|
|
||||||
|
|
||||||
for (int i = 50; i <= 99; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_5[minim((i div 5),fr5-1)],15,15,80,140+((i mod 50) div 5));
|
|
||||||
JD8_BlitCK(80, 140 + ((i % 50) / 5), gfx, fr_ani_5[minim(i / 5, fr5 - 1)], 45, 15, 15, 0);
|
|
||||||
// Put_sprite(from,where,fr_ani_6[4],15,15,95,150);
|
|
||||||
JD8_BlitCK(95, 150, gfx, fr_ani_6[4], 60, 15, 15, 0);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// camina cap a la ESQUERRA }
|
|
||||||
|
|
||||||
for (int i = 80; i >= 0; i--) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_2[(i div 5) mod fr2],15,15,i,150);
|
|
||||||
JD8_BlitCK(i, 150, gfx, fr_ani_2[(i / 5) % fr2], 15, 15, 15, 0);
|
|
||||||
// Put_sprite(from,where,fr_ani_6[4],15,15,95,150);
|
|
||||||
JD8_BlitCK(95, 150, gfx, fr_ani_6[4], 60, 15, 15, 0);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// final }
|
|
||||||
|
|
||||||
for (int i = 0; i <= 150; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_6[4],15,15,95,150);
|
|
||||||
JD8_BlitCK(95, 150, gfx, fr_ani_6[4], 60, 15, 15, 0);
|
|
||||||
// Put_sprite(from,where,interrogant,15,15,95,133);
|
|
||||||
JD8_BlitCK(95, 133, gfx, 0, interrogant, 15, 15, 0);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
}
|
|
||||||
//-----}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
// camina cap a la DRETA }
|
|
||||||
for (int i = 0; i <= 200; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,creu,15,15,200,155);
|
|
||||||
JD8_BlitCK(200, 155, gfx, 0, creu, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_1[(i div 5) mod fr1],15,15,i,150);
|
|
||||||
JD8_BlitCK(i, 150, gfx, fr_ani_1[(i / 5) % fr1], 0, 15, 15, 255);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// trau el MAPA DRETA }
|
|
||||||
|
|
||||||
for (int i = 0; i <= 300; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,creu,15,15,200,155);
|
|
||||||
JD8_BlitCK(200, 155, gfx, 0, creu, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_3[minim((i div 5),fr3-1)],15,15,200,150);
|
|
||||||
JD8_BlitCK(200, 150, gfx, fr_ani_3[minim(i / 5, fr3 - 1)], 30, 15, 15, 255);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// INTERROGANT }
|
|
||||||
|
|
||||||
for (int i = 0; i <= 100; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,creu,15,15,200,155);
|
|
||||||
JD8_BlitCK(200, 155, gfx, 0, creu, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,interrogant,15,15,200,134);
|
|
||||||
JD8_BlitCK(200, 134, gfx, 0, interrogant, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_3[fr3-1],15,15,200,150);
|
|
||||||
JD8_BlitCK(200, 150, gfx, fr_ani_3[fr3 - 1], 30, 15, 15, 255);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// deixa caure el MAPA i SOMBRA }
|
|
||||||
|
|
||||||
for (int i = 0; i <= 200; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,creu,15,15,200,155);
|
|
||||||
JD8_BlitCK(200, 155, gfx, 0, creu, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_7[minim((i div 5),fr7-1)],15,15,200,150);
|
|
||||||
if (minim(i / 5, fr7 - 1) <= 13) {
|
|
||||||
JD8_BlitCK(200, 150, gfx, fr_ani_7[minim(i / 5, fr7 - 1)], 75, 15, 15, 255);
|
|
||||||
} else {
|
|
||||||
JD8_BlitCK(200, 150, gfx, fr_ani_7[minim(i / 5, fr7 - 1)], 105, 15, 15, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SOMBRA i PEDRA }
|
|
||||||
|
|
||||||
for (int i = 0; i <= 75; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,creu,15,15,200,155);
|
|
||||||
JD8_BlitCK(200, 155, gfx, 0, creu, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_7[fr7-1],15,15,200,150);
|
|
||||||
JD8_BlitCK(200, 150, gfx, fr_ani_7[fr7 - 1], 105, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_8[0],15,15,200,i*2);
|
|
||||||
JD8_BlitCK(200, i * 2, gfx, fr_ani_8[0], 75, 15, 15, 255);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// trencar PEDRA }
|
|
||||||
|
|
||||||
for (int i = 0; i <= 19; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,creu,15,15,200,155);
|
|
||||||
JD8_BlitCK(200, 155, gfx, 0, creu, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_8[i div 10],15,15,200,150);
|
|
||||||
JD8_BlitCK(200, 150, gfx, fr_ani_8[i / 10], 75, 15, 15, 255);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FINAL }
|
|
||||||
|
|
||||||
for (int i = 0; i <= 200; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,creu,15,15,200,155);
|
|
||||||
JD8_BlitCK(200, 155, gfx, 0, creu, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_8[1],15,15,200,150);
|
|
||||||
JD8_BlitCK(200, 150, gfx, fr_ani_8[1], 75, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_8[2],15,15,185,150);
|
|
||||||
JD8_BlitCK(185, 150, gfx, fr_ani_8[2], 75, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_8[3],15,15,215,150);
|
|
||||||
JD8_BlitCK(215, 150, gfx, fr_ani_8[3], 75, 15, 15, 255);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
// camina cap a la DRETA }
|
|
||||||
for (int i = 0; i <= 145; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_1[(i div 5) mod fr1],15,15,i,150);
|
|
||||||
JD8_BlitCK(i, 150, gfx, fr_ani_1[(i / 5) % fr1], 0, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_6[(i div 10) mod fr6],15,15,304-i,150);
|
|
||||||
JD8_BlitCK(304 - i, 150, gfx, fr_ani_6[(i / 10) % fr6], 60, 15, 15, 255);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// els dos quets }
|
|
||||||
|
|
||||||
for (int i = 0; i <= 100; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_1[1],15,15,145,150);
|
|
||||||
JD8_BlitCK(145, 150, gfx, fr_ani_1[1], 0, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_6[1],15,15,160,150);
|
|
||||||
JD8_BlitCK(160, 150, gfx, fr_ani_6[1], 60, 15, 15, 255);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// aparicio altaveu }
|
|
||||||
|
|
||||||
for (int i = 0; i <= 50; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_11[(i div 10) mod 2],15,15,125,150);
|
|
||||||
JD8_BlitCK(125, 150, gfx, fr_ani_11[(i / 10) % 2], 90, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_1[1],15,15,145,150);
|
|
||||||
JD8_BlitCK(145, 150, gfx, fr_ani_1[1], 0, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_6[1],15,15,160,150);
|
|
||||||
JD8_BlitCK(160, 150, gfx, fr_ani_6[1], 60, 15, 15, 255);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BALL }
|
|
||||||
|
|
||||||
for (int i = 0; i <= 800; i++) {
|
|
||||||
JD8_ClearScreen(0);
|
|
||||||
drawIntroWordmark(gfx);
|
|
||||||
// Put_sprite(from,where,fr_ani_9[(i div 10) mod fr9],15,15,145,150);
|
|
||||||
JD8_BlitCK(145, 150, gfx, fr_ani_9[(i / 10) % fr9], 120, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_10[(i div 10) mod fr10],15,15,160,150);
|
|
||||||
JD8_BlitCK(160, 150, gfx, fr_ani_10[(i / 10) % fr10], 135, 15, 15, 255);
|
|
||||||
// Put_sprite(from,where,fr_ani_11[((i div 5) mod 4)+2],15,15,125,150);
|
|
||||||
JD8_BlitCK(125, 150, gfx, fr_ani_11[((i / 5) % 4) + 2], 90, 15, 15, 255);
|
|
||||||
|
|
||||||
JD8_Flip();
|
|
||||||
if (wait_frame_or_skip()) {
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
JD8_FreeSurface(gfx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// doIntroNewLogo() — migrat a scenes::IntroNewLogoScene (source/scenes/intro_new_logo_scene.cpp)
|
|
||||||
|
|
||||||
// doMenu() — migrat a scenes::MenuScene (source/scenes/menu_scene.cpp)
|
|
||||||
|
|
||||||
// doSlides() — migrat a scenes::SlidesScene (source/scenes/slides_scene.cpp)
|
|
||||||
|
|
||||||
// doBanner() — migrat a scenes::BannerScene (source/scenes/banner_scene.cpp)
|
|
||||||
|
|
||||||
// doSecreta() — migrat a scenes::SecretaScene (source/scenes/secreta_scene.cpp)
|
|
||||||
|
|
||||||
// doCredits() — migrat a scenes::CreditsScene (source/scenes/credits_scene.cpp)
|
|
||||||
|
|
||||||
// doMort() — migrat a scenes::MortScene (source/scenes/mort_scene.cpp)
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include "game/info.hpp"
|
|
||||||
|
|
||||||
class ModuleSequence {
|
|
||||||
public:
|
|
||||||
ModuleSequence();
|
|
||||||
~ModuleSequence(void);
|
|
||||||
|
|
||||||
int Go();
|
|
||||||
|
|
||||||
// Exposat temporalment (public) fins al Step 9 del pla de migració,
|
|
||||||
// quan `doIntroSprites` es reescriurà com a scenes::IntroSpritesScene.
|
|
||||||
// Mentrestant, scenes::IntroNewLogoScene el crida al final del seu
|
|
||||||
// ciclo per delegar la part de les animacions de sprites.
|
|
||||||
void doIntroSprites(Uint8* gfx);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void doIntro();
|
|
||||||
void doIntroNewLogo();
|
|
||||||
// doMenu() → migrat a scenes::MenuScene
|
|
||||||
// doSlides() → migrat a scenes::SlidesScene
|
|
||||||
// doBanner() → migrat a scenes::BannerScene
|
|
||||||
// doSecreta() → migrat a scenes::SecretaScene
|
|
||||||
// doCredits() → migrat a scenes::CreditsScene
|
|
||||||
// doMort() → migrat a scenes::MortScene
|
|
||||||
|
|
||||||
int contador;
|
|
||||||
};
|
|
||||||
@@ -5,7 +5,6 @@
|
|||||||
#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/info.hpp"
|
||||||
#include "game/modulesequence.hpp"
|
|
||||||
#include "scenes/scene_utils.hpp"
|
#include "scenes/scene_utils.hpp"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -98,7 +97,7 @@ void IntroNewLogoScene::render() {
|
|||||||
LETTER_WIDTHS[8], LOGO_HEIGHT);
|
LETTER_WIDTHS[8], LOGO_HEIGHT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Phase::Delegate:
|
case Phase::Sprites:
|
||||||
case Phase::Done:
|
case Phase::Done:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -122,10 +121,10 @@ void IntroNewLogoScene::advancePaletteCycle() {
|
|||||||
|
|
||||||
void IntroNewLogoScene::tick(int delta_ms) {
|
void IntroNewLogoScene::tick(int delta_ms) {
|
||||||
// Qualsevol tecla durant el revelat o el ciclo de paleta salta
|
// Qualsevol tecla durant el revelat o el ciclo de paleta salta
|
||||||
// TOTA la intro (inclou saltar doIntroSprites). Aquest era el
|
// TOTA la intro (inclou saltar la fase de sprites). Durant Sprites
|
||||||
// comportament del vell `doIntroNewLogo`: a cada `waitTick()`
|
// deixem que la sub-escena gestione el seu propi skip (que a més
|
||||||
// retornava abans de cridar `doIntroSprites`.
|
// respecta la fase "final" no skippable de la variant 0).
|
||||||
if (phase_ != Phase::Delegate && phase_ != Phase::Done && JI_AnyKey()) {
|
if (phase_ != Phase::Sprites && phase_ != Phase::Done && JI_AnyKey()) {
|
||||||
info::ctx.num_piramide = 0;
|
info::ctx.num_piramide = 0;
|
||||||
phase_ = Phase::Done;
|
phase_ = Phase::Done;
|
||||||
return;
|
return;
|
||||||
@@ -189,28 +188,27 @@ void IntroNewLogoScene::tick(int delta_ms) {
|
|||||||
phase_acc_ms_ += delta_ms;
|
phase_acc_ms_ += delta_ms;
|
||||||
render();
|
render();
|
||||||
if (phase_acc_ms_ >= FINAL_WAIT_MS) {
|
if (phase_acc_ms_ >= FINAL_WAIT_MS) {
|
||||||
phase_ = Phase::Delegate;
|
phase_ = Phase::Sprites;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Phase::Delegate: {
|
case Phase::Sprites:
|
||||||
// Delegació temporal al codi legacy: crea un ModuleSequence
|
// Sub-escena construïda al primer tick. Transferim el gfx_
|
||||||
// instància i li crida `doIntroSprites(gfx)`. La funció
|
// per move — la sub-escena se n'ocupa fins que es destruix.
|
||||||
// legacy *sempre* allibera `gfx` ella mateixa (al final o en
|
// Cada tick successiu delega l'animació dels sprites.
|
||||||
// els paths de skip amb JI_AnyKey), així que necessitem
|
if (!sprites_scene_) {
|
||||||
// transferir-li ownership via `release()` per evitar un
|
sprites_scene_ = std::make_unique<IntroSpritesScene>(std::move(gfx_));
|
||||||
// double free al destructor de SurfaceHandle. Step 9
|
sprites_scene_->onEnter();
|
||||||
// d'aquesta migració la reescriurà com a IntroSpritesScene
|
}
|
||||||
// i la delegació desapareixerà.
|
sprites_scene_->tick(delta_ms);
|
||||||
ModuleSequence legacy;
|
if (sprites_scene_->done()) {
|
||||||
legacy.doIntroSprites(gfx_.release());
|
// El vell `Go()` post-switch feia `num_piramide = 0`
|
||||||
// El vell `Go()` post-switch feia `num_piramide = 0` per a
|
// per passar al menú. Sense açò el while del fiber
|
||||||
// passar al menú. Ho reproduïm ací — si no, el while extern
|
// tornaria a crear IntroNewLogoScene infinitament.
|
||||||
// del fiber tornaria a crear IntroNewLogoScene infinitament.
|
info::ctx.num_piramide = 0;
|
||||||
info::ctx.num_piramide = 0;
|
phase_ = Phase::Done;
|
||||||
phase_ = Phase::Done;
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case Phase::Done:
|
case Phase::Done:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "core/jail/jdraw8.hpp"
|
#include "core/jail/jdraw8.hpp"
|
||||||
|
#include "scenes/intro_sprites_scene.hpp"
|
||||||
#include "scenes/scene.hpp"
|
#include "scenes/scene.hpp"
|
||||||
#include "scenes/surface_handle.hpp"
|
#include "scenes/surface_handle.hpp"
|
||||||
|
|
||||||
@@ -17,10 +20,10 @@ namespace scenes {
|
|||||||
// 3. Logo complet amb cursor fix 200 ms.
|
// 3. Logo complet amb cursor fix 200 ms.
|
||||||
// 4. Cicle de paleta de 256 passos modificant índexs 16–31 cada 20 ms.
|
// 4. Cicle de paleta de 256 passos modificant índexs 16–31 cada 20 ms.
|
||||||
// 5. Espera final 20 ms.
|
// 5. Espera final 20 ms.
|
||||||
// 6. Delega a la funció legacy `ModuleSequence::doIntroSprites(gfx)`
|
// 6. Transfereix el gfx_ a una `IntroSpritesScene` com a sub-escena
|
||||||
// (que s'executa dins del mateix fiber i fa els seus propis Flips
|
// i li delega els ticks fins que acaba (anima el prota + momia +
|
||||||
// cooperatius). Aquesta delegació desapareixerà al Step 9 del pla,
|
// mapa, amb 3 variants aleatòries). En acabar, setzea num_piramide
|
||||||
// quan `doIntroSprites` es reescriga com a `IntroSpritesScene`.
|
// = 0 per passar al menú.
|
||||||
//
|
//
|
||||||
// Registrada al SceneRegistry amb state_key = 255, amb una factory
|
// Registrada al SceneRegistry amb state_key = 255, amb una factory
|
||||||
// condicional: només s'activa si `Options::game.use_new_logo == true`.
|
// condicional: només s'activa si `Options::game.use_new_logo == true`.
|
||||||
@@ -43,7 +46,7 @@ class IntroNewLogoScene : public Scene {
|
|||||||
FullLogoFlash, // logo complet + cursor, 200 ms
|
FullLogoFlash, // logo complet + cursor, 200 ms
|
||||||
PaletteCycle, // 256 passos × 20 ms modificant paleta
|
PaletteCycle, // 256 passos × 20 ms modificant paleta
|
||||||
FinalWait, // 20 ms final
|
FinalWait, // 20 ms final
|
||||||
Delegate, // delega a doIntroSprites legacy i marca done
|
Sprites, // tick delegat a IntroSpritesScene fins que acaba
|
||||||
Done,
|
Done,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -53,6 +56,7 @@ class IntroNewLogoScene : public Scene {
|
|||||||
SurfaceHandle gfx_;
|
SurfaceHandle gfx_;
|
||||||
SurfaceHandle cursor_surf_;
|
SurfaceHandle cursor_surf_;
|
||||||
JD8_Palette pal_{nullptr}; // propietat transferida a main_palette via SetScreenPalette
|
JD8_Palette pal_{nullptr}; // propietat transferida a main_palette via SetScreenPalette
|
||||||
|
std::unique_ptr<IntroSpritesScene> sprites_scene_;
|
||||||
|
|
||||||
Phase phase_{Phase::Initial};
|
Phase phase_{Phase::Initial};
|
||||||
int phase_acc_ms_{0};
|
int phase_acc_ms_{0};
|
||||||
|
|||||||
218
source/scenes/intro_scene.cpp
Normal file
218
source/scenes/intro_scene.cpp
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
#include "scenes/intro_scene.hpp"
|
||||||
|
|
||||||
|
#include "core/jail/jdraw8.hpp"
|
||||||
|
#include "core/jail/jinput.hpp"
|
||||||
|
#include "game/info.hpp"
|
||||||
|
#include "scenes/scene_utils.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Timings idèntics als del vell `doIntro()`: el JG_SetUpdateTicks(1000)
|
||||||
|
// inicial, (100) per a les 3 primeres lletres (J, A, I), (200) per a
|
||||||
|
// "JAIL" i el seu clear, (100) per a les 4 lletres centrals
|
||||||
|
// (G, A, M, E) i (200) per a la resta fins al cicle de paleta.
|
||||||
|
constexpr int INITIAL_MS = 1000;
|
||||||
|
constexpr int PALETTE_CYCLE_STEP_MS = 20;
|
||||||
|
constexpr int PALETTE_CYCLE_STEPS = 256;
|
||||||
|
constexpr int FINAL_WAIT_MS = 200;
|
||||||
|
|
||||||
|
// Un pas del revelat. Dos blits configurables (cos del wordmark + avió)
|
||||||
|
// més una variant per al wordmark sencer i un flag de ClearScreen previ.
|
||||||
|
struct RevealStep {
|
||||||
|
int duration_ms;
|
||||||
|
int body_w; // amplada del blit body (43,78) ← (43,155, body_w, 45); 0 si s'usa wordmark
|
||||||
|
int plane_x; // x del blit de l'avió (274,155, 27×45); -1 = no avió
|
||||||
|
bool clear; // fa ClearScreen(0) abans dels blits
|
||||||
|
bool wordmark; // usa drawWordmark() en lloc del blit body (wordmark complet)
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr RevealStep REVEAL_STEPS[] = {
|
||||||
|
{100, 27, 68, false, false}, // J
|
||||||
|
{100, 53, 96, false, false}, // JA
|
||||||
|
{100, 66, 109, false, false}, // JAI
|
||||||
|
{200, 92, 136, false, false}, // JAIL
|
||||||
|
{200, 92, -1, true, false}, // JAIL (clear, sense avió — parpelleig)
|
||||||
|
{100, 118, 160, false, false}, // JAILG
|
||||||
|
{100, 145, 188, false, false}, // JAILGA
|
||||||
|
{100, 178, 221, false, false}, // JAILGAM
|
||||||
|
{100, 205, 248, false, false}, // JAILGAME
|
||||||
|
{200, 0, 274, false, true}, // JAILGAMES (wordmark complet) + avió
|
||||||
|
{200, 0, -1, true, true}, // JAILGAMES (clear, sense avió)
|
||||||
|
{200, 0, 274, false, true}, // JAILGAMES + avió (sense clear)
|
||||||
|
{200, 0, -1, true, true}, // JAILGAMES (clear, sense avió)
|
||||||
|
{200, 0, 274, false, true}, // JAILGAMES + avió (sense clear)
|
||||||
|
{200, 0, -1, true, true}, // JAILGAMES (clear, sense avió)
|
||||||
|
};
|
||||||
|
constexpr int REVEAL_COUNT = sizeof(REVEAL_STEPS) / sizeof(REVEAL_STEPS[0]);
|
||||||
|
|
||||||
|
// Branca `!use_new_logo` del drawIntroWordmark de modulesequence.cpp:
|
||||||
|
// blit únic del wordmark "JAILGAMES" complet (231×45 al destí 43,78).
|
||||||
|
// IntroScene només s'activa quan use_new_logo == false, així que la
|
||||||
|
// branca use_new_logo d'aquell helper aquí no es necessita.
|
||||||
|
void drawWordmark(JD8_Surface gfx) {
|
||||||
|
JD8_Blit(43, 78, gfx, 43, 155, 231, 45);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace scenes {
|
||||||
|
|
||||||
|
IntroScene::IntroScene() = default;
|
||||||
|
|
||||||
|
IntroScene::~IntroScene() {
|
||||||
|
// No alliberem `pal_`: JD8_SetScreenPalette n'ha pres ownership i el
|
||||||
|
// proper SetScreenPalette / FadeToPal la lliurarà. Alliberar-la ací
|
||||||
|
// provocaria double free.
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntroScene::onEnter() {
|
||||||
|
playMusic("00000003.ogg");
|
||||||
|
|
||||||
|
gfx_ = SurfaceHandle("logo.gif");
|
||||||
|
pal_ = JD8_LoadPalette("logo.gif");
|
||||||
|
JD8_SetScreenPalette(pal_);
|
||||||
|
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
|
||||||
|
phase_ = Phase::InitialWait;
|
||||||
|
phase_acc_ms_ = 0;
|
||||||
|
reveal_index_ = 0;
|
||||||
|
palette_step_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntroScene::render() {
|
||||||
|
switch (phase_) {
|
||||||
|
case Phase::InitialWait:
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Phase::Reveal: {
|
||||||
|
const RevealStep& s = REVEAL_STEPS[reveal_index_];
|
||||||
|
if (s.clear) JD8_ClearScreen(0);
|
||||||
|
if (s.wordmark) {
|
||||||
|
drawWordmark(gfx_);
|
||||||
|
} else if (s.body_w > 0) {
|
||||||
|
JD8_Blit(43, 78, gfx_, 43, 155, s.body_w, 45);
|
||||||
|
}
|
||||||
|
if (s.plane_x >= 0) {
|
||||||
|
JD8_Blit(s.plane_x, 78, gfx_, 274, 155, 27, 45);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Phase::PaletteCycle:
|
||||||
|
case Phase::FinalWait:
|
||||||
|
// Wordmark complet fix mentre cicla la paleta — l'últim
|
||||||
|
// pas del revelat (PAS 15) deixa la pantalla en aquest mateix
|
||||||
|
// estat, i el vell doIntro no redibuixava durant el cicle.
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx_);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Phase::Sprites:
|
||||||
|
case Phase::Done:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntroScene::advancePaletteCycle() {
|
||||||
|
// Replica exacta del cicle del doIntro vell sobre pal[16..31] — el
|
||||||
|
// grup del verd brillant del logo. Index 17 s'acosta a blanc mentre
|
||||||
|
// els altres convergeixen cap al mateix gris mitjà.
|
||||||
|
for (int i = 16; i < 32; i++) {
|
||||||
|
if (i == 17) {
|
||||||
|
if (pal_[i].r < 255) pal_[i].r++;
|
||||||
|
if (pal_[i].g < 255) pal_[i].g++;
|
||||||
|
if (pal_[i].b < 255) pal_[i].b++;
|
||||||
|
}
|
||||||
|
if (pal_[i].b < pal_[i].g) pal_[i].b++;
|
||||||
|
if (pal_[i].b > pal_[i].g) pal_[i].b--;
|
||||||
|
if (pal_[i].r < pal_[i].g) pal_[i].r++;
|
||||||
|
if (pal_[i].r > pal_[i].g) pal_[i].r--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntroScene::tick(int delta_ms) {
|
||||||
|
// Qualsevol tecla durant revelat/paleta salta TOTA la intro
|
||||||
|
// (inclou saltar la fase de sprites). Durant Sprites deixem que
|
||||||
|
// la sub-escena gestione el seu propi skip internament, que a més
|
||||||
|
// respecta la fase "final" no skippable de la variant 0.
|
||||||
|
if (phase_ != Phase::Sprites && phase_ != Phase::Done && JI_AnyKey()) {
|
||||||
|
info::ctx.num_piramide = 0;
|
||||||
|
phase_ = Phase::Done;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (phase_) {
|
||||||
|
case Phase::InitialWait:
|
||||||
|
phase_acc_ms_ += delta_ms;
|
||||||
|
render();
|
||||||
|
if (phase_acc_ms_ >= INITIAL_MS) {
|
||||||
|
phase_ = Phase::Reveal;
|
||||||
|
phase_acc_ms_ = 0;
|
||||||
|
reveal_index_ = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Phase::Reveal:
|
||||||
|
phase_acc_ms_ += delta_ms;
|
||||||
|
render();
|
||||||
|
if (phase_acc_ms_ >= REVEAL_STEPS[reveal_index_].duration_ms) {
|
||||||
|
phase_acc_ms_ = 0;
|
||||||
|
++reveal_index_;
|
||||||
|
if (reveal_index_ >= REVEAL_COUNT) {
|
||||||
|
phase_ = Phase::PaletteCycle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Phase::PaletteCycle:
|
||||||
|
phase_acc_ms_ += delta_ms;
|
||||||
|
// Avancem tants passos com permet el delta, per evitar
|
||||||
|
// saltar-ne si el frame ha vingut lent.
|
||||||
|
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::FinalWait;
|
||||||
|
phase_acc_ms_ = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Phase::FinalWait:
|
||||||
|
phase_acc_ms_ += delta_ms;
|
||||||
|
render();
|
||||||
|
if (phase_acc_ms_ >= FINAL_WAIT_MS) {
|
||||||
|
phase_ = Phase::Sprites;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Phase::Sprites:
|
||||||
|
// Sub-escena construïda al vol al primer tick d'aquesta fase.
|
||||||
|
// Transferim el gfx_ per move — la sub-escena se n'ocupa
|
||||||
|
// fins que es destruix. Una vegada feta, els ticks delegats
|
||||||
|
// avancen 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()) {
|
||||||
|
// Equivalent al vell `Go()` post-switch: passem al menú.
|
||||||
|
// Sense açò el while del fiber tornaria a crear IntroScene
|
||||||
|
// infinitament amb num_piramide encara a 255.
|
||||||
|
info::ctx.num_piramide = 0;
|
||||||
|
phase_ = Phase::Done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Phase::Done:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace scenes
|
||||||
66
source/scenes/intro_scene.hpp
Normal file
66
source/scenes/intro_scene.hpp
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "core/jail/jdraw8.hpp"
|
||||||
|
#include "scenes/intro_sprites_scene.hpp"
|
||||||
|
#include "scenes/scene.hpp"
|
||||||
|
#include "scenes/surface_handle.hpp"
|
||||||
|
|
||||||
|
namespace scenes {
|
||||||
|
|
||||||
|
// Intro "legacy" del wordmark JAILGAMES lletra a lletra + cicle de paleta.
|
||||||
|
// Reemplaça `ModuleSequence::doIntro()`. S'activa quan
|
||||||
|
// `Options::game.use_new_logo == false`; l'alternativa moderna és
|
||||||
|
// `IntroNewLogoScene`.
|
||||||
|
//
|
||||||
|
// Flux:
|
||||||
|
// 1. Carrega logo.gif, arranca música "00000003.ogg", pantalla negra
|
||||||
|
// 1000 ms.
|
||||||
|
// 2. Revelat: 15 passos (100 o 200 ms) que van acumulant les lletres
|
||||||
|
// "JAILGAMES" d'esquerra a dreta amb un avió escombrant al final
|
||||||
|
// de la paraula. Els passos 5, 11, 13 i 15 netegen la pantalla
|
||||||
|
// per generar els parpelleigs finals.
|
||||||
|
// 3. Cicle de paleta: 256 passos × 20 ms modificant els índexs 16..31.
|
||||||
|
// 4. Espera final 200 ms.
|
||||||
|
// 5. Transfereix el gfx_ a una `IntroSpritesScene` com a sub-escena
|
||||||
|
// i li delega els ticks fins que acaba (anima el prota + momia +
|
||||||
|
// mapa, amb 3 variants aleatòries). En acabar, setzea num_piramide
|
||||||
|
// = 0 per passar al menú.
|
||||||
|
//
|
||||||
|
// Registrada al SceneRegistry amb state_key = 255: la mateixa factory que
|
||||||
|
// per a IntroNewLogoScene, però retornada quan `use_new_logo == false`.
|
||||||
|
class IntroScene : public Scene {
|
||||||
|
public:
|
||||||
|
IntroScene();
|
||||||
|
~IntroScene() 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 {
|
||||||
|
InitialWait, // 1000 ms pantalla negra
|
||||||
|
Reveal, // 15 passos del wordmark
|
||||||
|
PaletteCycle, // 256 × 20 ms mutant pal[16..31]
|
||||||
|
FinalWait, // 200 ms abans de la sub-escena de sprites
|
||||||
|
Sprites, // tick delegat a IntroSpritesScene fins que acaba
|
||||||
|
Done,
|
||||||
|
};
|
||||||
|
|
||||||
|
void render();
|
||||||
|
void advancePaletteCycle();
|
||||||
|
|
||||||
|
SurfaceHandle gfx_;
|
||||||
|
JD8_Palette pal_{nullptr}; // propietat transferida a main_palette via SetScreenPalette
|
||||||
|
std::unique_ptr<IntroSpritesScene> sprites_scene_;
|
||||||
|
|
||||||
|
Phase phase_{Phase::InitialWait};
|
||||||
|
int phase_acc_ms_{0};
|
||||||
|
int reveal_index_{0};
|
||||||
|
int palette_step_{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace scenes
|
||||||
346
source/scenes/intro_sprites_scene.cpp
Normal file
346
source/scenes/intro_sprites_scene.cpp
Normal file
@@ -0,0 +1,346 @@
|
|||||||
|
#include "scenes/intro_sprites_scene.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "core/jail/jdraw8.hpp"
|
||||||
|
#include "core/jail/jinput.hpp"
|
||||||
|
#include "game/options.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Duració d'un pas. El vell doIntroSprites feia JG_SetUpdateTicks(20);
|
||||||
|
// cada iteració del seu for (i) consumia un tick de 20 ms.
|
||||||
|
constexpr int TICK_MS = 20;
|
||||||
|
|
||||||
|
// Taules de frames. Ubicacions de cada sprite dins el gfx de la intro
|
||||||
|
// (logo.gif o logo/logo_new.gif — el layout de sprites és el mateix).
|
||||||
|
// Cada sprite ocupa 15×15 px, disposats horitzontalment per fila.
|
||||||
|
// Els valors són els offsets x (la y la posa l'invocador al src_y).
|
||||||
|
// Derivats dels `fr_ani_N[i] = ...` del vell doIntroSprites.
|
||||||
|
constexpr Uint16 fr1[] = {0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180}; // camina dreta (y=0)
|
||||||
|
constexpr Uint16 fr2[] = {0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180}; // camina esquerra (y=15)
|
||||||
|
constexpr Uint16 fr3[] = {0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150}; // trau mapa dreta (y=30)
|
||||||
|
constexpr Uint16 fr4[] = {0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150}; // trau mapa esquerra (y=45)
|
||||||
|
constexpr Uint16 fr5[] = {165, 180, 195, 210, 225, 240, 255, 270, 285, 300,
|
||||||
|
300, 285, 270, 255, 240, 225, 210, 195, 180, 165}; // bot de susto (y=45, mirror)
|
||||||
|
constexpr Uint16 fr6[] = {0, 15, 30, 45, 60, 75, 90, 105}; // momia (y=60)
|
||||||
|
constexpr Uint16 fr7[] = {75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225, 240, 255, 270, // paper (y=75, idx 0..13)
|
||||||
|
0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210}; // sombra (y=105, idx 14..28)
|
||||||
|
constexpr Uint16 fr8[] = {15, 30, 45, 60}; // pedra (y=75)
|
||||||
|
constexpr Uint16 fr9[] = {0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225}; // prota ball (y=120)
|
||||||
|
constexpr Uint16 fr10[] = {0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225}; // momia ball (y=135)
|
||||||
|
constexpr Uint16 fr11[] = {15, 30, 45, 60, 75, 60}; // altaveu (y=90, [5]=[3] pel loop de 4)
|
||||||
|
|
||||||
|
constexpr Uint16 CREU = 75; // src_y de la creu (overlay)
|
||||||
|
constexpr Uint16 INTERROGANT = 90; // src_y del signe d'interrogant
|
||||||
|
|
||||||
|
// Equivalent de la funció `drawIntroWordmark` de modulesequence.cpp.
|
||||||
|
// Branqueja segons use_new_logo perquè la mateixa sub-escena es
|
||||||
|
// reutilitza des de IntroScene (logo vell) i IntroNewLogoScene (logo
|
||||||
|
// nou) amb arxius diferents però mateix layout de sprites.
|
||||||
|
void drawWordmark(JD8_Surface gfx) {
|
||||||
|
if (Options::game.use_new_logo) {
|
||||||
|
JD8_Blit(60, 78, gfx, 60, 158, 188, 28);
|
||||||
|
} else {
|
||||||
|
JD8_Blit(43, 78, gfx, 43, 155, 231, 45);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using RenderFn = void (*)(JD8_Surface, int);
|
||||||
|
|
||||||
|
// Una fase — rang [start_i..end_i] inclusive (direcció implícita per
|
||||||
|
// signe), funció de render, i flag d'skippable. Totes les fases actuals
|
||||||
|
// són skippables; el flag es conserva per si alguna futura ha de ser
|
||||||
|
// no interrompuda (p.ex. un logo fatídic que cal veure sencer).
|
||||||
|
struct SpritePhase {
|
||||||
|
int start_i;
|
||||||
|
int end_i;
|
||||||
|
RenderFn render;
|
||||||
|
bool skippable;
|
||||||
|
};
|
||||||
|
|
||||||
|
// =========================================================================
|
||||||
|
// Variant 0 — Interrogant / Momia
|
||||||
|
// =========================================================================
|
||||||
|
|
||||||
|
void v0_walk_right(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(i, 150, gfx, fr1[(i / 5) % 13], 0, 15, 15, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v0_pull_map_right(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(200, 150, gfx, fr3[std::min(i / 5, 10)], 30, 15, 15, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v0_walk_left_to_80(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(i, 150, gfx, fr2[(i / 5) % 13], 15, 15, 15, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v0_pull_map_left(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(80, 150, gfx, fr4[std::min(i / 5, 10)], 45, 15, 15, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v0_momia_left(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(i, 150, gfx, fr6[(i / 5) % 8], 60, 15, 15, 0);
|
||||||
|
JD8_BlitCK(80, 150, gfx, fr4[10], 45, 15, 15, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v0_turn(JD8_Surface gfx, int /*i*/) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(80, 150, gfx, fr1[1], 0, 15, 15, 0);
|
||||||
|
JD8_BlitCK(95, 150, gfx, fr6[4], 60, 15, 15, 0);
|
||||||
|
JD8_BlitCK(80, 133, gfx, 0, INTERROGANT, 15, 15, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v0_jump1(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(80, 150 - ((i % 50) / 5), gfx, fr5[std::min(i / 5, 19)], 45, 15, 15, 0);
|
||||||
|
JD8_BlitCK(95, 150, gfx, fr6[4], 60, 15, 15, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v0_jump2(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(80, 140 + ((i % 50) / 5), gfx, fr5[std::min(i / 5, 19)], 45, 15, 15, 0);
|
||||||
|
JD8_BlitCK(95, 150, gfx, fr6[4], 60, 15, 15, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v0_walk_final(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(i, 150, gfx, fr2[(i / 5) % 13], 15, 15, 15, 0);
|
||||||
|
JD8_BlitCK(95, 150, gfx, fr6[4], 60, 15, 15, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v0_final(JD8_Surface gfx, int /*i*/) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(95, 150, gfx, fr6[4], 60, 15, 15, 0);
|
||||||
|
JD8_BlitCK(95, 133, gfx, 0, INTERROGANT, 15, 15, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr SpritePhase variant_0[] = {
|
||||||
|
{0, 200, v0_walk_right, true},
|
||||||
|
{0, 200, v0_pull_map_right, true},
|
||||||
|
{200, 0, v0_pull_map_right, true}, // guarda el mapa (reprodueix inversament)
|
||||||
|
{200, 80, v0_walk_left_to_80, true},
|
||||||
|
{0, 200, v0_pull_map_left, true},
|
||||||
|
{300, 95, v0_momia_left, true},
|
||||||
|
{0, 50, v0_turn, true},
|
||||||
|
{0, 49, v0_jump1, true},
|
||||||
|
{50, 99, v0_jump2, true},
|
||||||
|
{80, 0, v0_walk_final, true},
|
||||||
|
{0, 150, v0_final, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
// =========================================================================
|
||||||
|
// Variant 1 — Creu / Pedra
|
||||||
|
// =========================================================================
|
||||||
|
|
||||||
|
void v1_walk_right(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
||||||
|
JD8_BlitCK(i, 150, gfx, fr1[(i / 5) % 13], 0, 15, 15, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v1_pull_map(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
||||||
|
JD8_BlitCK(200, 150, gfx, fr3[std::min(i / 5, 10)], 30, 15, 15, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v1_interrogant(JD8_Surface gfx, int /*i*/) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
||||||
|
JD8_BlitCK(200, 134, gfx, 0, INTERROGANT, 15, 15, 255);
|
||||||
|
JD8_BlitCK(200, 150, gfx, fr3[10], 30, 15, 15, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v1_drop_map(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
||||||
|
const int idx = std::min(i / 5, 28);
|
||||||
|
// fr7 té 29 frames dividits en dos grups: paper (idx 0..13, src_y=75)
|
||||||
|
// i sombra (idx 14..28, src_y=105). El vell feia una branca al bucle.
|
||||||
|
if (idx <= 13) {
|
||||||
|
JD8_BlitCK(200, 150, gfx, fr7[idx], 75, 15, 15, 255);
|
||||||
|
} else {
|
||||||
|
JD8_BlitCK(200, 150, gfx, fr7[idx], 105, 15, 15, 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void v1_stone_fall(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
||||||
|
JD8_BlitCK(200, 150, gfx, fr7[28], 105, 15, 15, 255);
|
||||||
|
JD8_BlitCK(200, i * 2, gfx, fr8[0], 75, 15, 15, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v1_stone_break(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
||||||
|
JD8_BlitCK(200, 150, gfx, fr8[i / 10], 75, 15, 15, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v1_final(JD8_Surface gfx, int /*i*/) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
||||||
|
JD8_BlitCK(200, 150, gfx, fr8[1], 75, 15, 15, 255);
|
||||||
|
JD8_BlitCK(185, 150, gfx, fr8[2], 75, 15, 15, 255);
|
||||||
|
JD8_BlitCK(215, 150, gfx, fr8[3], 75, 15, 15, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr SpritePhase variant_1[] = {
|
||||||
|
{0, 200, v1_walk_right, true},
|
||||||
|
{0, 300, v1_pull_map, true},
|
||||||
|
{0, 100, v1_interrogant, true},
|
||||||
|
{0, 200, v1_drop_map, true},
|
||||||
|
{0, 75, v1_stone_fall, true},
|
||||||
|
{0, 19, v1_stone_break, true},
|
||||||
|
{0, 200, v1_final, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
// =========================================================================
|
||||||
|
// Variant 2 — Ball de carnaval
|
||||||
|
// =========================================================================
|
||||||
|
|
||||||
|
void v2_approach(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(i, 150, gfx, fr1[(i / 5) % 13], 0, 15, 15, 255);
|
||||||
|
JD8_BlitCK(304 - i, 150, gfx, fr6[(i / 10) % 8], 60, 15, 15, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v2_still(JD8_Surface gfx, int /*i*/) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(145, 150, gfx, fr1[1], 0, 15, 15, 255);
|
||||||
|
JD8_BlitCK(160, 150, gfx, fr6[1], 60, 15, 15, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v2_horn(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(125, 150, gfx, fr11[(i / 10) % 2], 90, 15, 15, 255);
|
||||||
|
JD8_BlitCK(145, 150, gfx, fr1[1], 0, 15, 15, 255);
|
||||||
|
JD8_BlitCK(160, 150, gfx, fr6[1], 60, 15, 15, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v2_ball(JD8_Surface gfx, int i) {
|
||||||
|
JD8_ClearScreen(0);
|
||||||
|
drawWordmark(gfx);
|
||||||
|
JD8_BlitCK(145, 150, gfx, fr9[(i / 10) % 16], 120, 15, 15, 255);
|
||||||
|
JD8_BlitCK(160, 150, gfx, fr10[(i / 10) % 16], 135, 15, 15, 255);
|
||||||
|
JD8_BlitCK(125, 150, gfx, fr11[((i / 5) % 4) + 2], 90, 15, 15, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr SpritePhase variant_2[] = {
|
||||||
|
{0, 145, v2_approach, true},
|
||||||
|
{0, 100, v2_still, true},
|
||||||
|
{0, 50, v2_horn, true},
|
||||||
|
{0, 800, v2_ball, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
// =========================================================================
|
||||||
|
// Dispatch per variant
|
||||||
|
// =========================================================================
|
||||||
|
|
||||||
|
const SpritePhase* variant_table(int variant) {
|
||||||
|
switch (variant) {
|
||||||
|
case 0: return variant_0;
|
||||||
|
case 1: return variant_1;
|
||||||
|
case 2: return variant_2;
|
||||||
|
}
|
||||||
|
return variant_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int variant_length(int variant) {
|
||||||
|
switch (variant) {
|
||||||
|
case 0: return sizeof(variant_0) / sizeof(variant_0[0]);
|
||||||
|
case 1: return sizeof(variant_1) / sizeof(variant_1[0]);
|
||||||
|
case 2: return sizeof(variant_2) / sizeof(variant_2[0]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int phase_step_count(const SpritePhase& p) {
|
||||||
|
return std::abs(p.end_i - p.start_i) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int phase_current_i(const SpritePhase& p, int step) {
|
||||||
|
return p.end_i >= p.start_i ? p.start_i + step : p.start_i - step;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace scenes {
|
||||||
|
|
||||||
|
IntroSpritesScene::IntroSpritesScene(SurfaceHandle&& gfx)
|
||||||
|
: gfx_(std::move(gfx)) {}
|
||||||
|
|
||||||
|
void IntroSpritesScene::onEnter() {
|
||||||
|
// El vell doIntroSprites feia `rand() % 3` al principi. El seed ve
|
||||||
|
// establert per `srand(time(0))` al boot del joc (info.cpp / main),
|
||||||
|
// així que la variant canvia entre execucions.
|
||||||
|
variant_ = std::rand() % 3;
|
||||||
|
phase_ = 0;
|
||||||
|
phase_step_ = 0;
|
||||||
|
step_acc_ms_ = 0;
|
||||||
|
done_ = false;
|
||||||
|
|
||||||
|
// Renderitzem ja el primer frame (step 0 de la primera fase) perquè
|
||||||
|
// el JD8_Flip del mini-loop del fiber el pinte al primer cicle.
|
||||||
|
const SpritePhase* phases = variant_table(variant_);
|
||||||
|
phases[0].render(gfx_.get(), phase_current_i(phases[0], 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntroSpritesScene::tick(int delta_ms) {
|
||||||
|
if (done_) return;
|
||||||
|
|
||||||
|
const SpritePhase* phases = variant_table(variant_);
|
||||||
|
const int num_phases = variant_length(variant_);
|
||||||
|
|
||||||
|
// Skip per tecla. Durant la fase marcada com a no skippable (només
|
||||||
|
// v0_final al vell codi) s'ignora — preserva la semàntica del vell
|
||||||
|
// bucle final de la variant 0 que no cridava wait_frame_or_skip.
|
||||||
|
if (phases[phase_].skippable && JI_AnyKey()) {
|
||||||
|
done_ = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
step_acc_ms_ += delta_ms;
|
||||||
|
while (step_acc_ms_ >= TICK_MS && !done_) {
|
||||||
|
step_acc_ms_ -= TICK_MS;
|
||||||
|
++phase_step_;
|
||||||
|
if (phase_step_ >= phase_step_count(phases[phase_])) {
|
||||||
|
++phase_;
|
||||||
|
phase_step_ = 0;
|
||||||
|
if (phase_ >= num_phases) {
|
||||||
|
done_ = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
phases[phase_].render(gfx_.get(), phase_current_i(phases[phase_], phase_step_));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace scenes
|
||||||
43
source/scenes/intro_sprites_scene.hpp
Normal file
43
source/scenes/intro_sprites_scene.hpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "scenes/scene.hpp"
|
||||||
|
#include "scenes/surface_handle.hpp"
|
||||||
|
|
||||||
|
namespace scenes {
|
||||||
|
|
||||||
|
// Sub-escena de sprites de la intro (prota + momia + mapa + etc).
|
||||||
|
// Reemplaça `ModuleSequence::doIntroSprites()`. No es registra al
|
||||||
|
// SceneRegistry — es construeix com a membre de `IntroScene` o
|
||||||
|
// `IntroNewLogoScene` quan aquestes completen el seu revelat del logo.
|
||||||
|
// Rep el `SurfaceHandle` del gfx de la intro via move, de manera que
|
||||||
|
// quan acabe l'escena el surface es lliberarà automàticament.
|
||||||
|
//
|
||||||
|
// En entrar tria una de 3 variants (`rand() % 3`): "interrogant/momia",
|
||||||
|
// "creu/pedra" o "ball de carnaval". Cada variant té un nombre
|
||||||
|
// diferent de fases però comparteixen el mateix motor: un comptador
|
||||||
|
// `step` que s'incrementa cada 20 ms, amb una taula per variant que
|
||||||
|
// mapeja (rang d'i, renderer) a cada fase. Qualsevol tecla salta
|
||||||
|
// l'escena — el flag `skippable` per fase es manté com a mecanisme
|
||||||
|
// per si alguna fase futura ha de ser no interrompuda (al vell codi
|
||||||
|
// la fase "final" de la variant 0 no cridava wait_frame_or_skip, cosa
|
||||||
|
// molt probablement un oversight: ací es tracta com a skippable).
|
||||||
|
class IntroSpritesScene : public Scene {
|
||||||
|
public:
|
||||||
|
explicit IntroSpritesScene(SurfaceHandle&& gfx);
|
||||||
|
~IntroSpritesScene() override = default;
|
||||||
|
|
||||||
|
void onEnter() override;
|
||||||
|
void tick(int delta_ms) override;
|
||||||
|
bool done() const override { return done_; }
|
||||||
|
int nextState() const override { return 1; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
SurfaceHandle gfx_;
|
||||||
|
int variant_{0}; // 0..2 — triada a onEnter() amb rand() % 3
|
||||||
|
int phase_{0}; // índex dins la variant actual
|
||||||
|
int phase_step_{0}; // passos consumits dins la fase actual
|
||||||
|
int step_acc_ms_{0}; // acumulador per emetre steps de 20 ms
|
||||||
|
bool done_{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace scenes
|
||||||
@@ -9,13 +9,13 @@ namespace scenes {
|
|||||||
|
|
||||||
void playMusic(const char* filename, int loop) {
|
void playMusic(const char* filename, int loop) {
|
||||||
if (!filename) return;
|
if (!filename) return;
|
||||||
int size = 0;
|
auto buffer = file_readfile(filename);
|
||||||
char* buffer = file_getfilebuffer(filename, size);
|
if (buffer.empty()) return;
|
||||||
if (!buffer) return;
|
// JA_LoadMusic fa una còpia interna del OGG comprimit (via SDL_malloc)
|
||||||
// JA_LoadMusic fa una còpia del OGG comprimit (SDL_malloc), així que
|
// per a stb_vorbis. El `buffer` local es destruirà en sortir d'àmbit.
|
||||||
// el `buffer` original es queda huérfano. Leak conegut heredat del
|
JA_PlayMusic(JA_LoadMusic(reinterpret_cast<Uint8*>(buffer.data()),
|
||||||
// codi original — es tractarà quan jfile tinga una API std::vector.
|
static_cast<Uint32>(buffer.size()), filename),
|
||||||
JA_PlayMusic(JA_LoadMusic(reinterpret_cast<Uint8*>(buffer), size, filename), loop);
|
loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
Reference in New Issue
Block a user