8 Commits

Author SHA1 Message Date
b1f9e57f36 fix: color de fonde dels sliders de 050505 a 000000 2026-04-18 15:20:25 +02:00
f7875baa2d refactor: fase 6 — Rule of 5 a Mapa i ModuleGame (no-copiables, no-movibles)
- Mapa té un JD8_Surface fondo propi que s'allibera al destructor: una
  còpia accidental provocaria double-free. Ara els 4 copy/move ops estan
  = delete.
- ModuleGame ja era no-copiable implícitament per tindre unique_ptr
  members, però els = delete expliciten la intenció i protegeixen
  davant refactors futurs que afegeixquen tipus copiables.

Fi de la modernització RAII per fases (1–6).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 14:03:51 +02:00
c6e37af7d1 refactor: fase 5 — singletons a std::unique_ptr (elimina new/delete manual)
5 singletons afectats: Audio, Screen, Director, Resource::Cache, Resource::List.

- static T* instance → static std::unique_ptr<T> instance
- init(): new T() adoptat immediatament per unique_ptr (ownership RAII)
- destroy(): instance.reset() (sense delete manual)
- get(): retorna instance.get()
- Destructors moguts a public perquè std::default_delete hi pugui accedir
  (ctors privats + copy/move deleted → encapsulació efectiva mantinguda)

