clang-format
mogudes coses de config.yaml a debug.yaml
This commit is contained in:
@@ -226,7 +226,9 @@ inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) {
|
|||||||
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
music->vorbis = stb_vorbis_open_memory(music->ogg_data.data(),
|
music->vorbis = stb_vorbis_open_memory(music->ogg_data.data(),
|
||||||
static_cast<int>(length), &error, nullptr);
|
static_cast<int>(length),
|
||||||
|
&error,
|
||||||
|
nullptr);
|
||||||
if (!music->vorbis) {
|
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;
|
delete music;
|
||||||
|
|||||||
@@ -189,19 +189,19 @@ void JD8_SetPaletteColor(Uint8 index, Uint8 r, Uint8 g, Uint8 b) {
|
|||||||
// el caller decideix quan fer Flip.
|
// el caller decideix quan fer Flip.
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
enum FadeType {
|
enum FadeType {
|
||||||
FADE_NONE = 0,
|
FADE_NONE = 0,
|
||||||
FADE_OUT,
|
FADE_OUT,
|
||||||
FADE_TO_PAL,
|
FADE_TO_PAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr int FADE_STEPS = 32;
|
constexpr int FADE_STEPS = 32;
|
||||||
|
|
||||||
FadeType fade_type = FADE_NONE;
|
FadeType fade_type = FADE_NONE;
|
||||||
Color fade_target[256];
|
Color fade_target[256];
|
||||||
int fade_step = 0;
|
int fade_step = 0;
|
||||||
|
|
||||||
void apply_fade_step() {
|
void apply_fade_step() {
|
||||||
if (fade_type == FADE_OUT) {
|
if (fade_type == FADE_OUT) {
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
main_palette[i].r = main_palette[i].r >= 8 ? main_palette[i].r - 8 : 0;
|
main_palette[i].r = main_palette[i].r >= 8 ? main_palette[i].r - 8 : 0;
|
||||||
@@ -221,7 +221,7 @@ void apply_fade_step() {
|
|||||||
: fade_target[i].b;
|
: fade_target[i].b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|||||||
@@ -14,16 +14,16 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct keyvalue {
|
struct keyvalue {
|
||||||
std::string key;
|
std::string key;
|
||||||
std::string value;
|
std::string value;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<keyvalue> config;
|
std::vector<keyvalue> config;
|
||||||
std::string resource_folder;
|
std::string resource_folder;
|
||||||
std::string config_folder;
|
std::string config_folder;
|
||||||
|
|
||||||
void load_config_values() {
|
void load_config_values() {
|
||||||
config.clear();
|
config.clear();
|
||||||
const std::string config_file = config_folder + "/config.txt";
|
const std::string config_file = config_folder + "/config.txt";
|
||||||
std::ifstream fi(config_file);
|
std::ifstream fi(config_file);
|
||||||
@@ -35,16 +35,16 @@ void load_config_values() {
|
|||||||
if (eq == std::string::npos) continue;
|
if (eq == std::string::npos) continue;
|
||||||
config.push_back({line.substr(0, eq), line.substr(eq + 1)});
|
config.push_back({line.substr(0, eq), line.substr(eq + 1)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_config_values() {
|
void save_config_values() {
|
||||||
const std::string config_file = config_folder + "/config.txt";
|
const std::string config_file = config_folder + "/config.txt";
|
||||||
std::ofstream fo(config_file);
|
std::ofstream fo(config_file);
|
||||||
if (!fo.is_open()) return;
|
if (!fo.is_open()) return;
|
||||||
for (const auto& pair : config) {
|
for (const auto& pair : config) {
|
||||||
fo << pair.key << '=' << pair.value << '\n';
|
fo << pair.key << '=' << pair.value << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool quitting = false;
|
bool quitting = false;
|
||||||
Uint32 update_ticks = 0;
|
Uint32 update_ticks = 0;
|
||||||
Uint32 update_time = 0;
|
Uint32 update_time = 0;
|
||||||
Uint32 cycle_counter = 0;
|
Uint32 cycle_counter = 0;
|
||||||
Uint32 last_delta_time = 0;
|
Uint32 last_delta_time = 0;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|||||||
@@ -6,35 +6,35 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// keystates és actualitzat per SDL internament. Des del joc només fem lectures.
|
// keystates és actualitzat per SDL internament. Des del joc només fem lectures.
|
||||||
const bool* keystates = nullptr;
|
const bool* keystates = nullptr;
|
||||||
|
|
||||||
// Buffer dels últims 5 caràcters tecle. Emmagatzemem caràcters ASCII
|
// Buffer dels últims 5 caràcters tecle. Emmagatzemem caràcters ASCII
|
||||||
// lowercase (traduïts des de SDL_Scancode) per a poder comparar directament
|
// lowercase (traduïts des de SDL_Scancode) per a poder comparar directament
|
||||||
// amb les cadenes dels cheats ("reviu", "alone", "obert").
|
// amb les cadenes dels cheats ("reviu", "alone", "obert").
|
||||||
Uint8 cheat[5] = {0, 0, 0, 0, 0};
|
Uint8 cheat[5] = {0, 0, 0, 0, 0};
|
||||||
|
|
||||||
bool key_pressed = false;
|
bool key_pressed = false;
|
||||||
|
|
||||||
// Temps restant en mil·lisegons durant el qual JI_KeyPressed/JI_AnyKey
|
// Temps restant en mil·lisegons durant el qual JI_KeyPressed/JI_AnyKey
|
||||||
// retornen false. Utilitzat per a evitar que pulsacions fortuïtes
|
// retornen false. Utilitzat per a evitar que pulsacions fortuïtes
|
||||||
// saltin cinemàtiques al començament.
|
// saltin cinemàtiques al començament.
|
||||||
float wait_ms = 0.0f;
|
float wait_ms = 0.0f;
|
||||||
|
|
||||||
// Per a calcular el delta entre crides a JI_Update sense que els callers
|
// Per a calcular el delta entre crides a JI_Update sense que els callers
|
||||||
// hagen de passar-lo explícitament. Es reinicia a la primera crida.
|
// hagen de passar-lo explícitament. Es reinicia a la primera crida.
|
||||||
Uint64 last_update_tick = 0;
|
Uint64 last_update_tick = 0;
|
||||||
|
|
||||||
bool input_blocked = false;
|
bool input_blocked = false;
|
||||||
|
|
||||||
Uint8 virtual_keystates[JI_VSRC_COUNT][SDL_SCANCODE_COUNT] = {{0}};
|
Uint8 virtual_keystates[JI_VSRC_COUNT][SDL_SCANCODE_COUNT] = {{0}};
|
||||||
|
|
||||||
Uint8 scancode_to_ascii(Uint8 scancode) {
|
Uint8 scancode_to_ascii(Uint8 scancode) {
|
||||||
if (scancode >= SDL_SCANCODE_A && scancode <= SDL_SCANCODE_Z) {
|
if (scancode >= SDL_SCANCODE_A && scancode <= SDL_SCANCODE_Z) {
|
||||||
return static_cast<Uint8>('a' + (scancode - SDL_SCANCODE_A));
|
return static_cast<Uint8>('a' + (scancode - SDL_SCANCODE_A));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
const std::string ResourcePack::DEFAULT_ENCRYPT_KEY = "AEE_RESOURCES__2026";
|
const std::string ResourcePack::DEFAULT_ENCRYPT_KEY = "AEE_RESOURCES__2026";
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr const char* MAGIC = "AEE1";
|
constexpr const char* MAGIC = "AEE1";
|
||||||
constexpr uint32_t VERSION = 1;
|
constexpr uint32_t VERSION = 1;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ResourcePack::ResourcePack() = default;
|
ResourcePack::ResourcePack() = default;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace info {
|
namespace info {
|
||||||
|
|
||||||
struct GameContext {
|
struct GameContext {
|
||||||
int num_piramide = 0;
|
int num_piramide = 0;
|
||||||
int num_habitacio = 0;
|
int num_habitacio = 0;
|
||||||
int diners = 0;
|
int diners = 0;
|
||||||
@@ -14,11 +14,11 @@ struct GameContext {
|
|||||||
bool pepe_activat = false;
|
bool pepe_activat = false;
|
||||||
|
|
||||||
void reset() { *this = GameContext{}; }
|
void reset() { *this = GameContext{}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instància única de l'estat del joc. Reemplaça les variables soltes del
|
// Instància única de l'estat del joc. Reemplaça les variables soltes del
|
||||||
// namespace `info::` per una struct encapsulada. A Fase 5 (single-threaded)
|
// namespace `info::` per una struct encapsulada. A Fase 5 (single-threaded)
|
||||||
// es podrà passar per referència als mòduls en lloc d'accedir via singleton.
|
// es podrà passar per referència als mòduls en lloc d'accedir via singleton.
|
||||||
inline GameContext ctx;
|
inline GameContext ctx;
|
||||||
|
|
||||||
} // namespace info
|
} // namespace info
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ void ModuleGame::onEnter() {
|
|||||||
strcmp(music, current_music) != 0) {
|
strcmp(music, current_music) != 0) {
|
||||||
auto buffer = ResourceHelper::loadFile(music);
|
auto buffer = ResourceHelper::loadFile(music);
|
||||||
JA_PlayMusic(JA_LoadMusic(buffer.data(),
|
JA_PlayMusic(JA_LoadMusic(buffer.data(),
|
||||||
static_cast<Uint32>(buffer.size()), music));
|
static_cast<Uint32>(buffer.size()),
|
||||||
|
music));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arranca el fade-in tick-based. El `PaletteFade` avança un pas (de
|
// Arranca el fade-in tick-based. El `PaletteFade` avança un pas (de
|
||||||
|
|||||||
@@ -16,6 +16,66 @@ namespace Options {
|
|||||||
config_file_path = path;
|
config_file_path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setDebugFile(const std::string& path) {
|
||||||
|
debug_file_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto saveDebugToFile() -> bool {
|
||||||
|
std::ofstream file(debug_file_path);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
std::cerr << "Error: Unable to open file " << debug_file_path << " for writing\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Writing debug file: " << debug_file_path << '\n';
|
||||||
|
|
||||||
|
file << "# Aventures En Egipte - Debug Configuration File\n";
|
||||||
|
file << "#\n";
|
||||||
|
file << "# Loaded only in debug builds. Override gameplay starting state for testing.\n";
|
||||||
|
file << "\n";
|
||||||
|
file << "game:\n";
|
||||||
|
file << " habitacio_inicial: " << game.habitacio_inicial << "\n";
|
||||||
|
file << " piramide_inicial: " << game.piramide_inicial << "\n";
|
||||||
|
file << " vides: " << game.vides << "\n";
|
||||||
|
file << " diamants_inicial: " << game.diamants_inicial << "\n";
|
||||||
|
file << " diners_inicial: " << game.diners_inicial << "\n";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto loadDebugFromFile() -> bool {
|
||||||
|
std::ifstream file(debug_file_path);
|
||||||
|
if (!file.good()) {
|
||||||
|
std::cout << "Debug file not found, creating default: " << debug_file_path << '\n';
|
||||||
|
return saveDebugToFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::cout << "Reading debug file: " << debug_file_path << '\n';
|
||||||
|
auto yaml = fkyaml::node::deserialize(content);
|
||||||
|
if (yaml.contains("game")) {
|
||||||
|
const auto& node = yaml["game"];
|
||||||
|
if (node.contains("habitacio_inicial"))
|
||||||
|
game.habitacio_inicial = node["habitacio_inicial"].get_value<int>();
|
||||||
|
if (node.contains("piramide_inicial"))
|
||||||
|
game.piramide_inicial = node["piramide_inicial"].get_value<int>();
|
||||||
|
if (node.contains("vides"))
|
||||||
|
game.vides = node["vides"].get_value<int>();
|
||||||
|
if (node.contains("diamants_inicial"))
|
||||||
|
game.diamants_inicial = node["diamants_inicial"].get_value<int>();
|
||||||
|
if (node.contains("diners_inicial"))
|
||||||
|
game.diners_inicial = node["diners_inicial"].get_value<int>();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (const fkyaml::exception& e) {
|
||||||
|
std::cerr << "Error parsing YAML debug: " << e.what() << '\n';
|
||||||
|
return saveDebugToFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void applyAudio() {
|
void applyAudio() {
|
||||||
const float master = audio.enabled ? audio.volume : 0.0F;
|
const float master = audio.enabled ? audio.volume : 0.0F;
|
||||||
JA_EnableMusic(audio.music_enabled);
|
JA_EnableMusic(audio.music_enabled);
|
||||||
@@ -138,16 +198,6 @@ namespace Options {
|
|||||||
if (!yaml.contains("game")) return;
|
if (!yaml.contains("game")) return;
|
||||||
const auto& node = yaml["game"];
|
const auto& node = yaml["game"];
|
||||||
|
|
||||||
if (node.contains("habitacio_inicial"))
|
|
||||||
game.habitacio_inicial = node["habitacio_inicial"].get_value<int>();
|
|
||||||
if (node.contains("piramide_inicial"))
|
|
||||||
game.piramide_inicial = node["piramide_inicial"].get_value<int>();
|
|
||||||
if (node.contains("vides"))
|
|
||||||
game.vides = node["vides"].get_value<int>();
|
|
||||||
if (node.contains("diamants_inicial"))
|
|
||||||
game.diamants_inicial = node["diamants_inicial"].get_value<int>();
|
|
||||||
if (node.contains("diners_inicial"))
|
|
||||||
game.diners_inicial = node["diners_inicial"].get_value<int>();
|
|
||||||
if (node.contains("use_new_logo"))
|
if (node.contains("use_new_logo"))
|
||||||
game.use_new_logo = node["use_new_logo"].get_value<bool>();
|
game.use_new_logo = node["use_new_logo"].get_value<bool>();
|
||||||
if (node.contains("show_title_credits"))
|
if (node.contains("show_title_credits"))
|
||||||
@@ -279,11 +329,6 @@ namespace Options {
|
|||||||
// GAME
|
// GAME
|
||||||
file << "# GAME\n";
|
file << "# GAME\n";
|
||||||
file << "game:\n";
|
file << "game:\n";
|
||||||
file << " habitacio_inicial: " << game.habitacio_inicial << "\n";
|
|
||||||
file << " piramide_inicial: " << game.piramide_inicial << "\n";
|
|
||||||
file << " vides: " << game.vides << "\n";
|
|
||||||
file << " diamants_inicial: " << game.diamants_inicial << "\n";
|
|
||||||
file << " diners_inicial: " << game.diners_inicial << "\n";
|
|
||||||
file << " use_new_logo: " << (game.use_new_logo ? "true" : "false") << "\n";
|
file << " use_new_logo: " << (game.use_new_logo ? "true" : "false") << "\n";
|
||||||
file << " show_title_credits: " << (game.show_title_credits ? "true" : "false") << "\n";
|
file << " show_title_credits: " << (game.show_title_credits ? "true" : "false") << "\n";
|
||||||
file << "\n";
|
file << "\n";
|
||||||
|
|||||||
@@ -141,11 +141,21 @@ namespace Options {
|
|||||||
inline std::string crtpi_file_path{};
|
inline std::string crtpi_file_path{};
|
||||||
inline int current_crtpi_preset{0};
|
inline int current_crtpi_preset{0};
|
||||||
|
|
||||||
|
inline std::string debug_file_path{};
|
||||||
|
|
||||||
// --- API ---
|
// --- API ---
|
||||||
void setConfigFile(const std::string& path);
|
void setConfigFile(const std::string& path);
|
||||||
auto loadFromFile() -> bool;
|
auto loadFromFile() -> bool;
|
||||||
auto saveToFile() -> bool;
|
auto saveToFile() -> bool;
|
||||||
|
|
||||||
|
// debug.yaml: estat inicial de gameplay per a tests ràpids
|
||||||
|
// (`habitacio_inicial`, `piramide_inicial`, `vides`, `diamants_inicial`,
|
||||||
|
// `diners_inicial`). Només es carrega/desa en builds de debug; en release
|
||||||
|
// els camps queden als seus defaults.
|
||||||
|
void setDebugFile(const std::string& path);
|
||||||
|
auto loadDebugFromFile() -> bool;
|
||||||
|
auto saveDebugToFile() -> bool;
|
||||||
|
|
||||||
void setPostFXFile(const std::string& path);
|
void setPostFXFile(const std::string& path);
|
||||||
auto loadPostFXFromFile() -> bool;
|
auto loadPostFXFromFile() -> bool;
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,13 @@ SDL_AppResult SDL_AppInit(void** /*appstate*/, int /*argc*/, char* /*argv*/[]) {
|
|||||||
Options::setConfigFile(std::string(file_getconfigfolder()) + "config.yaml");
|
Options::setConfigFile(std::string(file_getconfigfolder()) + "config.yaml");
|
||||||
Options::loadFromFile();
|
Options::loadFromFile();
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// debug.yaml: estat inicial de gameplay per a tests ràpids,
|
||||||
|
// només en builds de debug.
|
||||||
|
Options::setDebugFile(std::string(file_getconfigfolder()) + "debug.yaml");
|
||||||
|
Options::loadDebugFromFile();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
// MEMFS no persistix entre recàrregues: força valors sensats per a web.
|
// MEMFS no persistix entre recàrregues: força valors sensats per a web.
|
||||||
Options::window.fullscreen = false;
|
Options::window.fullscreen = false;
|
||||||
@@ -112,6 +119,9 @@ void SDL_AppQuit(void* /*appstate*/, SDL_AppResult /*result*/) {
|
|||||||
Director::get()->teardown();
|
Director::get()->teardown();
|
||||||
|
|
||||||
Options::saveToFile();
|
Options::saveToFile();
|
||||||
|
#ifndef NDEBUG
|
||||||
|
Options::saveDebugToFile();
|
||||||
|
#endif
|
||||||
|
|
||||||
Director::destroy();
|
Director::destroy();
|
||||||
Menu::destroy();
|
Menu::destroy();
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
void BannerScene::onEnter() {
|
void BannerScene::onEnter() {
|
||||||
playMusic("music/00000004.ogg");
|
playMusic("music/00000004.ogg");
|
||||||
|
|
||||||
gfx_ = SurfaceHandle("gfx/ffase.gif");
|
gfx_ = SurfaceHandle("gfx/ffase.gif");
|
||||||
@@ -36,9 +36,9 @@ void BannerScene::onEnter() {
|
|||||||
|
|
||||||
phase_ = Phase::FadingIn;
|
phase_ = Phase::FadingIn;
|
||||||
remaining_ms_ = 5000;
|
remaining_ms_ = 5000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BannerScene::tick(int delta_ms) {
|
void BannerScene::tick(int delta_ms) {
|
||||||
switch (phase_) {
|
switch (phase_) {
|
||||||
case Phase::FadingIn:
|
case Phase::FadingIn:
|
||||||
fade_.tick(delta_ms);
|
fade_.tick(delta_ms);
|
||||||
@@ -66,6 +66,6 @@ void BannerScene::tick(int delta_ms) {
|
|||||||
case Phase::Done:
|
case Phase::Done:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -6,19 +6,19 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Banner pre-piràmide ("PIRÀMIDE X"). Reemplaça `ModuleSequence::doBanner()`.
|
// Banner pre-piràmide ("PIRÀMIDE X"). Reemplaça `ModuleSequence::doBanner()`.
|
||||||
//
|
//
|
||||||
// Flux:
|
// Flux:
|
||||||
// 1. Arranca música "music/00000004.ogg" i carrega gfx/ffase.gif.
|
// 1. Arranca música "music/00000004.ogg" i carrega gfx/ffase.gif.
|
||||||
// 2. Pinta títol, subtítol i número de piràmide segons info::ctx.num_piramide.
|
// 2. Pinta títol, subtítol i número de piràmide segons info::ctx.num_piramide.
|
||||||
// 3. Fade-in de paleta.
|
// 3. Fade-in de paleta.
|
||||||
// 4. Mostra ~5s o fins que es polse una tecla.
|
// 4. Mostra ~5s o fins que es polse una tecla.
|
||||||
// 5. JA_FadeOutMusic(250) + fade-out de paleta.
|
// 5. JA_FadeOutMusic(250) + fade-out de paleta.
|
||||||
// 6. Retorna nextState=0 per a entrar al ModuleGame.
|
// 6. Retorna nextState=0 per a entrar al ModuleGame.
|
||||||
//
|
//
|
||||||
// Registrat al SceneRegistry amb state_keys 2..5 (els num_piramide on
|
// Registrat al SceneRegistry amb state_keys 2..5 (els num_piramide on
|
||||||
// el vell `doBanner()` es cridava).
|
// el vell `doBanner()` es cridava).
|
||||||
class BannerScene : public Scene {
|
class BannerScene : public Scene {
|
||||||
public:
|
public:
|
||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void tick(int delta_ms) override;
|
void tick(int delta_ms) override;
|
||||||
@@ -35,6 +35,6 @@ class BannerScene : public Scene {
|
|||||||
PaletteFade fade_;
|
PaletteFade fade_;
|
||||||
Phase phase_{Phase::FadingIn};
|
Phase phase_{Phase::FadingIn};
|
||||||
int remaining_ms_{5000};
|
int remaining_ms_{5000};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -11,29 +11,36 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Frames del cotxe: 8 posicions dins del sprite sheet gfx/final.gif. El
|
// Frames del cotxe: 8 posicions dins del sprite sheet gfx/final.gif. El
|
||||||
// vell doCredits tenia aquesta taula inline — la reproduïm idèntica.
|
// vell doCredits tenia aquesta taula inline — la reproduïm idèntica.
|
||||||
struct CocheFrame {
|
struct CocheFrame {
|
||||||
Uint16 x, y;
|
Uint16 x, y;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr CocheFrame COCHE_FRAMES[8] = {
|
constexpr CocheFrame COCHE_FRAMES[8] = {
|
||||||
{214, 152}, {214, 104}, {214, 56}, {214, 104}, {214, 152}, {214, 8}, {108, 152}, {214, 8},
|
{214, 152},
|
||||||
};
|
{214, 104},
|
||||||
|
{214, 56},
|
||||||
|
{214, 104},
|
||||||
|
{214, 152},
|
||||||
|
{214, 8},
|
||||||
|
{108, 152},
|
||||||
|
{214, 8},
|
||||||
|
};
|
||||||
|
|
||||||
constexpr int CONTADOR_MAX = 3100; // ~62 s de crèdits a 20 ms/tick
|
constexpr int CONTADOR_MAX = 3100; // ~62 s de crèdits a 20 ms/tick
|
||||||
constexpr int TICK_MS = 20; // JG_SetUpdateTicks heretat del doSlides previ
|
constexpr int TICK_MS = 20; // JG_SetUpdateTicks heretat del doSlides previ
|
||||||
constexpr int BG_INDEX = 255;
|
constexpr int BG_INDEX = 255;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
CreditsScene::~CreditsScene() {
|
CreditsScene::~CreditsScene() {
|
||||||
// No toquem la paleta activa: SetScreenPalette n'ha pres ownership.
|
// No toquem la paleta activa: SetScreenPalette n'ha pres ownership.
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreditsScene::onEnter() {
|
void CreditsScene::onEnter() {
|
||||||
// El vell doCredits no tocava música — heretava la del doSlides
|
// El vell doCredits no tocava música — heretava la del doSlides
|
||||||
// previ ("music/00000005.ogg"). Si l'escena s'arrenca directament (test
|
// previ ("music/00000005.ogg"). Si l'escena s'arrenca directament (test
|
||||||
// amb piramide_inicial=8) no hi ha res que heretar, així que
|
// amb piramide_inicial=8) no hi ha res que heretar, així que
|
||||||
@@ -53,9 +60,9 @@ void CreditsScene::onEnter() {
|
|||||||
phase_ = Phase::Rolling;
|
phase_ = Phase::Rolling;
|
||||||
contador_ = 1;
|
contador_ = 1;
|
||||||
contador_acc_ms_ = 0;
|
contador_acc_ms_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreditsScene::render() {
|
void CreditsScene::render() {
|
||||||
JD8_ClearScreen(BG_INDEX);
|
JD8_ClearScreen(BG_INDEX);
|
||||||
|
|
||||||
// Columna 1: scroll vertical del bloc (0,0,80,200) pujant des de
|
// Columna 1: scroll vertical del bloc (0,0,80,200) pujant des de
|
||||||
@@ -90,18 +97,18 @@ void CreditsScene::render() {
|
|||||||
// Barres de marc que cobreixen els extrems del scroll vertical.
|
// Barres de marc que cobreixen els extrems del scroll vertical.
|
||||||
JD8_FillSquare(0, 50, BG_INDEX);
|
JD8_FillSquare(0, 50, BG_INDEX);
|
||||||
JD8_FillSquare(100, 10, BG_INDEX);
|
JD8_FillSquare(100, 10, BG_INDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreditsScene::writeTrickIni() {
|
void CreditsScene::writeTrickIni() {
|
||||||
FILE* ini = std::fopen("trick.ini", "wb");
|
FILE* ini = std::fopen("trick.ini", "wb");
|
||||||
if (ini) {
|
if (ini) {
|
||||||
std::fwrite("1", 1, 1, ini);
|
std::fwrite("1", 1, 1, ini);
|
||||||
std::fclose(ini);
|
std::fclose(ini);
|
||||||
}
|
}
|
||||||
info::ctx.nou_personatge = true;
|
info::ctx.nou_personatge = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreditsScene::tick(int delta_ms) {
|
void CreditsScene::tick(int delta_ms) {
|
||||||
switch (phase_) {
|
switch (phase_) {
|
||||||
case Phase::Rolling: {
|
case Phase::Rolling: {
|
||||||
// Avancem el contador en passos discrets de 20 ms, igual
|
// Avancem el contador en passos discrets de 20 ms, igual
|
||||||
@@ -134,6 +141,6 @@ void CreditsScene::tick(int delta_ms) {
|
|||||||
case Phase::Done:
|
case Phase::Done:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -8,20 +8,20 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Crèdits finals del joc. Reemplaça `ModuleSequence::doCredits()`.
|
// Crèdits finals del joc. Reemplaça `ModuleSequence::doCredits()`.
|
||||||
//
|
//
|
||||||
// Flux:
|
// Flux:
|
||||||
// 1. Carrega gfx/final.gif (sprites de crèdits) i gfx/finals.gif (fons).
|
// 1. Carrega gfx/final.gif (sprites de crèdits) i gfx/finals.gif (fons).
|
||||||
// 2. Mostra els crèdits amb scroll vertical de 2 columnes durant
|
// 2. Mostra els crèdits amb scroll vertical de 2 columnes durant
|
||||||
// ~62 segons (contador 0..3100 × 20 ms).
|
// ~62 segons (contador 0..3100 × 20 ms).
|
||||||
// 3. Si `info::ctx.diamants == 16`, pinta addicionalment un parallax
|
// 3. Si `info::ctx.diamants == 16`, pinta addicionalment un parallax
|
||||||
// de 4 capes amb cotxe animat (8 frames). Si no, 2 blits fixos.
|
// de 4 capes amb cotxe animat (8 frames). Si no, 2 blits fixos.
|
||||||
// 4. Al acabar (per tecla o per contador), crea el fitxer `trick.ini`
|
// 4. Al acabar (per tecla o per contador), crea el fitxer `trick.ini`
|
||||||
// i activa `info::ctx.nou_personatge`.
|
// i activa `info::ctx.nou_personatge`.
|
||||||
// 5. Fade-out de paleta. Torna a la intro (num_piramide = 255).
|
// 5. Fade-out de paleta. Torna a la intro (num_piramide = 255).
|
||||||
//
|
//
|
||||||
// Registrada al SceneRegistry amb state_key = 8.
|
// Registrada al SceneRegistry amb state_key = 8.
|
||||||
class CreditsScene : public Scene {
|
class CreditsScene : public Scene {
|
||||||
public:
|
public:
|
||||||
CreditsScene() = default;
|
CreditsScene() = default;
|
||||||
~CreditsScene() override;
|
~CreditsScene() override;
|
||||||
@@ -47,6 +47,6 @@ class CreditsScene : public Scene {
|
|||||||
Phase phase_{Phase::Rolling};
|
Phase phase_{Phase::Rolling};
|
||||||
int contador_{1};
|
int contador_{1};
|
||||||
int contador_acc_ms_{0};
|
int contador_acc_ms_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
FrameAnimator::FrameAnimator(int num_frames, int frame_ms, bool loop)
|
FrameAnimator::FrameAnimator(int num_frames, int frame_ms, bool loop)
|
||||||
: num_frames_(std::max(1, num_frames)),
|
: num_frames_(std::max(1, num_frames)),
|
||||||
frame_ms_(std::max(1, frame_ms)),
|
frame_ms_(std::max(1, frame_ms)),
|
||||||
loop_(loop) {}
|
loop_(loop) {}
|
||||||
|
|
||||||
void FrameAnimator::tick(int delta_ms) {
|
void FrameAnimator::tick(int delta_ms) {
|
||||||
if (finished_) return;
|
if (finished_) return;
|
||||||
elapsed_ms_ += delta_ms;
|
elapsed_ms_ += delta_ms;
|
||||||
while (elapsed_ms_ >= frame_ms_) {
|
while (elapsed_ms_ >= frame_ms_) {
|
||||||
@@ -25,12 +25,12 @@ void FrameAnimator::tick(int delta_ms) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameAnimator::reset() {
|
void FrameAnimator::reset() {
|
||||||
current_frame_ = 0;
|
current_frame_ = 0;
|
||||||
elapsed_ms_ = 0;
|
elapsed_ms_ = 0;
|
||||||
finished_ = false;
|
finished_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Cicla per un conjunt de frames numerats (0..num_frames-1) avançant un
|
// Cicla per un conjunt de frames numerats (0..num_frames-1) avançant un
|
||||||
// frame cada `frame_ms` mil·lisegons. No carrega ni dibuixa cap sprite —
|
// frame cada `frame_ms` mil·lisegons. No carrega ni dibuixa cap sprite —
|
||||||
// només el caller sap quins frames dibuixar a partir de `frame()`.
|
// només el caller sap quins frames dibuixar a partir de `frame()`.
|
||||||
//
|
//
|
||||||
// Usat per animacions periòdiques amb frames subsamplejats: palmeres,
|
// Usat per animacions periòdiques amb frames subsamplejats: palmeres,
|
||||||
// camell, aigua, torxes, Sam caminant amb `(i/5) % fr` del codi original.
|
// camell, aigua, torxes, Sam caminant amb `(i/5) % fr` del codi original.
|
||||||
class FrameAnimator {
|
class FrameAnimator {
|
||||||
public:
|
public:
|
||||||
FrameAnimator() = default;
|
FrameAnimator() = default;
|
||||||
FrameAnimator(int num_frames, int frame_ms, bool loop = true);
|
FrameAnimator(int num_frames, int frame_ms, bool loop = true);
|
||||||
@@ -29,6 +29,6 @@ class FrameAnimator {
|
|||||||
int current_frame_{0};
|
int current_frame_{0};
|
||||||
int elapsed_ms_{0};
|
int elapsed_ms_{0};
|
||||||
bool finished_{false};
|
bool finished_{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -9,41 +9,41 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Coordenades mesurades del wordmark "Jailgames" dins gfx/logo_new.gif.
|
// Coordenades mesurades del wordmark "Jailgames" dins gfx/logo_new.gif.
|
||||||
// Idèntiques a les del doIntroNewLogo vell — si canvies el logo, aquí i
|
// Idèntiques a les del doIntroNewLogo vell — si canvies el logo, aquí i
|
||||||
// al GIF són els únics llocs a tocar.
|
// al GIF són els únics llocs a tocar.
|
||||||
constexpr int LOGO_SRC_X = 60;
|
constexpr int LOGO_SRC_X = 60;
|
||||||
constexpr int LOGO_SRC_Y = 158;
|
constexpr int LOGO_SRC_Y = 158;
|
||||||
constexpr int LOGO_DST_Y = 78;
|
constexpr int LOGO_DST_Y = 78;
|
||||||
constexpr int LOGO_HEIGHT = 28;
|
constexpr int LOGO_HEIGHT = 28;
|
||||||
constexpr int LETTER_WIDTHS[9] = {16, 39, 50, 69, 92, 115, 146, 169, 188};
|
constexpr int LETTER_WIDTHS[9] = {16, 39, 50, 69, 92, 115, 146, 169, 188};
|
||||||
constexpr int CURSOR_X[9] = {77, 100, 111, 130, 153, 176, 207, 230, 249};
|
constexpr int CURSOR_X[9] = {77, 100, 111, 130, 153, 176, 207, 230, 249};
|
||||||
constexpr int CURSOR_W = 12;
|
constexpr int CURSOR_W = 12;
|
||||||
constexpr int CURSOR_H = 3;
|
constexpr int CURSOR_H = 3;
|
||||||
constexpr int CURSOR_Y = LOGO_DST_Y + LOGO_HEIGHT - CURSOR_H; // y = 103
|
constexpr int CURSOR_Y = LOGO_DST_Y + LOGO_HEIGHT - CURSOR_H; // y = 103
|
||||||
constexpr Uint8 CURSOR_COLOR = 17; // mateix index verd que les lletres
|
constexpr Uint8 CURSOR_COLOR = 17; // mateix index verd que les lletres
|
||||||
|
|
||||||
// Timings (ms) — idèntics als de doIntroNewLogo vell.
|
// Timings (ms) — idèntics als de doIntroNewLogo vell.
|
||||||
constexpr int INITIAL_MS = 1000;
|
constexpr int INITIAL_MS = 1000;
|
||||||
constexpr int REVEAL_FRAME_MS = 150;
|
constexpr int REVEAL_FRAME_MS = 150;
|
||||||
constexpr int FULL_LOGO_MS = 200;
|
constexpr int FULL_LOGO_MS = 200;
|
||||||
constexpr int PALETTE_CYCLE_STEP_MS = 20;
|
constexpr int PALETTE_CYCLE_STEP_MS = 20;
|
||||||
constexpr int FINAL_WAIT_MS = 20;
|
constexpr int FINAL_WAIT_MS = 20;
|
||||||
constexpr int PALETTE_CYCLE_STEPS = 256;
|
constexpr int PALETTE_CYCLE_STEPS = 256;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
IntroNewLogoScene::IntroNewLogoScene() = default;
|
IntroNewLogoScene::IntroNewLogoScene() = default;
|
||||||
|
|
||||||
IntroNewLogoScene::~IntroNewLogoScene() {
|
IntroNewLogoScene::~IntroNewLogoScene() {
|
||||||
// No alliberem `pal_`: JD8_SetScreenPalette n'ha pres ownership i
|
// No alliberem `pal_`: JD8_SetScreenPalette n'ha pres ownership i
|
||||||
// el proper SetScreenPalette / FadeToPal el lliurarà. Alliberar-lo
|
// el proper SetScreenPalette / FadeToPal el lliurarà. Alliberar-lo
|
||||||
// ací provocaria double free.
|
// ací provocaria double free.
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroNewLogoScene::onEnter() {
|
void IntroNewLogoScene::onEnter() {
|
||||||
playMusic("music/00000003.ogg");
|
playMusic("music/00000003.ogg");
|
||||||
|
|
||||||
gfx_ = SurfaceHandle("gfx/logo_new.gif");
|
gfx_ = SurfaceHandle("gfx/logo_new.gif");
|
||||||
@@ -62,9 +62,9 @@ void IntroNewLogoScene::onEnter() {
|
|||||||
reveal_letter_ = 0;
|
reveal_letter_ = 0;
|
||||||
reveal_cursor_visible_ = true;
|
reveal_cursor_visible_ = true;
|
||||||
palette_step_ = 0;
|
palette_step_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroNewLogoScene::render() {
|
void IntroNewLogoScene::render() {
|
||||||
switch (phase_) {
|
switch (phase_) {
|
||||||
case Phase::Initial:
|
case Phase::Initial:
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
@@ -72,19 +72,16 @@ void IntroNewLogoScene::render() {
|
|||||||
|
|
||||||
case Phase::Revealing: {
|
case Phase::Revealing: {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
JD8_Blit(LOGO_SRC_X, LOGO_DST_Y, gfx_, LOGO_SRC_X, LOGO_SRC_Y,
|
JD8_Blit(LOGO_SRC_X, LOGO_DST_Y, gfx_, LOGO_SRC_X, LOGO_SRC_Y, LETTER_WIDTHS[reveal_letter_], LOGO_HEIGHT);
|
||||||
LETTER_WIDTHS[reveal_letter_], LOGO_HEIGHT);
|
|
||||||
if (reveal_cursor_visible_) {
|
if (reveal_cursor_visible_) {
|
||||||
JD8_Blit(CURSOR_X[reveal_letter_], CURSOR_Y, cursor_surf_,
|
JD8_Blit(CURSOR_X[reveal_letter_], CURSOR_Y, cursor_surf_, 0, 0, CURSOR_W, CURSOR_H);
|
||||||
0, 0, CURSOR_W, CURSOR_H);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Phase::FullLogoFlash:
|
case Phase::FullLogoFlash:
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
JD8_Blit(LOGO_SRC_X, LOGO_DST_Y, gfx_, LOGO_SRC_X, LOGO_SRC_Y,
|
JD8_Blit(LOGO_SRC_X, LOGO_DST_Y, gfx_, LOGO_SRC_X, LOGO_SRC_Y, LETTER_WIDTHS[8], LOGO_HEIGHT);
|
||||||
LETTER_WIDTHS[8], LOGO_HEIGHT);
|
|
||||||
JD8_Blit(CURSOR_X[8], CURSOR_Y, cursor_surf_, 0, 0, CURSOR_W, CURSOR_H);
|
JD8_Blit(CURSOR_X[8], CURSOR_Y, cursor_surf_, 0, 0, CURSOR_W, CURSOR_H);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -93,17 +90,16 @@ void IntroNewLogoScene::render() {
|
|||||||
// Logo complet sense cursor — els pixels del cursor
|
// Logo complet sense cursor — els pixels del cursor
|
||||||
// ciclarien de color durant el cicle de paleta.
|
// ciclarien de color durant el cicle de paleta.
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
JD8_Blit(LOGO_SRC_X, LOGO_DST_Y, gfx_, LOGO_SRC_X, LOGO_SRC_Y,
|
JD8_Blit(LOGO_SRC_X, LOGO_DST_Y, gfx_, LOGO_SRC_X, LOGO_SRC_Y, LETTER_WIDTHS[8], LOGO_HEIGHT);
|
||||||
LETTER_WIDTHS[8], LOGO_HEIGHT);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Phase::Sprites:
|
case Phase::Sprites:
|
||||||
case Phase::Done:
|
case Phase::Done:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroNewLogoScene::advancePaletteCycle() {
|
void IntroNewLogoScene::advancePaletteCycle() {
|
||||||
// Replica exacta del ciclo de paleta del doIntroNewLogo vell sobre
|
// Replica exacta del ciclo de paleta del doIntroNewLogo vell sobre
|
||||||
// els índexs 16..31 (grup del verd brillant del logo).
|
// els índexs 16..31 (grup del verd brillant del logo).
|
||||||
for (int i = 16; i < 32; i++) {
|
for (int i = 16; i < 32; i++) {
|
||||||
@@ -117,9 +113,9 @@ void IntroNewLogoScene::advancePaletteCycle() {
|
|||||||
if (pal_[i].r < pal_[i].g) pal_[i].r++;
|
if (pal_[i].r < pal_[i].g) pal_[i].r++;
|
||||||
if (pal_[i].r > pal_[i].g) pal_[i].r--;
|
if (pal_[i].r > pal_[i].g) pal_[i].r--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 la fase de sprites). Durant Sprites
|
// TOTA la intro (inclou saltar la fase de sprites). Durant Sprites
|
||||||
// deixem que la sub-escena gestione el seu propi skip (que a més
|
// deixem que la sub-escena gestione el seu propi skip (que a més
|
||||||
@@ -213,6 +209,6 @@ void IntroNewLogoScene::tick(int delta_ms) {
|
|||||||
case Phase::Done:
|
case Phase::Done:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -9,27 +9,27 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Intro "moderna" del logo Jailgames amb revelat lletra-a-lletra +
|
// Intro "moderna" del logo Jailgames amb revelat lletra-a-lletra +
|
||||||
// ciclo de paleta final. Reemplaça `ModuleSequence::doIntroNewLogo()`.
|
// ciclo de paleta final. Reemplaça `ModuleSequence::doIntroNewLogo()`.
|
||||||
//
|
//
|
||||||
// Flux:
|
// Flux:
|
||||||
// 1. Carrega gfx/logo_new.gif, arranca música "music/00000003.ogg" i posa
|
// 1. Carrega gfx/logo_new.gif, arranca música "music/00000003.ogg" i posa
|
||||||
// la paleta directament (sense fade-in). Mostra pantalla negra 1s.
|
// la paleta directament (sense fade-in). Mostra pantalla negra 1s.
|
||||||
// 2. Revelat: 9 lletres × 2 frames (amb cursor / sense cursor), 150 ms
|
// 2. Revelat: 9 lletres × 2 frames (amb cursor / sense cursor), 150 ms
|
||||||
// cada frame.
|
// cada frame.
|
||||||
// 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. Transfereix el gfx_ a una `IntroSpritesScene` com a sub-escena
|
// 6. Transfereix el gfx_ a una `IntroSpritesScene` com a sub-escena
|
||||||
// i li delega els ticks fins que acaba (anima el prota + momia +
|
// i li delega els ticks fins que acaba (anima el prota + momia +
|
||||||
// mapa, amb 3 variants aleatòries). En acabar, setzea num_piramide
|
// mapa, amb 3 variants aleatòries). En acabar, setzea num_piramide
|
||||||
// = 0 per passar al menú.
|
// = 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`.
|
||||||
// Si és false, la factory retorna nullptr i el gameFiberEntry cau al
|
// Si és false, la factory retorna nullptr i el gameFiberEntry cau al
|
||||||
// path legacy (`ModuleSequence::doIntro()` vell).
|
// path legacy (`ModuleSequence::doIntro()` vell).
|
||||||
class IntroNewLogoScene : public Scene {
|
class IntroNewLogoScene : public Scene {
|
||||||
public:
|
public:
|
||||||
IntroNewLogoScene();
|
IntroNewLogoScene();
|
||||||
~IntroNewLogoScene() override;
|
~IntroNewLogoScene() override;
|
||||||
@@ -63,6 +63,6 @@ class IntroNewLogoScene : public Scene {
|
|||||||
int reveal_letter_{0};
|
int reveal_letter_{0};
|
||||||
bool reveal_cursor_visible_{true};
|
bool reveal_cursor_visible_{true};
|
||||||
int palette_step_{0};
|
int palette_step_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -7,26 +7,26 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Timings idèntics als del vell `doIntro()`: el JG_SetUpdateTicks(1000)
|
// 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
|
// 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
|
// "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.
|
// (G, A, M, E) i (200) per a la resta fins al cicle de paleta.
|
||||||
constexpr int INITIAL_MS = 1000;
|
constexpr int INITIAL_MS = 1000;
|
||||||
constexpr int PALETTE_CYCLE_STEP_MS = 20;
|
constexpr int PALETTE_CYCLE_STEP_MS = 20;
|
||||||
constexpr int PALETTE_CYCLE_STEPS = 256;
|
constexpr int PALETTE_CYCLE_STEPS = 256;
|
||||||
constexpr int FINAL_WAIT_MS = 200;
|
constexpr int FINAL_WAIT_MS = 200;
|
||||||
|
|
||||||
// Un pas del revelat. Dos blits configurables (cos del wordmark + avió)
|
// 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.
|
// més una variant per al wordmark sencer i un flag de ClearScreen previ.
|
||||||
struct RevealStep {
|
struct RevealStep {
|
||||||
int duration_ms;
|
int duration_ms;
|
||||||
int body_w; // amplada del blit body (43,78) ← (43,155, body_w, 45); 0 si s'usa wordmark
|
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ó
|
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 clear; // fa ClearScreen(0) abans dels blits
|
||||||
bool wordmark; // usa drawWordmark() en lloc del blit body (wordmark complet)
|
bool wordmark; // usa drawWordmark() en lloc del blit body (wordmark complet)
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr RevealStep REVEAL_STEPS[] = {
|
constexpr RevealStep REVEAL_STEPS[] = {
|
||||||
{100, 27, 68, false, false}, // J
|
{100, 27, 68, false, false}, // J
|
||||||
{100, 53, 96, false, false}, // JA
|
{100, 53, 96, false, false}, // JA
|
||||||
{100, 66, 109, false, false}, // JAI
|
{100, 66, 109, false, false}, // JAI
|
||||||
@@ -42,30 +42,30 @@ constexpr RevealStep REVEAL_STEPS[] = {
|
|||||||
{200, 0, -1, true, true}, // JAILGAMES (clear, sense avió)
|
{200, 0, -1, true, true}, // JAILGAMES (clear, sense avió)
|
||||||
{200, 0, 274, false, true}, // JAILGAMES + avió (sense clear)
|
{200, 0, 274, false, true}, // JAILGAMES + avió (sense clear)
|
||||||
{200, 0, -1, true, true}, // JAILGAMES (clear, sense avió)
|
{200, 0, -1, true, true}, // JAILGAMES (clear, sense avió)
|
||||||
};
|
};
|
||||||
constexpr int REVEAL_COUNT = sizeof(REVEAL_STEPS) / sizeof(REVEAL_STEPS[0]);
|
constexpr int REVEAL_COUNT = sizeof(REVEAL_STEPS) / sizeof(REVEAL_STEPS[0]);
|
||||||
|
|
||||||
// Branca `!use_new_logo` del drawIntroWordmark de modulesequence.cpp:
|
// Branca `!use_new_logo` del drawIntroWordmark de modulesequence.cpp:
|
||||||
// blit únic del wordmark "JAILGAMES" complet (231×45 al destí 43,78).
|
// 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
|
// IntroScene només s'activa quan use_new_logo == false, així que la
|
||||||
// branca use_new_logo d'aquell helper aquí no es necessita.
|
// branca use_new_logo d'aquell helper aquí no es necessita.
|
||||||
void drawWordmark(JD8_Surface gfx) {
|
void drawWordmark(JD8_Surface gfx) {
|
||||||
JD8_Blit(43, 78, gfx, 43, 155, 231, 45);
|
JD8_Blit(43, 78, gfx, 43, 155, 231, 45);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
IntroScene::IntroScene() = default;
|
IntroScene::IntroScene() = default;
|
||||||
|
|
||||||
IntroScene::~IntroScene() {
|
IntroScene::~IntroScene() {
|
||||||
// No alliberem `pal_`: JD8_SetScreenPalette n'ha pres ownership i el
|
// No alliberem `pal_`: JD8_SetScreenPalette n'ha pres ownership i el
|
||||||
// proper SetScreenPalette / FadeToPal la lliurarà. Alliberar-la ací
|
// proper SetScreenPalette / FadeToPal la lliurarà. Alliberar-la ací
|
||||||
// provocaria double free.
|
// provocaria double free.
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroScene::onEnter() {
|
void IntroScene::onEnter() {
|
||||||
playMusic("music/00000003.ogg");
|
playMusic("music/00000003.ogg");
|
||||||
|
|
||||||
gfx_ = SurfaceHandle("gfx/logo.gif");
|
gfx_ = SurfaceHandle("gfx/logo.gif");
|
||||||
@@ -78,9 +78,9 @@ void IntroScene::onEnter() {
|
|||||||
phase_acc_ms_ = 0;
|
phase_acc_ms_ = 0;
|
||||||
reveal_index_ = 0;
|
reveal_index_ = 0;
|
||||||
palette_step_ = 0;
|
palette_step_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroScene::render() {
|
void IntroScene::render() {
|
||||||
switch (phase_) {
|
switch (phase_) {
|
||||||
case Phase::InitialWait:
|
case Phase::InitialWait:
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
@@ -113,9 +113,9 @@ void IntroScene::render() {
|
|||||||
case Phase::Done:
|
case Phase::Done:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroScene::advancePaletteCycle() {
|
void IntroScene::advancePaletteCycle() {
|
||||||
// Replica exacta del cicle del doIntro vell sobre pal[16..31] — el
|
// 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
|
// grup del verd brillant del logo. Index 17 s'acosta a blanc mentre
|
||||||
// els altres convergeixen cap al mateix gris mitjà.
|
// els altres convergeixen cap al mateix gris mitjà.
|
||||||
@@ -130,9 +130,9 @@ void IntroScene::advancePaletteCycle() {
|
|||||||
if (pal_[i].r < pal_[i].g) pal_[i].r++;
|
if (pal_[i].r < pal_[i].g) pal_[i].r++;
|
||||||
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) {
|
void IntroScene::tick(int delta_ms) {
|
||||||
// Qualsevol tecla durant revelat/paleta salta TOTA la intro
|
// Qualsevol tecla durant revelat/paleta salta TOTA la intro
|
||||||
// (inclou saltar la fase de sprites). Durant Sprites deixem que
|
// (inclou saltar la fase de sprites). Durant Sprites deixem que
|
||||||
// la sub-escena gestione el seu propi skip internament, que a més
|
// la sub-escena gestione el seu propi skip internament, que a més
|
||||||
@@ -213,6 +213,6 @@ void IntroScene::tick(int delta_ms) {
|
|||||||
case Phase::Done:
|
case Phase::Done:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -9,28 +9,28 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Intro "legacy" del wordmark JAILGAMES lletra a lletra + cicle de paleta.
|
// Intro "legacy" del wordmark JAILGAMES lletra a lletra + cicle de paleta.
|
||||||
// Reemplaça `ModuleSequence::doIntro()`. S'activa quan
|
// Reemplaça `ModuleSequence::doIntro()`. S'activa quan
|
||||||
// `Options::game.use_new_logo == false`; l'alternativa moderna és
|
// `Options::game.use_new_logo == false`; l'alternativa moderna és
|
||||||
// `IntroNewLogoScene`.
|
// `IntroNewLogoScene`.
|
||||||
//
|
//
|
||||||
// Flux:
|
// Flux:
|
||||||
// 1. Carrega gfx/logo.gif, arranca música "music/00000003.ogg", pantalla negra
|
// 1. Carrega gfx/logo.gif, arranca música "music/00000003.ogg", pantalla negra
|
||||||
// 1000 ms.
|
// 1000 ms.
|
||||||
// 2. Revelat: 15 passos (100 o 200 ms) que van acumulant les lletres
|
// 2. Revelat: 15 passos (100 o 200 ms) que van acumulant les lletres
|
||||||
// "JAILGAMES" d'esquerra a dreta amb un avió escombrant al final
|
// "JAILGAMES" d'esquerra a dreta amb un avió escombrant al final
|
||||||
// de la paraula. Els passos 5, 11, 13 i 15 netegen la pantalla
|
// de la paraula. Els passos 5, 11, 13 i 15 netegen la pantalla
|
||||||
// per generar els parpelleigs finals.
|
// per generar els parpelleigs finals.
|
||||||
// 3. Cicle de paleta: 256 passos × 20 ms modificant els índexs 16..31.
|
// 3. Cicle de paleta: 256 passos × 20 ms modificant els índexs 16..31.
|
||||||
// 4. Espera final 200 ms.
|
// 4. Espera final 200 ms.
|
||||||
// 5. Transfereix el gfx_ a una `IntroSpritesScene` com a sub-escena
|
// 5. Transfereix el gfx_ a una `IntroSpritesScene` com a sub-escena
|
||||||
// i li delega els ticks fins que acaba (anima el prota + momia +
|
// i li delega els ticks fins que acaba (anima el prota + momia +
|
||||||
// mapa, amb 3 variants aleatòries). En acabar, setzea num_piramide
|
// mapa, amb 3 variants aleatòries). En acabar, setzea num_piramide
|
||||||
// = 0 per passar al menú.
|
// = 0 per passar al menú.
|
||||||
//
|
//
|
||||||
// Registrada al SceneRegistry amb state_key = 255: la mateixa factory que
|
// Registrada al SceneRegistry amb state_key = 255: la mateixa factory que
|
||||||
// per a IntroNewLogoScene, però retornada quan `use_new_logo == false`.
|
// per a IntroNewLogoScene, però retornada quan `use_new_logo == false`.
|
||||||
class IntroScene : public Scene {
|
class IntroScene : public Scene {
|
||||||
public:
|
public:
|
||||||
IntroScene();
|
IntroScene();
|
||||||
~IntroScene() override;
|
~IntroScene() override;
|
||||||
@@ -61,6 +61,6 @@ class IntroScene : public Scene {
|
|||||||
int phase_acc_ms_{0};
|
int phase_acc_ms_{0};
|
||||||
int reveal_index_{0};
|
int reveal_index_{0};
|
||||||
int palette_step_{0};
|
int palette_step_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -9,129 +9,142 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Duració d'un pas. El vell doIntroSprites feia JG_SetUpdateTicks(20);
|
// Duració d'un pas. El vell doIntroSprites feia JG_SetUpdateTicks(20);
|
||||||
// cada iteració del seu for (i) consumia un tick de 20 ms.
|
// cada iteració del seu for (i) consumia un tick de 20 ms.
|
||||||
constexpr int TICK_MS = 20;
|
constexpr int TICK_MS = 20;
|
||||||
|
|
||||||
// Taules de frames. Ubicacions de cada sprite dins el gfx de la intro
|
// Taules de frames. Ubicacions de cada sprite dins el gfx de la intro
|
||||||
// (gfx/logo.gif o gfx/logo_new.gif — el layout de sprites és el mateix).
|
// (gfx/logo.gif o gfx/logo_new.gif — el layout de sprites és el mateix).
|
||||||
// Cada sprite ocupa 15×15 px, disposats horitzontalment per fila.
|
// 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).
|
// 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.
|
// 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 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 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 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 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,
|
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)
|
||||||
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 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)
|
||||||
constexpr Uint16 fr7[] = {75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225, 240, 255, 270, // paper (y=75, idx 0..13)
|
0,
|
||||||
0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210}; // sombra (y=105, idx 14..28)
|
15,
|
||||||
constexpr Uint16 fr8[] = {15, 30, 45, 60}; // pedra (y=75)
|
30,
|
||||||
constexpr Uint16 fr9[] = {0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225}; // prota ball (y=120)
|
45,
|
||||||
constexpr Uint16 fr10[] = {0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225}; // momia ball (y=135)
|
60,
|
||||||
constexpr Uint16 fr11[] = {15, 30, 45, 60, 75, 60}; // altaveu (y=90, [5]=[3] pel loop de 4)
|
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 CREU = 75; // src_y de la creu (overlay)
|
||||||
constexpr Uint16 INTERROGANT = 90; // src_y del signe d'interrogant
|
constexpr Uint16 INTERROGANT = 90; // src_y del signe d'interrogant
|
||||||
|
|
||||||
// Equivalent de la funció `drawIntroWordmark` de modulesequence.cpp.
|
// Equivalent de la funció `drawIntroWordmark` de modulesequence.cpp.
|
||||||
// Branqueja segons use_new_logo perquè la mateixa sub-escena es
|
// Branqueja segons use_new_logo perquè la mateixa sub-escena es
|
||||||
// reutilitza des de IntroScene (logo vell) i IntroNewLogoScene (logo
|
// reutilitza des de IntroScene (logo vell) i IntroNewLogoScene (logo
|
||||||
// nou) amb arxius diferents però mateix layout de sprites.
|
// nou) amb arxius diferents però mateix layout de sprites.
|
||||||
void drawWordmark(JD8_Surface gfx) {
|
void drawWordmark(JD8_Surface gfx) {
|
||||||
if (Options::game.use_new_logo) {
|
if (Options::game.use_new_logo) {
|
||||||
JD8_Blit(60, 78, gfx, 60, 158, 188, 28);
|
JD8_Blit(60, 78, gfx, 60, 158, 188, 28);
|
||||||
} else {
|
} else {
|
||||||
JD8_Blit(43, 78, gfx, 43, 155, 231, 45);
|
JD8_Blit(43, 78, gfx, 43, 155, 231, 45);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using RenderFn = void (*)(JD8_Surface, int);
|
using RenderFn = void (*)(JD8_Surface, int);
|
||||||
|
|
||||||
// Una fase — rang [start_i..end_i] inclusive (direcció implícita per
|
// Una fase — rang [start_i..end_i] inclusive (direcció implícita per
|
||||||
// signe), funció de render, i flag d'skippable. Totes les fases actuals
|
// 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
|
// 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).
|
// no interrompuda (p.ex. un logo fatídic que cal veure sencer).
|
||||||
struct SpritePhase {
|
struct SpritePhase {
|
||||||
int start_i;
|
int start_i;
|
||||||
int end_i;
|
int end_i;
|
||||||
RenderFn render;
|
RenderFn render;
|
||||||
bool skippable;
|
bool skippable;
|
||||||
};
|
};
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Variant 0 — Interrogant / Momia
|
// Variant 0 — Interrogant / Momia
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
void v0_walk_right(JD8_Surface gfx, int i) {
|
void v0_walk_right(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(i, 150, gfx, fr1[(i / 5) % 13], 0, 15, 15, 0);
|
JD8_BlitCK(i, 150, gfx, fr1[(i / 5) % 13], 0, 15, 15, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v0_pull_map_right(JD8_Surface gfx, int i) {
|
void v0_pull_map_right(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(200, 150, gfx, fr3[std::min(i / 5, 10)], 30, 15, 15, 0);
|
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) {
|
void v0_walk_left_to_80(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(i, 150, gfx, fr2[(i / 5) % 13], 15, 15, 15, 0);
|
JD8_BlitCK(i, 150, gfx, fr2[(i / 5) % 13], 15, 15, 15, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v0_pull_map_left(JD8_Surface gfx, int i) {
|
void v0_pull_map_left(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(80, 150, gfx, fr4[std::min(i / 5, 10)], 45, 15, 15, 0);
|
JD8_BlitCK(80, 150, gfx, fr4[std::min(i / 5, 10)], 45, 15, 15, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v0_momia_left(JD8_Surface gfx, int i) {
|
void v0_momia_left(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(i, 150, gfx, fr6[(i / 5) % 8], 60, 15, 15, 0);
|
JD8_BlitCK(i, 150, gfx, fr6[(i / 5) % 8], 60, 15, 15, 0);
|
||||||
JD8_BlitCK(80, 150, gfx, fr4[10], 45, 15, 15, 0);
|
JD8_BlitCK(80, 150, gfx, fr4[10], 45, 15, 15, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v0_turn(JD8_Surface gfx, int /*i*/) {
|
void v0_turn(JD8_Surface gfx, int /*i*/) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(80, 150, gfx, fr1[1], 0, 15, 15, 0);
|
JD8_BlitCK(80, 150, gfx, fr1[1], 0, 15, 15, 0);
|
||||||
JD8_BlitCK(95, 150, gfx, fr6[4], 60, 15, 15, 0);
|
JD8_BlitCK(95, 150, gfx, fr6[4], 60, 15, 15, 0);
|
||||||
JD8_BlitCK(80, 133, gfx, 0, INTERROGANT, 15, 15, 0);
|
JD8_BlitCK(80, 133, gfx, 0, INTERROGANT, 15, 15, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v0_jump1(JD8_Surface gfx, int i) {
|
void v0_jump1(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(80, 150 - ((i % 50) / 5), gfx, fr5[std::min(i / 5, 19)], 45, 15, 15, 0);
|
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);
|
JD8_BlitCK(95, 150, gfx, fr6[4], 60, 15, 15, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v0_jump2(JD8_Surface gfx, int i) {
|
void v0_jump2(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(80, 140 + ((i % 50) / 5), gfx, fr5[std::min(i / 5, 19)], 45, 15, 15, 0);
|
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);
|
JD8_BlitCK(95, 150, gfx, fr6[4], 60, 15, 15, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v0_walk_final(JD8_Surface gfx, int i) {
|
void v0_walk_final(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(i, 150, gfx, fr2[(i / 5) % 13], 15, 15, 15, 0);
|
JD8_BlitCK(i, 150, gfx, fr2[(i / 5) % 13], 15, 15, 15, 0);
|
||||||
JD8_BlitCK(95, 150, gfx, fr6[4], 60, 15, 15, 0);
|
JD8_BlitCK(95, 150, gfx, fr6[4], 60, 15, 15, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v0_final(JD8_Surface gfx, int /*i*/) {
|
void v0_final(JD8_Surface gfx, int /*i*/) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(95, 150, gfx, fr6[4], 60, 15, 15, 0);
|
JD8_BlitCK(95, 150, gfx, fr6[4], 60, 15, 15, 0);
|
||||||
JD8_BlitCK(95, 133, gfx, 0, INTERROGANT, 15, 15, 0);
|
JD8_BlitCK(95, 133, gfx, 0, INTERROGANT, 15, 15, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr SpritePhase variant_0[] = {
|
constexpr SpritePhase variant_0[] = {
|
||||||
{0, 200, v0_walk_right, true},
|
{0, 200, v0_walk_right, true},
|
||||||
{0, 200, v0_pull_map_right, true},
|
{0, 200, v0_pull_map_right, true},
|
||||||
{200, 0, v0_pull_map_right, true}, // guarda el mapa (reprodueix inversament)
|
{200, 0, v0_pull_map_right, true}, // guarda el mapa (reprodueix inversament)
|
||||||
@@ -143,35 +156,35 @@ constexpr SpritePhase variant_0[] = {
|
|||||||
{50, 99, v0_jump2, true},
|
{50, 99, v0_jump2, true},
|
||||||
{80, 0, v0_walk_final, true},
|
{80, 0, v0_walk_final, true},
|
||||||
{0, 150, v0_final, true},
|
{0, 150, v0_final, true},
|
||||||
};
|
};
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Variant 1 — Creu / Pedra
|
// Variant 1 — Creu / Pedra
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
void v1_walk_right(JD8_Surface gfx, int i) {
|
void v1_walk_right(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
||||||
JD8_BlitCK(i, 150, gfx, fr1[(i / 5) % 13], 0, 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) {
|
void v1_pull_map(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
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);
|
JD8_BlitCK(200, 150, gfx, fr3[std::min(i / 5, 10)], 30, 15, 15, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v1_interrogant(JD8_Surface gfx, int /*i*/) {
|
void v1_interrogant(JD8_Surface gfx, int /*i*/) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
||||||
JD8_BlitCK(200, 134, gfx, 0, INTERROGANT, 15, 15, 255);
|
JD8_BlitCK(200, 134, gfx, 0, INTERROGANT, 15, 15, 255);
|
||||||
JD8_BlitCK(200, 150, gfx, fr3[10], 30, 15, 15, 255);
|
JD8_BlitCK(200, 150, gfx, fr3[10], 30, 15, 15, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v1_drop_map(JD8_Surface gfx, int i) {
|
void v1_drop_map(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
||||||
@@ -183,33 +196,33 @@ void v1_drop_map(JD8_Surface gfx, int i) {
|
|||||||
} else {
|
} else {
|
||||||
JD8_BlitCK(200, 150, gfx, fr7[idx], 105, 15, 15, 255);
|
JD8_BlitCK(200, 150, gfx, fr7[idx], 105, 15, 15, 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void v1_stone_fall(JD8_Surface gfx, int i) {
|
void v1_stone_fall(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
||||||
JD8_BlitCK(200, 150, gfx, fr7[28], 105, 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);
|
JD8_BlitCK(200, i * 2, gfx, fr8[0], 75, 15, 15, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v1_stone_break(JD8_Surface gfx, int i) {
|
void v1_stone_break(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
||||||
JD8_BlitCK(200, 150, gfx, fr8[i / 10], 75, 15, 15, 255);
|
JD8_BlitCK(200, 150, gfx, fr8[i / 10], 75, 15, 15, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v1_final(JD8_Surface gfx, int /*i*/) {
|
void v1_final(JD8_Surface gfx, int /*i*/) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
JD8_BlitCK(200, 155, gfx, 0, CREU, 15, 15, 255);
|
||||||
JD8_BlitCK(200, 150, gfx, fr8[1], 75, 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(185, 150, gfx, fr8[2], 75, 15, 15, 255);
|
||||||
JD8_BlitCK(215, 150, gfx, fr8[3], 75, 15, 15, 255);
|
JD8_BlitCK(215, 150, gfx, fr8[3], 75, 15, 15, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr SpritePhase variant_1[] = {
|
constexpr SpritePhase variant_1[] = {
|
||||||
{0, 200, v1_walk_right, true},
|
{0, 200, v1_walk_right, true},
|
||||||
{0, 300, v1_pull_map, true},
|
{0, 300, v1_pull_map, true},
|
||||||
{0, 100, v1_interrogant, true},
|
{0, 100, v1_interrogant, true},
|
||||||
@@ -217,87 +230,93 @@ constexpr SpritePhase variant_1[] = {
|
|||||||
{0, 75, v1_stone_fall, true},
|
{0, 75, v1_stone_fall, true},
|
||||||
{0, 19, v1_stone_break, true},
|
{0, 19, v1_stone_break, true},
|
||||||
{0, 200, v1_final, true},
|
{0, 200, v1_final, true},
|
||||||
};
|
};
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Variant 2 — Ball de carnaval
|
// Variant 2 — Ball de carnaval
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
void v2_approach(JD8_Surface gfx, int i) {
|
void v2_approach(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(i, 150, gfx, fr1[(i / 5) % 13], 0, 15, 15, 255);
|
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);
|
JD8_BlitCK(304 - i, 150, gfx, fr6[(i / 10) % 8], 60, 15, 15, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v2_still(JD8_Surface gfx, int /*i*/) {
|
void v2_still(JD8_Surface gfx, int /*i*/) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(145, 150, gfx, fr1[1], 0, 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);
|
JD8_BlitCK(160, 150, gfx, fr6[1], 60, 15, 15, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v2_horn(JD8_Surface gfx, int i) {
|
void v2_horn(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(125, 150, gfx, fr11[(i / 10) % 2], 90, 15, 15, 255);
|
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(145, 150, gfx, fr1[1], 0, 15, 15, 255);
|
||||||
JD8_BlitCK(160, 150, gfx, fr6[1], 60, 15, 15, 255);
|
JD8_BlitCK(160, 150, gfx, fr6[1], 60, 15, 15, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void v2_ball(JD8_Surface gfx, int i) {
|
void v2_ball(JD8_Surface gfx, int i) {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
drawWordmark(gfx);
|
drawWordmark(gfx);
|
||||||
JD8_BlitCK(145, 150, gfx, fr9[(i / 10) % 16], 120, 15, 15, 255);
|
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(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);
|
JD8_BlitCK(125, 150, gfx, fr11[((i / 5) % 4) + 2], 90, 15, 15, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr SpritePhase variant_2[] = {
|
constexpr SpritePhase variant_2[] = {
|
||||||
{0, 145, v2_approach, true},
|
{0, 145, v2_approach, true},
|
||||||
{0, 100, v2_still, true},
|
{0, 100, v2_still, true},
|
||||||
{0, 50, v2_horn, true},
|
{0, 50, v2_horn, true},
|
||||||
{0, 800, v2_ball, true},
|
{0, 800, v2_ball, true},
|
||||||
};
|
};
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Dispatch per variant
|
// Dispatch per variant
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
const SpritePhase* variant_table(int variant) {
|
const SpritePhase* variant_table(int variant) {
|
||||||
switch (variant) {
|
switch (variant) {
|
||||||
case 0: return variant_0;
|
case 0:
|
||||||
case 1: return variant_1;
|
return variant_0;
|
||||||
case 2: return variant_2;
|
case 1:
|
||||||
|
return variant_1;
|
||||||
|
case 2:
|
||||||
|
return variant_2;
|
||||||
}
|
}
|
||||||
return variant_0;
|
return variant_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int variant_length(int variant) {
|
int variant_length(int variant) {
|
||||||
switch (variant) {
|
switch (variant) {
|
||||||
case 0: return sizeof(variant_0) / sizeof(variant_0[0]);
|
case 0:
|
||||||
case 1: return sizeof(variant_1) / sizeof(variant_1[0]);
|
return sizeof(variant_0) / sizeof(variant_0[0]);
|
||||||
case 2: return sizeof(variant_2) / sizeof(variant_2[0]);
|
case 1:
|
||||||
|
return sizeof(variant_1) / sizeof(variant_1[0]);
|
||||||
|
case 2:
|
||||||
|
return sizeof(variant_2) / sizeof(variant_2[0]);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int phase_step_count(const SpritePhase& p) {
|
int phase_step_count(const SpritePhase& p) {
|
||||||
return std::abs(p.end_i - p.start_i) + 1;
|
return std::abs(p.end_i - p.start_i) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int phase_current_i(const SpritePhase& p, int step) {
|
int phase_current_i(const SpritePhase& p, int step) {
|
||||||
return p.end_i >= p.start_i ? p.start_i + step : p.start_i - step;
|
return p.end_i >= p.start_i ? p.start_i + step : p.start_i - step;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
IntroSpritesScene::IntroSpritesScene(SurfaceHandle&& gfx)
|
IntroSpritesScene::IntroSpritesScene(SurfaceHandle&& gfx)
|
||||||
: gfx_(std::move(gfx)) {}
|
: gfx_(std::move(gfx)) {}
|
||||||
|
|
||||||
void IntroSpritesScene::onEnter() {
|
void IntroSpritesScene::onEnter() {
|
||||||
// El vell doIntroSprites feia `rand() % 3` al principi. El seed ve
|
// El vell doIntroSprites feia `rand() % 3` al principi. El seed ve
|
||||||
// establert per `srand(time(0))` al boot del joc (info.cpp / main),
|
// establert per `srand(time(0))` al boot del joc (info.cpp / main),
|
||||||
// així que la variant canvia entre execucions.
|
// així que la variant canvia entre execucions.
|
||||||
@@ -311,9 +330,9 @@ void IntroSpritesScene::onEnter() {
|
|||||||
// el JD8_Flip del mini-loop del fiber el pinte al primer cicle.
|
// el JD8_Flip del mini-loop del fiber el pinte al primer cicle.
|
||||||
const SpritePhase* phases = variant_table(variant_);
|
const SpritePhase* phases = variant_table(variant_);
|
||||||
phases[0].render(gfx_.get(), phase_current_i(phases[0], 0));
|
phases[0].render(gfx_.get(), phase_current_i(phases[0], 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntroSpritesScene::tick(int delta_ms) {
|
void IntroSpritesScene::tick(int delta_ms) {
|
||||||
if (done_) return;
|
if (done_) return;
|
||||||
|
|
||||||
const SpritePhase* phases = variant_table(variant_);
|
const SpritePhase* phases = variant_table(variant_);
|
||||||
@@ -341,6 +360,6 @@ void IntroSpritesScene::tick(int delta_ms) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
phases[phase_].render(gfx_.get(), phase_current_i(phases[phase_], phase_step_));
|
phases[phase_].render(gfx_.get(), phase_current_i(phases[phase_], phase_step_));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -5,23 +5,23 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Sub-escena de sprites de la intro (prota + momia + mapa + etc).
|
// Sub-escena de sprites de la intro (prota + momia + mapa + etc).
|
||||||
// Reemplaça `ModuleSequence::doIntroSprites()`. No es registra al
|
// Reemplaça `ModuleSequence::doIntroSprites()`. No es registra al
|
||||||
// SceneRegistry — es construeix com a membre de `IntroScene` o
|
// SceneRegistry — es construeix com a membre de `IntroScene` o
|
||||||
// `IntroNewLogoScene` quan aquestes completen el seu revelat del logo.
|
// `IntroNewLogoScene` quan aquestes completen el seu revelat del logo.
|
||||||
// Rep el `SurfaceHandle` del gfx de la intro via move, de manera que
|
// Rep el `SurfaceHandle` del gfx de la intro via move, de manera que
|
||||||
// quan acabe l'escena el surface es lliberarà automàticament.
|
// quan acabe l'escena el surface es lliberarà automàticament.
|
||||||
//
|
//
|
||||||
// En entrar tria una de 3 variants (`rand() % 3`): "interrogant/momia",
|
// En entrar tria una de 3 variants (`rand() % 3`): "interrogant/momia",
|
||||||
// "creu/pedra" o "ball de carnaval". Cada variant té un nombre
|
// "creu/pedra" o "ball de carnaval". Cada variant té un nombre
|
||||||
// diferent de fases però comparteixen el mateix motor: un comptador
|
// diferent de fases però comparteixen el mateix motor: un comptador
|
||||||
// `step` que s'incrementa cada 20 ms, amb una taula per variant que
|
// `step` que s'incrementa cada 20 ms, amb una taula per variant que
|
||||||
// mapeja (rang d'i, renderer) a cada fase. Qualsevol tecla salta
|
// mapeja (rang d'i, renderer) a cada fase. Qualsevol tecla salta
|
||||||
// l'escena — el flag `skippable` per fase es manté com a mecanisme
|
// 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
|
// 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
|
// la fase "final" de la variant 0 no cridava wait_frame_or_skip, cosa
|
||||||
// molt probablement un oversight: ací es tracta com a skippable).
|
// molt probablement un oversight: ací es tracta com a skippable).
|
||||||
class IntroSpritesScene : public Scene {
|
class IntroSpritesScene : public Scene {
|
||||||
public:
|
public:
|
||||||
explicit IntroSpritesScene(SurfaceHandle&& gfx);
|
explicit IntroSpritesScene(SurfaceHandle&& gfx);
|
||||||
~IntroSpritesScene() override = default;
|
~IntroSpritesScene() override = default;
|
||||||
@@ -38,6 +38,6 @@ class IntroSpritesScene : public Scene {
|
|||||||
int phase_step_{0}; // passos consumits dins la fase actual
|
int phase_step_{0}; // passos consumits dins la fase actual
|
||||||
int step_acc_ms_{0}; // acumulador per emetre steps de 20 ms
|
int step_acc_ms_{0}; // acumulador per emetre steps de 20 ms
|
||||||
bool done_{false};
|
bool done_{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
void MenuScene::onEnter() {
|
void MenuScene::onEnter() {
|
||||||
fondo_ = SurfaceHandle("gfx/menu.gif");
|
fondo_ = SurfaceHandle("gfx/menu.gif");
|
||||||
gfx_ = SurfaceHandle("gfx/menu2.gif");
|
gfx_ = SurfaceHandle("gfx/menu2.gif");
|
||||||
|
|
||||||
@@ -24,9 +24,9 @@ void MenuScene::onEnter() {
|
|||||||
std::free(pal);
|
std::free(pal);
|
||||||
|
|
||||||
phase_ = Phase::FadingIn;
|
phase_ = Phase::FadingIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuScene::render() {
|
void MenuScene::render() {
|
||||||
// Cel estàtic (els primers 100 pixels verticals)
|
// Cel estàtic (els primers 100 pixels verticals)
|
||||||
JD8_Blit(0, 0, fondo_, 0, 0, 320, 100);
|
JD8_Blit(0, 0, fondo_, 0, 0, 320, 100);
|
||||||
|
|
||||||
@@ -56,9 +56,9 @@ void MenuScene::render() {
|
|||||||
JD8_BlitCK(68, 141, gfx_, 128, 105, 189, 9, 255);
|
JD8_BlitCK(68, 141, gfx_, 128, 105, 189, 9, 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuScene::tick(int delta_ms) {
|
void MenuScene::tick(int delta_ms) {
|
||||||
switch (phase_) {
|
switch (phase_) {
|
||||||
case Phase::FadingIn:
|
case Phase::FadingIn:
|
||||||
fade_.tick(delta_ms);
|
fade_.tick(delta_ms);
|
||||||
@@ -108,6 +108,6 @@ void MenuScene::tick(int delta_ms) {
|
|||||||
case Phase::Done:
|
case Phase::Done:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -7,22 +7,22 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Menú del títol. Reemplaça `ModuleSequence::doMenu()`.
|
// Menú del títol. Reemplaça `ModuleSequence::doMenu()`.
|
||||||
//
|
//
|
||||||
// Flux:
|
// Flux:
|
||||||
// 1. Carrega gfx/menu.gif (fondo) i gfx/menu2.gif (sprites) + paleta.
|
// 1. Carrega gfx/menu.gif (fondo) i gfx/menu2.gif (sprites) + paleta.
|
||||||
// 2. Pintat inicial estàtic (fondo, logo, camell frame 0, base "jdes"),
|
// 2. Pintat inicial estàtic (fondo, logo, camell frame 0, base "jdes"),
|
||||||
// fade-in de paleta.
|
// fade-in de paleta.
|
||||||
// 3. Loop d'animació: escroll parallax de horitzó (cada 320 ms) i
|
// 3. Loop d'animació: escroll parallax de horitzó (cada 320 ms) i
|
||||||
// palmeres (cada 80 ms), cicle del camell (4 frames × 160 ms),
|
// palmeres (cada 80 ms), cicle del camell (4 frames × 160 ms),
|
||||||
// i el text "polsa tecla" parpallejant cada 2 s (visible 1.4 s,
|
// i el text "polsa tecla" parpallejant cada 2 s (visible 1.4 s,
|
||||||
// amagat 0.6 s, igual que el `contador % 100 > 30` original).
|
// amagat 0.6 s, igual que el `contador % 100 > 30` original).
|
||||||
// 4. Quan l'usuari polsa qualsevol tecla — o 'P' per a activar Pepe —
|
// 4. Quan l'usuari polsa qualsevol tecla — o 'P' per a activar Pepe —
|
||||||
// llegim `info::ctx.pepe_activat`, disparem fade-out i marquem
|
// llegim `info::ctx.pepe_activat`, disparem fade-out i marquem
|
||||||
// num_piramide=1 (vas a doSlides).
|
// num_piramide=1 (vas a doSlides).
|
||||||
//
|
//
|
||||||
// Registrat al SceneRegistry amb state_key = 0.
|
// Registrat al SceneRegistry amb state_key = 0.
|
||||||
class MenuScene : public Scene {
|
class MenuScene : public Scene {
|
||||||
public:
|
public:
|
||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void tick(int delta_ms) override;
|
void tick(int delta_ms) override;
|
||||||
@@ -52,6 +52,6 @@ class MenuScene : public Scene {
|
|||||||
|
|
||||||
// Acumulador per al parpalleig del text "polsa tecla".
|
// Acumulador per al parpalleig del text "polsa tecla".
|
||||||
int blink_ms_{0};
|
int blink_ms_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
void MortScene::onEnter() {
|
void MortScene::onEnter() {
|
||||||
playMusic("music/00000001.ogg");
|
playMusic("music/00000001.ogg");
|
||||||
JI_DisableKeyboard(60);
|
JI_DisableKeyboard(60);
|
||||||
info::ctx.vida = 5;
|
info::ctx.vida = 5;
|
||||||
@@ -26,9 +26,9 @@ void MortScene::onEnter() {
|
|||||||
|
|
||||||
phase_ = Phase::FadingIn;
|
phase_ = Phase::FadingIn;
|
||||||
remaining_ms_ = 10000;
|
remaining_ms_ = 10000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MortScene::tick(int delta_ms) {
|
void MortScene::tick(int delta_ms) {
|
||||||
switch (phase_) {
|
switch (phase_) {
|
||||||
case Phase::FadingIn:
|
case Phase::FadingIn:
|
||||||
fade_.tick(delta_ms);
|
fade_.tick(delta_ms);
|
||||||
@@ -59,6 +59,6 @@ void MortScene::tick(int delta_ms) {
|
|||||||
case Phase::Done:
|
case Phase::Done:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -6,15 +6,15 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Pantalla de "game over". Reemplaça `ModuleSequence::doMort()`.
|
// Pantalla de "game over". Reemplaça `ModuleSequence::doMort()`.
|
||||||
//
|
//
|
||||||
// Flux:
|
// Flux:
|
||||||
// 1. Carrega gfx/gameover.gif, arranca música "music/00000001.ogg", fade-in de paleta.
|
// 1. Carrega gfx/gameover.gif, arranca música "music/00000001.ogg", fade-in de paleta.
|
||||||
// 2. Mostra la pantalla ~10 segons o fins que l'usuari polse una tecla.
|
// 2. Mostra la pantalla ~10 segons o fins que l'usuari polse una tecla.
|
||||||
// 3. Arranca música del menú ("music/00000003.ogg") i fade-out de paleta.
|
// 3. Arranca música del menú ("music/00000003.ogg") i fade-out de paleta.
|
||||||
// 4. Marca num_piramide=0 i retorna nextState=1 perquè el Director
|
// 4. Marca num_piramide=0 i retorna nextState=1 perquè el Director
|
||||||
// passe a l'escena del menú.
|
// passe a l'escena del menú.
|
||||||
class MortScene : public Scene {
|
class MortScene : public Scene {
|
||||||
public:
|
public:
|
||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void tick(int delta_ms) override;
|
void tick(int delta_ms) override;
|
||||||
@@ -31,6 +31,6 @@ class MortScene : public Scene {
|
|||||||
PaletteFade fade_;
|
PaletteFade fade_;
|
||||||
Phase phase_{Phase::FadingIn};
|
Phase phase_{Phase::FadingIn};
|
||||||
int remaining_ms_{10000}; // 1000 ticks × 10 ms/tick del doMort original
|
int remaining_ms_{10000}; // 1000 ticks × 10 ms/tick del doMort original
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -2,17 +2,17 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
void PaletteFade::startFadeOut() {
|
void PaletteFade::startFadeOut() {
|
||||||
JD8_FadeStartOut();
|
JD8_FadeStartOut();
|
||||||
active_ = true;
|
active_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaletteFade::startFadeTo(JD8_Palette target) {
|
void PaletteFade::startFadeTo(JD8_Palette target) {
|
||||||
JD8_FadeStartToPal(target);
|
JD8_FadeStartToPal(target);
|
||||||
active_ = true;
|
active_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaletteFade::tick(int /*delta_ms*/) {
|
void PaletteFade::tick(int /*delta_ms*/) {
|
||||||
if (!active_) return;
|
if (!active_) return;
|
||||||
// El fade té 32 passos interns. Amb un tick per frame (~16ms)
|
// El fade té 32 passos interns. Amb un tick per frame (~16ms)
|
||||||
// dura ~512ms — el mateix temps que la versió bloquejant original.
|
// dura ~512ms — el mateix temps que la versió bloquejant original.
|
||||||
@@ -23,6 +23,6 @@ void PaletteFade::tick(int /*delta_ms*/) {
|
|||||||
if (JD8_FadeTickStep()) {
|
if (JD8_FadeTickStep()) {
|
||||||
active_ = false;
|
active_ = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Embolcall fi damunt de la màquina d'estats de fade de jdraw8
|
// Embolcall fi damunt de la màquina d'estats de fade de jdraw8
|
||||||
// (`JD8_FadeStart*` / `JD8_FadeTickStep`). Exposa una API time-based
|
// (`JD8_FadeStart*` / `JD8_FadeTickStep`). Exposa una API time-based
|
||||||
// però internament avança un pas del fade per cada crida a `tick()`.
|
// però internament avança un pas del fade per cada crida a `tick()`.
|
||||||
// La raó de tindre-ho com a classe a banda: que una escena no puga
|
// La raó de tindre-ho com a classe a banda: que una escena no puga
|
||||||
// cridar accidentalment a `JD8_FadeOut`/`JD8_FadeToPal` (els shims
|
// cridar accidentalment a `JD8_FadeOut`/`JD8_FadeToPal` (els shims
|
||||||
// bloquejants vells) i que el `done()` siga consultable com la resta
|
// bloquejants vells) i que el `done()` siga consultable com la resta
|
||||||
// dels helpers.
|
// dels helpers.
|
||||||
class PaletteFade {
|
class PaletteFade {
|
||||||
public:
|
public:
|
||||||
PaletteFade() = default;
|
PaletteFade() = default;
|
||||||
|
|
||||||
@@ -25,6 +25,6 @@ class PaletteFade {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool active_{false};
|
bool active_{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
class Scene {
|
class Scene {
|
||||||
public:
|
public:
|
||||||
virtual ~Scene() = default;
|
virtual ~Scene() = default;
|
||||||
|
|
||||||
@@ -32,6 +32,6 @@ class Scene {
|
|||||||
// 0 = entrar al gameplay (ModuleGame)
|
// 0 = entrar al gameplay (ModuleGame)
|
||||||
// -1 = eixir del joc
|
// -1 = eixir del joc
|
||||||
virtual int nextState() const { return 1; }
|
virtual int nextState() const { return 1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -2,19 +2,19 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
SceneRegistry& SceneRegistry::instance() {
|
SceneRegistry& SceneRegistry::instance() {
|
||||||
static SceneRegistry inst;
|
static SceneRegistry inst;
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneRegistry::registerScene(int state_key, Factory factory) {
|
void SceneRegistry::registerScene(int state_key, Factory factory) {
|
||||||
factories_[state_key] = std::move(factory);
|
factories_[state_key] = std::move(factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Scene> SceneRegistry::tryCreate(int state_key) const {
|
std::unique_ptr<Scene> SceneRegistry::tryCreate(int state_key) const {
|
||||||
const auto it = factories_.find(state_key);
|
const auto it = factories_.find(state_key);
|
||||||
if (it == factories_.end()) return nullptr;
|
if (it == factories_.end()) return nullptr;
|
||||||
return it->second();
|
return it->second();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -8,16 +8,16 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Mapa de `state_key` (actualment = `info::ctx.num_piramide`) a factory
|
// Mapa de `state_key` (actualment = `info::ctx.num_piramide`) a factory
|
||||||
// d'escena. Permet que el dispatch de `gameFiberEntry` provi primer una
|
// d'escena. Permet que el dispatch de `gameFiberEntry` provi primer una
|
||||||
// Scene nova i caiga al vell `ModuleSequence::Go()` si encara no està
|
// Scene nova i caiga al vell `ModuleSequence::Go()` si encara no està
|
||||||
// migrada.
|
// migrada.
|
||||||
//
|
//
|
||||||
// Registre inicial: `Director::init()` cridarà `instance()` i afegirà
|
// Registre inicial: `Director::init()` cridarà `instance()` i afegirà
|
||||||
// una entrada per cada escena ja portada. A mesura que vagen caient, les
|
// una entrada per cada escena ja portada. A mesura que vagen caient, les
|
||||||
// línies del registre creixen i les funcions `doX()` del modulesequence
|
// línies del registre creixen i les funcions `doX()` del modulesequence
|
||||||
// desapareixen.
|
// desapareixen.
|
||||||
class SceneRegistry {
|
class SceneRegistry {
|
||||||
public:
|
public:
|
||||||
using Factory = std::function<std::unique_ptr<Scene>()>;
|
using Factory = std::function<std::unique_ptr<Scene>()>;
|
||||||
|
|
||||||
@@ -32,6 +32,6 @@ class SceneRegistry {
|
|||||||
private:
|
private:
|
||||||
SceneRegistry() = default;
|
SceneRegistry() = default;
|
||||||
std::unordered_map<int, Factory> factories_;
|
std::unordered_map<int, Factory> factories_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -7,15 +7,16 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
void playMusic(const char* filename, int loop) {
|
void playMusic(const char* filename, int loop) {
|
||||||
if (!filename) return;
|
if (!filename) return;
|
||||||
auto buffer = ResourceHelper::loadFile(filename);
|
auto buffer = ResourceHelper::loadFile(filename);
|
||||||
if (buffer.empty()) return;
|
if (buffer.empty()) return;
|
||||||
// JA_LoadMusic fa una còpia interna del OGG comprimit (via SDL_malloc)
|
// JA_LoadMusic fa una còpia interna del OGG comprimit (via SDL_malloc)
|
||||||
// per a stb_vorbis. El `buffer` local es destruirà en sortir d'àmbit.
|
// per a stb_vorbis. El `buffer` local es destruirà en sortir d'àmbit.
|
||||||
JA_PlayMusic(JA_LoadMusic(buffer.data(),
|
JA_PlayMusic(JA_LoadMusic(buffer.data(),
|
||||||
static_cast<Uint32>(buffer.size()), filename),
|
static_cast<Uint32>(buffer.size()),
|
||||||
|
filename),
|
||||||
loop);
|
loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Carrega un OGG de `data/` i arranca'l com a música de fons. Substituïx
|
// Carrega un OGG de `data/` i arranca'l com a música de fons. Substituïx
|
||||||
// el `play_music()` repetit en tots els doX() del vell modulesequence.
|
// el `play_music()` repetit en tots els doX() del vell modulesequence.
|
||||||
// `loop`: -1 = infinit (per defecte), 0 = una sola vegada, N = N+1 passades.
|
// `loop`: -1 = infinit (per defecte), 0 = una sola vegada, N = N+1 passades.
|
||||||
void playMusic(const char* filename, int loop = -1);
|
void playMusic(const char* filename, int loop = -1);
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -12,36 +12,36 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr int TICK_MS = 20; // JG_SetUpdateTicks(20) del vell doSecreta
|
constexpr int TICK_MS = 20; // JG_SetUpdateTicks(20) del vell doSecreta
|
||||||
|
|
||||||
// Durades per fase, derivades dels contador-thresholds del vell:
|
// Durades per fase, derivades dels contador-thresholds del vell:
|
||||||
// tomba1 scroll: 127 passos (contador 1→128) × 20ms
|
// tomba1 scroll: 127 passos (contador 1→128) × 20ms
|
||||||
// tomba1 hold: 128 passos (contador 128→0) × 20ms
|
// tomba1 hold: 128 passos (contador 128→0) × 20ms
|
||||||
// tomba2 scroll: 94 passos × 20ms
|
// tomba2 scroll: 94 passos × 20ms
|
||||||
// tomba2 hold: 94 passos × 20ms
|
// tomba2 hold: 94 passos × 20ms
|
||||||
// reveal horit: 80 passos × 20ms
|
// reveal horit: 80 passos × 20ms
|
||||||
// reveal hold: 80 passos × 20ms
|
// reveal hold: 80 passos × 20ms
|
||||||
// red pulse: 51 passos × 20ms
|
// red pulse: 51 passos × 20ms
|
||||||
// red pulse hold: 51 passos × 20ms
|
// red pulse hold: 51 passos × 20ms
|
||||||
constexpr int TOMBA1_SCROLL_MS = 127 * TICK_MS;
|
constexpr int TOMBA1_SCROLL_MS = 127 * TICK_MS;
|
||||||
constexpr int TOMBA1_HOLD_MS = 128 * TICK_MS;
|
constexpr int TOMBA1_HOLD_MS = 128 * TICK_MS;
|
||||||
constexpr int TOMBA2_SCROLL_MS = 94 * TICK_MS;
|
constexpr int TOMBA2_SCROLL_MS = 94 * TICK_MS;
|
||||||
constexpr int TOMBA2_HOLD_MS = 94 * TICK_MS;
|
constexpr int TOMBA2_HOLD_MS = 94 * TICK_MS;
|
||||||
constexpr int TOMBA2_REVEAL_MS = 80 * TICK_MS;
|
constexpr int TOMBA2_REVEAL_MS = 80 * TICK_MS;
|
||||||
constexpr int TOMBA2_REVEAL_HOLD_MS = 80 * TICK_MS;
|
constexpr int TOMBA2_REVEAL_HOLD_MS = 80 * TICK_MS;
|
||||||
constexpr int RED_PULSE_MS = 51 * TICK_MS;
|
constexpr int RED_PULSE_MS = 51 * TICK_MS;
|
||||||
constexpr int RED_PULSE_HOLD_MS = 51 * TICK_MS;
|
constexpr int RED_PULSE_HOLD_MS = 51 * TICK_MS;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
SecretaScene::~SecretaScene() {
|
SecretaScene::~SecretaScene() {
|
||||||
if (pal_aux_) std::free(pal_aux_);
|
if (pal_aux_) std::free(pal_aux_);
|
||||||
// pal_active_ NO s'allibera: propietat de main_palette via SetScreenPalette.
|
// pal_active_ NO s'allibera: propietat de main_palette via SetScreenPalette.
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecretaScene::onEnter() {
|
void SecretaScene::onEnter() {
|
||||||
playMusic("music/00000002.ogg");
|
playMusic("music/00000002.ogg");
|
||||||
|
|
||||||
// Fade-out de la paleta anterior. Els assets es carreguen ja
|
// Fade-out de la paleta anterior. Els assets es carreguen ja
|
||||||
@@ -56,9 +56,9 @@ void SecretaScene::onEnter() {
|
|||||||
|
|
||||||
phase_ = Phase::InitialFadeOut;
|
phase_ = Phase::InitialFadeOut;
|
||||||
phase_acc_ms_ = 0;
|
phase_acc_ms_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecretaScene::swapToTomba2() {
|
void SecretaScene::swapToTomba2() {
|
||||||
JD8_ClearScreen(255);
|
JD8_ClearScreen(255);
|
||||||
gfx_.reset("gfx/tomba2.gif");
|
gfx_.reset("gfx/tomba2.gif");
|
||||||
|
|
||||||
@@ -67,21 +67,21 @@ void SecretaScene::swapToTomba2() {
|
|||||||
// pal_active_ continua sent el mateix buffer: només actualitzem
|
// pal_active_ continua sent el mateix buffer: només actualitzem
|
||||||
// el seu contingut. main_palette ja apunta ací.
|
// el seu contingut. main_palette ja apunta ací.
|
||||||
std::memcpy(pal_active_, pal_aux_, 768);
|
std::memcpy(pal_active_, pal_aux_, 768);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecretaScene::beginRedPulseSetup() {
|
void SecretaScene::beginRedPulseSetup() {
|
||||||
JD8_ClearScreen(0);
|
JD8_ClearScreen(0);
|
||||||
JD8_SetPaletteColor(254, 12, 11, 11);
|
JD8_SetPaletteColor(254, 12, 11, 11);
|
||||||
JD8_SetPaletteColor(253, 12, 11, 11);
|
JD8_SetPaletteColor(253, 12, 11, 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecretaScene::beginFinalFade() {
|
void SecretaScene::beginFinalFade() {
|
||||||
JA_FadeOutMusic(250);
|
JA_FadeOutMusic(250);
|
||||||
fade_.startFadeOut();
|
fade_.startFadeOut();
|
||||||
phase_ = Phase::FinalFadeOut;
|
phase_ = Phase::FinalFadeOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecretaScene::tick(int delta_ms) {
|
void SecretaScene::tick(int delta_ms) {
|
||||||
// Skip per tecla (després del fade inicial, no mentre). Salta
|
// Skip per tecla (després del fade inicial, no mentre). Salta
|
||||||
// directament al FinalFadeOut. Mateix patró que el vell, on
|
// directament al FinalFadeOut. Mateix patró que el vell, on
|
||||||
// qualsevol tecla sortia del loop.
|
// qualsevol tecla sortia del loop.
|
||||||
@@ -200,6 +200,6 @@ void SecretaScene::tick(int delta_ms) {
|
|||||||
case Phase::Done:
|
case Phase::Done:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -7,24 +7,24 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Pre-Secreta. Reemplaça `ModuleSequence::doSecreta()`.
|
// Pre-Secreta. Reemplaça `ModuleSequence::doSecreta()`.
|
||||||
//
|
//
|
||||||
// Flux:
|
// Flux:
|
||||||
// 1. Arranca música "music/00000002.ogg" i fa fade-out de la paleta anterior.
|
// 1. Arranca música "music/00000002.ogg" i fa fade-out de la paleta anterior.
|
||||||
// 2. Carrega gfx/tomba1.gif + paleta i pinta un scroll vertical doble
|
// 2. Carrega gfx/tomba1.gif + paleta i pinta un scroll vertical doble
|
||||||
// (dos blits solapats, un a velocitat meitat que l'altre) durant
|
// (dos blits solapats, un a velocitat meitat que l'altre) durant
|
||||||
// ~2.5 s + ~2.5 s de pausa.
|
// ~2.5 s + ~2.5 s de pausa.
|
||||||
// 3. Swap a gfx/tomba2.gif + reset de paleta, scroll vertical del segon
|
// 3. Swap a gfx/tomba2.gif + reset de paleta, scroll vertical del segon
|
||||||
// asset (~1.9 s + ~1.9 s de pausa).
|
// asset (~1.9 s + ~1.9 s de pausa).
|
||||||
// 4. ClearScreen a 0, set colors 253/254 a vermell fosc (12,11,11)
|
// 4. ClearScreen a 0, set colors 253/254 a vermell fosc (12,11,11)
|
||||||
// i pinta un revelat horitzontal (~1.6 s + ~1.6 s de pausa).
|
// i pinta un revelat horitzontal (~1.6 s + ~1.6 s de pausa).
|
||||||
// 5. "Red pulse": anima els colors 253/254 incrementant el canal R
|
// 5. "Red pulse": anima els colors 253/254 incrementant el canal R
|
||||||
// de 12 a 62 durant ~1 s (+ ~1 s de pausa).
|
// de 12 a 62 durant ~1 s (+ ~1 s de pausa).
|
||||||
// 6. FadeOut + JA_FadeOutMusic(250).
|
// 6. FadeOut + JA_FadeOutMusic(250).
|
||||||
// 7. Retorna nextState=0 per entrar al ModuleGame amb num_piramide=6.
|
// 7. Retorna nextState=0 per entrar al ModuleGame amb num_piramide=6.
|
||||||
//
|
//
|
||||||
// Registrada al SceneRegistry amb state_key = 6.
|
// Registrada al SceneRegistry amb state_key = 6.
|
||||||
class SecretaScene : public Scene {
|
class SecretaScene : public Scene {
|
||||||
public:
|
public:
|
||||||
SecretaScene() = default;
|
SecretaScene() = default;
|
||||||
~SecretaScene() override;
|
~SecretaScene() override;
|
||||||
@@ -61,6 +61,6 @@ class SecretaScene : public Scene {
|
|||||||
Phase phase_{Phase::InitialFadeOut};
|
Phase phase_{Phase::InitialFadeOut};
|
||||||
int phase_acc_ms_{0};
|
int phase_acc_ms_{0};
|
||||||
bool skip_triggered_{false};
|
bool skip_triggered_{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -13,29 +13,29 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr int SCROLL_MS = 1600; // 80 iters × 20 ms del vell doSlides
|
constexpr int SCROLL_MS = 1600; // 80 iters × 20 ms del vell doSlides
|
||||||
constexpr int HOLD_MS = 4600; // 230 iters × 20 ms (80 + 150) del vell
|
constexpr int HOLD_MS = 4600; // 230 iters × 20 ms (80 + 150) del vell
|
||||||
constexpr int SLIDE_Y = 65;
|
constexpr int SLIDE_Y = 65;
|
||||||
constexpr int SLIDE_H = 65;
|
constexpr int SLIDE_H = 65;
|
||||||
constexpr int BG_COLOR_INDEX = 255;
|
constexpr int BG_COLOR_INDEX = 255;
|
||||||
|
|
||||||
// Desplaçament inicial del slide segons direcció del wipe.
|
// Desplaçament inicial del slide segons direcció del wipe.
|
||||||
// Slide 1 i 3: "scroll in from right" (pos_x va de 320 → 0).
|
// Slide 1 i 3: "scroll in from right" (pos_x va de 320 → 0).
|
||||||
// Slide 2: "wipe reverse" (pos_x va de -320 → 0), el mateix efecte
|
// Slide 2: "wipe reverse" (pos_x va de -320 → 0), el mateix efecte
|
||||||
// estrany del doSlides vell on la imatge es desplaça des de l'esquerra
|
// estrany del doSlides vell on la imatge es desplaça des de l'esquerra
|
||||||
// però revela primer el lateral dret del src.
|
// però revela primer el lateral dret del src.
|
||||||
constexpr int SLIDE_START_X[3] = {320, -320, 320};
|
constexpr int SLIDE_START_X[3] = {320, -320, 320};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
SlidesScene::~SlidesScene() {
|
SlidesScene::~SlidesScene() {
|
||||||
if (pal_aux_) std::free(pal_aux_);
|
if (pal_aux_) std::free(pal_aux_);
|
||||||
// pal_active_ NO s'allibera: propietat de main_palette via SetScreenPalette.
|
// pal_active_ NO s'allibera: propietat de main_palette via SetScreenPalette.
|
||||||
}
|
}
|
||||||
|
|
||||||
void SlidesScene::onEnter() {
|
void SlidesScene::onEnter() {
|
||||||
num_piramide_at_start_ = info::ctx.num_piramide;
|
num_piramide_at_start_ = info::ctx.num_piramide;
|
||||||
|
|
||||||
const char* arxiu = nullptr;
|
const char* arxiu = nullptr;
|
||||||
@@ -63,9 +63,9 @@ void SlidesScene::onEnter() {
|
|||||||
phase_ = Phase::Slide1Enter;
|
phase_ = Phase::Slide1Enter;
|
||||||
phase_acc_ms_ = 0;
|
phase_acc_ms_ = 0;
|
||||||
next_state_ = 0;
|
next_state_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SlidesScene::drawSlide(int slide_idx, int pos_x) {
|
void SlidesScene::drawSlide(int slide_idx, int pos_x) {
|
||||||
const int src_y = slide_idx * SLIDE_H;
|
const int src_y = slide_idx * SLIDE_H;
|
||||||
|
|
||||||
// Clipping manual: translada un rect de 320×65 des de (pos_x, SLIDE_Y)
|
// Clipping manual: translada un rect de 320×65 des de (pos_x, SLIDE_Y)
|
||||||
@@ -85,21 +85,21 @@ void SlidesScene::drawSlide(int slide_idx, int pos_x) {
|
|||||||
if (w > 0) {
|
if (w > 0) {
|
||||||
JD8_Blit(dst_x, SLIDE_Y, gfx_, src_x, src_y, w, SLIDE_H);
|
JD8_Blit(dst_x, SLIDE_Y, gfx_, src_x, src_y, w, SLIDE_H);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SlidesScene::restorePalette() {
|
void SlidesScene::restorePalette() {
|
||||||
std::memcpy(pal_active_, pal_aux_, 768);
|
std::memcpy(pal_active_, pal_aux_, 768);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SlidesScene::beginFinalFade() {
|
void SlidesScene::beginFinalFade() {
|
||||||
if (num_piramide_at_start_ != 7) {
|
if (num_piramide_at_start_ != 7) {
|
||||||
JA_FadeOutMusic(250);
|
JA_FadeOutMusic(250);
|
||||||
}
|
}
|
||||||
fade_.startFadeOut();
|
fade_.startFadeOut();
|
||||||
phase_ = Phase::FadeFinal;
|
phase_ = Phase::FadeFinal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SlidesScene::tick(int delta_ms) {
|
void SlidesScene::tick(int delta_ms) {
|
||||||
// Skip: qualsevol tecla salta directament al fade final. Per fidelitat
|
// Skip: qualsevol tecla salta directament al fade final. Per fidelitat
|
||||||
// al vell doSlides, el skip NO atura la música explícitament — només
|
// al vell doSlides, el skip NO atura la música explícitament — només
|
||||||
// el final natural crida JA_FadeOutMusic (beginFinalFade() distingeix).
|
// el final natural crida JA_FadeOutMusic (beginFinalFade() distingeix).
|
||||||
@@ -118,8 +118,7 @@ void SlidesScene::tick(int delta_ms) {
|
|||||||
const int slide_idx = (phase_ == Phase::Slide1Enter ? 0
|
const int slide_idx = (phase_ == Phase::Slide1Enter ? 0
|
||||||
: phase_ == Phase::Slide2Enter ? 1
|
: phase_ == Phase::Slide2Enter ? 1
|
||||||
: 2);
|
: 2);
|
||||||
const float t = std::min(1.0f, static_cast<float>(phase_acc_ms_) /
|
const float t = std::min(1.0f, static_cast<float>(phase_acc_ms_) / static_cast<float>(SCROLL_MS));
|
||||||
static_cast<float>(SCROLL_MS));
|
|
||||||
const float eased = Easing::outCubic(t);
|
const float eased = Easing::outCubic(t);
|
||||||
const int pos_x = Easing::lerpInt(SLIDE_START_X[slide_idx], 0, eased);
|
const int pos_x = Easing::lerpInt(SLIDE_START_X[slide_idx], 0, eased);
|
||||||
drawSlide(slide_idx, pos_x);
|
drawSlide(slide_idx, pos_x);
|
||||||
@@ -127,9 +126,12 @@ void SlidesScene::tick(int delta_ms) {
|
|||||||
if (phase_acc_ms_ >= SCROLL_MS) {
|
if (phase_acc_ms_ >= SCROLL_MS) {
|
||||||
// Garanteix posició final exacta (pos_x=0).
|
// Garanteix posició final exacta (pos_x=0).
|
||||||
drawSlide(slide_idx, 0);
|
drawSlide(slide_idx, 0);
|
||||||
if (phase_ == Phase::Slide1Enter) phase_ = Phase::Slide1Hold;
|
if (phase_ == Phase::Slide1Enter)
|
||||||
else if (phase_ == Phase::Slide2Enter) phase_ = Phase::Slide2Hold;
|
phase_ = Phase::Slide1Hold;
|
||||||
else phase_ = Phase::Slide3Hold;
|
else if (phase_ == Phase::Slide2Enter)
|
||||||
|
phase_ = Phase::Slide2Hold;
|
||||||
|
else
|
||||||
|
phase_ = Phase::Slide3Hold;
|
||||||
phase_acc_ms_ = 0;
|
phase_acc_ms_ = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -140,8 +142,10 @@ void SlidesScene::tick(int delta_ms) {
|
|||||||
phase_acc_ms_ += delta_ms;
|
phase_acc_ms_ += delta_ms;
|
||||||
if (phase_acc_ms_ >= HOLD_MS) {
|
if (phase_acc_ms_ >= HOLD_MS) {
|
||||||
fade_.startFadeOut();
|
fade_.startFadeOut();
|
||||||
if (phase_ == Phase::Slide1Hold) phase_ = Phase::FadeOut1;
|
if (phase_ == Phase::Slide1Hold)
|
||||||
else phase_ = Phase::FadeOut2;
|
phase_ = Phase::FadeOut1;
|
||||||
|
else
|
||||||
|
phase_ = Phase::FadeOut2;
|
||||||
phase_acc_ms_ = 0;
|
phase_acc_ms_ = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -159,8 +163,10 @@ void SlidesScene::tick(int delta_ms) {
|
|||||||
if (fade_.done()) {
|
if (fade_.done()) {
|
||||||
restorePalette();
|
restorePalette();
|
||||||
JD8_ClearScreen(BG_COLOR_INDEX);
|
JD8_ClearScreen(BG_COLOR_INDEX);
|
||||||
if (phase_ == Phase::FadeOut1) phase_ = Phase::Slide2Enter;
|
if (phase_ == Phase::FadeOut1)
|
||||||
else phase_ = Phase::Slide3Enter;
|
phase_ = Phase::Slide2Enter;
|
||||||
|
else
|
||||||
|
phase_ = Phase::Slide3Enter;
|
||||||
phase_acc_ms_ = 0;
|
phase_acc_ms_ = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -181,6 +187,6 @@ void SlidesScene::tick(int delta_ms) {
|
|||||||
case Phase::Done:
|
case Phase::Done:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -7,33 +7,33 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// 3 slides narratius amb scroll d'entrada + espera + transició amb
|
// 3 slides narratius amb scroll d'entrada + espera + transició amb
|
||||||
// fade-out. Reemplaça `ModuleSequence::doSlides()`.
|
// fade-out. Reemplaça `ModuleSequence::doSlides()`.
|
||||||
//
|
//
|
||||||
// Tria d'asset segons context:
|
// Tria d'asset segons context:
|
||||||
// - num_piramide == 7 i diners < 200: gfx/intro2.gif + música "music/00000005.ogg"
|
// - num_piramide == 7 i diners < 200: gfx/intro2.gif + música "music/00000005.ogg"
|
||||||
// - num_piramide == 7 i diners >= 200: gfx/intro3.gif + música "music/00000005.ogg"
|
// - num_piramide == 7 i diners >= 200: gfx/intro3.gif + música "music/00000005.ogg"
|
||||||
// - altre cas (num_piramide == 1): gfx/intro.gif, sense música nova
|
// - altre cas (num_piramide == 1): gfx/intro.gif, sense música nova
|
||||||
//
|
//
|
||||||
// Flux:
|
// Flux:
|
||||||
// Slide1Enter (1600 ms scroll dreta→centre, easing outCubic)
|
// Slide1Enter (1600 ms scroll dreta→centre, easing outCubic)
|
||||||
// → Slide1Hold (4600 ms)
|
// → Slide1Hold (4600 ms)
|
||||||
// → FadeOut1 + clear + reset paleta
|
// → FadeOut1 + clear + reset paleta
|
||||||
// → Slide2Enter (1600 ms scroll esquerra→centre)
|
// → Slide2Enter (1600 ms scroll esquerra→centre)
|
||||||
// → Slide2Hold (4600 ms)
|
// → Slide2Hold (4600 ms)
|
||||||
// → FadeOut2 + clear + reset paleta
|
// → FadeOut2 + clear + reset paleta
|
||||||
// → Slide3Enter (1600 ms scroll dreta→centre)
|
// → Slide3Enter (1600 ms scroll dreta→centre)
|
||||||
// → Slide3Hold (4600 ms)
|
// → Slide3Hold (4600 ms)
|
||||||
// → FadeFinal (JA_FadeOutMusic si num_piramide != 7 + fade paleta)
|
// → FadeFinal (JA_FadeOutMusic si num_piramide != 7 + fade paleta)
|
||||||
// → Done
|
// → Done
|
||||||
//
|
//
|
||||||
// Qualsevol tecla salta directament a FadeFinal (sense cortar la música
|
// Qualsevol tecla salta directament a FadeFinal (sense cortar la música
|
||||||
// si hem entrat per num_piramide==7, per fidelitat al vell).
|
// si hem entrat per num_piramide==7, per fidelitat al vell).
|
||||||
//
|
//
|
||||||
// NextState:
|
// NextState:
|
||||||
// - num_piramide==7 al entrar → num_piramide=8 + return 1 (a Credits)
|
// - num_piramide==7 al entrar → num_piramide=8 + return 1 (a Credits)
|
||||||
// - altre cas → return 0 (entra al ModuleGame)
|
// - altre cas → return 0 (entra al ModuleGame)
|
||||||
class SlidesScene : public Scene {
|
class SlidesScene : public Scene {
|
||||||
public:
|
public:
|
||||||
SlidesScene() = default;
|
SlidesScene() = default;
|
||||||
~SlidesScene() override;
|
~SlidesScene() override;
|
||||||
@@ -74,6 +74,6 @@ class SlidesScene : public Scene {
|
|||||||
int num_piramide_at_start_{1};
|
int num_piramide_at_start_{1};
|
||||||
int next_state_{0};
|
int next_state_{0};
|
||||||
bool skip_triggered_{false};
|
bool skip_triggered_{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
void SpriteMover::moveTo(int x0, int y0, int x1, int y1, int duration_ms, EaseFn ease) {
|
void SpriteMover::moveTo(int x0, int y0, int x1, int y1, int duration_ms, EaseFn ease) {
|
||||||
x0_ = x0;
|
x0_ = x0;
|
||||||
y0_ = y0;
|
y0_ = y0;
|
||||||
x1_ = x1;
|
x1_ = x1;
|
||||||
@@ -14,18 +14,18 @@ void SpriteMover::moveTo(int x0, int y0, int x1, int y1, int duration_ms, EaseFn
|
|||||||
ease_ = ease ? ease : Easing::linear;
|
ease_ = ease ? ease : Easing::linear;
|
||||||
cur_x_ = x0;
|
cur_x_ = x0;
|
||||||
cur_y_ = y0;
|
cur_y_ = y0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteMover::setPosition(int x, int y) {
|
void SpriteMover::setPosition(int x, int y) {
|
||||||
cur_x_ = x;
|
cur_x_ = x;
|
||||||
cur_y_ = y;
|
cur_y_ = y;
|
||||||
x0_ = x1_ = x;
|
x0_ = x1_ = x;
|
||||||
y0_ = y1_ = y;
|
y0_ = y1_ = y;
|
||||||
duration_ms_ = 0;
|
duration_ms_ = 0;
|
||||||
elapsed_ms_ = 0;
|
elapsed_ms_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteMover::tick(int delta_ms) {
|
void SpriteMover::tick(int delta_ms) {
|
||||||
if (duration_ms_ <= 0) {
|
if (duration_ms_ <= 0) {
|
||||||
cur_x_ = x1_;
|
cur_x_ = x1_;
|
||||||
cur_y_ = y1_;
|
cur_y_ = y1_;
|
||||||
@@ -36,11 +36,11 @@ void SpriteMover::tick(int delta_ms) {
|
|||||||
const float eased = ease_(t);
|
const float eased = ease_(t);
|
||||||
cur_x_ = Easing::lerpInt(x0_, x1_, eased);
|
cur_x_ = Easing::lerpInt(x0_, x1_, eased);
|
||||||
cur_y_ = Easing::lerpInt(y0_, y1_, eased);
|
cur_y_ = Easing::lerpInt(y0_, y1_, eased);
|
||||||
}
|
}
|
||||||
|
|
||||||
float SpriteMover::progress() const {
|
float SpriteMover::progress() const {
|
||||||
if (duration_ms_ <= 0) return 1.0f;
|
if (duration_ms_ <= 0) return 1.0f;
|
||||||
return static_cast<float>(elapsed_ms_) / static_cast<float>(duration_ms_);
|
return static_cast<float>(elapsed_ms_) / static_cast<float>(duration_ms_);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -4,19 +4,18 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Interpola una posició 2D entre dos punts durant un temps donat amb
|
// Interpola una posició 2D entre dos punts durant un temps donat amb
|
||||||
// una funció d'easing. No toca cap surface — el caller llegix x()/y()
|
// una funció d'easing. No toca cap surface — el caller llegix x()/y()
|
||||||
// i fa el blit ell mateix. Pensat per a scrolls, sprites que entren/
|
// i fa el blit ell mateix. Pensat per a scrolls, sprites que entren/
|
||||||
// ixen per pantalla, i moviments d'objectes interpolats.
|
// ixen per pantalla, i moviments d'objectes interpolats.
|
||||||
class SpriteMover {
|
class SpriteMover {
|
||||||
public:
|
public:
|
||||||
using EaseFn = float (*)(float);
|
using EaseFn = float (*)(float);
|
||||||
|
|
||||||
SpriteMover() = default;
|
SpriteMover() = default;
|
||||||
|
|
||||||
// Arrenca un moviment nou. Si ja n'hi havia un en curs, es descarta.
|
// Arrenca un moviment nou. Si ja n'hi havia un en curs, es descarta.
|
||||||
void moveTo(int x0, int y0, int x1, int y1, int duration_ms,
|
void moveTo(int x0, int y0, int x1, int y1, int duration_ms, EaseFn ease = Easing::linear);
|
||||||
EaseFn ease = Easing::linear);
|
|
||||||
|
|
||||||
// Posicionament immediat (útil per a "teleportar" entre moviments).
|
// Posicionament immediat (útil per a "teleportar" entre moviments).
|
||||||
void setPosition(int x, int y);
|
void setPosition(int x, int y);
|
||||||
@@ -34,6 +33,6 @@ class SpriteMover {
|
|||||||
int elapsed_ms_{0};
|
int elapsed_ms_{0};
|
||||||
int cur_x_{0}, cur_y_{0};
|
int cur_x_{0}, cur_y_{0};
|
||||||
EaseFn ease_{Easing::linear};
|
EaseFn ease_{Easing::linear};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -2,41 +2,41 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
SurfaceHandle::SurfaceHandle(const char* file)
|
SurfaceHandle::SurfaceHandle(const char* file)
|
||||||
: surface_(JD8_LoadSurface(file)) {}
|
: surface_(JD8_LoadSurface(file)) {}
|
||||||
|
|
||||||
SurfaceHandle::~SurfaceHandle() {
|
SurfaceHandle::~SurfaceHandle() {
|
||||||
if (surface_) JD8_FreeSurface(surface_);
|
if (surface_) JD8_FreeSurface(surface_);
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceHandle::SurfaceHandle(SurfaceHandle&& other) noexcept
|
SurfaceHandle::SurfaceHandle(SurfaceHandle&& other) noexcept
|
||||||
: surface_(other.surface_) {
|
: surface_(other.surface_) {
|
||||||
other.surface_ = nullptr;
|
other.surface_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceHandle& SurfaceHandle::operator=(SurfaceHandle&& other) noexcept {
|
SurfaceHandle& SurfaceHandle::operator=(SurfaceHandle&& other) noexcept {
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
if (surface_) JD8_FreeSurface(surface_);
|
if (surface_) JD8_FreeSurface(surface_);
|
||||||
surface_ = other.surface_;
|
surface_ = other.surface_;
|
||||||
other.surface_ = nullptr;
|
other.surface_ = nullptr;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceHandle::reset(const char* file) {
|
void SurfaceHandle::reset(const char* file) {
|
||||||
if (surface_) JD8_FreeSurface(surface_);
|
if (surface_) JD8_FreeSurface(surface_);
|
||||||
surface_ = file ? JD8_LoadSurface(file) : nullptr;
|
surface_ = file ? JD8_LoadSurface(file) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceHandle::adopt(JD8_Surface raw) {
|
void SurfaceHandle::adopt(JD8_Surface raw) {
|
||||||
if (surface_) JD8_FreeSurface(surface_);
|
if (surface_) JD8_FreeSurface(surface_);
|
||||||
surface_ = raw;
|
surface_ = raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
JD8_Surface SurfaceHandle::release() {
|
JD8_Surface SurfaceHandle::release() {
|
||||||
JD8_Surface r = surface_;
|
JD8_Surface r = surface_;
|
||||||
surface_ = nullptr;
|
surface_ = nullptr;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Wrapper RAII damunt de `JD8_Surface`. Allibera automàticament amb
|
// Wrapper RAII damunt de `JD8_Surface`. Allibera automàticament amb
|
||||||
// `JD8_FreeSurface` al destructor. Move-only per evitar dobles alliberaments.
|
// `JD8_FreeSurface` al destructor. Move-only per evitar dobles alliberaments.
|
||||||
// Converteix implícitament a `JD8_Surface` per a poder passar-lo
|
// Converteix implícitament a `JD8_Surface` per a poder passar-lo
|
||||||
// directament a `JD8_Blit*` sense haver de cridar `.get()`.
|
// directament a `JD8_Blit*` sense haver de cridar `.get()`.
|
||||||
class SurfaceHandle {
|
class SurfaceHandle {
|
||||||
public:
|
public:
|
||||||
SurfaceHandle() = default;
|
SurfaceHandle() = default;
|
||||||
explicit SurfaceHandle(const char* file);
|
explicit SurfaceHandle(const char* file);
|
||||||
@@ -44,6 +44,6 @@ class SurfaceHandle {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
JD8_Surface surface_{nullptr};
|
JD8_Surface surface_{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -4,23 +4,23 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
Timeline& Timeline::step(int duration_ms, StepFn fn) {
|
Timeline& Timeline::step(int duration_ms, StepFn fn) {
|
||||||
Step s;
|
Step s;
|
||||||
s.duration_ms = duration_ms;
|
s.duration_ms = duration_ms;
|
||||||
s.continuous = std::move(fn);
|
s.continuous = std::move(fn);
|
||||||
steps_.push_back(std::move(s));
|
steps_.push_back(std::move(s));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Timeline& Timeline::once(OnceFn fn) {
|
Timeline& Timeline::once(OnceFn fn) {
|
||||||
Step s;
|
Step s;
|
||||||
s.duration_ms = 0;
|
s.duration_ms = 0;
|
||||||
s.oneshot = std::move(fn);
|
s.oneshot = std::move(fn);
|
||||||
steps_.push_back(std::move(s));
|
steps_.push_back(std::move(s));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timeline::flushOneShots() {
|
void Timeline::flushOneShots() {
|
||||||
while (current_ < steps_.size() && steps_[current_].duration_ms == 0) {
|
while (current_ < steps_.size() && steps_[current_].duration_ms == 0) {
|
||||||
auto& s = steps_[current_];
|
auto& s = steps_[current_];
|
||||||
if (!s.entered) {
|
if (!s.entered) {
|
||||||
@@ -30,9 +30,9 @@ void Timeline::flushOneShots() {
|
|||||||
++current_;
|
++current_;
|
||||||
elapsed_in_step_ = 0;
|
elapsed_in_step_ = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timeline::tick(int delta_ms) {
|
void Timeline::tick(int delta_ms) {
|
||||||
if (skipped_) return;
|
if (skipped_) return;
|
||||||
flushOneShots();
|
flushOneShots();
|
||||||
if (current_ >= steps_.size()) return;
|
if (current_ >= steps_.size()) return;
|
||||||
@@ -57,29 +57,29 @@ void Timeline::tick(int delta_ms) {
|
|||||||
static_cast<float>(std::max(1, s.duration_ms));
|
static_cast<float>(std::max(1, s.duration_ms));
|
||||||
s.continuous(p);
|
s.continuous(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timeline::skip() {
|
void Timeline::skip() {
|
||||||
skipped_ = true;
|
skipped_ = true;
|
||||||
current_ = steps_.size();
|
current_ = steps_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timeline::reset() {
|
void Timeline::reset() {
|
||||||
for (auto& s : steps_) s.entered = false;
|
for (auto& s : steps_) s.entered = false;
|
||||||
current_ = 0;
|
current_ = 0;
|
||||||
elapsed_in_step_ = 0;
|
elapsed_in_step_ = 0;
|
||||||
skipped_ = false;
|
skipped_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Timeline::done() const {
|
bool Timeline::done() const {
|
||||||
return skipped_ || current_ >= steps_.size();
|
return skipped_ || current_ >= steps_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
float Timeline::currentProgress() const {
|
float Timeline::currentProgress() const {
|
||||||
if (current_ >= steps_.size()) return 1.0f;
|
if (current_ >= steps_.size()) return 1.0f;
|
||||||
const auto& s = steps_[current_];
|
const auto& s = steps_[current_];
|
||||||
if (s.duration_ms <= 0) return 0.0f;
|
if (s.duration_ms <= 0) return 0.0f;
|
||||||
return static_cast<float>(elapsed_in_step_) / static_cast<float>(s.duration_ms);
|
return static_cast<float>(elapsed_in_step_) / static_cast<float>(s.duration_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
@@ -5,22 +5,22 @@
|
|||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
// Timeline declaratiu de passos seqüencials. Cada pas té una duració en
|
// Timeline declaratiu de passos seqüencials. Cada pas té una duració en
|
||||||
// ms i un callback. Exemple d'ús:
|
// ms i un callback. Exemple d'ús:
|
||||||
//
|
//
|
||||||
// timeline_
|
// timeline_
|
||||||
// .once([this] { JD8_ClearScreen(0); fade_.startFadeTo(pal); })
|
// .once([this] { JD8_ClearScreen(0); fade_.startFadeTo(pal); })
|
||||||
// .step(5000) // espera pura
|
// .step(5000) // espera pura
|
||||||
// .step(1000, [this](float p) { /*...*/ }) // animat amb progress
|
// .step(1000, [this](float p) { /*...*/ }) // animat amb progress
|
||||||
// .once([this] { JA_FadeOutMusic(250); });
|
// .once([this] { JA_FadeOutMusic(250); });
|
||||||
//
|
//
|
||||||
// `tick(delta_ms)` avança el temps. Els passos one-shot s'executen al
|
// `tick(delta_ms)` avança el temps. Els passos one-shot s'executen al
|
||||||
// moment d'entrar-hi i avancen immediatament. Els passos amb duració
|
// moment d'entrar-hi i avancen immediatament. Els passos amb duració
|
||||||
// criden el seu callback cada tick amb el progress [0..1] i passen al
|
// criden el seu callback cada tick amb el progress [0..1] i passen al
|
||||||
// següent quan s'exhaureix el temps. `skip()` marca tota la timeline
|
// següent quan s'exhaureix el temps. `skip()` marca tota la timeline
|
||||||
// com a acabada (no executa res més) — útil per als "polsa una tecla
|
// com a acabada (no executa res més) — útil per als "polsa una tecla
|
||||||
// per a saltar la cinemàtica".
|
// per a saltar la cinemàtica".
|
||||||
class Timeline {
|
class Timeline {
|
||||||
public:
|
public:
|
||||||
using StepFn = std::function<void(float progress_0_1)>;
|
using StepFn = std::function<void(float progress_0_1)>;
|
||||||
using OnceFn = std::function<void()>;
|
using OnceFn = std::function<void()>;
|
||||||
@@ -52,6 +52,6 @@ class Timeline {
|
|||||||
std::size_t current_{0};
|
std::size_t current_{0};
|
||||||
int elapsed_in_step_{0};
|
int elapsed_in_step_{0};
|
||||||
bool skipped_{false};
|
bool skipped_{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scenes
|
} // namespace scenes
|
||||||
|
|||||||
Reference in New Issue
Block a user