Compare commits
10 Commits
2e1a82ff40
...
v1.2
| Author | SHA1 | Date | |
|---|---|---|---|
| 4a4485c6f8 | |||
| d09bb1cf6b | |||
| b1f9e57f36 | |||
| f7875baa2d | |||
| c6e37af7d1 | |||
| 5e57034a38 | |||
| 2a8fbbb095 | |||
| 53e93ef697 | |||
| e7aa2463b4 | |||
| 27f8b0ae36 |
1
.claude/scheduled_tasks.lock
Normal file
1
.claude/scheduled_tasks.lock
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"sessionId":"7b0c9c32-3dd4-48a3-ba06-c2303dc08243","pid":123890,"acquiredAt":1776510185734}
|
||||||
87
CHANGELOG.md
87
CHANGELOG.md
@@ -1,6 +1,88 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
Tots els canvis de la reconstrucció moderna (C++/SDL3) d'**Aventures en Egipte**, des de l'inici del port fins a la v1.1.
|
Tots els canvis de la reconstrucció moderna (C++/SDL3) d'**Aventures en Egipte**.
|
||||||
|
|
||||||
|
## [1.2] — 2026-04-18
|
||||||
|
|
||||||
|
Versió de modernització profunda: desapareix el model *threads estil emulador* i tot el runtime passa a un sol fil tick-based compatible amb emscripten. Zero regressions de gameplay.
|
||||||
|
|
||||||
|
### Afegit
|
||||||
|
|
||||||
|
#### Arquitectura: capa `scenes::` tick-based
|
||||||
|
- Infraestructura `scenes::` ([source/scenes/](source/scenes/)): `Scene`, `SceneRegistry`, `Timeline`, `SpriteMover`, `FrameAnimator`, `PaletteFade`, `SurfaceHandle`, helper `playMusic` (`4436f7f`)
|
||||||
|
- **MortScene** substitueix `doMort()` (`d86cb21`)
|
||||||
|
- **BannerScene** substitueix `doBanner()` per piràmides 2–5 (`2cb38ff`)
|
||||||
|
- **MenuScene** substitueix `doMenu()` + fix `JI_Update` al loop (`8720e77`)
|
||||||
|
- **IntroNewLogoScene** substitueix `doIntroNewLogo()` (`ad38fc0`)
|
||||||
|
- **SlidesScene** amb wipe suau per easing (`605c273`)
|
||||||
|
- **CreditsScene** amb scroll vertical + parallax condicional (`829d743`)
|
||||||
|
- **SecretaScene** amb swap `tomba1→tomba2` i red pulse animat (`6063b1c`)
|
||||||
|
- **IntroScene** amb revelat *JAILGAMES* lletra a lletra + cicle de paleta (`e18b732`)
|
||||||
|
- **IntroSpritesScene** com a sub-escena amb 3 variants aleatòries (`d343e71`)
|
||||||
|
- **ModuleGame** migrat a `scenes::Scene` amb fases `FadingIn`/`FadingOut` (`4e18f83`)
|
||||||
|
- Pla de migració documentat a [docs/scenes-migration-plan.md](docs/scenes-migration-plan.md) (`6125277`)
|
||||||
|
|
||||||
|
#### Resource pack
|
||||||
|
- Sistema d'empaquetat d'assets `resources.pack` (format **AEE1**, XOR-xifrat) estil *coffee_crisis* (`b2d5f5a`, `4244bca`)
|
||||||
|
- Classe `ResourcePack` + namespace `ResourceHelper` + eina CLI standalone `pack_resources` (target `make pack`)
|
||||||
|
- Cablejat a tots els callsites de recursos via `ResourceHelper::loadFile`
|
||||||
|
- Scaffold `.jrf` llegat eliminat completament de `jfile.cpp`
|
||||||
|
- Releases natius depenen del pack i l'usen obligatòriament (sense fallback); WASM i Debug mantenen fallback
|
||||||
|
- Normalització de `resource::cache` per a `Audio` (`94aa69c`)
|
||||||
|
|
||||||
|
#### Build WebAssembly
|
||||||
|
- Build WASM via Docker (`emscripten/emsdk:latest`) amb desplegament a maverick (`make wasm`)
|
||||||
|
- SDL3 compilat des de font via `FetchContent`; shaders omesos; `sdl3gpu_shader.cpp` exclòs
|
||||||
|
- Events de canvas d'emscripten (`1c11a30`)
|
||||||
|
- Fix de mandos en emscripten Android (`d3bdd9b`)
|
||||||
|
- Defaults específics d'emscripten (`7f26b8d`)
|
||||||
|
- Internal resolution configurable (`e8b0b12`, `16a3f5b`)
|
||||||
|
|
||||||
|
#### Menú i UI
|
||||||
|
- **Menú de sistema** amb versió i opció de tancar/reiniciar (`e0f9b60`)
|
||||||
|
- Animació de tancar el menú (`5956d87`)
|
||||||
|
- Items ocultables condicionalment en funció d'altres items (`a3fc111`)
|
||||||
|
- Tots els valors d'escala que exposa SDL3 (`52431ad`)
|
||||||
|
- `debug.yaml` separat de `config.yaml` (`fe41919`)
|
||||||
|
|
||||||
|
### Canviat
|
||||||
|
|
||||||
|
#### Runtime: sense fibers, sense threads, sense mutex
|
||||||
|
- **Fase 1** — jail i game a C++ idiomàtic: RAII, `info::ctx` com a singleton `inline`, cheats arreglats (`scancode→ASCII`) (`7f85b50`)
|
||||||
|
- **Fase 2** — fades de `jd8` a màquina d'estats + helper `wait_frame_or_skip` a les cinemàtiques (`80fa7b4`)
|
||||||
|
- **Fase 3** — `jail_audio` header-only amb streaming real (`stb_vorbis_open_memory` + `JA_PumpMusic`), sense `SDL_AddTimer` (`801a8ad`)
|
||||||
|
- **Fase 4+5** — fibers cooperatius substitueixen el game thread, sense mutex ni `cv` (`1507a1c`)
|
||||||
|
- **Step B.1** — fades de `ModuleGame` tick-based amb `scenes::PaletteFade` (`4e18f83`)
|
||||||
|
- **Step B.2** — **eliminació total del fiber**: `Director` posseeix l'escena (`current_scene_`, `game_state_`), `JD8_Flip` sense yield, `fiber.{hpp,cpp}` esborrats (`96a3cf9`)
|
||||||
|
- **Step 10** — `ModuleSequence` eliminat; dispatch via `SceneRegistry::tryCreate()` i `game_state_ == 0/1` directe des del `Director`
|
||||||
|
- Main loop via **SDL3 Callback API** (`SDL_MAIN_USE_CALLBACKS`): `SDL_AppInit`/`Iterate`/`Event`/`Quit`, compatible amb emscripten
|
||||||
|
|
||||||
|
#### RAII i neteja de memòria
|
||||||
|
- **Fase 1** — cleanup mecànic: `NULL→nullptr`, `typedef→using`, `explicit`, `enum class` local (`e7aa246`)
|
||||||
|
- **Fase 2** — elimina `malloc`/`free` a `jdraw8` i paletes d'escenes (`53e93ef`)
|
||||||
|
- **Fase 3** — `Text::bitmap_` a `std::vector<Uint8>` (`2a8fbbb`)
|
||||||
|
- **Fase 4** — llista enllaçada de Momia a `std::vector<std::unique_ptr>` (`5e57034`)
|
||||||
|
- **Fase 5** — singletons a `std::unique_ptr` (elimina `new`/`delete` manual) (`c6e37af`)
|
||||||
|
- **Fase 6** — Rule of 5 a `Mapa` i `ModuleGame` (no-copiables, no-movibles) (`f7875ba`)
|
||||||
|
- `file_getfilebuffer` → `file_readfile` retornant `std::vector<char>` — elimina 3 leaks silenciosos (paleta + música gameplay + música cinemàtica) (`b3ff620`)
|
||||||
|
- `JA_Music_t` RAII amb `vector<Uint8>`/`string`, elimina overload i camps morts (`f9346ad`)
|
||||||
|
- `JA_Sound_t` RAII amb `unique_ptr + SDLFreeDeleter`, elimina `JA_NewSound` (`550e3e0`)
|
||||||
|
|
||||||
|
#### Build i tooling
|
||||||
|
- Unificats `.clang-format` i `.clang-tidy`, amb exclusió de `external/` i `spv/` via dummies (`7409c79`)
|
||||||
|
- `cppcheck` integrat amb suppress list (`27f8b0a`, `2e1a82f`)
|
||||||
|
- `make`/`cmake` estandarditzats amb la resta de projectes JailGames (`9d86137`)
|
||||||
|
- Fitxers de música renombrats a noms temàtics (`417699d`)
|
||||||
|
- Carpeta `data/` reordenada (`083a57d`)
|
||||||
|
|
||||||
|
### Arreglat
|
||||||
|
|
||||||
|
- Shaders ON/OFF no afectaven a CRT-Pi (`a36662a`)
|
||||||
|
- Logo nou de la intro tornava a descentrar-se (`52369be`, `5cda8fc`)
|
||||||
|
- Color de fons dels sliders de `0x050505` a `0x000000` (`b1f9e57`)
|
||||||
|
- Diversos detalls menors (`6394e9a`, `0cd09f6`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## [1.1] — 2026-04-05
|
## [1.1] — 2026-04-05
|
||||||
|
|
||||||
@@ -64,4 +146,5 @@ Versió que fa coincidir la numeració amb la del joc original del 2000.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[1.1]: https://gitea/aee/compare/9e0ab87...HEAD
|
[1.2]: https://gitea/aee/compare/486f00b...HEAD
|
||||||
|
[1.1]: https://gitea/aee/compare/9e0ab87...486f00b
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@@ -21,6 +21,7 @@ menu:
|
|||||||
exit_game: "Eixir del joc"
|
exit_game: "Eixir del joc"
|
||||||
use_new_logo: "Logo nou"
|
use_new_logo: "Logo nou"
|
||||||
show_title_credits: "Crèdits del port"
|
show_title_credits: "Crèdits del port"
|
||||||
|
show_preload: "Barra de precàrrega"
|
||||||
zoom: "Zoom"
|
zoom: "Zoom"
|
||||||
screen: "Pantalla"
|
screen: "Pantalla"
|
||||||
shader: "Shader"
|
shader: "Shader"
|
||||||
|
|||||||
@@ -24,19 +24,16 @@
|
|||||||
#include "game/options.hpp" // Para Options::audio
|
#include "game/options.hpp" // Para Options::audio
|
||||||
|
|
||||||
// Singleton
|
// Singleton
|
||||||
Audio* Audio::instance = nullptr;
|
std::unique_ptr<Audio> Audio::instance;
|
||||||
|
|
||||||
// Inicializa la instancia única del singleton
|
// Inicializa la instancia única del singleton
|
||||||
void Audio::init() { Audio::instance = new Audio(); }
|
void Audio::init() { Audio::instance = std::unique_ptr<Audio>(new Audio()); }
|
||||||
|
|
||||||
// Libera la instancia
|
// Libera la instancia
|
||||||
void Audio::destroy() {
|
void Audio::destroy() { Audio::instance.reset(); }
|
||||||
delete Audio::instance;
|
|
||||||
Audio::instance = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtiene la instancia
|
// Obtiene la instancia
|
||||||
auto Audio::get() -> Audio* { return Audio::instance; }
|
auto Audio::get() -> Audio* { return Audio::instance.get(); }
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Audio::Audio() { initSDLAudio(); }
|
Audio::Audio() { initSDLAudio(); }
|
||||||
@@ -172,20 +169,18 @@ auto Audio::getRealMusicState() -> MusicState {
|
|||||||
|
|
||||||
// Establece el volumen de los sonidos (float 0.0..1.0)
|
// Establece el volumen de los sonidos (float 0.0..1.0)
|
||||||
void Audio::setSoundVolume(float sound_volume, Group group) const {
|
void Audio::setSoundVolume(float sound_volume, Group group) const {
|
||||||
if (sound_enabled_) {
|
|
||||||
sound_volume = std::clamp(sound_volume, MIN_VOLUME, MAX_VOLUME);
|
sound_volume = std::clamp(sound_volume, MIN_VOLUME, MAX_VOLUME);
|
||||||
const float CONVERTED_VOLUME = sound_volume * Options::audio.volume;
|
const bool active = enabled_ && sound_enabled_;
|
||||||
|
const float CONVERTED_VOLUME = active ? sound_volume * Options::audio.volume : 0.0F;
|
||||||
JA_SetSoundVolume(CONVERTED_VOLUME, static_cast<int>(group));
|
JA_SetSoundVolume(CONVERTED_VOLUME, static_cast<int>(group));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el volumen de la música (float 0.0..1.0)
|
// Establece el volumen de la música (float 0.0..1.0)
|
||||||
void Audio::setMusicVolume(float music_volume) const {
|
void Audio::setMusicVolume(float music_volume) const {
|
||||||
if (music_enabled_) {
|
|
||||||
music_volume = std::clamp(music_volume, MIN_VOLUME, MAX_VOLUME);
|
music_volume = std::clamp(music_volume, MIN_VOLUME, MAX_VOLUME);
|
||||||
const float CONVERTED_VOLUME = music_volume * Options::audio.volume;
|
const bool active = enabled_ && music_enabled_;
|
||||||
|
const float CONVERTED_VOLUME = active ? music_volume * Options::audio.volume : 0.0F;
|
||||||
JA_SetMusicVolume(CONVERTED_VOLUME);
|
JA_SetMusicVolume(CONVERTED_VOLUME);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aplica la configuración
|
// Aplica la configuración
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint> // Para int8_t, uint8_t
|
#include <cstdint> // Para int8_t, uint8_t
|
||||||
|
#include <memory> // Para std::unique_ptr
|
||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <utility> // Para move
|
#include <utility> // Para move
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ class Audio {
|
|||||||
static void init(); // Inicializa el objeto Audio
|
static void init(); // Inicializa el objeto Audio
|
||||||
static void destroy(); // Libera el objeto Audio
|
static void destroy(); // Libera el objeto Audio
|
||||||
static auto get() -> Audio*; // Obtiene el puntero al objeto Audio
|
static auto get() -> Audio*; // Obtiene el puntero al objeto Audio
|
||||||
|
~Audio(); // Destructor (públic per a std::unique_ptr)
|
||||||
Audio(const Audio&) = delete; // Evitar copia
|
Audio(const Audio&) = delete; // Evitar copia
|
||||||
auto operator=(const Audio&) -> Audio& = delete; // Evitar asignación
|
auto operator=(const Audio&) -> Audio& = delete; // Evitar asignación
|
||||||
|
|
||||||
@@ -101,11 +103,10 @@ class Audio {
|
|||||||
|
|
||||||
// --- Métodos ---
|
// --- Métodos ---
|
||||||
Audio(); // Constructor privado
|
Audio(); // Constructor privado
|
||||||
~Audio(); // Destructor privado
|
|
||||||
void initSDLAudio(); // Inicializa SDL Audio
|
void initSDLAudio(); // Inicializa SDL Audio
|
||||||
|
|
||||||
// --- Variables miembro ---
|
// --- Variables miembro ---
|
||||||
static Audio* instance; // Instancia única de Audio
|
static std::unique_ptr<Audio> instance; // Instancia única de Audio
|
||||||
|
|
||||||
Music music_; // Estado de la música
|
Music music_; // Estado de la música
|
||||||
bool enabled_{true}; // Estado general del audio
|
bool enabled_{true}; // Estado general del audio
|
||||||
|
|||||||
@@ -265,13 +265,13 @@ inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) {
|
|||||||
auto* music = new JA_Music_t();
|
auto* music = new JA_Music_t();
|
||||||
music->ogg_data.assign(buffer, buffer + length);
|
music->ogg_data.assign(buffer, buffer + length);
|
||||||
|
|
||||||
int error = 0;
|
int vorbis_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),
|
static_cast<int>(length),
|
||||||
&error,
|
&vorbis_error,
|
||||||
nullptr);
|
nullptr);
|
||||||
if (!music->vorbis) {
|
if (!music->vorbis) {
|
||||||
std::cout << "JA_LoadMusic: stb_vorbis_open_memory failed (error " << error << ")" << '\n';
|
std::cout << "JA_LoadMusic: stb_vorbis_open_memory failed (error " << vorbis_error << ")" << '\n';
|
||||||
delete music;
|
delete music;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,20 +19,23 @@
|
|||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JD8_Surface screen = NULL;
|
JD8_Surface screen = nullptr;
|
||||||
JD8_Palette main_palette = NULL;
|
JD8_Palette main_palette = nullptr;
|
||||||
Uint32* pixel_data = NULL;
|
Uint32* pixel_data = nullptr;
|
||||||
|
|
||||||
void JD8_Init() {
|
void JD8_Init() {
|
||||||
screen = (JD8_Surface)calloc(1, 64000);
|
screen = new Uint8[64000]{};
|
||||||
main_palette = (JD8_Palette)calloc(1, 768);
|
main_palette = new Color[256]{};
|
||||||
pixel_data = (Uint32*)calloc(1, 320 * 200 * 4);
|
pixel_data = new Uint32[320 * 200]{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void JD8_Quit() {
|
void JD8_Quit() {
|
||||||
if (screen != NULL) free(screen);
|
delete[] screen;
|
||||||
if (main_palette != NULL) free(main_palette);
|
delete[] main_palette;
|
||||||
if (pixel_data != NULL) free(pixel_data);
|
delete[] pixel_data;
|
||||||
|
screen = nullptr;
|
||||||
|
main_palette = nullptr;
|
||||||
|
pixel_data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JD8_ClearScreen(Uint8 color) {
|
void JD8_ClearScreen(Uint8 color) {
|
||||||
@@ -40,9 +43,7 @@ void JD8_ClearScreen(Uint8 color) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JD8_Surface JD8_NewSurface() {
|
JD8_Surface JD8_NewSurface() {
|
||||||
JD8_Surface surface = (JD8_Surface)malloc(64000);
|
return new Uint8[64000]{};
|
||||||
memset(surface, 0, 64000);
|
|
||||||
return surface;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper intern: deriva el basename d'una ruta per a buscar al Cache.
|
// Helper intern: deriva el basename d'una ruta per a buscar al Cache.
|
||||||
@@ -71,7 +72,7 @@ JD8_Surface JD8_LoadSurface(const char* file) {
|
|||||||
auto buffer = ResourceHelper::loadFile(file);
|
auto buffer = ResourceHelper::loadFile(file);
|
||||||
unsigned short w, h;
|
unsigned short w, h;
|
||||||
Uint8* pixels = LoadGif(buffer.data(), &w, &h);
|
Uint8* pixels = LoadGif(buffer.data(), &w, &h);
|
||||||
if (pixels == NULL) {
|
if (pixels == nullptr) {
|
||||||
printf("Unable to load bitmap: %s\n", SDL_GetError());
|
printf("Unable to load bitmap: %s\n", SDL_GetError());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -82,27 +83,31 @@ JD8_Surface JD8_LoadSurface(const char* file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JD8_Palette JD8_LoadPalette(const char* file) {
|
JD8_Palette JD8_LoadPalette(const char* file) {
|
||||||
|
// Sempre retorna un buffer de 256 colors reservat amb `new Color[256]`
|
||||||
|
// — el caller és responsable d'alliberar-lo amb `delete[]` (o lliurar-ne
|
||||||
|
// l'ownership a `JD8_SetScreenPalette`).
|
||||||
|
JD8_Palette palette = new Color[256];
|
||||||
|
|
||||||
if (Resource::Cache::get() != nullptr) {
|
if (Resource::Cache::get() != nullptr) {
|
||||||
try {
|
try {
|
||||||
const auto& cached = Resource::Cache::get()->getPaletteBytes(jd8_basename(file));
|
const auto& cached = Resource::Cache::get()->getPaletteBytes(jd8_basename(file));
|
||||||
// Reservem un buffer 768 bytes (256 * RGB) que el caller ha
|
|
||||||
// d'alliberar amb free() — mateixa convenció que el LoadPalette
|
|
||||||
// original (retornava un malloc).
|
|
||||||
JD8_Palette palette = (JD8_Palette)malloc(768);
|
|
||||||
memcpy(palette, cached.data(), 768);
|
memcpy(palette, cached.data(), 768);
|
||||||
return palette;
|
return palette;
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
// No està al cache.
|
// No està al cache — fallback a lectura + LoadPalette.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto buffer = ResourceHelper::loadFile(file);
|
auto buffer = ResourceHelper::loadFile(file);
|
||||||
return (JD8_Palette)LoadPalette(buffer.data());
|
Uint8* raw = LoadPalette(buffer.data()); // external malloc
|
||||||
|
memcpy(palette, raw, 768);
|
||||||
|
free(raw);
|
||||||
|
return palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JD8_SetScreenPalette(JD8_Palette palette) {
|
void JD8_SetScreenPalette(JD8_Palette palette) {
|
||||||
if (main_palette == palette) return;
|
if (main_palette == palette) return;
|
||||||
if (main_palette != NULL) free(main_palette);
|
delete[] main_palette;
|
||||||
main_palette = palette;
|
main_palette = palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +223,7 @@ Uint32* JD8_GetFramebuffer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JD8_FreeSurface(JD8_Surface surface) {
|
void JD8_FreeSurface(JD8_Surface surface) {
|
||||||
free(surface);
|
delete[] surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint8 JD8_GetPixel(JD8_Surface surface, int x, int y) {
|
Uint8 JD8_GetPixel(JD8_Surface surface, int x, int y) {
|
||||||
@@ -240,26 +245,26 @@ 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 class FadeType {
|
||||||
FADE_NONE = 0,
|
None = 0,
|
||||||
FADE_OUT,
|
Out,
|
||||||
FADE_TO_PAL,
|
ToPal,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr int FADE_STEPS = 32;
|
constexpr int FADE_STEPS = 32;
|
||||||
|
|
||||||
FadeType fade_type = FADE_NONE;
|
FadeType fade_type = FadeType::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 == FadeType::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;
|
||||||
main_palette[i].g = main_palette[i].g >= 8 ? main_palette[i].g - 8 : 0;
|
main_palette[i].g = main_palette[i].g >= 8 ? main_palette[i].g - 8 : 0;
|
||||||
main_palette[i].b = main_palette[i].b >= 8 ? main_palette[i].b - 8 : 0;
|
main_palette[i].b = main_palette[i].b >= 8 ? main_palette[i].b - 8 : 0;
|
||||||
}
|
}
|
||||||
} else if (fade_type == FADE_TO_PAL) {
|
} else if (fade_type == FadeType::ToPal) {
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
main_palette[i].r = main_palette[i].r <= int(fade_target[i].r) - 8
|
main_palette[i].r = main_palette[i].r <= int(fade_target[i].r) - 8
|
||||||
? main_palette[i].r + 8
|
? main_palette[i].r + 8
|
||||||
@@ -277,28 +282,28 @@ namespace {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void JD8_FadeStartOut() {
|
void JD8_FadeStartOut() {
|
||||||
fade_type = FADE_OUT;
|
fade_type = FadeType::Out;
|
||||||
fade_step = 0;
|
fade_step = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JD8_FadeStartToPal(JD8_Palette pal) {
|
void JD8_FadeStartToPal(JD8_Palette pal) {
|
||||||
fade_type = FADE_TO_PAL;
|
fade_type = FadeType::ToPal;
|
||||||
memcpy(fade_target, pal, sizeof(Color) * 256);
|
memcpy(fade_target, pal, sizeof(Color) * 256);
|
||||||
fade_step = 0;
|
fade_step = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JD8_FadeIsActive() {
|
bool JD8_FadeIsActive() {
|
||||||
return fade_type != FADE_NONE;
|
return fade_type != FadeType::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JD8_FadeTickStep() {
|
bool JD8_FadeTickStep() {
|
||||||
if (fade_type == FADE_NONE) return true;
|
if (fade_type == FadeType::None) return true;
|
||||||
|
|
||||||
apply_fade_step();
|
apply_fade_step();
|
||||||
fade_step++;
|
fade_step++;
|
||||||
|
|
||||||
if (fade_step >= FADE_STEPS) {
|
if (fade_step >= FADE_STEPS) {
|
||||||
fade_type = FADE_NONE;
|
fade_type = FadeType::None;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ struct Color {
|
|||||||
Uint8 b;
|
Uint8 b;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Uint8* JD8_Surface;
|
using JD8_Surface = Uint8*;
|
||||||
typedef Color* JD8_Palette;
|
using JD8_Palette = Color*;
|
||||||
|
|
||||||
void JD8_Init();
|
void JD8_Init();
|
||||||
|
|
||||||
|
|||||||
@@ -70,21 +70,26 @@ void file_setconfigfolder(const char* foldername) {
|
|||||||
if (!homedir) homedir = "/tmp";
|
if (!homedir) homedir = "/tmp";
|
||||||
config_folder = std::string(homedir) + "/Library/Application Support/" + foldername;
|
config_folder = std::string(homedir) + "/Library/Application Support/" + foldername;
|
||||||
#elif __linux__
|
#elif __linux__
|
||||||
// Nota emscripten: `__linux__` també està definit, però `getpwuid` no
|
// Nota emscripten: `__linux__` també està definit, però `getpwuid` pot
|
||||||
// troba cap /etc/passwd al MEMFS i retorna nullptr. Amb els fallbacks
|
// retornar nullptr (sense /etc/passwd al MEMFS) o un passwd amb pw_dir
|
||||||
// HOME → /tmp evitem crashejar al primer arranque dins del navegador.
|
// buit. Amb els fallbacks HOME → /tmp evitem crashejar al primer
|
||||||
// La config no persistirà entre recàrregues de la pàgina (MEMFS és
|
// arranque dins del navegador. La config no persistirà entre recàrregues
|
||||||
// volàtil); caldria IDBFS si volguéssem persistència a web.
|
// (MEMFS és volàtil); caldria IDBFS si volguéssem persistència a web.
|
||||||
struct passwd* pw = getpwuid(getuid());
|
struct passwd* pw = getpwuid(getuid());
|
||||||
const char* homedir = (pw && pw->pw_dir) ? pw->pw_dir : nullptr;
|
const char* homedir = (pw && pw->pw_dir && pw->pw_dir[0]) ? pw->pw_dir : nullptr;
|
||||||
if (!homedir) homedir = getenv("HOME");
|
if (!homedir || !homedir[0]) homedir = getenv("HOME");
|
||||||
if (!homedir) homedir = "/tmp";
|
if (!homedir || !homedir[0]) homedir = "/tmp";
|
||||||
config_folder = std::string(homedir) + "/.config/" + foldername;
|
config_folder = std::string(homedir) + "/.config/" + foldername;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!config_folder.empty()) {
|
if (config_folder.empty()) {
|
||||||
std::filesystem::create_directories(config_folder);
|
config_folder = "/tmp/jailgames_config";
|
||||||
}
|
}
|
||||||
|
std::error_code ec;
|
||||||
|
std::filesystem::create_directories(config_folder, ec);
|
||||||
|
// A emscripten/MEMFS create_directories pot fallar (p.ex. parent
|
||||||
|
// read-only o libc++ amb path empty-check estricte). La config és
|
||||||
|
// volàtil al navegador de totes formes: ignorem l'error i continuem.
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* file_getconfigfolder() {
|
const char* file_getconfigfolder() {
|
||||||
|
|||||||
@@ -271,6 +271,8 @@ namespace Menu {
|
|||||||
|
|
||||||
p.items.push_back({Locale::get("menu.items.show_title_credits"), ItemKind::Toggle, [] { return yesNo(Options::game.show_title_credits); }, [](int) { Options::game.show_title_credits = !Options::game.show_title_credits; }, nullptr});
|
p.items.push_back({Locale::get("menu.items.show_title_credits"), ItemKind::Toggle, [] { return yesNo(Options::game.show_title_credits); }, [](int) { Options::game.show_title_credits = !Options::game.show_title_credits; }, nullptr});
|
||||||
|
|
||||||
|
p.items.push_back({Locale::get("menu.items.show_preload"), ItemKind::Toggle, [] { return yesNo(Options::game.show_preload); }, [](int) { Options::game.show_preload = !Options::game.show_preload; }, nullptr});
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,19 +55,18 @@ namespace {
|
|||||||
} // namespace
|
} // namespace
|
||||||
#endif // __EMSCRIPTEN__
|
#endif // __EMSCRIPTEN__
|
||||||
|
|
||||||
Screen* Screen::instance_ = nullptr;
|
std::unique_ptr<Screen> Screen::instance_;
|
||||||
|
|
||||||
void Screen::init() {
|
void Screen::init() {
|
||||||
instance_ = new Screen();
|
instance_ = std::unique_ptr<Screen>(new Screen());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::destroy() {
|
void Screen::destroy() {
|
||||||
delete instance_;
|
instance_.reset();
|
||||||
instance_ = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Screen::get() -> Screen* {
|
auto Screen::get() -> Screen* {
|
||||||
return instance_;
|
return instance_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Screen::Screen() {
|
Screen::Screen() {
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ class Screen {
|
|||||||
static void destroy();
|
static void destroy();
|
||||||
static auto get() -> Screen*;
|
static auto get() -> Screen*;
|
||||||
|
|
||||||
|
~Screen(); // públic per a std::unique_ptr
|
||||||
|
|
||||||
// Presentació — rep el buffer ARGB de 320x200 de JD8
|
// Presentació — rep el buffer ARGB de 320x200 de JD8
|
||||||
void present(Uint32* pixel_data);
|
void present(Uint32* pixel_data);
|
||||||
|
|
||||||
@@ -62,7 +64,6 @@ class Screen {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Screen();
|
Screen();
|
||||||
~Screen();
|
|
||||||
|
|
||||||
void adjustWindowSize();
|
void adjustWindowSize();
|
||||||
void calculateMaxZoom();
|
void calculateMaxZoom();
|
||||||
@@ -70,7 +71,7 @@ class Screen {
|
|||||||
void applyFallbackPresentation(); // Logical presentation + scale mode per al path SDL_Renderer
|
void applyFallbackPresentation(); // Logical presentation + scale mode per al path SDL_Renderer
|
||||||
void ensureFallbackInternalTexture(); // Recrea internal_texture_sdl_ si cal (fallback path)
|
void ensureFallbackInternalTexture(); // Recrea internal_texture_sdl_ si cal (fallback path)
|
||||||
|
|
||||||
static Screen* instance_;
|
static std::unique_ptr<Screen> instance_;
|
||||||
|
|
||||||
SDL_Window* window_{nullptr};
|
SDL_Window* window_{nullptr};
|
||||||
SDL_Renderer* renderer_{nullptr};
|
SDL_Renderer* renderer_{nullptr};
|
||||||
|
|||||||
@@ -19,10 +19,6 @@ Text::Text(const char* fnt_file, const char* gif_file) {
|
|||||||
loadFont(fnt_file);
|
loadFont(fnt_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
Text::~Text() {
|
|
||||||
if (bitmap_) free(bitmap_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- UTF-8 ---
|
// --- UTF-8 ---
|
||||||
|
|
||||||
auto Text::nextCodepoint(const char*& ptr) -> uint32_t {
|
auto Text::nextCodepoint(const char*& ptr) -> uint32_t {
|
||||||
@@ -80,27 +76,27 @@ void Text::loadFont(const char* fnt_file) {
|
|||||||
// Elimina comentaris inline
|
// Elimina comentaris inline
|
||||||
auto comment_pos = line.find('#');
|
auto comment_pos = line.find('#');
|
||||||
if (comment_pos != std::string::npos) {
|
if (comment_pos != std::string::npos) {
|
||||||
line = line.substr(0, comment_pos);
|
line.resize(comment_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parseja directives
|
// Parseja directives
|
||||||
if (line.find("box_width") == 0) {
|
if (line.starts_with("box_width")) {
|
||||||
sscanf(line.c_str(), "box_width %d", &box_width_);
|
sscanf(line.c_str(), "box_width %d", &box_width_);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (line.find("box_height") == 0) {
|
if (line.starts_with("box_height")) {
|
||||||
sscanf(line.c_str(), "box_height %d", &box_height_);
|
sscanf(line.c_str(), "box_height %d", &box_height_);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (line.find("columns") == 0) {
|
if (line.starts_with("columns")) {
|
||||||
sscanf(line.c_str(), "columns %d", &columns_);
|
sscanf(line.c_str(), "columns %d", &columns_);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (line.find("cell_spacing") == 0) {
|
if (line.starts_with("cell_spacing")) {
|
||||||
sscanf(line.c_str(), "cell_spacing %d", &cell_spacing_);
|
sscanf(line.c_str(), "cell_spacing %d", &cell_spacing_);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (line.find("row_spacing") == 0) {
|
if (line.starts_with("row_spacing")) {
|
||||||
sscanf(line.c_str(), "row_spacing %d", &row_spacing_);
|
sscanf(line.c_str(), "row_spacing %d", &row_spacing_);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -146,7 +142,8 @@ void Text::loadBitmap(const char* gif_file) {
|
|||||||
|
|
||||||
bitmap_width_ = w;
|
bitmap_width_ = w;
|
||||||
bitmap_height_ = h;
|
bitmap_height_ = h;
|
||||||
bitmap_ = pixels;
|
bitmap_.assign(pixels, pixels + (static_cast<size_t>(w) * h));
|
||||||
|
free(pixels); // LoadGif usa malloc internament
|
||||||
|
|
||||||
std::cout << "Text: bitmap loaded " << w << "x" << h << '\n';
|
std::cout << "Text: bitmap loaded " << w << "x" << h << '\n';
|
||||||
}
|
}
|
||||||
@@ -154,7 +151,7 @@ void Text::loadBitmap(const char* gif_file) {
|
|||||||
// --- Renderitzat ---
|
// --- Renderitzat ---
|
||||||
|
|
||||||
void Text::draw(Uint32* pixel_data, int x, int y, const char* text, Uint32 color) const {
|
void Text::draw(Uint32* pixel_data, int x, int y, const char* text, Uint32 color) const {
|
||||||
if (!bitmap_ || !pixel_data) return;
|
if (bitmap_.empty() || !pixel_data) return;
|
||||||
|
|
||||||
const char* ptr = text;
|
const char* ptr = text;
|
||||||
int cursor_x = x;
|
int cursor_x = x;
|
||||||
@@ -207,7 +204,7 @@ void Text::drawCentered(Uint32* pixel_data, int y, const char* text, Uint32 colo
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Text::drawClipped(Uint32* pixel_data, int x, int y, const char* text, Uint32 color, int clip_x_min, int clip_x_max, int clip_y_min, int clip_y_max) const {
|
void Text::drawClipped(Uint32* pixel_data, int x, int y, const char* text, Uint32 color, int clip_x_min, int clip_x_max, int clip_y_min, int clip_y_max) const {
|
||||||
if (!bitmap_ || !pixel_data) return;
|
if (bitmap_.empty() || !pixel_data) return;
|
||||||
|
|
||||||
// Descart ràpid si el glifo sencer cau fora verticalment
|
// Descart ràpid si el glifo sencer cau fora verticalment
|
||||||
if (y + box_height_ <= clip_y_min || y >= clip_y_max) return;
|
if (y + box_height_ <= clip_y_min || y >= clip_y_max) return;
|
||||||
@@ -262,7 +259,7 @@ void Text::drawClipped(Uint32* pixel_data, int x, int y, const char* text, Uint3
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Text::drawMono(Uint32* pixel_data, int x, int y, const char* text, Uint32 color, int cell_w) const {
|
void Text::drawMono(Uint32* pixel_data, int x, int y, const char* text, Uint32 color, int cell_w) const {
|
||||||
if (!bitmap_ || !pixel_data) return;
|
if (bitmap_.empty() || !pixel_data) return;
|
||||||
|
|
||||||
const char* ptr = text;
|
const char* ptr = text;
|
||||||
int cursor_x = x;
|
int cursor_x = x;
|
||||||
@@ -308,7 +305,7 @@ void Text::drawMono(Uint32* pixel_data, int x, int y, const char* text, Uint32 c
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Text::drawMonoDigits(Uint32* pixel_data, int x, int y, const char* text, Uint32 color, int digit_cell_w) const {
|
void Text::drawMonoDigits(Uint32* pixel_data, int x, int y, const char* text, Uint32 color, int digit_cell_w) const {
|
||||||
if (!bitmap_ || !pixel_data) return;
|
if (bitmap_.empty() || !pixel_data) return;
|
||||||
|
|
||||||
const char* ptr = text;
|
const char* ptr = text;
|
||||||
int cursor_x = x;
|
int cursor_x = x;
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class Text {
|
class Text {
|
||||||
public:
|
public:
|
||||||
Text(const char* fnt_file, const char* gif_file);
|
Text(const char* fnt_file, const char* gif_file);
|
||||||
~Text();
|
|
||||||
|
|
||||||
// Pinta texto sobre un buffer ARGB de 320x200
|
// Pinta texto sobre un buffer ARGB de 320x200
|
||||||
void draw(Uint32* pixel_data, int x, int y, const char* text, Uint32 color) const;
|
void draw(Uint32* pixel_data, int x, int y, const char* text, Uint32 color) const;
|
||||||
@@ -46,7 +46,7 @@ class Text {
|
|||||||
int cell_spacing_{0};
|
int cell_spacing_{0};
|
||||||
int row_spacing_{0};
|
int row_spacing_{0};
|
||||||
|
|
||||||
Uint8* bitmap_{nullptr}; // píxels 8-bit del GIF de la font
|
std::vector<Uint8> bitmap_; // píxels 8-bit del GIF de la font
|
||||||
int bitmap_width_{0};
|
int bitmap_width_{0};
|
||||||
int bitmap_height_{0};
|
int bitmap_height_{0};
|
||||||
|
|
||||||
|
|||||||
@@ -20,14 +20,11 @@ extern unsigned char* LoadPalette(unsigned char* data);
|
|||||||
|
|
||||||
namespace Resource {
|
namespace Resource {
|
||||||
|
|
||||||
Cache* Cache::instance = nullptr;
|
std::unique_ptr<Cache> Cache::instance;
|
||||||
|
|
||||||
void Cache::init() { instance = new Cache(); }
|
void Cache::init() { instance = std::unique_ptr<Cache>(new Cache()); }
|
||||||
void Cache::destroy() {
|
void Cache::destroy() { instance.reset(); }
|
||||||
delete instance;
|
auto Cache::get() -> Cache* { return instance.get(); }
|
||||||
instance = nullptr;
|
|
||||||
}
|
|
||||||
auto Cache::get() -> Cache* { return instance; }
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
auto basename(const std::string& path) -> std::string {
|
auto basename(const std::string& path) -> std::string {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -20,6 +21,7 @@ namespace Resource {
|
|||||||
static void destroy();
|
static void destroy();
|
||||||
static auto get() -> Cache*;
|
static auto get() -> Cache*;
|
||||||
|
|
||||||
|
~Cache() = default;
|
||||||
Cache(const Cache&) = delete;
|
Cache(const Cache&) = delete;
|
||||||
auto operator=(const Cache&) -> Cache& = delete;
|
auto operator=(const Cache&) -> Cache& = delete;
|
||||||
|
|
||||||
@@ -39,7 +41,6 @@ namespace Resource {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Cache() = default;
|
Cache() = default;
|
||||||
~Cache() = default;
|
|
||||||
|
|
||||||
enum class LoadStage {
|
enum class LoadStage {
|
||||||
MUSICS,
|
MUSICS,
|
||||||
@@ -66,7 +67,7 @@ namespace Resource {
|
|||||||
int loaded_count_{0};
|
int loaded_count_{0};
|
||||||
std::string current_loading_name_;
|
std::string current_loading_name_;
|
||||||
|
|
||||||
static Cache* instance;
|
static std::unique_ptr<Cache> instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Resource
|
} // namespace Resource
|
||||||
|
|||||||
@@ -9,19 +9,16 @@
|
|||||||
|
|
||||||
namespace Resource {
|
namespace Resource {
|
||||||
|
|
||||||
List* List::instance = nullptr;
|
std::unique_ptr<List> List::instance;
|
||||||
|
|
||||||
void List::init(const std::string& yaml_path) {
|
void List::init(const std::string& yaml_path) {
|
||||||
instance = new List();
|
instance = std::unique_ptr<List>(new List());
|
||||||
instance->loadFromYaml(yaml_path);
|
instance->loadFromYaml(yaml_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void List::destroy() {
|
void List::destroy() { instance.reset(); }
|
||||||
delete instance;
|
|
||||||
instance = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto List::get() -> List* { return instance; }
|
auto List::get() -> List* { return instance.get(); }
|
||||||
|
|
||||||
void List::loadFromYaml(const std::string& yaml_path) {
|
void List::loadFromYaml(const std::string& yaml_path) {
|
||||||
auto bytes = ResourceHelper::loadFile(yaml_path);
|
auto bytes = ResourceHelper::loadFile(yaml_path);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -25,6 +26,7 @@ namespace Resource {
|
|||||||
static void destroy();
|
static void destroy();
|
||||||
static auto get() -> List*;
|
static auto get() -> List*;
|
||||||
|
|
||||||
|
~List() = default;
|
||||||
List(const List&) = delete;
|
List(const List&) = delete;
|
||||||
auto operator=(const List&) -> List& = delete;
|
auto operator=(const List&) -> List& = delete;
|
||||||
|
|
||||||
@@ -44,7 +46,6 @@ namespace Resource {
|
|||||||
};
|
};
|
||||||
|
|
||||||
List() = default;
|
List() = default;
|
||||||
~List() = default;
|
|
||||||
|
|
||||||
void loadFromYaml(const std::string& yaml_path);
|
void loadFromYaml(const std::string& yaml_path);
|
||||||
void loadFromString(const std::string& yaml_content);
|
void loadFromString(const std::string& yaml_content);
|
||||||
@@ -55,7 +56,7 @@ namespace Resource {
|
|||||||
|
|
||||||
std::unordered_map<std::string, Item> file_list_;
|
std::unordered_map<std::string, Item> file_list_;
|
||||||
|
|
||||||
static List* instance;
|
static std::unique_ptr<List> instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Resource
|
} // namespace Resource
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
// Cheats del joc original — declarats a jinput.cpp
|
// Cheats del joc original — declarats a jinput.cpp
|
||||||
extern void JI_moveCheats(Uint8 new_key);
|
extern void JI_moveCheats(Uint8 new_key);
|
||||||
|
|
||||||
Director* Director::instance_ = nullptr;
|
std::unique_ptr<Director> Director::instance_;
|
||||||
|
|
||||||
Director::~Director() = default;
|
Director::~Director() = default;
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ std::unique_ptr<scenes::Scene> Director::createNextScene() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Director::init() {
|
void Director::init() {
|
||||||
instance_ = new Director();
|
instance_ = std::unique_ptr<Director>(new Director());
|
||||||
Gamepad::init();
|
Gamepad::init();
|
||||||
|
|
||||||
// Registre d'escenes. Cada entrada = un state_key (`num_piramide`)
|
// Registre d'escenes. Cada entrada = un state_key (`num_piramide`)
|
||||||
@@ -116,12 +116,11 @@ void Director::init() {
|
|||||||
|
|
||||||
void Director::destroy() {
|
void Director::destroy() {
|
||||||
Gamepad::destroy();
|
Gamepad::destroy();
|
||||||
delete instance_;
|
instance_.reset();
|
||||||
instance_ = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Director::get() -> Director* {
|
auto Director::get() -> Director* {
|
||||||
return instance_;
|
return instance_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Director::togglePause() {
|
void Director::togglePause() {
|
||||||
|
|||||||
@@ -52,11 +52,13 @@ class Director {
|
|||||||
void togglePause();
|
void togglePause();
|
||||||
auto isPaused() const -> bool { return paused_; }
|
auto isPaused() const -> bool { return paused_; }
|
||||||
|
|
||||||
private:
|
public:
|
||||||
Director() = default;
|
|
||||||
~Director();
|
~Director();
|
||||||
|
|
||||||
static Director* instance_;
|
private:
|
||||||
|
Director() = default;
|
||||||
|
|
||||||
|
static std::unique_ptr<Director> instance_;
|
||||||
|
|
||||||
void pollAllEvents(); // drenatge amb SDL_PollEvent, només per al bucle natiu
|
void pollAllEvents(); // drenatge amb SDL_PollEvent, només per al bucle natiu
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
class Bola : public Sprite {
|
class Bola : public Sprite {
|
||||||
public:
|
public:
|
||||||
Bola(JD8_Surface gfx, Prota* sam);
|
explicit Bola(JD8_Surface gfx, Prota* sam);
|
||||||
|
|
||||||
void draw();
|
void draw() override;
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -46,4 +46,5 @@ namespace Defaults::Game {
|
|||||||
constexpr int DINERS_INICIAL = 0;
|
constexpr int DINERS_INICIAL = 0;
|
||||||
constexpr bool USE_NEW_LOGO = true;
|
constexpr bool USE_NEW_LOGO = true;
|
||||||
constexpr bool SHOW_TITLE_CREDITS = true;
|
constexpr bool SHOW_TITLE_CREDITS = true;
|
||||||
|
constexpr bool SHOW_PRELOAD = false;
|
||||||
} // namespace Defaults::Game
|
} // namespace Defaults::Game
|
||||||
|
|||||||
@@ -29,10 +29,6 @@ Engendro::Engendro(JD8_Surface gfx, Uint16 x, Uint16 y)
|
|||||||
this->cycles_per_frame = 30;
|
this->cycles_per_frame = 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engendro::draw() {
|
|
||||||
Sprite::draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Engendro::update() {
|
bool Engendro::update() {
|
||||||
bool mort = false;
|
bool mort = false;
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,8 @@
|
|||||||
|
|
||||||
class Engendro : public Sprite {
|
class Engendro : public Sprite {
|
||||||
public:
|
public:
|
||||||
Engendro(JD8_Surface gfx, Uint16 x, Uint16 y);
|
explicit Engendro(JD8_Surface gfx, Uint16 x, Uint16 y);
|
||||||
|
|
||||||
void draw();
|
|
||||||
bool update();
|
bool update();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -27,9 +27,14 @@ struct Vertex {
|
|||||||
|
|
||||||
class Mapa {
|
class Mapa {
|
||||||
public:
|
public:
|
||||||
Mapa(JD8_Surface gfx, Prota* sam);
|
explicit Mapa(JD8_Surface gfx, Prota* sam);
|
||||||
~Mapa(void);
|
~Mapa(void);
|
||||||
|
|
||||||
|
Mapa(const Mapa&) = delete;
|
||||||
|
Mapa& operator=(const Mapa&) = delete;
|
||||||
|
Mapa(Mapa&&) = delete;
|
||||||
|
Mapa& operator=(Mapa&&) = delete;
|
||||||
|
|
||||||
void draw();
|
void draw();
|
||||||
void update();
|
void update();
|
||||||
bool novaMomia();
|
bool novaMomia();
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
class Marcador {
|
class Marcador {
|
||||||
public:
|
public:
|
||||||
Marcador(JD8_Surface gfx, Prota* sam);
|
explicit Marcador(JD8_Surface gfx, Prota* sam);
|
||||||
~Marcador(void);
|
~Marcador(void);
|
||||||
|
|
||||||
void draw();
|
void draw();
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "game/modulegame.hpp"
|
#include "game/modulegame.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "core/audio/audio.hpp"
|
#include "core/audio/audio.hpp"
|
||||||
#include "core/jail/jdraw8.hpp"
|
#include "core/jail/jdraw8.hpp"
|
||||||
#include "core/jail/jgame.hpp"
|
#include "core/jail/jgame.hpp"
|
||||||
@@ -9,29 +11,17 @@ ModuleGame::ModuleGame() {
|
|||||||
this->gfx = JD8_LoadSurface(info::ctx.pepe_activat ? "gfx/frames2.gif" : "gfx/frames.gif");
|
this->gfx = JD8_LoadSurface(info::ctx.pepe_activat ? "gfx/frames2.gif" : "gfx/frames.gif");
|
||||||
JG_SetUpdateTicks(10);
|
JG_SetUpdateTicks(10);
|
||||||
|
|
||||||
this->sam = new Prota(this->gfx);
|
this->sam = std::make_unique<Prota>(this->gfx);
|
||||||
this->mapa = new Mapa(this->gfx, this->sam);
|
this->mapa = std::make_unique<Mapa>(this->gfx, this->sam.get());
|
||||||
this->marcador = new Marcador(this->gfx, this->sam);
|
this->marcador = std::make_unique<Marcador>(this->gfx, this->sam.get());
|
||||||
if (info::ctx.num_piramide == 2) {
|
if (info::ctx.num_piramide == 2) {
|
||||||
this->bola = new Bola(this->gfx, this->sam);
|
this->bola = std::make_unique<Bola>(this->gfx, this->sam.get());
|
||||||
} else {
|
|
||||||
this->bola = nullptr;
|
|
||||||
}
|
}
|
||||||
this->momies = nullptr;
|
|
||||||
|
|
||||||
this->iniciarMomies();
|
this->iniciarMomies();
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleGame::~ModuleGame() {
|
ModuleGame::~ModuleGame() {
|
||||||
if (this->bola != nullptr) delete this->bola;
|
|
||||||
if (this->momies != nullptr) {
|
|
||||||
this->momies->clear();
|
|
||||||
delete this->momies;
|
|
||||||
}
|
|
||||||
delete this->marcador;
|
|
||||||
delete this->mapa;
|
|
||||||
delete this->sam;
|
|
||||||
|
|
||||||
JD8_FreeSurface(this->gfx);
|
JD8_FreeSurface(this->gfx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,8 +112,8 @@ void ModuleGame::Draw() {
|
|||||||
this->mapa->draw();
|
this->mapa->draw();
|
||||||
this->marcador->draw();
|
this->marcador->draw();
|
||||||
this->sam->draw();
|
this->sam->draw();
|
||||||
if (this->momies != nullptr) this->momies->draw();
|
for (auto& m : this->momies) m->draw();
|
||||||
if (this->bola != nullptr) this->bola->draw();
|
if (this->bola) this->bola->draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleGame::Update() {
|
void ModuleGame::Update() {
|
||||||
@@ -131,33 +121,20 @@ void ModuleGame::Update() {
|
|||||||
JI_Update();
|
JI_Update();
|
||||||
|
|
||||||
this->final_ = this->sam->update();
|
this->final_ = this->sam->update();
|
||||||
if (this->momies != nullptr && this->momies->update()) {
|
const auto erased = std::erase_if(this->momies, [](auto& m) { return m->update(); });
|
||||||
Momia* seguent = this->momies->next;
|
info::ctx.momies -= static_cast<int>(erased);
|
||||||
delete this->momies;
|
if (this->bola) this->bola->update();
|
||||||
this->momies = seguent;
|
|
||||||
info::ctx.momies--;
|
|
||||||
}
|
|
||||||
if (this->bola != nullptr) this->bola->update();
|
|
||||||
this->mapa->update();
|
this->mapa->update();
|
||||||
if (this->mapa->novaMomia()) {
|
if (this->mapa->novaMomia()) {
|
||||||
if (this->momies != nullptr) {
|
this->momies.emplace_back(std::make_unique<Momia>(this->gfx, true, 0, 0, this->sam.get()));
|
||||||
this->momies->insertar(new Momia(this->gfx, true, 0, 0, this->sam));
|
|
||||||
info::ctx.momies++;
|
info::ctx.momies++;
|
||||||
} else {
|
|
||||||
this->momies = new Momia(this->gfx, true, 0, 0, this->sam);
|
|
||||||
info::ctx.momies++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JI_CheatActivated("reviu")) info::ctx.vida = 5;
|
if (JI_CheatActivated("reviu")) info::ctx.vida = 5;
|
||||||
if (JI_CheatActivated("alone")) {
|
if (JI_CheatActivated("alone")) {
|
||||||
if (this->momies != nullptr) {
|
this->momies.clear();
|
||||||
this->momies->clear();
|
|
||||||
delete this->momies;
|
|
||||||
this->momies = nullptr;
|
|
||||||
info::ctx.momies = 0;
|
info::ctx.momies = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (JI_CheatActivated("obert")) {
|
if (JI_CheatActivated("obert")) {
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
this->mapa->tombes[i].costat[0] = true;
|
this->mapa->tombes[i].costat[0] = true;
|
||||||
@@ -186,11 +163,7 @@ void ModuleGame::iniciarMomies() {
|
|||||||
int y = 170;
|
int y = 170;
|
||||||
bool dimonis = info::ctx.num_piramide == 6;
|
bool dimonis = info::ctx.num_piramide == 6;
|
||||||
for (int i = 0; i < info::ctx.momies; i++) {
|
for (int i = 0; i < info::ctx.momies; i++) {
|
||||||
if (this->momies == nullptr) {
|
this->momies.emplace_back(std::make_unique<Momia>(this->gfx, dimonis, x, y, this->sam.get()));
|
||||||
this->momies = new Momia(this->gfx, dimonis, x, y, this->sam);
|
|
||||||
} else {
|
|
||||||
this->momies->insertar(new Momia(this->gfx, dimonis, x, y, this->sam));
|
|
||||||
}
|
|
||||||
x += 65;
|
x += 65;
|
||||||
if (x == 345) {
|
if (x == 345) {
|
||||||
x = 20;
|
x = 20;
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "game/bola.hpp"
|
#include "game/bola.hpp"
|
||||||
#include "game/info.hpp"
|
#include "game/info.hpp"
|
||||||
#include "game/mapa.hpp"
|
#include "game/mapa.hpp"
|
||||||
@@ -28,6 +31,11 @@ class ModuleGame : public scenes::Scene {
|
|||||||
ModuleGame();
|
ModuleGame();
|
||||||
~ModuleGame() override;
|
~ModuleGame() override;
|
||||||
|
|
||||||
|
ModuleGame(const ModuleGame&) = delete;
|
||||||
|
ModuleGame& operator=(const ModuleGame&) = delete;
|
||||||
|
ModuleGame(ModuleGame&&) = delete;
|
||||||
|
ModuleGame& operator=(ModuleGame&&) = delete;
|
||||||
|
|
||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void tick(int delta_ms) override;
|
void tick(int delta_ms) override;
|
||||||
bool done() const override { return phase_ == Phase::Done; }
|
bool done() const override { return phase_ == Phase::Done; }
|
||||||
@@ -52,9 +60,9 @@ class ModuleGame : public scenes::Scene {
|
|||||||
Uint8 final_{0};
|
Uint8 final_{0};
|
||||||
JD8_Surface gfx{nullptr};
|
JD8_Surface gfx{nullptr};
|
||||||
|
|
||||||
Mapa* mapa{nullptr};
|
std::unique_ptr<Mapa> mapa;
|
||||||
Prota* sam{nullptr};
|
std::unique_ptr<Prota> sam;
|
||||||
Marcador* marcador{nullptr};
|
std::unique_ptr<Marcador> marcador;
|
||||||
Momia* momies{nullptr};
|
std::vector<std::unique_ptr<Momia>> momies;
|
||||||
Bola* bola{nullptr};
|
std::unique_ptr<Bola> bola;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,15 +10,15 @@ Momia::Momia(JD8_Surface gfx, bool dimoni, Uint16 x, Uint16 y, Prota* sam)
|
|||||||
this->sam = sam;
|
this->sam = sam;
|
||||||
|
|
||||||
entitat.frames.reserve(20);
|
entitat.frames.reserve(20);
|
||||||
for (int y = 0; y < 4; y++) {
|
for (int row = 0; row < 4; row++) {
|
||||||
for (int x = 0; x < 5; x++) {
|
for (int col = 0; col < 5; col++) {
|
||||||
Frame f;
|
Frame f;
|
||||||
f.w = 15;
|
f.w = 15;
|
||||||
f.h = 15;
|
f.h = 15;
|
||||||
if (info::ctx.num_piramide == 4) f.h -= 5;
|
if (info::ctx.num_piramide == 4) f.h -= 5;
|
||||||
f.x = (x * 15) + 75;
|
f.x = (col * 15) + 75;
|
||||||
if (this->dimoni) f.x += 75;
|
if (this->dimoni) f.x += 75;
|
||||||
f.y = 20 + (y * 15);
|
f.y = 20 + (row * 15);
|
||||||
entitat.frames.push_back(f);
|
entitat.frames.push_back(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,6 @@ Momia::Momia(JD8_Surface gfx, bool dimoni, Uint16 x, Uint16 y, Prota* sam)
|
|||||||
this->cur_frame = 0;
|
this->cur_frame = 0;
|
||||||
this->o = rand() % 4;
|
this->o = rand() % 4;
|
||||||
this->cycles_per_frame = 4;
|
this->cycles_per_frame = 4;
|
||||||
this->next = NULL;
|
|
||||||
|
|
||||||
if (this->dimoni) {
|
if (this->dimoni) {
|
||||||
if (x == 0) {
|
if (x == 0) {
|
||||||
@@ -57,22 +56,15 @@ Momia::Momia(JD8_Surface gfx, bool dimoni, Uint16 x, Uint16 y, Prota* sam)
|
|||||||
} else {
|
} else {
|
||||||
this->y = y;
|
this->y = y;
|
||||||
}
|
}
|
||||||
this->engendro = new Engendro(gfx, this->x, this->y);
|
this->engendro = std::make_unique<Engendro>(gfx, this->x, this->y);
|
||||||
} else {
|
} else {
|
||||||
this->engendro = NULL;
|
|
||||||
this->x = x;
|
this->x = x;
|
||||||
this->y = y;
|
this->y = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Momia::clear() {
|
|
||||||
if (this->next != NULL) this->next->clear();
|
|
||||||
if (this->engendro != NULL) delete this->engendro;
|
|
||||||
delete this->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Momia::draw() {
|
void Momia::draw() {
|
||||||
if (this->engendro != NULL) {
|
if (this->engendro) {
|
||||||
this->engendro->draw();
|
this->engendro->draw();
|
||||||
} else {
|
} else {
|
||||||
Sprite::draw();
|
Sprite::draw();
|
||||||
@@ -85,18 +77,18 @@ void Momia::draw() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this->next != NULL) this->next->draw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Momia::update() {
|
bool Momia::update() {
|
||||||
bool morta = false;
|
bool morta = false;
|
||||||
|
|
||||||
if (this->engendro != NULL) {
|
if (this->engendro) {
|
||||||
if (this->engendro->update()) {
|
if (this->engendro->update()) {
|
||||||
delete this->engendro;
|
this->engendro.reset();
|
||||||
this->engendro = NULL;
|
|
||||||
}
|
}
|
||||||
} else {
|
return morta;
|
||||||
|
}
|
||||||
|
|
||||||
if (this->sam->o < 4 && (this->dimoni || info::ctx.num_piramide == 5 || JG_GetCycleCounter() % 2 == 0)) {
|
if (this->sam->o < 4 && (this->dimoni || info::ctx.num_piramide == 5 || JG_GetCycleCounter() % 2 == 0)) {
|
||||||
if ((this->x - 20) % 65 == 0 && (this->y - 30) % 35 == 0) {
|
if ((this->x - 20) % 65 == 0 && (this->y - 30) % 35 == 0) {
|
||||||
if (this->dimoni) {
|
if (this->dimoni) {
|
||||||
@@ -156,24 +148,6 @@ bool Momia::update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (this->next != NULL) {
|
|
||||||
if (this->next->update()) {
|
|
||||||
Momia* seguent = this->next->next;
|
|
||||||
delete this->next;
|
|
||||||
this->next = seguent;
|
|
||||||
info::ctx.momies--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return morta;
|
return morta;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Momia::insertar(Momia* momia) {
|
|
||||||
if (this->next != NULL) {
|
|
||||||
this->next->insertar(momia);
|
|
||||||
} else {
|
|
||||||
this->next = momia;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "game/engendro.hpp"
|
#include "game/engendro.hpp"
|
||||||
#include "game/info.hpp"
|
#include "game/info.hpp"
|
||||||
#include "game/prota.hpp"
|
#include "game/prota.hpp"
|
||||||
@@ -7,17 +9,14 @@
|
|||||||
|
|
||||||
class Momia : public Sprite {
|
class Momia : public Sprite {
|
||||||
public:
|
public:
|
||||||
Momia(JD8_Surface gfx, bool dimoni, Uint16 x, Uint16 y, Prota* sam);
|
explicit Momia(JD8_Surface gfx, bool dimoni, Uint16 x, Uint16 y, Prota* sam);
|
||||||
|
|
||||||
void clear();
|
void draw() override;
|
||||||
void draw();
|
|
||||||
bool update();
|
bool update();
|
||||||
void insertar(Momia* momia);
|
|
||||||
|
|
||||||
bool dimoni;
|
bool dimoni;
|
||||||
Momia* next;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Prota* sam;
|
Prota* sam;
|
||||||
Engendro* engendro;
|
std::unique_ptr<Engendro> engendro;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -219,6 +219,8 @@ namespace Options {
|
|||||||
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"))
|
||||||
game.show_title_credits = node["show_title_credits"].get_value<bool>();
|
game.show_title_credits = node["show_title_credits"].get_value<bool>();
|
||||||
|
if (node.contains("show_preload"))
|
||||||
|
game.show_preload = node["show_preload"].get_value<bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carrega les opcions des del fitxer configurat
|
// Carrega les opcions des del fitxer configurat
|
||||||
@@ -368,6 +370,7 @@ namespace Options {
|
|||||||
file << "game:\n";
|
file << "game:\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 << " show_preload: " << (game.show_preload ? "true" : "false") << "\n";
|
||||||
file << "\n";
|
file << "\n";
|
||||||
|
|
||||||
// CONTROLS — només moviment del jugador. Les tecles d'UI viuen a
|
// CONTROLS — només moviment del jugador. Les tecles d'UI viuen a
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ namespace Options {
|
|||||||
int diners_inicial{Defaults::Game::DINERS_INICIAL};
|
int diners_inicial{Defaults::Game::DINERS_INICIAL};
|
||||||
bool use_new_logo{Defaults::Game::USE_NEW_LOGO};
|
bool use_new_logo{Defaults::Game::USE_NEW_LOGO};
|
||||||
bool show_title_credits{Defaults::Game::SHOW_TITLE_CREDITS};
|
bool show_title_credits{Defaults::Game::SHOW_TITLE_CREDITS};
|
||||||
|
bool show_preload{Defaults::Game::SHOW_PRELOAD};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Preset PostFX
|
// Preset PostFX
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
class Prota : public Sprite {
|
class Prota : public Sprite {
|
||||||
public:
|
public:
|
||||||
Prota(JD8_Surface gfx);
|
explicit Prota(JD8_Surface gfx);
|
||||||
|
|
||||||
void draw();
|
void draw() override;
|
||||||
Uint8 update();
|
Uint8 update();
|
||||||
|
|
||||||
Uint8 frame_pejades;
|
Uint8 frame_pejades;
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ struct Entitat {
|
|||||||
|
|
||||||
class Sprite {
|
class Sprite {
|
||||||
public:
|
public:
|
||||||
Sprite(JD8_Surface gfx);
|
explicit Sprite(JD8_Surface gfx);
|
||||||
virtual ~Sprite() = default;
|
virtual ~Sprite() = default;
|
||||||
|
|
||||||
void draw();
|
virtual void draw();
|
||||||
|
|
||||||
Entitat entitat;
|
Entitat entitat;
|
||||||
Uint8 cur_frame = 0;
|
Uint8 cur_frame = 0;
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ SDL_AppResult SDL_AppInit(void** /*appstate*/, int /*argc*/, char* /*argv*/[]) {
|
|||||||
#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;
|
||||||
Options::window.zoom = 1;
|
Options::window.zoom = 3;
|
||||||
Options::video.aspect_ratio_4_3 = true;
|
Options::video.aspect_ratio_4_3 = true;
|
||||||
Options::video.scaling_mode = Options::ScalingMode::INTEGER;
|
Options::video.scaling_mode = Options::ScalingMode::INTEGER;
|
||||||
Options::video.texture_filter = Options::TextureFilter::LINEAR;
|
Options::video.texture_filter = Options::TextureFilter::LINEAR;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace scenes {
|
|||||||
// PaletteFade copia internament amb memcpy; alliberem la paleta temporal.
|
// PaletteFade copia internament amb memcpy; alliberem la paleta temporal.
|
||||||
JD8_Palette pal = JD8_LoadPalette("gfx/ffase.gif");
|
JD8_Palette pal = JD8_LoadPalette("gfx/ffase.gif");
|
||||||
fade_.startFadeTo(pal);
|
fade_.startFadeTo(pal);
|
||||||
std::free(pal);
|
delete[] pal;
|
||||||
|
|
||||||
phase_ = Phase::FadingIn;
|
phase_ = Phase::FadingIn;
|
||||||
remaining_ms_ = 5000;
|
remaining_ms_ = 5000;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "core/jail/jdraw8.hpp"
|
#include "core/jail/jdraw8.hpp"
|
||||||
#include "core/resources/resource_cache.hpp"
|
#include "core/resources/resource_cache.hpp"
|
||||||
|
#include "game/options.hpp"
|
||||||
|
|
||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
@@ -37,6 +38,8 @@ namespace scenes {
|
|||||||
void BootLoaderScene::render() const {
|
void BootLoaderScene::render() const {
|
||||||
JD8_ClearScreen(BG_COLOR);
|
JD8_ClearScreen(BG_COLOR);
|
||||||
|
|
||||||
|
if (!Options::game.show_preload) return;
|
||||||
|
|
||||||
const float pct = Resource::Cache::get()->getProgress();
|
const float pct = Resource::Cache::get()->getProgress();
|
||||||
const int filled = static_cast<int>(static_cast<float>(BAR_W) * pct);
|
const int filled = static_cast<int>(static_cast<float>(BAR_W) * pct);
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ namespace scenes {
|
|||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void tick(int delta_ms) override;
|
void tick(int delta_ms) override;
|
||||||
bool done() const override { return done_; }
|
bool done() const override { return done_; }
|
||||||
int nextState() const override { return 1; } // 1 → SceneRegistry::tryCreate(num_piramide=255 → intro)
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void render() const;
|
void render() const;
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ namespace scenes {
|
|||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void tick(int delta_ms) override;
|
void tick(int delta_ms) override;
|
||||||
bool done() const override { return phase_ == Phase::Done; }
|
bool done() const override { return phase_ == Phase::Done; }
|
||||||
int nextState() const override { return 1; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Phase { Rolling,
|
enum class Phase { Rolling,
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ namespace scenes {
|
|||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void tick(int delta_ms) override;
|
void tick(int delta_ms) override;
|
||||||
bool done() const override { return phase_ == Phase::Done; }
|
bool done() const override { return phase_ == Phase::Done; }
|
||||||
int nextState() const override { return 1; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Phase {
|
enum class Phase {
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ namespace scenes {
|
|||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void tick(int delta_ms) override;
|
void tick(int delta_ms) override;
|
||||||
bool done() const override { return phase_ == Phase::Done; }
|
bool done() const override { return phase_ == Phase::Done; }
|
||||||
int nextState() const override { return 1; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Phase {
|
enum class Phase {
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ namespace scenes {
|
|||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void tick(int delta_ms) override;
|
void tick(int delta_ms) override;
|
||||||
bool done() const override { return done_; }
|
bool done() const override { return done_; }
|
||||||
int nextState() const override { return 1; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SurfaceHandle gfx_;
|
SurfaceHandle gfx_;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace scenes {
|
|||||||
|
|
||||||
JD8_Palette pal = JD8_LoadPalette("gfx/menu2.gif");
|
JD8_Palette pal = JD8_LoadPalette("gfx/menu2.gif");
|
||||||
fade_.startFadeTo(pal);
|
fade_.startFadeTo(pal);
|
||||||
std::free(pal);
|
delete[] pal;
|
||||||
|
|
||||||
phase_ = Phase::FadingIn;
|
phase_ = Phase::FadingIn;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ namespace scenes {
|
|||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void tick(int delta_ms) override;
|
void tick(int delta_ms) override;
|
||||||
bool done() const override { return phase_ == Phase::Done; }
|
bool done() const override { return phase_ == Phase::Done; }
|
||||||
int nextState() const override { return 1; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Phase { FadingIn,
|
enum class Phase { FadingIn,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace scenes {
|
|||||||
// la paleta temporal immediatament.
|
// la paleta temporal immediatament.
|
||||||
JD8_Palette pal = JD8_LoadPalette("gfx/gameover.gif");
|
JD8_Palette pal = JD8_LoadPalette("gfx/gameover.gif");
|
||||||
fade_.startFadeTo(pal);
|
fade_.startFadeTo(pal);
|
||||||
std::free(pal);
|
delete[] pal;
|
||||||
|
|
||||||
phase_ = Phase::FadingIn;
|
phase_ = Phase::FadingIn;
|
||||||
remaining_ms_ = 10000;
|
remaining_ms_ = 10000;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ namespace scenes {
|
|||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void tick(int delta_ms) override;
|
void tick(int delta_ms) override;
|
||||||
bool done() const override { return phase_ == Phase::Done; }
|
bool done() const override { return phase_ == Phase::Done; }
|
||||||
int nextState() const override { return 1; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Phase { FadingIn,
|
enum class Phase { FadingIn,
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace {
|
|||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
SecretaScene::~SecretaScene() {
|
SecretaScene::~SecretaScene() {
|
||||||
if (pal_aux_) std::free(pal_aux_);
|
delete[] pal_aux_;
|
||||||
// pal_active_ NO s'allibera: propietat de main_palette via SetScreenPalette.
|
// pal_active_ NO s'allibera: propietat de main_palette via SetScreenPalette.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ namespace scenes {
|
|||||||
|
|
||||||
gfx_ = SurfaceHandle("gfx/tomba1.gif");
|
gfx_ = SurfaceHandle("gfx/tomba1.gif");
|
||||||
pal_aux_ = JD8_LoadPalette("gfx/tomba1.gif");
|
pal_aux_ = JD8_LoadPalette("gfx/tomba1.gif");
|
||||||
pal_active_ = static_cast<JD8_Palette>(std::malloc(768));
|
pal_active_ = new Color[256];
|
||||||
std::memcpy(pal_active_, pal_aux_, 768);
|
std::memcpy(pal_active_, pal_aux_, 768);
|
||||||
|
|
||||||
phase_ = Phase::InitialFadeOut;
|
phase_ = Phase::InitialFadeOut;
|
||||||
@@ -62,7 +62,7 @@ namespace scenes {
|
|||||||
JD8_ClearScreen(255);
|
JD8_ClearScreen(255);
|
||||||
gfx_.reset("gfx/tomba2.gif");
|
gfx_.reset("gfx/tomba2.gif");
|
||||||
|
|
||||||
std::free(pal_aux_);
|
delete[] pal_aux_;
|
||||||
pal_aux_ = JD8_LoadPalette("gfx/tomba2.gif");
|
pal_aux_ = JD8_LoadPalette("gfx/tomba2.gif");
|
||||||
// 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í.
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace {
|
|||||||
namespace scenes {
|
namespace scenes {
|
||||||
|
|
||||||
SlidesScene::~SlidesScene() {
|
SlidesScene::~SlidesScene() {
|
||||||
if (pal_aux_) std::free(pal_aux_);
|
delete[] pal_aux_;
|
||||||
// pal_active_ NO s'allibera: propietat de main_palette via SetScreenPalette.
|
// pal_active_ NO s'allibera: propietat de main_palette via SetScreenPalette.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ namespace scenes {
|
|||||||
// main_palette després del SetScreenPalette — modificar-la modifica
|
// main_palette després del SetScreenPalette — modificar-la modifica
|
||||||
// main_palette directament. `pal_aux_` es manté intacte per a poder
|
// main_palette directament. `pal_aux_` es manté intacte per a poder
|
||||||
// restaurar després de cada fade-out intermedi.
|
// restaurar després de cada fade-out intermedi.
|
||||||
pal_active_ = static_cast<JD8_Palette>(std::malloc(768));
|
pal_active_ = new Color[256];
|
||||||
std::memcpy(pal_active_, pal_aux_, 768);
|
std::memcpy(pal_active_, pal_aux_, 768);
|
||||||
JD8_SetScreenPalette(pal_active_);
|
JD8_SetScreenPalette(pal_active_);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user