Ordre de destrucció preservat: SDL_AppQuit segueix cridant destroy() en
l'ordre invers a init() — la RAII automàtica no s'activa fins al final
del programa (LIFO de variables static).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 14:02:01 +02:00
5e57034a38 refactor: fase 4 — llista enllaçada de Momia a std::vector<unique_ptr>
Eliminada completament la recursivitat per next-pointer:
- Momia::next, clear(), insertar() desapareixen
- update()/draw() no recursen: operen només sobre la instància pròpia
- ModuleGame::momies: Momia* (head de llista) → std::vector<std::unique_ptr<Momia>>
  - Destructor simplificat (vector s'autodestrueix)
  - Draw: range-for sobre el vector
  - Update: std::erase_if + decrement sincronitzat de info::ctx.momies
  - Cheat "alone": momies.clear()
  - iniciarMomies i nova_momia: emplace_back(std::make_unique<Momia>(...))

Zero new/delete manuals al cicle de vida de les momies.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 13:56:05 +02:00
2a8fbbb095 refactor: fase 3 — Text::bitmap_ a std::vector<Uint8>
- bitmap_: Uint8* (owning, free'd al destructor) → std::vector<Uint8>
- loadBitmap copia des del buffer de LoadGif i fa free(pixels) de
  l'intermedi (gif.h usa malloc internament)
- ~Text() eliminat: regla 0 aplicada (vector es destrueix sol)
- Les 4 comprovacions !bitmap_ → bitmap_.empty()

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 13:44:07 +02:00
53e93ef697 refactor: fase 2 — elimina malloc/free a jdraw8 i paletes d'escenes
- JD8_Init/Quit: new[]/delete[] per a screen, main_palette, pixel_data
- JD8_NewSurface/FreeSurface: new Uint8[64000]{}/delete[]
- JD8_LoadPalette: uniforme — sempre retorna `new Color[256]`, copiant del
  LoadPalette extern al path no-cached (l'intermedi raw es frees amb free()
  perquè gif.h el malloca)
- JD8_SetScreenPalette: delete[] la paleta reemplaçada
- slides/secreta/menu/banner/mort scenes: std::free/std::malloc → delete[]/new Color[256]

Ownership uniforme: tot el cicle de vida de surface/palette usa new[]/delete[].

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 13:42:31 +02:00
e7aa2463b4 refactor: fase 1 — cleanup mecànic de baix risc (NULL→nullptr, typedef→using, explicit, enum class local)
- jdraw8.hpp: typedef → using (JD8_Surface, JD8_Palette)
- jdraw8.cpp: NULL → nullptr, C-casts → static_cast/reinterpret_cast, anon enum FadeType → enum class
- momia.cpp: NULL → nullptr
- bola/mapa/marcador/momia/engendro: explicit als constructors

Zero canvis de lògica ni ownership. Primera fase de la modernització RAII.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 13:37:48 +02:00
27f8b0ae36 cppcheck 2026-04-18 13:22:13 +02:00
43 changed files with 235 additions and 292 deletions

View File

@@ -0,0 +1 @@
{"sessionId":"7b0c9c32-3dd4-48a3-ba06-c2303dc08243","pid":123890,"acquiredAt":1776510185734}

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

View File

@@ -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(); }

View File

@@ -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

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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();

View File

@@ -82,9 +82,7 @@ void file_setconfigfolder(const char* foldername) {
config_folder = std::string(homedir) + "/.config/" + foldername; config_folder = std::string(homedir) + "/.config/" + foldername;
#endif #endif
if (!config_folder.empty()) { std::filesystem::create_directories(config_folder);
std::filesystem::create_directories(config_folder);
}
} }
const char* file_getconfigfolder() { const char* file_getconfigfolder() {

View File

@@ -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() {

View File

@@ -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};

View File

@@ -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;

View File

@@ -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};

View File

@@ -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 {

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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() {

View File

@@ -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

View File

@@ -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:

View File

@@ -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;

View File

@@ -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:

View File

@@ -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();

View File

@@ -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();

View File

@@ -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,32 +121,19 @@ 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(); info::ctx.momies = 0;
delete this->momies;
this->momies = nullptr;
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++) {
@@ -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;

View File

@@ -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;
}; };

View File

@@ -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,95 +77,77 @@ 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 {
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->dimoni) {
if (rand() % 2 == 0) {
if (this->x > this->sam->x) {
this->o = 3;
} else if (this->x < this->sam->x) {
this->o = 2;
} else if (this->y < this->sam->y) {
this->o = 0;
} else if (this->y > this->sam->y) {
this->o = 1;
}
} else {
if (this->y < this->sam->y) {
this->o = 0;
} else if (this->y > this->sam->y) {
this->o = 1;
} else if (this->x > this->sam->x) {
this->o = 3;
} else if (this->x < this->sam->x) {
this->o = 2;
}
}
} else {
this->o = rand() % 4;
}
}
switch (this->o) {
case 0:
if (y < 170) this->y++;
break;
case 1:
if (y > 30) this->y--;
break;
case 2:
if (x < 280) this->x++;
break;
case 3:
if (x > 20) this->x--;
break;
}
if (JG_GetCycleCounter() % this->cycles_per_frame == 0) {
this->cur_frame++;
if (this->cur_frame == entitat.animacions[this->o].frames.size()) this->cur_frame = 0;
}
if (this->x > (this->sam->x - 7) && this->x < (this->sam->x + 7) && this->y > (this->sam->y - 7) && this->y < (this->sam->y + 7)) {
morta = true;
if (this->sam->pergami) {
this->sam->pergami = false;
} else {
info::ctx.vida--;
if (info::ctx.vida == 0) this->sam->o = 5;
}
}
} }
return morta;
} }
if (this->next != NULL) { if (this->sam->o < 4 && (this->dimoni || info::ctx.num_piramide == 5 || JG_GetCycleCounter() % 2 == 0)) {
if (this->next->update()) { if ((this->x - 20) % 65 == 0 && (this->y - 30) % 35 == 0) {
Momia* seguent = this->next->next; if (this->dimoni) {
delete this->next; if (rand() % 2 == 0) {
this->next = seguent; if (this->x > this->sam->x) {
info::ctx.momies--; this->o = 3;
} else if (this->x < this->sam->x) {
this->o = 2;
} else if (this->y < this->sam->y) {
this->o = 0;
} else if (this->y > this->sam->y) {
this->o = 1;
}
} else {
if (this->y < this->sam->y) {
this->o = 0;
} else if (this->y > this->sam->y) {
this->o = 1;
} else if (this->x > this->sam->x) {
this->o = 3;
} else if (this->x < this->sam->x) {
this->o = 2;
}
}
} else {
this->o = rand() % 4;
}
}
switch (this->o) {
case 0:
if (y < 170) this->y++;
break;
case 1:
if (y > 30) this->y--;
break;
case 2:
if (x < 280) this->x++;
break;
case 3:
if (x > 20) this->x--;
break;
}
if (JG_GetCycleCounter() % this->cycles_per_frame == 0) {
this->cur_frame++;
if (this->cur_frame == entitat.animacions[this->o].frames.size()) this->cur_frame = 0;
}
if (this->x > (this->sam->x - 7) && this->x < (this->sam->x + 7) && this->y > (this->sam->y - 7) && this->y < (this->sam->y + 7)) {
morta = true;
if (this->sam->pergami) {
this->sam->pergami = false;
} else {
info::ctx.vida--;
if (info::ctx.vida == 0) this->sam->o = 5;
}
} }
} }
return morta; return morta;
} }
void Momia::insertar(Momia* momia) {
if (this->next != NULL) {
this->next->insertar(momia);
} else {
this->next = momia;
}
}

View File

@@ -1,23 +1,22 @@
#pragma once #pragma once
#include "game/engendro.hpp" #include <memory>
#include "game/info.hpp"
#include "game/prota.hpp" #include "game/engendro.hpp"
#include "game/sprite.hpp" #include "game/info.hpp"
#include "game/prota.hpp"
class Momia : public Sprite { #include "game/sprite.hpp"
public:
Momia(JD8_Surface gfx, bool dimoni, Uint16 x, Uint16 y, Prota* sam); class Momia : public Sprite {
public:
void clear(); explicit Momia(JD8_Surface gfx, bool dimoni, Uint16 x, Uint16 y, Prota* sam);
void draw();
bool update(); void draw() override;
void insertar(Momia* momia); bool update();
bool dimoni; bool dimoni;
Momia* next;
protected:
protected: Prota* sam;
Prota* sam; std::unique_ptr<Engendro> engendro;
Engendro* engendro; };
};

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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_;

View File

@@ -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;
} }

View File

@@ -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,

View File

@@ -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;

View File

@@ -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,

View File

@@ -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í.

View File

@@ -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_);