neteja tidy a source/core i encamina Texture::loadFromFile pel ResourceHelper

This commit is contained in:
2026-05-14 20:22:54 +02:00
parent 88fa3f296f
commit 1912200b21
40 changed files with 699 additions and 578 deletions
+10 -4
View File
@@ -51,7 +51,7 @@ void Audio::update() {
JA_Update();
// Sincronizar estado: detectar cuando la música se para (ej. fade-out completado)
if (instance && instance->music_.state == MusicState::PLAYING && JA_GetMusicState() != JA_MUSIC_PLAYING) {
if ((instance != nullptr) && instance->music_.state == MusicState::PLAYING && JA_GetMusicState() != JA_MUSIC_PLAYING) {
instance->music_.state = MusicState::STOPPED;
}
}
@@ -65,10 +65,14 @@ void Audio::playMusic(const std::string& name, const int loop, const int crossfa
return;
}
if (!music_enabled_) return;
if (!music_enabled_) {
return;
}
auto* resource = AudioResource::getMusic(name);
if (resource == nullptr) return;
if (resource == nullptr) {
return;
}
if (crossfade_ms > 0 && music_.state == MusicState::PLAYING) {
JA_CrossfadeMusic(resource, crossfade_ms, loop);
@@ -86,7 +90,9 @@ void Audio::playMusic(const std::string& name, const int loop, const int crossfa
// Reproduce la música por puntero (con crossfade opcional)
void Audio::playMusic(JA_Music_t* music, const int loop, const int crossfade_ms) {
if (!music_enabled_ || music == nullptr) return;
if (!music_enabled_ || music == nullptr) {
return;
}
if (crossfade_ms > 0 && music_.state == MusicState::PLAYING) {
JA_CrossfadeMusic(music, crossfade_ms, loop);
+1 -1
View File
@@ -60,7 +60,7 @@ class Audio {
// --- Helpers de conversió per a la capa de presentació ---
// UI (menús, notificacions) manega enters 0..100; internament viu float 0..1.
static constexpr auto toPercent(float volume) -> int {
return static_cast<int>(volume * 100.0F + 0.5F);
return static_cast<int>((volume * 100.0F) + 0.5F);
}
static constexpr auto fromPercent(int percent) -> float {
return static_cast<float>(percent) / 100.0F;
+2 -2
View File
@@ -3,11 +3,11 @@
#include "core/resources/resource.h"
namespace AudioResource {
JA_Music_t* getMusic(const std::string& name) {
auto getMusic(const std::string& name) -> JA_Music_t* {
return Resource::get()->getMusic(name);
}
JA_Sound_t* getSound(const std::string& name) {
auto getSound(const std::string& name) -> JA_Sound_t* {
return Resource::get()->getSound(name);
}
} // namespace AudioResource
+2 -2
View File
@@ -12,6 +12,6 @@ struct JA_Music_t;
struct JA_Sound_t;
namespace AudioResource {
JA_Music_t* getMusic(const std::string& name);
JA_Sound_t* getSound(const std::string& name);
auto getMusic(const std::string& name) -> JA_Music_t*;
auto getSound(const std::string& name) -> JA_Sound_t*;
} // namespace AudioResource
+218 -117
View File
@@ -19,7 +19,9 @@
// overhead gràcies a EBO, igual que un unique_ptr amb default_delete.
struct SDLFreeDeleter {
void operator()(Uint8* p) const noexcept {
if (p) SDL_free(p);
if (p != nullptr) {
SDL_free(p);
}
}
};
@@ -40,8 +42,10 @@ enum JA_Music_state {
};
// --- Struct Definitions ---
#define JA_MAX_SIMULTANEOUS_CHANNELS 20
#define JA_MAX_GROUPS 2
enum {
JA_MAX_SIMULTANEOUS_CHANNELS = 20,
JA_MAX_GROUPS = 2
};
struct JA_Sound_t {
SDL_AudioSpec spec{SDL_AUDIO_S16, 2, 48000};
@@ -84,7 +88,7 @@ inline JA_Music_t* current_music{nullptr};
inline JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
inline SDL_AudioSpec JA_audioSpec{SDL_AUDIO_S16, 2, 48000};
inline float JA_musicVolume{1.0f};
inline float JA_musicVolume{1.0F};
inline float JA_soundVolume[JA_MAX_GROUPS];
inline bool JA_musicEnabled{true};
inline bool JA_soundEnabled{true};
@@ -95,7 +99,7 @@ struct JA_FadeState {
bool active{false};
Uint64 start_time{0};
int duration_ms{0};
float initial_volume{0.0f};
float initial_volume{0.0F};
};
struct JA_OutgoingMusic {
@@ -108,8 +112,8 @@ inline JA_FadeState incoming_fade;
// --- Forward Declarations ---
inline void JA_StopMusic();
inline void JA_StopChannel(const int channel);
inline int JA_PlaySoundOnChannel(JA_Sound_t* sound, const int channel, const int loop = 0, const int group = 0);
inline void JA_StopChannel(int channel);
inline auto JA_PlaySoundOnChannel(JA_Sound_t* sound, int channel, int loop = 0, int group = 0) -> int;
inline void JA_CrossfadeMusic(JA_Music_t* music, int crossfade_ms, int loop = -1);
// --- Music streaming internals ---
@@ -120,12 +124,14 @@ static constexpr int JA_MUSIC_BYTES_PER_SAMPLE = 2;
static constexpr int JA_MUSIC_CHUNK_SHORTS = 8192;
// Umbral d'audio per davant del cursor de reproducció. Mantenim ≥ 0.5 s a
// l'SDL_AudioStream per absorbir jitter de frame i evitar underruns.
static constexpr float JA_MUSIC_LOW_WATER_SECONDS = 0.5f;
static constexpr float JA_MUSIC_LOW_WATER_SECONDS = 0.5F;
// Decodifica un chunk del vorbis i el volca a l'stream. Retorna samples
// decodificats per canal (0 = EOF de l'stream vorbis).
inline int JA_FeedMusicChunk(JA_Music_t* music) {
if (!music || !music->vorbis || !music->stream) return 0;
inline auto JA_FeedMusicChunk(JA_Music_t* music) -> int {
if ((music == nullptr) || (music->vorbis == nullptr) || (music->stream == nullptr)) {
return 0;
}
short chunk[JA_MUSIC_CHUNK_SHORTS];
const int num_channels = music->spec.channels;
@@ -134,7 +140,9 @@ inline int JA_FeedMusicChunk(JA_Music_t* music) {
num_channels,
chunk,
JA_MUSIC_CHUNK_SHORTS);
if (samples_per_channel <= 0) return 0;
if (samples_per_channel <= 0) {
return 0;
}
const int bytes = samples_per_channel * num_channels * JA_MUSIC_BYTES_PER_SAMPLE;
SDL_PutAudioStreamData(music->stream, chunk, bytes);
@@ -144,19 +152,25 @@ inline int JA_FeedMusicChunk(JA_Music_t* music) {
// Reompli l'stream fins que tinga ≥ JA_MUSIC_LOW_WATER_SECONDS bufferats.
// En arribar a EOF del vorbis, aplica el loop (times) o deixa drenar.
inline void JA_PumpMusic(JA_Music_t* music) {
if (!music || !music->vorbis || !music->stream) return;
if ((music == nullptr) || (music->vorbis == nullptr) || (music->stream == nullptr)) {
return;
}
const int bytes_per_second = music->spec.freq * music->spec.channels * JA_MUSIC_BYTES_PER_SAMPLE;
const int low_water_bytes = static_cast<int>(JA_MUSIC_LOW_WATER_SECONDS * static_cast<float>(bytes_per_second));
while (SDL_GetAudioStreamAvailable(music->stream) < low_water_bytes) {
const int decoded = JA_FeedMusicChunk(music);
if (decoded > 0) continue;
if (decoded > 0) {
continue;
}
// EOF: si queden loops, rebobinar; si no, tallar i deixar drenar.
if (music->times != 0) {
stb_vorbis_seek_start(music->vorbis);
if (music->times > 0) music->times--;
if (music->times > 0) {
music->times--;
}
} else {
break;
}
@@ -168,14 +182,18 @@ inline void JA_PumpMusic(JA_Music_t* music) {
// streaming: l'stream robat no es pot re-alimentar perquè perd la referència
// al seu vorbis decoder. No aplica loop — si el vorbis s'esgota abans, parem.
inline void JA_PreFillOutgoing(JA_Music_t* music, int duration_ms) {
if (!music || !music->vorbis || !music->stream) return;
if ((music == nullptr) || (music->vorbis == nullptr) || (music->stream == nullptr)) {
return;
}
const int bytes_per_second = music->spec.freq * music->spec.channels * JA_MUSIC_BYTES_PER_SAMPLE;
const int needed_bytes = static_cast<int>((static_cast<int64_t>(duration_ms) * bytes_per_second) / 1000);
while (SDL_GetAudioStreamAvailable(music->stream) < needed_bytes) {
const int decoded = JA_FeedMusicChunk(music);
if (decoded <= 0) break; // EOF: deixem drenar el que hi haja
if (decoded <= 0) {
break; // EOF: deixem drenar el que hi haja
}
}
}
@@ -183,7 +201,7 @@ inline void JA_PreFillOutgoing(JA_Music_t* music, int duration_ms) {
inline void JA_Update() {
// --- Outgoing music fade-out (crossfade o fade-out a silencio) ---
if (outgoing_music.stream && outgoing_music.fade.active) {
if ((outgoing_music.stream != nullptr) && outgoing_music.fade.active) {
Uint64 now = SDL_GetTicks();
Uint64 elapsed = now - outgoing_music.fade.start_time;
if (elapsed >= (Uint64)outgoing_music.fade.duration_ms) {
@@ -192,12 +210,12 @@ inline void JA_Update() {
outgoing_music.fade.active = false;
} else {
float percent = (float)elapsed / (float)outgoing_music.fade.duration_ms;
SDL_SetAudioStreamGain(outgoing_music.stream, outgoing_music.fade.initial_volume * (1.0f - percent));
SDL_SetAudioStreamGain(outgoing_music.stream, outgoing_music.fade.initial_volume * (1.0F - percent));
}
}
// --- Current music ---
if (JA_musicEnabled && current_music && current_music->state == JA_MUSIC_PLAYING) {
if (JA_musicEnabled && (current_music != nullptr) && current_music->state == JA_MUSIC_PLAYING) {
// Fade-in (parte de un crossfade)
if (incoming_fade.active) {
Uint64 now = SDL_GetTicks();
@@ -221,42 +239,59 @@ inline void JA_Update() {
// --- Sound channels ---
if (JA_soundEnabled) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; ++i)
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; ++i) {
if (channels[i].state == JA_CHANNEL_PLAYING) {
if (channels[i].times != 0) {
if ((Uint32)SDL_GetAudioStreamAvailable(channels[i].stream) < (channels[i].sound->length / 2)) {
SDL_PutAudioStreamData(channels[i].stream, channels[i].sound->buffer.get(), channels[i].sound->length);
if (channels[i].times > 0) channels[i].times--;
if (channels[i].times > 0) {
channels[i].times--;
}
}
} else {
if (SDL_GetAudioStreamAvailable(channels[i].stream) == 0) JA_StopChannel(i);
if (SDL_GetAudioStreamAvailable(channels[i].stream) == 0) {
JA_StopChannel(i);
}
}
}
}
}
}
inline void JA_Init(const int freq, const SDL_AudioFormat format, const int num_channels) {
JA_audioSpec = {format, num_channels, freq};
if (sdlAudioDevice) SDL_CloseAudioDevice(sdlAudioDevice);
JA_audioSpec = {.format = format, .channels = num_channels, .freq = freq};
if (sdlAudioDevice != 0U) {
SDL_CloseAudioDevice(sdlAudioDevice);
}
sdlAudioDevice = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &JA_audioSpec);
if (sdlAudioDevice == 0) std::cout << "Failed to initialize SDL audio!" << '\n';
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; ++i) channels[i].state = JA_CHANNEL_FREE;
for (int i = 0; i < JA_MAX_GROUPS; ++i) JA_soundVolume[i] = 0.5f;
if (sdlAudioDevice == 0) {
std::cout << "Failed to initialize SDL audio!" << '\n';
}
for (auto& channel : channels) {
channel.state = JA_CHANNEL_FREE;
}
for (float& i : JA_soundVolume) {
i = 0.5F;
}
}
inline void JA_Quit() {
if (outgoing_music.stream) {
if (outgoing_music.stream != nullptr) {
SDL_DestroyAudioStream(outgoing_music.stream);
outgoing_music.stream = nullptr;
}
if (sdlAudioDevice) SDL_CloseAudioDevice(sdlAudioDevice);
if (sdlAudioDevice != 0U) {
SDL_CloseAudioDevice(sdlAudioDevice);
}
sdlAudioDevice = 0;
}
// --- Music Functions ---
inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) {
if (!buffer || length == 0) return nullptr;
inline auto JA_LoadMusic(const Uint8* buffer, Uint32 length) -> JA_Music_t* {
if ((buffer == nullptr) || length == 0) {
return nullptr;
}
// Allocem el JA_Music_t primer per aprofitar el seu `std::vector<Uint8>`
// com a propietari del OGG comprimit. stb_vorbis guarda un punter
@@ -270,7 +305,7 @@ inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) {
static_cast<int>(length),
&err,
nullptr);
if (!music->vorbis) {
if (music->vorbis == nullptr) {
std::cout << "JA_LoadMusic: stb_vorbis_open_memory failed (error " << err << ")" << '\n';
delete music;
return nullptr;
@@ -287,21 +322,25 @@ inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) {
// Overload amb filename — els callers l'usen per poder comparar la música
// en curs amb JA_GetMusicFilename() i no rearrancar-la si ja és la mateixa.
inline JA_Music_t* JA_LoadMusic(Uint8* buffer, Uint32 length, const char* filename) {
inline auto JA_LoadMusic(Uint8* buffer, Uint32 length, const char* filename) -> JA_Music_t* {
JA_Music_t* music = JA_LoadMusic(static_cast<const Uint8*>(buffer), length);
if (music && filename) music->filename = filename;
if ((music != nullptr) && (filename != nullptr)) {
music->filename = filename;
}
return music;
}
inline JA_Music_t* JA_LoadMusic(const char* filename) {
inline auto JA_LoadMusic(const char* filename) -> JA_Music_t* {
// Carreguem primer el arxiu en memòria i després el descomprimim.
FILE* f = fopen(filename, "rb");
if (!f) return nullptr;
if (f == nullptr) {
return nullptr;
}
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
auto* buffer = static_cast<Uint8*>(malloc(fsize + 1));
if (!buffer) {
if (buffer == nullptr) {
fclose(f);
return nullptr;
}
@@ -313,7 +352,7 @@ inline JA_Music_t* JA_LoadMusic(const char* filename) {
fclose(f);
JA_Music_t* music = JA_LoadMusic(static_cast<const Uint8*>(buffer), static_cast<Uint32>(fsize));
if (music) {
if (music != nullptr) {
music->filename = filename;
}
@@ -323,7 +362,9 @@ inline JA_Music_t* JA_LoadMusic(const char* filename) {
}
inline void JA_PlayMusic(JA_Music_t* music, const int loop = -1) {
if (!JA_musicEnabled || !music || !music->vorbis) return;
if (!JA_musicEnabled || (music == nullptr) || (music->vorbis == nullptr)) {
return;
}
JA_StopMusic();
@@ -336,7 +377,7 @@ inline void JA_PlayMusic(JA_Music_t* music, const int loop = -1) {
stb_vorbis_seek_start(current_music->vorbis);
current_music->stream = SDL_CreateAudioStream(&current_music->spec, &JA_audioSpec);
if (!current_music->stream) {
if (current_music->stream == nullptr) {
std::cout << "Failed to create audio stream!" << '\n';
current_music->state = JA_MUSIC_STOPPED;
return;
@@ -351,23 +392,35 @@ inline void JA_PlayMusic(JA_Music_t* music, const int loop = -1) {
}
}
inline const char* JA_GetMusicFilename(const JA_Music_t* music = nullptr) {
if (!music) music = current_music;
if (!music || music->filename.empty()) return nullptr;
inline auto JA_GetMusicFilename(const JA_Music_t* music = nullptr) -> const char* {
if (music == nullptr) {
music = current_music;
}
if ((music == nullptr) || music->filename.empty()) {
return nullptr;
}
return music->filename.c_str();
}
inline void JA_PauseMusic() {
if (!JA_musicEnabled) return;
if (!current_music || current_music->state != JA_MUSIC_PLAYING) return;
if (!JA_musicEnabled) {
return;
}
if ((current_music == nullptr) || current_music->state != JA_MUSIC_PLAYING) {
return;
}
current_music->state = JA_MUSIC_PAUSED;
SDL_UnbindAudioStream(current_music->stream);
}
inline void JA_ResumeMusic() {
if (!JA_musicEnabled) return;
if (!current_music || current_music->state != JA_MUSIC_PAUSED) return;
if (!JA_musicEnabled) {
return;
}
if ((current_music == nullptr) || current_music->state != JA_MUSIC_PAUSED) {
return;
}
current_music->state = JA_MUSIC_PLAYING;
SDL_BindAudioStream(sdlAudioDevice, current_music->stream);
@@ -375,33 +428,39 @@ inline void JA_ResumeMusic() {
inline void JA_StopMusic() {
// Limpiar outgoing crossfade si existe
if (outgoing_music.stream) {
if (outgoing_music.stream != nullptr) {
SDL_DestroyAudioStream(outgoing_music.stream);
outgoing_music.stream = nullptr;
outgoing_music.fade.active = false;
}
incoming_fade.active = false;
if (!current_music || current_music->state == JA_MUSIC_INVALID || current_music->state == JA_MUSIC_STOPPED) return;
if ((current_music == nullptr) || current_music->state == JA_MUSIC_INVALID || current_music->state == JA_MUSIC_STOPPED) {
return;
}
current_music->state = JA_MUSIC_STOPPED;
if (current_music->stream) {
if (current_music->stream != nullptr) {
SDL_DestroyAudioStream(current_music->stream);
current_music->stream = nullptr;
}
// Deixem el handle de vorbis viu — es tanca en JA_DeleteMusic.
// Rebobinem perquè un futur JA_PlayMusic comence des del principi.
if (current_music->vorbis) {
if (current_music->vorbis != nullptr) {
stb_vorbis_seek_start(current_music->vorbis);
}
}
inline void JA_FadeOutMusic(const int milliseconds) {
if (!JA_musicEnabled) return;
if (!current_music || current_music->state != JA_MUSIC_PLAYING) return;
if (!JA_musicEnabled) {
return;
}
if ((current_music == nullptr) || current_music->state != JA_MUSIC_PLAYING) {
return;
}
// Destruir outgoing anterior si existe
if (outgoing_music.stream) {
if (outgoing_music.stream != nullptr) {
SDL_DestroyAudioStream(outgoing_music.stream);
outgoing_music.stream = nullptr;
}
@@ -412,20 +471,24 @@ inline void JA_FadeOutMusic(const int milliseconds) {
// Robar el stream del current_music al outgoing
outgoing_music.stream = current_music->stream;
outgoing_music.fade = {true, SDL_GetTicks(), milliseconds, JA_musicVolume};
outgoing_music.fade = {.active = true, .start_time = SDL_GetTicks(), .duration_ms = milliseconds, .initial_volume = JA_musicVolume};
// Dejar current_music sin stream (ya lo tiene outgoing)
current_music->stream = nullptr;
current_music->state = JA_MUSIC_STOPPED;
if (current_music->vorbis) stb_vorbis_seek_start(current_music->vorbis);
if (current_music->vorbis != nullptr) {
stb_vorbis_seek_start(current_music->vorbis);
}
incoming_fade.active = false;
}
inline void JA_CrossfadeMusic(JA_Music_t* music, const int crossfade_ms, const int loop) {
if (!JA_musicEnabled || !music || !music->vorbis) return;
if (!JA_musicEnabled || (music == nullptr) || (music->vorbis == nullptr)) {
return;
}
// Destruir outgoing anterior si existe (crossfade durante crossfade)
if (outgoing_music.stream) {
if (outgoing_music.stream != nullptr) {
SDL_DestroyAudioStream(outgoing_music.stream);
outgoing_music.stream = nullptr;
outgoing_music.fade.active = false;
@@ -434,13 +497,15 @@ inline void JA_CrossfadeMusic(JA_Music_t* music, const int crossfade_ms, const i
// Robar el stream de la musica actual al outgoing para el fade-out.
// Pre-omplim amb `crossfade_ms` de so perquè no es quede en silenci
// abans d'acabar el fade (l'stream robat ja no pot alimentar-se).
if (current_music && current_music->state == JA_MUSIC_PLAYING && current_music->stream) {
if ((current_music != nullptr) && current_music->state == JA_MUSIC_PLAYING && (current_music->stream != nullptr)) {
JA_PreFillOutgoing(current_music, crossfade_ms);
outgoing_music.stream = current_music->stream;
outgoing_music.fade = {true, SDL_GetTicks(), crossfade_ms, JA_musicVolume};
outgoing_music.fade = {.active = true, .start_time = SDL_GetTicks(), .duration_ms = crossfade_ms, .initial_volume = JA_musicVolume};
current_music->stream = nullptr;
current_music->state = JA_MUSIC_STOPPED;
if (current_music->vorbis) stb_vorbis_seek_start(current_music->vorbis);
if (current_music->vorbis != nullptr) {
stb_vorbis_seek_start(current_music->vorbis);
}
}
// Iniciar la nueva pista con gain=0 (el fade-in la sube gradualmente)
@@ -450,42 +515,52 @@ inline void JA_CrossfadeMusic(JA_Music_t* music, const int crossfade_ms, const i
stb_vorbis_seek_start(current_music->vorbis);
current_music->stream = SDL_CreateAudioStream(&current_music->spec, &JA_audioSpec);
if (!current_music->stream) {
if (current_music->stream == nullptr) {
std::cout << "Failed to create audio stream for crossfade!" << '\n';
current_music->state = JA_MUSIC_STOPPED;
return;
}
SDL_SetAudioStreamGain(current_music->stream, 0.0f);
SDL_SetAudioStreamGain(current_music->stream, 0.0F);
JA_PumpMusic(current_music); // pre-carrega abans de bindejar
SDL_BindAudioStream(sdlAudioDevice, current_music->stream);
// Configurar fade-in
incoming_fade = {true, SDL_GetTicks(), crossfade_ms, 0.0f};
incoming_fade = {.active = true, .start_time = SDL_GetTicks(), .duration_ms = crossfade_ms, .initial_volume = 0.0F};
}
inline JA_Music_state JA_GetMusicState() {
if (!JA_musicEnabled) return JA_MUSIC_DISABLED;
if (!current_music) return JA_MUSIC_INVALID;
inline auto JA_GetMusicState() -> JA_Music_state {
if (!JA_musicEnabled) {
return JA_MUSIC_DISABLED;
}
if (current_music == nullptr) {
return JA_MUSIC_INVALID;
}
return current_music->state;
}
inline void JA_DeleteMusic(JA_Music_t* music) {
if (!music) return;
if (music == nullptr) {
return;
}
if (current_music == music) {
JA_StopMusic();
current_music = nullptr;
}
if (music->stream) SDL_DestroyAudioStream(music->stream);
if (music->vorbis) stb_vorbis_close(music->vorbis);
if (music->stream != nullptr) {
SDL_DestroyAudioStream(music->stream);
}
if (music->vorbis != nullptr) {
stb_vorbis_close(music->vorbis);
}
// ogg_data (std::vector) i filename (std::string) s'alliberen sols
// al destructor de JA_Music_t.
delete music;
}
inline float JA_SetMusicVolume(float volume) {
JA_musicVolume = SDL_clamp(volume, 0.0f, 1.0f);
if (current_music && current_music->stream) {
inline auto JA_SetMusicVolume(float volume) -> float {
JA_musicVolume = SDL_clamp(volume, 0.0F, 1.0F);
if ((current_music != nullptr) && (current_music->stream != nullptr)) {
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume);
}
return JA_musicVolume;
@@ -495,18 +570,20 @@ inline void JA_SetMusicPosition(float /*value*/) {
// No implementat amb el backend de streaming.
}
inline float JA_GetMusicPosition() {
return 0.0f;
inline auto JA_GetMusicPosition() -> float {
return 0.0F;
}
inline void JA_EnableMusic(const bool value) {
if (!value && current_music && (current_music->state == JA_MUSIC_PLAYING)) JA_StopMusic();
if (!value && (current_music != nullptr) && (current_music->state == JA_MUSIC_PLAYING)) {
JA_StopMusic();
}
JA_musicEnabled = value;
}
// --- Sound Functions ---
inline JA_Sound_t* JA_LoadSound(uint8_t* buffer, uint32_t size) {
inline auto JA_LoadSound(uint8_t* buffer, uint32_t size) -> JA_Sound_t* {
auto sound = std::make_unique<JA_Sound_t>();
Uint8* raw = nullptr;
if (!SDL_LoadWAV_IO(SDL_IOFromMem(buffer, size), 1, &sound->spec, &raw, &sound->length)) {
@@ -517,7 +594,7 @@ inline JA_Sound_t* JA_LoadSound(uint8_t* buffer, uint32_t size) {
return sound.release();
}
inline JA_Sound_t* JA_LoadSound(const char* filename) {
inline auto JA_LoadSound(const char* filename) -> JA_Sound_t* {
auto sound = std::make_unique<JA_Sound_t>();
Uint8* raw = nullptr;
if (!SDL_LoadWAV(filename, &sound->spec, &raw, &sound->length)) {
@@ -528,8 +605,10 @@ inline JA_Sound_t* JA_LoadSound(const char* filename) {
return sound.release();
}
inline int JA_PlaySound(JA_Sound_t* sound, const int loop = 0, const int group = 0) {
if (!JA_soundEnabled || !sound) return -1;
inline auto JA_PlaySound(JA_Sound_t* sound, const int loop = 0, const int group = 0) -> int {
if (!JA_soundEnabled || (sound == nullptr)) {
return -1;
}
int channel = 0;
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; }
@@ -541,9 +620,13 @@ inline int JA_PlaySound(JA_Sound_t* sound, const int loop = 0, const int group =
return JA_PlaySoundOnChannel(sound, channel, loop, group);
}
inline int JA_PlaySoundOnChannel(JA_Sound_t* sound, const int channel, const int loop, const int group) {
if (!JA_soundEnabled || !sound) return -1;
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return -1;
inline auto JA_PlaySoundOnChannel(JA_Sound_t* sound, const int channel, const int loop, const int group) -> int {
if (!JA_soundEnabled || (sound == nullptr)) {
return -1;
}
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) {
return -1;
}
JA_StopChannel(channel);
@@ -554,7 +637,7 @@ inline int JA_PlaySoundOnChannel(JA_Sound_t* sound, const int channel, const int
channels[channel].state = JA_CHANNEL_PLAYING;
channels[channel].stream = SDL_CreateAudioStream(&channels[channel].sound->spec, &JA_audioSpec);
if (!channels[channel].stream) {
if (channels[channel].stream == nullptr) {
std::cout << "Failed to create audio stream for sound!" << '\n';
channels[channel].state = JA_CHANNEL_FREE;
return -1;
@@ -568,23 +651,30 @@ inline int JA_PlaySoundOnChannel(JA_Sound_t* sound, const int channel, const int
}
inline void JA_DeleteSound(JA_Sound_t* sound) {
if (!sound) return;
if (sound == nullptr) {
return;
}
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].sound == sound) JA_StopChannel(i);
if (channels[i].sound == sound) {
JA_StopChannel(i);
}
}
// buffer es destrueix automàticament via RAII (SDLFreeDeleter).
delete sound;
}
inline void JA_PauseChannel(const int channel) {
if (!JA_soundEnabled) return;
if (!JA_soundEnabled) {
return;
}
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
if (channels[i].state == JA_CHANNEL_PLAYING) {
channels[i].state = JA_CHANNEL_PAUSED;
SDL_UnbindAudioStream(channels[i].stream);
for (auto& channel : channels) {
if (channel.state == JA_CHANNEL_PLAYING) {
channel.state = JA_CHANNEL_PAUSED;
SDL_UnbindAudioStream(channel.stream);
}
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
if (channels[channel].state == JA_CHANNEL_PLAYING) {
channels[channel].state = JA_CHANNEL_PAUSED;
@@ -594,14 +684,17 @@ inline void JA_PauseChannel(const int channel) {
}
inline void JA_ResumeChannel(const int channel) {
if (!JA_soundEnabled) return;
if (!JA_soundEnabled) {
return;
}
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
if (channels[i].state == JA_CHANNEL_PAUSED) {
channels[i].state = JA_CHANNEL_PLAYING;
SDL_BindAudioStream(sdlAudioDevice, channels[i].stream);
for (auto& channel : channels) {
if (channel.state == JA_CHANNEL_PAUSED) {
channel.state = JA_CHANNEL_PLAYING;
SDL_BindAudioStream(sdlAudioDevice, channel.stream);
}
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
if (channels[channel].state == JA_CHANNEL_PAUSED) {
channels[channel].state = JA_CHANNEL_PLAYING;
@@ -612,18 +705,22 @@ inline void JA_ResumeChannel(const int channel) {
inline void JA_StopChannel(const int channel) {
if (channel == -1) {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if (channels[i].state != JA_CHANNEL_FREE) {
if (channels[i].stream) SDL_DestroyAudioStream(channels[i].stream);
channels[i].stream = nullptr;
channels[i].state = JA_CHANNEL_FREE;
channels[i].pos = 0;
channels[i].sound = nullptr;
for (auto& channel : channels) {
if (channel.state != JA_CHANNEL_FREE) {
if (channel.stream != nullptr) {
SDL_DestroyAudioStream(channel.stream);
}
channel.stream = nullptr;
channel.state = JA_CHANNEL_FREE;
channel.pos = 0;
channel.sound = nullptr;
}
}
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
if (channels[channel].state != JA_CHANNEL_FREE) {
if (channels[channel].stream) SDL_DestroyAudioStream(channels[channel].stream);
if (channels[channel].stream != nullptr) {
SDL_DestroyAudioStream(channels[channel].stream);
}
channels[channel].stream = nullptr;
channels[channel].state = JA_CHANNEL_FREE;
channels[channel].pos = 0;
@@ -632,19 +729,23 @@ inline void JA_StopChannel(const int channel) {
}
}
inline JA_Channel_state JA_GetChannelState(const int channel) {
if (!JA_soundEnabled) return JA_SOUND_DISABLED;
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID;
inline auto JA_GetChannelState(const int channel) -> JA_Channel_state {
if (!JA_soundEnabled) {
return JA_SOUND_DISABLED;
}
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) {
return JA_CHANNEL_INVALID;
}
return channels[channel].state;
}
inline float JA_SetSoundVolume(float volume, const int group = -1) {
const float v = SDL_clamp(volume, 0.0f, 1.0f);
inline auto JA_SetSoundVolume(float volume, const int group = -1) -> float {
const float v = SDL_clamp(volume, 0.0F, 1.0F);
if (group == -1) {
for (int i = 0; i < JA_MAX_GROUPS; ++i) {
JA_soundVolume[i] = v;
for (float& i : JA_soundVolume) {
i = v;
}
} else if (group >= 0 && group < JA_MAX_GROUPS) {
JA_soundVolume[group] = v;
@@ -653,11 +754,11 @@ inline float JA_SetSoundVolume(float volume, const int group = -1) {
}
// Aplicar volum als canals actius.
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
if ((channels[i].state == JA_CHANNEL_PLAYING) || (channels[i].state == JA_CHANNEL_PAUSED)) {
if (group == -1 || channels[i].group == group) {
if (channels[i].stream) {
SDL_SetAudioStreamGain(channels[i].stream, JA_soundVolume[channels[i].group]);
for (auto& channel : channels) {
if ((channel.state == JA_CHANNEL_PLAYING) || (channel.state == JA_CHANNEL_PAUSED)) {
if (group == -1 || channel.group == group) {
if (channel.stream != nullptr) {
SDL_SetAudioStreamGain(channel.stream, JA_soundVolume[channel.group]);
}
}
}
@@ -672,7 +773,7 @@ inline void JA_EnableSound(const bool value) {
JA_soundEnabled = value;
}
inline float JA_SetVolume(float volume) {
inline auto JA_SetVolume(float volume) -> float {
float v = JA_SetMusicVolume(volume);
JA_SetSoundVolume(v, -1);
return v;
+38 -49
View File
@@ -4,6 +4,7 @@
#include <algorithm> // for any_of
#include <iostream> // for basic_ostream, operator<<, cout, basi...
#include <utility>
// Emscripten-only: SDL 3.4+ ja no casa el GUID dels mandos de Chrome Android
// amb gamecontrollerdb (el gamepad.id d'Android no porta Vendor/Product, el
@@ -58,12 +59,8 @@ auto Input::get() -> Input * {
}
// Constructor
Input::Input(const std::string &file)
: numGamepads(0),
dbPath(file),
verbose(true),
disabledUntil(d_notDisabled),
enabled(true) {
Input::Input(std::string file)
: dbPath(std::move(file)) {
// Inicializa las variables
keyBindings_t kb;
kb.scancode = 0;
@@ -107,7 +104,7 @@ void Input::bindGameControllerButton(Uint8 input, SDL_GamepadButton button) {
}
// Comprueba si un input esta activo
bool Input::checkInput(Uint8 input, bool repeat, int device, int index) {
auto Input::checkInput(Uint8 input, bool repeat, int device, int index) -> bool {
if (!enabled) {
return false;
}
@@ -123,11 +120,7 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index) {
const bool *keyStates = SDL_GetKeyboardState(nullptr);
if (repeat) {
if (keyStates[keyBindings[input].scancode]) {
successKeyboard = true;
} else {
successKeyboard = false;
}
successKeyboard = keyStates[keyBindings[input].scancode];
} else {
if (!keyBindings[input].active) {
if (keyStates[keyBindings[input].scancode]) {
@@ -147,14 +140,10 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index) {
}
}
if (gameControllerFound() && index >= 0 && index < (int)connectedControllers.size())
if (gameControllerFound() && index >= 0 && index < (int)connectedControllers.size()) {
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY)) {
if (repeat) {
if (SDL_GetGamepadButton(connectedControllers[index], gameControllerBindings[input].button)) {
successGameController = true;
} else {
successGameController = false;
}
successGameController = SDL_GetGamepadButton(connectedControllers[index], gameControllerBindings[input].button);
} else {
if (!gameControllerBindings[input].active) {
if (SDL_GetGamepadButton(connectedControllers[index], gameControllerBindings[input].button)) {
@@ -173,12 +162,13 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index) {
}
}
}
}
return (successKeyboard || successGameController);
}
// Comprueba si hay almenos un input activo
bool Input::checkAnyInput(int device, int index) {
auto Input::checkAnyInput(int device, int index) -> bool {
if (device == INPUT_USE_ANY) {
index = 0;
}
@@ -186,8 +176,8 @@ bool Input::checkAnyInput(int device, int index) {
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY) {
const bool *mKeystates = SDL_GetKeyboardState(nullptr);
for (int i = 0; i < (int)keyBindings.size(); ++i) {
if (mKeystates[keyBindings[i].scancode]) {
for (auto &keyBinding : keyBindings) {
if (mKeystates[keyBinding.scancode]) {
return true;
}
}
@@ -195,8 +185,8 @@ bool Input::checkAnyInput(int device, int index) {
if (gameControllerFound() && index >= 0 && index < (int)connectedControllers.size()) {
if (device == INPUT_USE_GAMECONTROLLER || device == INPUT_USE_ANY) {
for (int i = 0; i < (int)gameControllerBindings.size(); ++i) {
if (SDL_GetGamepadButton(connectedControllers[index], gameControllerBindings[i].button)) {
for (auto &gameControllerBinding : gameControllerBindings) {
if (SDL_GetGamepadButton(connectedControllers[index], gameControllerBinding.button)) {
return true;
}
}
@@ -209,10 +199,10 @@ bool Input::checkAnyInput(int device, int index) {
// Construye el nombre visible de un mando.
// Recorta des del primer '(' o '[' (per a evitar coses tipus
// "Retroid Controller (vendor: 1001) ...") i talla a 25 caràcters.
std::string Input::buildControllerName(SDL_Gamepad *pad, int padIndex) {
auto Input::buildControllerName(SDL_Gamepad *pad, int padIndex) -> std::string {
(void)padIndex;
const char *padName = SDL_GetGamepadName(pad);
std::string name = padName ? padName : "Unknown";
std::string name = (padName != nullptr) ? padName : "Unknown";
const auto pos = name.find_first_of("([");
if (pos != std::string::npos) {
name.erase(pos);
@@ -228,7 +218,7 @@ std::string Input::buildControllerName(SDL_Gamepad *pad, int padIndex) {
// Busca si hay un mando conectado. Cierra y limpia el estado previo para
// que la función sea idempotente si se invoca más de una vez.
bool Input::discoverGameController() {
auto Input::discoverGameController() -> bool {
// Cierra los mandos ya abiertos y limpia los vectores paralelos
for (auto *pad : connectedControllers) {
if (pad != nullptr) {
@@ -248,14 +238,14 @@ bool Input::discoverGameController() {
if (SDL_AddGamepadMappingsFromFile(dbPath.c_str()) < 0) {
if (verbose) {
std::cout << "Error, could not load " << dbPath.c_str() << " file: " << SDL_GetError() << std::endl;
std::cout << "Error, could not load " << dbPath.c_str() << " file: " << SDL_GetError() << '\n';
}
}
int nJoysticks = 0;
SDL_JoystickID *joysticks = SDL_GetJoysticks(&nJoysticks);
if (joysticks) {
if (joysticks != nullptr) {
int gamepadCount = 0;
for (int i = 0; i < nJoysticks; ++i) {
if (SDL_IsGamepad(joysticks[i])) {
@@ -273,7 +263,9 @@ bool Input::discoverGameController() {
int padIndex = 0;
for (int i = 0; i < nJoysticks; i++) {
if (!SDL_IsGamepad(joysticks[i])) continue;
if (!SDL_IsGamepad(joysticks[i])) {
continue;
}
installWebStandardMapping(joysticks[i]);
SDL_Gamepad *pad = SDL_OpenGamepad(joysticks[i]);
@@ -285,11 +277,11 @@ bool Input::discoverGameController() {
numGamepads++;
padIndex++;
if (verbose) {
std::cout << name << std::endl;
std::cout << name << '\n';
}
} else {
if (verbose) {
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
std::cout << "SDL_GetError() = " << SDL_GetError() << '\n';
}
}
}
@@ -304,13 +296,13 @@ bool Input::discoverGameController() {
}
// Procesa un evento SDL_EVENT_GAMEPAD_ADDED
bool Input::handleGamepadAdded(SDL_JoystickID jid, std::string &outName) {
auto Input::handleGamepadAdded(SDL_JoystickID jid, std::string &outName) -> bool {
if (!SDL_IsGamepad(jid)) {
return false;
}
// Si el mando ya está registrado no hace nada (ej. evento retroactivo tras el scan inicial)
if (std::any_of(connectedControllerIds.begin(), connectedControllerIds.end(), [jid](SDL_JoystickID existing) { return existing == jid; })) {
if (std::ranges::any_of(connectedControllerIds, [jid](SDL_JoystickID existing) { return existing == jid; })) {
return false;
}
@@ -318,7 +310,7 @@ bool Input::handleGamepadAdded(SDL_JoystickID jid, std::string &outName) {
SDL_Gamepad *pad = SDL_OpenGamepad(jid);
if (pad == nullptr) {
if (verbose) {
std::cout << "Failed to open gamepad " << jid << ": " << SDL_GetError() << std::endl;
std::cout << "Failed to open gamepad " << jid << ": " << SDL_GetError() << '\n';
}
return false;
}
@@ -331,7 +323,7 @@ bool Input::handleGamepadAdded(SDL_JoystickID jid, std::string &outName) {
numGamepads++;
if (verbose) {
std::cout << "Gamepad connected: " << name << std::endl;
std::cout << "Gamepad connected: " << name << '\n';
}
outName = name;
@@ -339,9 +331,11 @@ bool Input::handleGamepadAdded(SDL_JoystickID jid, std::string &outName) {
}
// Procesa un evento SDL_EVENT_GAMEPAD_REMOVED
bool Input::handleGamepadRemoved(SDL_JoystickID jid, std::string &outName) {
auto Input::handleGamepadRemoved(SDL_JoystickID jid, std::string &outName) -> bool {
for (size_t i = 0; i < connectedControllerIds.size(); ++i) {
if (connectedControllerIds[i] != jid) continue;
if (connectedControllerIds[i] != jid) {
continue;
}
outName = controllerNames[i];
if (connectedControllers[i] != nullptr) {
@@ -351,10 +345,10 @@ bool Input::handleGamepadRemoved(SDL_JoystickID jid, std::string &outName) {
connectedControllerIds.erase(connectedControllerIds.begin() + i);
controllerNames.erase(controllerNames.begin() + i);
numGamepads--;
if (numGamepads < 0) numGamepads = 0;
numGamepads = std::max(numGamepads, 0);
if (verbose) {
std::cout << "Gamepad disconnected: " << outName << std::endl;
std::cout << "Gamepad disconnected: " << outName << '\n';
}
return true;
@@ -363,25 +357,20 @@ bool Input::handleGamepadRemoved(SDL_JoystickID jid, std::string &outName) {
}
// Comprueba si hay algun mando conectado
bool Input::gameControllerFound() {
if (numGamepads > 0) {
return true;
} else {
return false;
}
auto Input::gameControllerFound() const -> bool {
return numGamepads > 0;
}
// Obten el nombre de un mando de juego
std::string Input::getControllerName(int index) {
auto Input::getControllerName(int index) -> std::string {
if (numGamepads > 0) {
return controllerNames[index];
} else {
return "";
}
return "";
}
// Obten el numero de mandos conectados
int Input::getNumControllers() {
auto Input::getNumControllers() const -> int {
return numGamepads;
}
+19 -18
View File
@@ -2,8 +2,9 @@
#include <SDL3/SDL.h>
#include <string> // for string, basic_string
#include <vector> // for vector
#include <cstdint> // for uint8_t
#include <string> // for string, basic_string
#include <vector> // for vector
// Valores de repetición
constexpr bool REPEAT_TRUE = true;
@@ -14,7 +15,7 @@ constexpr int INPUT_USE_KEYBOARD = 0;
constexpr int INPUT_USE_GAMECONTROLLER = 1;
constexpr int INPUT_USE_ANY = 2;
enum inputs_e {
enum inputs_e : std::uint8_t {
// Inputs obligatorios
input_null,
input_up,
@@ -43,7 +44,7 @@ enum inputs_e {
input_number_of_inputs
};
enum i_disable_e {
enum i_disable_e : std::uint8_t {
d_notDisabled,
d_forever,
d_keyPressed
@@ -69,17 +70,17 @@ class Input {
std::vector<keyBindings_t> keyBindings; // Vector con las teclas asociadas a los inputs predefinidos
std::vector<GameControllerBindings_t> gameControllerBindings; // Vector con las teclas asociadas a los inputs predefinidos
std::vector<std::string> controllerNames; // Vector con los nombres de los mandos
int numGamepads; // Numero de mandos conectados
int numGamepads{0}; // Numero de mandos conectados
std::string dbPath; // Ruta al archivo gamecontrollerdb.txt
bool verbose; // Indica si ha de mostrar mensajes
i_disable_e disabledUntil; // Tiempo que esta deshabilitado
bool enabled; // Indica si está habilitado
bool verbose{true}; // Indica si ha de mostrar mensajes
i_disable_e disabledUntil{d_notDisabled}; // Tiempo que esta deshabilitado
bool enabled{true}; // Indica si está habilitado
// Construye el nombre visible de un mando (name truncado + sufijo #N)
std::string buildControllerName(SDL_Gamepad *pad, int padIndex);
static auto buildControllerName(SDL_Gamepad *pad, int padIndex) -> std::string;
// Constructor privado (usar Input::init)
explicit Input(const std::string &file);
explicit Input(std::string file);
// Instancia única
static Input *instance;
@@ -103,30 +104,30 @@ class Input {
void bindGameControllerButton(Uint8 input, SDL_GamepadButton button);
// Comprueba si un input esta activo
bool checkInput(Uint8 input, bool repeat = true, int device = INPUT_USE_ANY, int index = 0);
auto checkInput(Uint8 input, bool repeat = true, int device = INPUT_USE_ANY, int index = 0) -> bool;
// Comprueba si hay almenos un input activo
bool checkAnyInput(int device = INPUT_USE_ANY, int index = 0);
auto checkAnyInput(int device = INPUT_USE_ANY, int index = 0) -> bool;
// Busca si hay un mando conectado
bool discoverGameController();
auto discoverGameController() -> bool;
// Procesa un evento SDL_EVENT_GAMEPAD_ADDED. Devuelve true si el mando se ha añadido
// (no estaba ya registrado) y escribe el nombre visible en outName.
bool handleGamepadAdded(SDL_JoystickID jid, std::string &outName);
auto handleGamepadAdded(SDL_JoystickID jid, std::string &outName) -> bool;
// Procesa un evento SDL_EVENT_GAMEPAD_REMOVED. Devuelve true si se ha encontrado y
// eliminado, y escribe el nombre visible en outName.
bool handleGamepadRemoved(SDL_JoystickID jid, std::string &outName);
auto handleGamepadRemoved(SDL_JoystickID jid, std::string &outName) -> bool;
// Comprueba si hay algun mando conectado
bool gameControllerFound();
[[nodiscard]] auto gameControllerFound() const -> bool;
// Obten el numero de mandos conectados
int getNumControllers();
[[nodiscard]] auto getNumControllers() const -> int;
// Obten el nombre de un mando de juego
std::string getControllerName(int index);
auto getControllerName(int index) -> std::string;
// Establece si ha de mostrar mensajes
void setVerbose(bool value);
+7 -8
View File
@@ -24,15 +24,13 @@ auto Lang::get() -> Lang * {
}
// Constructor
Lang::Lang() {
}
Lang::Lang() = default;
// Destructor
Lang::~Lang() {
}
Lang::~Lang() = default;
// Inicializa los textos del juego en el idioma seleccionado
bool Lang::setLang(Uint8 lang) {
auto Lang::setLang(Uint8 lang) -> bool {
std::string file;
switch (lang) {
@@ -53,8 +51,9 @@ bool Lang::setLang(Uint8 lang) {
break;
}
for (int i = 0; i < MAX_TEXT_STRINGS; i++)
mTextStrings[i] = "";
for (auto &mTextString : mTextStrings) {
mTextString = "";
}
// Lee el fichero via ResourceHelper (pack o filesystem)
auto bytes = ResourceHelper::loadFile(file);
@@ -90,6 +89,6 @@ bool Lang::setLang(Uint8 lang) {
}
// Obtiene la cadena de texto del indice
std::string Lang::getText(int index) {
auto Lang::getText(int index) -> std::string {
return mTextStrings[index];
}
+2 -2
View File
@@ -34,8 +34,8 @@ class Lang {
~Lang();
// Inicializa los textos del juego en el idioma seleccionado
bool setLang(Uint8 lang);
auto setLang(Uint8 lang) -> bool;
// Obtiene la cadena de texto del indice
std::string getText(int index);
auto getText(int index) -> std::string;
};
+31 -27
View File
@@ -7,7 +7,7 @@
#include "core/rendering/texture.h" // for Texture
// Parser compartido: lee un istream con el formato .ani
static animatedSprite_t parseAnimationStream(std::istream &file, Texture *texture, const std::string &filename, bool verbose) {
static auto parseAnimationStream(std::istream &file, Texture *texture, const std::string &filename, bool verbose) -> animatedSprite_t {
animatedSprite_t as;
as.texture = texture;
int framesPerRow = 0;
@@ -17,13 +17,15 @@ static animatedSprite_t parseAnimationStream(std::istream &file, Texture *textur
std::string line;
if (verbose) {
std::cout << "Animation loaded: " << filename << std::endl;
std::cout << "Animation loaded: " << filename << '\n';
}
// Normalitza CRLF: fitxers .ani amb terminadors de Windows fan que
// line == "[animation]" no faci match i el parser entri en bucle
// infinit / no carregui cap animació.
auto strip_cr = [](std::string &s) {
if (!s.empty() && s.back() == '\r') s.pop_back();
if (!s.empty() && s.back() == '\r') {
s.pop_back();
}
};
while (std::getline(file, line)) {
@@ -37,10 +39,12 @@ static animatedSprite_t parseAnimationStream(std::istream &file, Texture *textur
buffer.completed = false;
do {
if (!std::getline(file, line)) break;
if (!std::getline(file, line)) {
break;
}
strip_cr(line);
int pos = line.find("=");
if (pos != (int)line.npos) {
int pos = line.find('=');
if (pos != (int)std::string::npos) {
if (line.substr(0, pos) == "name") {
buffer.name = line.substr(pos + 1, line.length());
} else if (line.substr(0, pos) == "speed") {
@@ -58,15 +62,15 @@ static animatedSprite_t parseAnimationStream(std::istream &file, Texture *textur
buffer.frames.push_back(rect);
}
} else {
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << '\n';
}
}
} while (line != "[/animation]");
as.animations.push_back(buffer);
} else {
int pos = line.find("=");
if (pos != (int)line.npos) {
int pos = line.find('=');
if (pos != (int)std::string::npos) {
if (line.substr(0, pos) == "framesPerRow") {
framesPerRow = std::stoi(line.substr(pos + 1, line.length()));
} else if (line.substr(0, pos) == "frameWidth") {
@@ -74,7 +78,7 @@ static animatedSprite_t parseAnimationStream(std::istream &file, Texture *textur
} else if (line.substr(0, pos) == "frameHeight") {
frameHeight = std::stoi(line.substr(pos + 1, line.length()));
} else {
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << '\n';
}
if (framesPerRow == 0 && frameWidth > 0) {
@@ -93,12 +97,12 @@ static animatedSprite_t parseAnimationStream(std::istream &file, Texture *textur
}
// Carga la animación desde un fichero
animatedSprite_t loadAnimationFromFile(Texture *texture, const std::string &filePath, bool verbose) {
auto loadAnimationFromFile(Texture *texture, const std::string &filePath, bool verbose) -> animatedSprite_t {
const std::string filename = filePath.substr(filePath.find_last_of("\\/") + 1);
std::ifstream file(filePath);
if (!file.good()) {
if (verbose) {
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl;
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << '\n';
}
animatedSprite_t as;
as.texture = texture;
@@ -108,7 +112,7 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, const std::string &file
}
// Carga la animación desde bytes en memoria
animatedSprite_t loadAnimationFromMemory(Texture *texture, const std::vector<uint8_t> &bytes, const std::string &nameForLogs, bool verbose) {
auto loadAnimationFromMemory(Texture *texture, const std::vector<uint8_t> &bytes, const std::string &nameForLogs, bool verbose) -> animatedSprite_t {
if (bytes.empty()) {
animatedSprite_t as;
as.texture = texture;
@@ -134,7 +138,7 @@ AnimatedSprite::AnimatedSprite(Texture *texture, SDL_Renderer *renderer, const s
animation.insert(animation.end(), as.animations.begin(), as.animations.end());
}
else if (buffer) {
else if (buffer != nullptr) {
loadFromVector(buffer);
}
}
@@ -159,7 +163,7 @@ AnimatedSprite::~AnimatedSprite() {
}
// Obtiene el indice de la animación a partir del nombre
int AnimatedSprite::getIndex(const std::string &name) {
auto AnimatedSprite::getIndex(const std::string &name) -> int {
int index = -1;
for (const auto &a : animation) {
@@ -169,7 +173,7 @@ int AnimatedSprite::getIndex(const std::string &name) {
}
}
std::cout << "** Warning: could not find \"" << name.c_str() << "\" animation" << std::endl;
std::cout << "** Warning: could not find \"" << name.c_str() << "\" animation" << '\n';
return -1;
}
@@ -205,7 +209,7 @@ void AnimatedSprite::animate() {
}
// Obtiene el numero de frames de la animación actual
int AnimatedSprite::getNumFrames() {
auto AnimatedSprite::getNumFrames() -> int {
return (int)animation[currentAnimation].frames.size();
}
@@ -260,22 +264,22 @@ void AnimatedSprite::setAnimationCompleted(int index, bool value) {
}
// Comprueba si ha terminado la animación
bool AnimatedSprite::animationIsCompleted() {
auto AnimatedSprite::animationIsCompleted() -> bool {
return animation[currentAnimation].completed;
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(const std::string &name, Uint8 index) {
auto AnimatedSprite::getAnimationClip(const std::string &name, Uint8 index) -> SDL_Rect {
return animation[getIndex(name)].frames[index];
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF) {
auto AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF) -> SDL_Rect {
return animation[indexA].frames[indexF];
}
// Carga la animación desde un vector
bool AnimatedSprite::loadFromVector(std::vector<std::string> *source) {
auto AnimatedSprite::loadFromVector(std::vector<std::string> *source) -> bool {
// Inicializa variables
int framesPerRow = 0;
int frameWidth = 0;
@@ -307,10 +311,10 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source) {
line = source->at(index);
// Encuentra la posición del caracter '='
int pos = line.find("=");
int pos = line.find('=');
// Procesa las dos subcadenas
if (pos != (int)line.npos) {
if (pos != (int)std::string::npos) {
if (line.substr(0, pos) == "name") {
buffer.name = line.substr(pos + 1, line.length());
}
@@ -338,7 +342,7 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source) {
}
else {
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl;
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << '\n';
success = false;
}
}
@@ -351,10 +355,10 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source) {
// En caso contrario se parsea el fichero para buscar las variables y los valores
else {
// Encuentra la posición del caracter '='
int pos = line.find("=");
int pos = line.find('=');
// Procesa las dos subcadenas
if (pos != (int)line.npos) {
if (pos != (int)std::string::npos) {
if (line.substr(0, pos) == "framesPerRow") {
framesPerRow = std::stoi(line.substr(pos + 1, line.length()));
}
@@ -368,7 +372,7 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source) {
}
else {
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl;
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << '\n';
success = false;
}
+8 -8
View File
@@ -25,10 +25,10 @@ struct animatedSprite_t {
};
// Carga la animación desde un fichero
animatedSprite_t loadAnimationFromFile(Texture *texture, const std::string &filePath, bool verbose = false);
auto loadAnimationFromFile(Texture *texture, const std::string &filePath, bool verbose = false) -> animatedSprite_t;
// Carga la animación desde bytes en memoria
animatedSprite_t loadAnimationFromMemory(Texture *texture, const std::vector<uint8_t> &bytes, const std::string &nameForLogs = "", bool verbose = false);
auto loadAnimationFromMemory(Texture *texture, const std::vector<uint8_t> &bytes, const std::string &nameForLogs = "", bool verbose = false) -> animatedSprite_t;
class AnimatedSprite : public MovingSprite {
private:
@@ -48,7 +48,7 @@ class AnimatedSprite : public MovingSprite {
void animate();
// Obtiene el numero de frames de la animación actual
int getNumFrames();
auto getNumFrames() -> int;
// Establece el frame actual de la animación
void setCurrentFrame(int num);
@@ -69,17 +69,17 @@ class AnimatedSprite : public MovingSprite {
void setAnimationCompleted(int index, bool value);
// Comprueba si ha terminado la animación
bool animationIsCompleted();
auto animationIsCompleted() -> bool;
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect getAnimationClip(const std::string &name = "default", Uint8 index = 0);
SDL_Rect getAnimationClip(int indexA = 0, Uint8 indexF = 0);
auto getAnimationClip(const std::string &name = "default", Uint8 index = 0) -> SDL_Rect;
auto getAnimationClip(int indexA = 0, Uint8 indexF = 0) -> SDL_Rect;
// Obtiene el indice de la animación a partir del nombre
int getIndex(const std::string &name);
auto getIndex(const std::string &name) -> int;
// Carga la animación desde un vector
bool loadFromVector(std::vector<std::string> *source);
auto loadFromVector(std::vector<std::string> *source) -> bool;
// Establece la animacion actual
void setCurrentAnimation(const std::string &name = "default");
+8 -6
View File
@@ -1,8 +1,8 @@
#include "core/rendering/fade.h"
#include <SDL3/SDL.h>
#include <stdlib.h> // for rand
#include <cstdlib> // for rand
#include <iostream> // for char_traits, basic_ostream, operator<<
#include "game/defaults.hpp" // for GAMECANVAS_HEIGHT, GAMECANVAS_WIDTH
@@ -15,7 +15,7 @@ Fade::Fade(SDL_Renderer *renderer)
SDL_SetTextureScaleMode(mBackbuffer, SDL_SCALEMODE_NEAREST);
}
if (mBackbuffer == nullptr) {
std::cout << "Error: textTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
std::cout << "Error: textTexture could not be created!\nSDL Error: " << SDL_GetError() << '\n';
}
}
@@ -92,8 +92,9 @@ void Fade::render() {
SDL_RenderFillRect(mRenderer, &fR2);
}
if ((mCounter * 4) > GAMECANVAS_HEIGHT)
if ((mCounter * 4) > GAMECANVAS_HEIGHT) {
mFinished = true;
}
break;
}
@@ -145,8 +146,9 @@ void Fade::render() {
// Actualiza las variables internas
void Fade::update() {
if (mEnabled)
if (mEnabled) {
mCounter++;
}
}
// Activa el fade
@@ -163,12 +165,12 @@ void Fade::activateFade() {
}
// Comprueba si está activo
bool Fade::isEnabled() {
auto Fade::isEnabled() const -> bool {
return mEnabled;
}
// Comprueba si ha terminado la transicion
bool Fade::hasEnded() {
auto Fade::hasEnded() const -> bool {
return mFinished;
}
+2 -2
View File
@@ -44,10 +44,10 @@ class Fade {
void activateFade();
// Comprueba si ha terminado la transicion
bool hasEnded();
[[nodiscard]] auto hasEnded() const -> bool;
// Comprueba si está activo
bool isEnabled();
[[nodiscard]] auto isEnabled() const -> bool;
// Establece el tipo de fade
void setFadeType(Uint8 fadeType);
+26 -34
View File
@@ -12,31 +12,22 @@ MovingSprite::MovingSprite(float x, float y, int w, int h, float velx, float vel
vx(velx),
vy(vely),
ax(accelx),
ay(accely),
zoomW(1),
zoomH(1),
angle(0.0),
rotateEnabled(false),
rotateSpeed(0),
rotateAmount(0.0),
counter(0),
center(nullptr),
currentFlip(SDL_FLIP_NONE) {
ay(accely) {
}
// Reinicia todas las variables
void MovingSprite::clear() {
x = 0.0f; // Posición en el eje X
y = 0.0f; // Posición en el eje Y
x = 0.0F; // Posición en el eje X
y = 0.0F; // Posición en el eje Y
vx = 0.0f; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
vy = 0.0f; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
vx = 0.0F; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
vy = 0.0F; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
ax = 0.0f; // Aceleración en el eje X. Variación de la velocidad
ay = 0.0f; // Aceleración en el eje Y. Variación de la velocidad
ax = 0.0F; // Aceleración en el eje X. Variación de la velocidad
ay = 0.0F; // Aceleración en el eje Y. Variación de la velocidad
zoomW = 1.0f; // Zoom aplicado a la anchura
zoomH = 1.0f; // Zoom aplicado a la altura
zoomW = 1.0F; // Zoom aplicado a la anchura
zoomH = 1.0F; // Zoom aplicado a la altura
angle = 0.0; // Angulo para dibujarlo
rotateEnabled = false; // Indica si ha de rotar
@@ -71,48 +62,48 @@ void MovingSprite::render() {
// Obtiene el valor de la variable
// cppcheck-suppress duplInheritedMember
float MovingSprite::getPosX() {
auto MovingSprite::getPosX() const -> float {
return x;
}
// Obtiene el valor de la variable
// cppcheck-suppress duplInheritedMember
float MovingSprite::getPosY() {
auto MovingSprite::getPosY() const -> float {
return y;
}
// Obtiene el valor de la variable
float MovingSprite::getVelX() {
auto MovingSprite::getVelX() const -> float {
return vx;
}
// Obtiene el valor de la variable
float MovingSprite::getVelY() {
auto MovingSprite::getVelY() const -> float {
return vy;
}
// Obtiene el valor de la variable
float MovingSprite::getAccelX() {
auto MovingSprite::getAccelX() const -> float {
return ax;
}
// Obtiene el valor de la variable
float MovingSprite::getAccelY() {
auto MovingSprite::getAccelY() const -> float {
return ay;
}
// Obtiene el valor de la variable
float MovingSprite::getZoomW() {
auto MovingSprite::getZoomW() const -> float {
return zoomW;
}
// Obtiene el valor de la variable
float MovingSprite::getZoomH() {
auto MovingSprite::getZoomH() const -> float {
return zoomH;
}
// Obtiene el valor de la variable
double MovingSprite::getAngle() {
auto MovingSprite::getAngle() const -> double {
return angle;
}
@@ -180,23 +171,24 @@ void MovingSprite::decAngle(double value) {
}
// Obtiene el valor de la variable
bool MovingSprite::getRotate() {
auto MovingSprite::getRotate() const -> bool {
return rotateEnabled;
}
// Obtiene el valor de la variable
Uint16 MovingSprite::getRotateSpeed() {
auto MovingSprite::getRotateSpeed() const -> Uint16 {
return rotateSpeed;
}
// Establece la rotacion
void MovingSprite::rotate() {
if (enabled)
if (enabled) {
if (rotateEnabled) {
if (counter % rotateSpeed == 0) {
incAngle(rotateAmount);
}
}
}
}
// Establece el valor de la variable
@@ -250,12 +242,12 @@ void MovingSprite::flip() {
}
// Obtiene el valor de la variable
SDL_FlipMode MovingSprite::getFlip() {
auto MovingSprite::getFlip() -> SDL_FlipMode {
return currentFlip;
}
// Devuelve el rectangulo donde está el sprite
SDL_Rect MovingSprite::getRect() {
auto MovingSprite::getRect() -> SDL_Rect {
const SDL_Rect rect = {(int)x, (int)y, w, h};
return rect;
}
@@ -278,10 +270,10 @@ void MovingSprite::undoMoveY() {
// Pone a cero las velocidades de desplacamiento
void MovingSprite::clearVel() {
vx = vy = 0.0f;
vx = vy = 0.0F;
}
// Devuelve el incremento en el eje X en pixels
int MovingSprite::getIncX() {
auto MovingSprite::getIncX() const -> int {
return (int)x - (int)xPrev;
}
+24 -24
View File
@@ -22,16 +22,16 @@ class MovingSprite : public Sprite {
float ax; // Aceleración en el eje X. Variación de la velocidad
float ay; // Aceleración en el eje Y. Variación de la velocidad
float zoomW; // Zoom aplicado a la anchura
float zoomH; // Zoom aplicado a la altura
float zoomW{1}; // Zoom aplicado a la anchura
float zoomH{1}; // Zoom aplicado a la altura
double angle; // Angulo para dibujarlo
bool rotateEnabled; // Indica si ha de rotar
int rotateSpeed; // Velocidad de giro
double rotateAmount; // Cantidad de grados a girar en cada iteración
int counter; // Contador interno
SDL_Point *center; // Centro de rotación
SDL_FlipMode currentFlip; // Indica como se voltea el sprite
double angle{0.0}; // Angulo para dibujarlo
bool rotateEnabled{false}; // Indica si ha de rotar
int rotateSpeed{0}; // Velocidad de giro
double rotateAmount{0.0}; // Cantidad de grados a girar en cada iteración
int counter{0}; // Contador interno
SDL_Point *center{nullptr}; // Centro de rotación
SDL_FlipMode currentFlip{SDL_FLIP_NONE}; // Indica como se voltea el sprite
public:
// Constructor
@@ -54,38 +54,38 @@ class MovingSprite : public Sprite {
// Obten el valor de la variable
// cppcheck-suppress duplInheritedMember
float getPosX();
[[nodiscard]] auto getPosX() const -> float;
// Obten el valor de la variable
// cppcheck-suppress duplInheritedMember
float getPosY();
[[nodiscard]] auto getPosY() const -> float;
// Obten el valor de la variable
float getVelX();
[[nodiscard]] auto getVelX() const -> float;
// Obten el valor de la variable
float getVelY();
[[nodiscard]] auto getVelY() const -> float;
// Obten el valor de la variable
float getAccelX();
[[nodiscard]] auto getAccelX() const -> float;
// Obten el valor de la variable
float getAccelY();
[[nodiscard]] auto getAccelY() const -> float;
// Obten el valor de la variable
float getZoomW();
[[nodiscard]] auto getZoomW() const -> float;
// Obten el valor de la variable
float getZoomH();
[[nodiscard]] auto getZoomH() const -> float;
// Obten el valor de la variable
double getAngle();
[[nodiscard]] auto getAngle() const -> double;
// Obtiene el valor de la variable
bool getRotate();
[[nodiscard]] auto getRotate() const -> bool;
// Obtiene el valor de la variable
Uint16 getRotateSpeed();
[[nodiscard]] auto getRotateSpeed() const -> Uint16;
// Establece la posición y el tamaño del objeto
void setRect(SDL_Rect rect) override;
@@ -115,7 +115,7 @@ class MovingSprite : public Sprite {
void setZoomH(float value);
// Establece el valor de la variable
void setAngle(double vaue);
void setAngle(double value);
// Incrementa el valor de la variable
void incAngle(double value);
@@ -145,10 +145,10 @@ class MovingSprite : public Sprite {
void flip();
// Obtiene el valor de la variable
SDL_FlipMode getFlip();
auto getFlip() -> SDL_FlipMode;
// Devuelve el rectangulo donde está el sprite
SDL_Rect getRect() override;
auto getRect() -> SDL_Rect override;
// Deshace el último movimiento
void undoMove();
@@ -163,5 +163,5 @@ class MovingSprite : public Sprite {
void clearVel();
// Devuelve el incremento en el eje X en pixels
int getIncX();
[[nodiscard]] auto getIncX() const -> int;
};
+7 -6
View File
@@ -3,6 +3,7 @@
#include <SDL3/SDL.h>
#include <algorithm> // for max, min
#include <cmath> // for lround
#include <cstring> // for memcpy
#include <iostream> // for basic_ostream, operator<<, cout, endl
#include <string> // for basic_string, char_traits, string
@@ -108,7 +109,7 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer)
}
if (gameCanvas == nullptr) {
if (Options::settings.console) {
std::cout << "gameCanvas could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
std::cout << "gameCanvas could not be created!\nSDL Error: " << SDL_GetError() << '\n';
}
}
@@ -351,7 +352,7 @@ void Screen::applyFullscreen(bool fullscreen) {
void Screen::applyWindowedLayout() {
windowWidth = gameCanvasWidth;
windowHeight = gameCanvasHeight;
dest = {0, 0, gameCanvasWidth, gameCanvasHeight};
dest = {.x = 0, .y = 0, .w = gameCanvasWidth, .h = gameCanvasHeight};
#ifdef __EMSCRIPTEN__
windowWidth *= WASM_RENDER_SCALE;
@@ -396,12 +397,12 @@ void Screen::computeFullscreenGameRect() {
float ratio = (float)gameCanvasWidth / (float)gameCanvasHeight;
if ((windowWidth - gameCanvasWidth) >= (windowHeight - gameCanvasHeight)) {
dest.h = windowHeight;
dest.w = (int)((windowHeight * ratio) + 0.5f);
dest.w = static_cast<int>(std::lround(windowHeight * ratio));
dest.x = (windowWidth - dest.w) / 2;
dest.y = (windowHeight - dest.h) / 2;
} else {
dest.w = windowWidth;
dest.h = (int)((windowWidth / ratio) + 0.5f);
dest.h = static_cast<int>(std::lround(windowWidth / ratio));
dest.x = (windowWidth - dest.w) / 2;
dest.y = (windowHeight - dest.h) / 2;
}
@@ -579,7 +580,7 @@ void Screen::toggleShaderEnabled() {
setShaderEnabled(!Options::video.shader.enabled);
}
auto Screen::isShaderEnabled() const -> bool {
auto Screen::isShaderEnabled() -> bool {
return Options::video.shader.enabled;
}
@@ -595,7 +596,7 @@ void Screen::setActiveShader(Rendering::ShaderType type) {
notify(type == Rendering::ShaderType::CRTPI ? "Shader: CRTPI" : "Shader: POSTFX", MAGENTA, BLACK, DUR_MS);
}
auto Screen::getActiveShader() const -> Rendering::ShaderType {
auto Screen::getActiveShader() -> Rendering::ShaderType {
return Options::video.shader.current_shader;
}
#endif
+5 -5
View File
@@ -46,7 +46,7 @@ class Screen {
void setVideoMode(bool fullscreen); // Establece el modo de video
void toggleVideoMode(); // Cambia entre pantalla completa y ventana
void handleCanvasResized(); // En Emscripten, reaplica setVideoMode tras un cambio del navegador (salida de fullscreen con Esc, rotación). No-op fuera de Emscripten
void syncFullscreenFlagFromBrowser(bool isFullscreen); // Sincroniza el flag interno de fullscreen con el estado real del navegador. Debe llamarse antes de diferir handleCanvasResized. No-op fuera de Emscripten
static void syncFullscreenFlagFromBrowser(bool isFullscreen); // Sincroniza el flag interno de fullscreen con el estado real del navegador. Debe llamarse antes de diferir handleCanvasResized. No-op fuera de Emscripten
void toggleIntegerScale(); // Alterna el escalado entero
void setIntegerScale(bool enabled); // Establece el escalado entero
void toggleVSync(); // Alterna el V-Sync
@@ -66,13 +66,13 @@ class Screen {
// GPU / shaders (post-procesado). En builds con NO_SHADERS (Emscripten) son no-op.
void initShaders(); // Crea el backend GPU si no existe y lo inicializa
void shutdownShaders(); // Libera el backend GPU
auto isGpuAccelerated() const -> bool; // true si el backend existe y reporta hardware OK
[[nodiscard]] auto isGpuAccelerated() const -> bool; // true si el backend existe y reporta hardware OK
void setShaderEnabled(bool enabled); // Activa o desactiva el post-procesado (persiste)
void toggleShaderEnabled(); // Alterna post-procesado
auto isShaderEnabled() const -> bool; // Estado actual (lee options)
[[nodiscard]] static auto isShaderEnabled() -> bool; // Estado actual (lee options)
#ifndef NO_SHADERS
void setActiveShader(Rendering::ShaderType type); // POSTFX o CRTPI
auto getActiveShader() const -> Rendering::ShaderType;
[[nodiscard]] static auto getActiveShader() -> Rendering::ShaderType;
#endif
void toggleActiveShader(); // Alterna POSTFX ↔ CRTPI
@@ -80,7 +80,7 @@ class Screen {
// Retornen false si GPU off / shaders off / llista buida (igual que a aee_plus).
auto nextPreset() -> bool;
auto prevPreset() -> bool;
auto getCurrentPresetName() const -> const char *;
[[nodiscard]] auto getCurrentPresetName() const -> const char *;
void applyCurrentPostFXPreset(); // Escriu el preset PostFX actiu al backend
void applyCurrentCrtPiPreset(); // Escriu el preset CrtPi actiu al backend
@@ -762,7 +762,7 @@ namespace Rendering {
}
// Copia directa — el upscale lo hace la GPU en el primer render pass
std::memcpy(mapped, pixels, static_cast<size_t>(width * height * 4));
std::memcpy(mapped, pixels, static_cast<size_t>(width) * height * 4);
SDL_UnmapGPUTransferBuffer(device_, upload_buffer_);
}
+2 -1
View File
@@ -2,13 +2,14 @@
#include <SDL3/SDL.h>
#include <cstdint>
#include <string>
#include <utility>
namespace Rendering {
/** @brief Identificador del shader de post-procesado activo */
enum class ShaderType { POSTFX,
enum class ShaderType : std::uint8_t { POSTFX,
CRTPI };
/**
+16 -16
View File
@@ -27,8 +27,8 @@ void SmartSprite::init() {
// Actualiza la posición y comprueba si ha llegado a su destino
void SmartSprite::update() {
if (enabled) {
// Actualiza las variables internas del objeto
MovingSprite::update();
// Actualiza animació + posició (delegant en AnimatedSprite::update)
AnimatedSprite::update();
// Comprueba el movimiento
checkMove();
@@ -47,7 +47,7 @@ void SmartSprite::render() {
}
// Obtiene el valor de la variable
int SmartSprite::getEnabledCounter() {
auto SmartSprite::getEnabledCounter() const -> int {
return enabledCounter;
}
@@ -67,12 +67,12 @@ void SmartSprite::setDestY(int y) {
}
// Obtiene el valor de la variable
int SmartSprite::getDestX() {
auto SmartSprite::getDestX() const -> int {
return destX;
}
// Obtiene el valor de la variable
int SmartSprite::getDestY() {
auto SmartSprite::getDestY() const -> int {
return destY;
}
@@ -86,8 +86,8 @@ void SmartSprite::checkMove() {
setPosX(destX);
// Lo detiene
setVelX(0.0f);
setAccelX(0.0f);
setVelX(0.0F);
setAccelX(0.0F);
}
}
// Comprueba si se desplaza en el eje X hacia la izquierda
@@ -98,8 +98,8 @@ void SmartSprite::checkMove() {
setPosX(destX);
// Lo detiene
setVelX(0.0f);
setAccelX(0.0f);
setVelX(0.0F);
setAccelX(0.0F);
}
}
@@ -111,8 +111,8 @@ void SmartSprite::checkMove() {
setPosY(destY);
// Lo detiene
setVelY(0.0f);
setAccelY(0.0f);
setVelY(0.0F);
setAccelY(0.0F);
}
}
// Comprueba si se desplaza en el eje Y hacia arriba
@@ -123,8 +123,8 @@ void SmartSprite::checkMove() {
setPosY(destY);
// Lo detiene
setVelY(0.0f);
setAccelY(0.0f);
setVelY(0.0F);
setAccelY(0.0F);
}
}
}
@@ -132,7 +132,7 @@ void SmartSprite::checkMove() {
// Comprueba si ha terminado
void SmartSprite::checkFinished() {
// Comprueba si ha llegado a su destino
onDestination = (getPosX() == destX && getPosY() == destY) ? true : false;
onDestination = getPosX() == destX && getPosY() == destY;
if (onDestination) { // Si esta en el destino comprueba su contador
if (enabledCounter == 0) { // Si ha llegado a cero, deshabilita el objeto y lo marca como finalizado
@@ -144,11 +144,11 @@ void SmartSprite::checkFinished() {
}
// Obtiene el valor de la variable
bool SmartSprite::isOnDestination() {
auto SmartSprite::isOnDestination() const -> bool {
return onDestination;
}
// Obtiene el valor de la variable
bool SmartSprite::hasFinished() {
auto SmartSprite::hasFinished() const -> bool {
return finished;
}
+5 -5
View File
@@ -35,7 +35,7 @@ class SmartSprite : public AnimatedSprite {
void render() override;
// Obtiene el valor de la variable
int getEnabledCounter();
[[nodiscard]] auto getEnabledCounter() const -> int;
// Establece el valor de la variable
void setEnabledCounter(int value);
@@ -47,14 +47,14 @@ class SmartSprite : public AnimatedSprite {
void setDestY(int y);
// Obtiene el valor de la variable
int getDestX();
[[nodiscard]] auto getDestX() const -> int;
// Obtiene el valor de la variable
int getDestY();
[[nodiscard]] auto getDestY() const -> int;
// Obtiene el valor de la variable
bool isOnDestination();
[[nodiscard]] auto isOnDestination() const -> bool;
// Obtiene el valor de la variable
bool hasFinished();
[[nodiscard]] auto hasFinished() const -> bool;
};
+10 -10
View File
@@ -39,22 +39,22 @@ void Sprite::render() {
}
// Obten el valor de la variable
int Sprite::getPosX() {
auto Sprite::getPosX() const -> int {
return x;
}
// Obten el valor de la variable
int Sprite::getPosY() {
auto Sprite::getPosY() const -> int {
return y;
}
// Obten el valor de la variable
int Sprite::getWidth() {
auto Sprite::getWidth() const -> int {
return w;
}
// Obten el valor de la variable
int Sprite::getHeight() {
auto Sprite::getHeight() const -> int {
return h;
}
@@ -85,7 +85,7 @@ void Sprite::setHeight(int h) {
}
// Obten el valor de la variable
SDL_Rect Sprite::getSpriteClip() {
auto Sprite::getSpriteClip() -> SDL_Rect {
return spriteClip;
}
@@ -96,11 +96,11 @@ void Sprite::setSpriteClip(SDL_Rect rect) {
// Establece el valor de la variable
void Sprite::setSpriteClip(int x, int y, int w, int h) {
spriteClip = {x, y, w, h};
spriteClip = {.x = x, .y = y, .w = w, .h = h};
}
// Obten el valor de la variable
Texture *Sprite::getTexture() {
auto Sprite::getTexture() -> Texture * {
return texture;
}
@@ -110,7 +110,7 @@ void Sprite::setTexture(Texture *texture) {
}
// Obten el valor de la variable
SDL_Renderer *Sprite::getRenderer() {
auto Sprite::getRenderer() -> SDL_Renderer * {
return renderer;
}
@@ -125,12 +125,12 @@ void Sprite::setEnabled(bool value) {
}
// Comprueba si el objeto está habilitado
bool Sprite::isEnabled() {
auto Sprite::isEnabled() -> bool {
return enabled;
}
// Devuelve el rectangulo donde está el sprite
SDL_Rect Sprite::getRect() {
auto Sprite::getRect() -> SDL_Rect {
SDL_Rect rect = {x, y, w, h};
return rect;
}
+9 -9
View File
@@ -29,16 +29,16 @@ class Sprite {
virtual void render();
// Obten el valor de la variable
int getPosX();
[[nodiscard]] auto getPosX() const -> int;
// Obten el valor de la variable
int getPosY();
[[nodiscard]] auto getPosY() const -> int;
// Obten el valor de la variable
int getWidth();
[[nodiscard]] auto getWidth() const -> int;
// Obten el valor de la variable
int getHeight();
[[nodiscard]] auto getHeight() const -> int;
// Establece la posición del objeto
void setPos(SDL_Rect rect);
@@ -56,7 +56,7 @@ class Sprite {
void setHeight(int h);
// Obten el valor de la variable
SDL_Rect getSpriteClip();
auto getSpriteClip() -> SDL_Rect;
// Establece el valor de la variable
void setSpriteClip(SDL_Rect rect);
@@ -65,13 +65,13 @@ class Sprite {
void setSpriteClip(int x, int y, int w, int h);
// Obten el valor de la variable
Texture *getTexture();
auto getTexture() -> Texture *;
// Establece el valor de la variable
void setTexture(Texture *texture);
// Obten el valor de la variable
SDL_Renderer *getRenderer();
auto getRenderer() -> SDL_Renderer *;
// Establece el valor de la variable
void setRenderer(SDL_Renderer *renderer);
@@ -80,10 +80,10 @@ class Sprite {
virtual void setEnabled(bool value);
// Comprueba si el objeto está habilitado
virtual bool isEnabled();
virtual auto isEnabled() -> bool;
// Devuelve el rectangulo donde está el sprite
virtual SDL_Rect getRect();
virtual auto getRect() -> SDL_Rect;
// Establece los valores de posición y tamaño del sprite
virtual void setRect(SDL_Rect rect);
+22 -22
View File
@@ -39,25 +39,25 @@ static void computeTextFileOffsets(textFile_t &tf) {
}
// Llena una estructuta textFile_t desde un fichero
textFile_t LoadTextFile(const std::string &file, bool verbose) {
auto LoadTextFile(const std::string &file, bool verbose) -> textFile_t {
textFile_t tf;
tf.boxWidth = 0;
tf.boxHeight = 0;
for (int i = 0; i < 128; ++i) {
tf.offset[i].x = 0;
tf.offset[i].y = 0;
tf.offset[i].w = 0;
for (auto &i : tf.offset) {
i.x = 0;
i.y = 0;
i.w = 0;
}
const std::string filename = file.substr(file.find_last_of("\\/") + 1).c_str();
const std::string filename = file.substr(file.find_last_of("\\/") + 1);
std::ifstream rfile(file);
if (rfile.is_open() && rfile.good()) {
parseTextFileStream(rfile, tf);
if (verbose) {
std::cout << "Text loaded: " << filename.c_str() << std::endl;
std::cout << "Text loaded: " << filename.c_str() << '\n';
}
} else if (verbose) {
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl;
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << '\n';
}
computeTextFileOffsets(tf);
@@ -65,21 +65,21 @@ textFile_t LoadTextFile(const std::string &file, bool verbose) {
}
// Llena una estructura textFile_t desde bytes en memoria
textFile_t LoadTextFileFromMemory(const std::vector<uint8_t> &bytes, bool verbose) {
auto LoadTextFileFromMemory(const std::vector<uint8_t> &bytes, bool verbose) -> textFile_t {
textFile_t tf;
tf.boxWidth = 0;
tf.boxHeight = 0;
for (int i = 0; i < 128; ++i) {
tf.offset[i].x = 0;
tf.offset[i].y = 0;
tf.offset[i].w = 0;
for (auto &i : tf.offset) {
i.x = 0;
i.y = 0;
i.w = 0;
}
if (!bytes.empty()) {
std::string content(reinterpret_cast<const char *>(bytes.data()), bytes.size());
std::stringstream ss(content);
parseTextFileStream(ss, tf);
if (verbose) {
std::cout << "Text loaded from memory" << std::endl;
std::cout << "Text loaded from memory" << '\n';
}
}
computeTextFileOffsets(tf);
@@ -170,9 +170,8 @@ Text::Text(const std::vector<uint8_t> &pngBytes, const std::vector<uint8_t> &txt
// Destructor
Text::~Text() {
delete sprite;
if (texture != nullptr) {
delete texture;
}
}
// Escribe texto en pantalla
@@ -187,11 +186,11 @@ void Text::write(int x, int y, const std::string &text, int kerning, int lenght)
const int width = sprite->getWidth();
const int height = sprite->getHeight();
for (int i = 0; i < lenght; ++i) {
const int index = text[i];
const int index = static_cast<unsigned char>(text[i]);
sprite->setSpriteClip(offset[index].x, offset[index].y, width, height);
sprite->setPosX(x + shift);
sprite->render();
shift += fixedWidth ? boxWidth : (offset[int(text[i])].w + kerning);
shift += fixedWidth ? boxWidth : (offset[index].w + kerning);
}
}
@@ -249,18 +248,19 @@ void Text::writeDX(Uint8 flags, int x, int y, const std::string &text, int kerni
}
// Obtiene la longitud en pixels de una cadena
int Text::lenght(const std::string &text, int kerning) {
auto Text::lenght(const std::string &text, int kerning) -> int {
int shift = 0;
for (int i = 0; i < (int)text.length(); ++i)
shift += (offset[int(text[i])].w + kerning);
for (int i = 0; i < (int)text.length(); ++i) {
shift += (offset[static_cast<unsigned char>(text[i])].w + kerning);
}
// Descuenta el kerning del último caracter
return shift - kerning;
}
// Devuelve el valor de la variable
int Text::getCharacterSize() {
auto Text::getCharacterSize() const -> int {
return boxWidth;
}
+5 -5
View File
@@ -28,10 +28,10 @@ struct textFile_t {
};
// Llena una estructuta textFile_t desde un fichero
textFile_t LoadTextFile(const std::string &file, bool verbose = false);
auto LoadTextFile(const std::string &file, bool verbose = false) -> textFile_t;
// Llena una estructura textFile_t desde bytes en memoria
textFile_t LoadTextFileFromMemory(const std::vector<uint8_t> &bytes, bool verbose = false);
auto LoadTextFileFromMemory(const std::vector<uint8_t> &bytes, bool verbose = false) -> textFile_t;
// Clase texto. Pinta texto en pantalla a partir de un bitmap
class Text {
@@ -60,7 +60,7 @@ class Text {
// No copiable (gestiona memoria dinámica)
Text(const Text &) = delete;
Text &operator=(const Text &) = delete;
auto operator=(const Text &) -> Text & = delete;
// Escribe el texto en pantalla
void write(int x, int y, const std::string &text, int kerning = 1, int lenght = -1);
@@ -78,10 +78,10 @@ class Text {
void writeDX(Uint8 flags, int x, int y, const std::string &text, int kerning = 1, color_t textColor = color_t(255, 255, 255), Uint8 shadowDistance = 1, color_t shadowColor = color_t(0, 0, 0), int lenght = -1);
// Obtiene la longitud en pixels de una cadena
int lenght(const std::string &text, int kerning = 1);
auto lenght(const std::string &text, int kerning = 1) -> int;
// Devuelve el valor de la variable
int getCharacterSize();
[[nodiscard]] auto getCharacterSize() const -> int;
// Recarga la textura
void reLoadTexture();
+33 -22
View File
@@ -2,11 +2,12 @@
#include "core/rendering/texture.h"
#include <SDL3/SDL.h>
#include <stdlib.h> // for exit
#include <cstdlib> // for exit
#include <iostream> // for basic_ostream, operator<<, cout, endl
#define STB_IMAGE_IMPLEMENTATION
#include "external/stb_image.h" // for stbi_failure_reason, stbi_image_free
#include "core/resources/resource_helper.h" // for loadFile (pack + filesystem fallback)
#include "external/stb_image.h" // for stbi_failure_reason, stbi_image_free
SDL_ScaleMode Texture::currentScaleMode = SDL_SCALEMODE_NEAREST;
@@ -32,8 +33,7 @@ Texture::Texture(SDL_Renderer *renderer, const std::vector<uint8_t> &bytes, bool
: texture(nullptr),
renderer(renderer),
width(0),
height(0),
path("") {
height(0) {
if (!bytes.empty()) {
loadFromMemory(bytes.data(), bytes.size(), renderer, verbose);
}
@@ -46,7 +46,7 @@ Texture::~Texture() {
}
// Helper: convierte píxeles RGBA decodificados por stbi en SDL_Texture
static SDL_Texture *createTextureFromPixels(SDL_Renderer *renderer, unsigned char *data, int w, int h, int *out_w, int *out_h) {
static auto createTextureFromPixels(SDL_Renderer *renderer, unsigned char *data, int w, int h, int *out_w, int *out_h) -> SDL_Texture * {
const int pitch = 4 * w;
SDL_Surface *loadedSurface = SDL_CreateSurfaceFrom(w, h, SDL_PIXELFORMAT_RGBA32, static_cast<void *>(data), pitch);
if (loadedSurface == nullptr) {
@@ -62,23 +62,32 @@ static SDL_Texture *createTextureFromPixels(SDL_Renderer *renderer, unsigned cha
return newTexture;
}
// Carga una imagen desde un fichero
bool Texture::loadFromFile(const std::string &path, SDL_Renderer *renderer, bool verbose) {
// Carga una imagen desde un fichero (vía ResourceHelper: pack si està inicialitzat, filesystem si no)
auto Texture::loadFromFile(const std::string &path, SDL_Renderer *renderer, bool verbose) -> bool {
const std::string filename = path.substr(path.find_last_of("\\/") + 1);
auto bytes = ResourceHelper::loadFile(path);
if (bytes.empty()) {
SDL_Log("Loading image failed: can't open %s", path.c_str());
exit(1);
}
int req_format = STBI_rgb_alpha;
int w, h, orig_format;
unsigned char *data = stbi_load(path.c_str(), &w, &h, &orig_format, req_format);
int w;
int h;
int orig_format;
unsigned char *data = stbi_load_from_memory(bytes.data(), static_cast<int>(bytes.size()), &w, &h, &orig_format, req_format);
if (data == nullptr) {
SDL_Log("Loading image failed: %s", stbi_failure_reason());
exit(1);
} else if (verbose) {
std::cout << "Image loaded: " << filename.c_str() << std::endl;
std::cout << "Image loaded: " << filename.c_str() << '\n';
}
unload();
SDL_Texture *newTexture = createTextureFromPixels(renderer, data, w, h, &this->width, &this->height);
if (newTexture == nullptr && verbose) {
std::cout << "Unable to load image " << path.c_str() << std::endl;
std::cout << "Unable to load image " << path.c_str() << '\n';
}
stbi_image_free(data);
@@ -87,8 +96,10 @@ bool Texture::loadFromFile(const std::string &path, SDL_Renderer *renderer, bool
}
// Carga una imagen desde bytes en memoria
bool Texture::loadFromMemory(const uint8_t *data, size_t size, SDL_Renderer *renderer, bool verbose) {
int w, h, orig_format;
auto Texture::loadFromMemory(const uint8_t *data, size_t size, SDL_Renderer *renderer, bool verbose) -> bool {
int w;
int h;
int orig_format;
unsigned char *pixels = stbi_load_from_memory(data, (int)size, &w, &h, &orig_format, STBI_rgb_alpha);
if (pixels == nullptr) {
SDL_Log("Loading image from memory failed: %s", stbi_failure_reason());
@@ -98,7 +109,7 @@ bool Texture::loadFromMemory(const uint8_t *data, size_t size, SDL_Renderer *ren
unload();
SDL_Texture *newTexture = createTextureFromPixels(renderer, pixels, w, h, &this->width, &this->height);
if (newTexture == nullptr && verbose) {
std::cout << "Unable to create texture from memory" << std::endl;
std::cout << "Unable to create texture from memory" << '\n';
}
stbi_image_free(pixels);
@@ -107,11 +118,11 @@ bool Texture::loadFromMemory(const uint8_t *data, size_t size, SDL_Renderer *ren
}
// Crea una textura en blanco
bool Texture::createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess access) {
auto Texture::createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess access) -> bool {
// Crea una textura sin inicializar
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, access, width, height);
if (texture == nullptr) {
std::cout << "Unable to create blank texture! SDL Error: " << SDL_GetError() << std::endl;
std::cout << "Unable to create blank texture! SDL Error: " << SDL_GetError() << '\n';
} else {
this->width = width;
this->height = height;
@@ -165,7 +176,7 @@ void Texture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, float
SDL_FRect srcRect;
SDL_FRect *srcRectPtr = nullptr;
if (clip != nullptr) {
srcRect = {(float)clip->x, (float)clip->y, (float)clip->w, (float)clip->h};
srcRect = {.x = (float)clip->x, .y = (float)clip->y, .w = (float)clip->w, .h = (float)clip->h};
srcRectPtr = &srcRect;
}
@@ -173,7 +184,7 @@ void Texture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, float
SDL_FPoint fCenter;
SDL_FPoint *fCenterPtr = nullptr;
if (center != nullptr) {
fCenter = {(float)center->x, (float)center->y};
fCenter = {.x = (float)center->x, .y = (float)center->y};
fCenterPtr = &fCenter;
}
@@ -187,21 +198,21 @@ void Texture::setAsRenderTarget(SDL_Renderer *renderer) {
}
// Obtiene el ancho de la imagen
int Texture::getWidth() {
auto Texture::getWidth() const -> int {
return width;
}
// Obtiene el alto de la imagen
int Texture::getHeight() {
auto Texture::getHeight() const -> int {
return height;
}
// Recarga la textura
bool Texture::reLoad() {
auto Texture::reLoad() -> bool {
return loadFromFile(path, renderer);
}
// Obtiene la textura
SDL_Texture *Texture::getSDLTexture() {
auto Texture::getSDLTexture() -> SDL_Texture * {
return texture;
}
+7 -7
View File
@@ -33,13 +33,13 @@ class Texture {
~Texture();
// Carga una imagen desde un fichero
bool loadFromFile(const std::string &path, SDL_Renderer *renderer, bool verbose = false);
auto loadFromFile(const std::string &path, SDL_Renderer *renderer, bool verbose = false) -> bool;
// Carga una imagen desde bytes en memoria
bool loadFromMemory(const uint8_t *data, size_t size, SDL_Renderer *renderer, bool verbose = false);
auto loadFromMemory(const uint8_t *data, size_t size, SDL_Renderer *renderer, bool verbose = false) -> bool;
// Crea una textura en blanco
bool createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING);
auto createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess /*access*/ = SDL_TEXTUREACCESS_STREAMING) -> bool;
// Libera la memoria de la textura
void unload();
@@ -60,14 +60,14 @@ class Texture {
void setAsRenderTarget(SDL_Renderer *renderer);
// Obtiene el ancho de la imagen
int getWidth();
[[nodiscard]] auto getWidth() const -> int;
// Obtiene el alto de la imagen
int getHeight();
[[nodiscard]] auto getHeight() const -> int;
// Recarga la textura
bool reLoad();
auto reLoad() -> bool;
// Obtiene la textura
SDL_Texture *getSDLTexture();
auto getSDLTexture() -> SDL_Texture *;
};
+4 -16
View File
@@ -4,19 +4,7 @@
// Constructor
Writer::Writer(Text *text)
: text(text),
posX(0),
posY(0),
kerning(0),
caption(""),
speed(0),
writingCounter(0),
index(0),
lenght(0),
completed(false),
enabled(false),
enabledCounter(0),
finished(false) {
: text(text) {
}
// Actualiza el objeto
@@ -87,7 +75,7 @@ void Writer::setEnabled(bool value) {
}
// Obtiene el valor de la variable
bool Writer::IsEnabled() {
auto Writer::IsEnabled() const -> bool {
return enabled;
}
@@ -97,7 +85,7 @@ void Writer::setEnabledCounter(int time) {
}
// Obtiene el valor de la variable
int Writer::getEnabledCounter() {
auto Writer::getEnabledCounter() const -> int {
return enabledCounter;
}
@@ -107,6 +95,6 @@ void Writer::center(int x) {
}
// Obtiene el valor de la variable
bool Writer::hasFinished() {
auto Writer::hasFinished() const -> bool {
return finished;
}
+14 -14
View File
@@ -10,18 +10,18 @@ class Writer {
Text *text; // Objeto encargado de escribir el texto
// Variables
int posX; // Posicion en el eje X donde empezar a escribir el texto
int posY; // Posicion en el eje Y donde empezar a escribir el texto
int kerning; // Kerning del texto, es decir, espaciado entre caracteres
int posX{0}; // Posicion en el eje X donde empezar a escribir el texto
int posY{0}; // Posicion en el eje Y donde empezar a escribir el texto
int kerning{0}; // Kerning del texto, es decir, espaciado entre caracteres
std::string caption; // El texto para escribir
int speed; // Velocidad de escritura
int writingCounter; // Temporizador de escritura para cada caracter
int index; // Posición del texto que se está escribiendo
int lenght; // Longitud de la cadena a escribir
bool completed; // Indica si se ha escrito todo el texto
bool enabled; // Indica si el objeto está habilitado
int enabledCounter; // Temporizador para deshabilitar el objeto
bool finished; // Indica si ya ha terminado
int speed{0}; // Velocidad de escritura
int writingCounter{0}; // Temporizador de escritura para cada caracter
int index{0}; // Posición del texto que se está escribiendo
int lenght{0}; // Longitud de la cadena a escribir
bool completed{false}; // Indica si se ha escrito todo el texto
bool enabled{false}; // Indica si el objeto está habilitado
int enabledCounter{0}; // Temporizador para deshabilitar el objeto
bool finished{false}; // Indica si ya ha terminado
public:
// Constructor
@@ -52,17 +52,17 @@ class Writer {
void setEnabled(bool value);
// Obtiene el valor de la variable
bool IsEnabled();
[[nodiscard]] auto IsEnabled() const -> bool;
// Establece el valor de la variable
void setEnabledCounter(int time);
// Obtiene el valor de la variable
int getEnabledCounter();
[[nodiscard]] auto getEnabledCounter() const -> int;
// Centra la cadena de texto a un punto X
void center(int x);
// Obtiene el valor de la variable
bool hasFinished();
[[nodiscard]] auto hasFinished() const -> bool;
};
+16 -18
View File
@@ -1,8 +1,8 @@
#include "core/resources/asset.h"
#include <SDL3/SDL.h>
#include <stddef.h> // for size_t
#include <cstddef> // for size_t
#include <iostream> // for basic_ostream, operator<<, cout, endl
#include "core/resources/resource_helper.h"
@@ -26,9 +26,7 @@ auto Asset::get() -> Asset * {
// Constructor
Asset::Asset(const std::string &executablePath)
: longestName(0),
executablePath(executablePath.substr(0, executablePath.find_last_of("\\/"))),
verbose(true) {
: executablePath(executablePath.substr(0, executablePath.find_last_of("\\/"))) {
}
// Añade un elemento a la lista
@@ -44,10 +42,10 @@ void Asset::add(const std::string &file, enum assetType type, bool required, boo
}
// Devuelve el fichero de un elemento de la lista a partir de una cadena
std::string Asset::get(const std::string &text) {
auto Asset::get(const std::string &text) -> std::string {
for (const auto &f : fileList) {
const size_t lastIndex = f.file.find_last_of("/") + 1;
const std::string file = f.file.substr(lastIndex, std::string::npos);
const size_t lastIndex = f.file.find_last_of('/') + 1;
const std::string file = f.file.substr(lastIndex);
if (file == text) {
return f.file;
@@ -55,20 +53,20 @@ std::string Asset::get(const std::string &text) {
}
if (verbose) {
std::cout << "Warning: file " << text.c_str() << " not found" << std::endl;
std::cout << "Warning: file " << text.c_str() << " not found" << '\n';
}
return "";
}
// Comprueba que existen todos los elementos
bool Asset::check() {
auto Asset::check() -> bool {
bool success = true;
if (verbose) {
std::cout << "\n** Checking files" << std::endl;
std::cout << "\n** Checking files" << '\n';
std::cout << "Executable path is: " << executablePath << std::endl;
std::cout << "Sample filepath: " << fileList.back().file << std::endl;
std::cout << "Executable path is: " << executablePath << '\n';
std::cout << "Sample filepath: " << fileList.back().file << '\n';
}
// Comprueba la lista de ficheros clasificandolos por tipo
@@ -85,7 +83,7 @@ bool Asset::check() {
// Si hay ficheros de ese tipo, comprueba si existen
if (any) {
if (verbose) {
std::cout << "\n>> " << getTypeName(type).c_str() << " FILES" << std::endl;
std::cout << "\n>> " << getTypeName(type).c_str() << " FILES" << '\n';
}
for (const auto &f : fileList) {
@@ -100,10 +98,10 @@ bool Asset::check() {
if (verbose) {
if (success) {
std::cout << "\n** All files OK.\n"
<< std::endl;
<< '\n';
} else {
std::cout << "\n** A file is missing. Exiting.\n"
<< std::endl;
<< '\n';
}
}
@@ -111,7 +109,7 @@ bool Asset::check() {
}
// Comprueba que existe un fichero
bool Asset::checkFile(const std::string &path) {
auto Asset::checkFile(const std::string &path) const -> bool {
bool success = false;
std::string result = "ERROR";
@@ -138,14 +136,14 @@ bool Asset::checkFile(const std::string &path) {
std::cout.width(longestName + 2);
std::cout.fill('.');
std::cout << filename + " ";
std::cout << " [" + result + "]" << std::endl;
std::cout << " [" + result + "]" << '\n';
}
return success;
}
// Devuelve el nombre del tipo de recurso
std::string Asset::getTypeName(int type) {
auto Asset::getTypeName(int type) -> std::string {
switch (type) {
case t_bitmap:
return "BITMAP";
+11 -10
View File
@@ -1,9 +1,10 @@
#pragma once
#include <string> // for string, basic_string
#include <vector> // for vector
#include <cstdint> // for uint8_t
#include <string> // for string, basic_string
#include <vector> // for vector
enum assetType {
enum assetType : std::uint8_t {
t_bitmap,
t_music,
t_sound,
@@ -28,16 +29,16 @@ class Asset {
private:
// Variables
int longestName; // Contiene la longitud del nombre de fichero mas largo
int longestName{0}; // Contiene la longitud del nombre de fichero mas largo
std::vector<item_t> fileList; // Listado con todas las rutas a los ficheros
std::string executablePath; // Ruta al ejecutable
bool verbose; // Indica si ha de mostrar información por pantalla
bool verbose{true}; // Indica si ha de mostrar información por pantalla
// Comprueba que existe un fichero
bool checkFile(const std::string &executablePath);
[[nodiscard]] auto checkFile(const std::string &executablePath) const -> bool;
// Devuelve el nombre del tipo de recurso
std::string getTypeName(int type);
static auto getTypeName(int type) -> std::string;
// Constructor privado (usar Asset::init)
explicit Asset(const std::string &path);
@@ -55,13 +56,13 @@ class Asset {
void add(const std::string &file, enum assetType type, bool required = true, bool absolute = false);
// Devuelve un elemento de la lista a partir de una cadena
std::string get(const std::string &text);
auto get(const std::string &text) -> std::string;
// Devuelve toda la lista de items registrados
const std::vector<item_t> &getAll() const { return fileList; }
[[nodiscard]] auto getAll() const -> const std::vector<item_t> & { return fileList; }
// Comprueba que existen todos los elementos
bool check();
auto check() -> bool;
// Establece si ha de mostrar texto por pantalla
void setVerbose(bool value);
+59 -31
View File
@@ -17,14 +17,16 @@
Resource *Resource::instance_ = nullptr;
static std::string basename(const std::string &path) {
static auto basename(const std::string &path) -> std::string {
return path.substr(path.find_last_of("\\/") + 1);
}
static std::string stem(const std::string &path) {
static auto stem(const std::string &path) -> std::string {
std::string b = basename(path);
size_t dot = b.find_last_of('.');
if (dot == std::string::npos) return b;
if (dot == std::string::npos) {
return b;
}
return b.substr(0, dot);
}
@@ -40,7 +42,7 @@ void Resource::destroy() {
instance_ = nullptr;
}
Resource *Resource::get() {
auto Resource::get() -> Resource * {
return instance_;
}
@@ -48,19 +50,29 @@ Resource::Resource(SDL_Renderer *renderer)
: renderer_(renderer) {}
Resource::~Resource() {
for (auto &[name, m] : menus_) delete m;
for (auto &[name, m] : menus_) {
delete m;
}
menus_.clear();
for (auto &[name, t] : texts_) delete t;
for (auto &[name, t] : texts_) {
delete t;
}
texts_.clear();
for (auto &[name, t] : textures_) delete t;
for (auto &[name, t] : textures_) {
delete t;
}
textures_.clear();
for (auto &[name, s] : sounds_) JA_DeleteSound(s);
for (auto &[name, s] : sounds_) {
JA_DeleteSound(s);
}
sounds_.clear();
for (auto &[name, m] : musics_) JA_DeleteMusic(m);
for (auto &[name, m] : musics_) {
JA_DeleteMusic(m);
}
musics_.clear();
}
@@ -74,7 +86,9 @@ void Resource::preloadAll() {
continue;
}
auto bytes = ResourceHelper::loadFile(it.file);
if (bytes.empty()) continue;
if (bytes.empty()) {
continue;
}
const std::string bname = basename(it.file);
@@ -86,12 +100,16 @@ void Resource::preloadAll() {
}
case t_sound: {
JA_Sound_t *s = JA_LoadSound(bytes.data(), (uint32_t)bytes.size());
if (s) sounds_[bname] = s;
if (s != nullptr) {
sounds_[bname] = s;
}
break;
}
case t_music: {
JA_Music_t *m = JA_LoadMusic(bytes.data(), (Uint32)bytes.size());
if (m) musics_[bname] = m;
if (m != nullptr) {
musics_[bname] = m;
}
break;
}
case t_data: {
@@ -103,7 +121,9 @@ void Resource::preloadAll() {
while (std::getline(ss, line)) {
// Normalitza CRLF perquè loadFromVector compari línies amb literals
// ("[animation]", "[/animation]") sense \r residual.
if (!line.empty() && line.back() == '\r') line.pop_back();
if (!line.empty() && line.back() == '\r') {
line.pop_back();
}
lines.push_back(line);
}
animationLines_[bname] = std::move(lines);
@@ -114,12 +134,8 @@ void Resource::preloadAll() {
}
break;
}
case t_font:
// Fonts: se emparejan en pass 2
break;
case t_lang:
// Lenguaje: lo sigue leyendo la clase Lang a través de ResourceHelper
break;
case t_font: // Fonts: se emparejan en pass 2
case t_lang: // Lenguaje: lo sigue leyendo la clase Lang via ResourceHelper
default:
break;
}
@@ -131,9 +147,13 @@ void Resource::preloadAll() {
std::unordered_map<std::string, std::vector<uint8_t>> fontPngs;
std::unordered_map<std::string, std::vector<uint8_t>> fontTxts;
for (const auto &it : items) {
if (it.type != t_font) continue;
if (it.type != t_font) {
continue;
}
auto bytes = ResourceHelper::loadFile(it.file);
if (bytes.empty()) continue;
if (bytes.empty()) {
continue;
}
const std::string s = stem(it.file);
const std::string bname = basename(it.file);
if (bname.size() >= 4 && bname.substr(bname.size() - 4) == ".png") {
@@ -144,7 +164,9 @@ void Resource::preloadAll() {
}
for (const auto &[s, png] : fontPngs) {
auto itTxt = fontTxts.find(s);
if (itTxt == fontTxts.end()) continue;
if (itTxt == fontTxts.end()) {
continue;
}
Text *t = new Text(png, itTxt->second, renderer_);
texts_[s] = t;
}
@@ -154,11 +176,17 @@ void Resource::preloadAll() {
// requiere que Menu se adapte a cargar desde ResourceHelper. Por ahora
// lo dejamos así y será una migración del paso 7.
for (const auto &it : items) {
if (it.type != t_data) continue;
if (it.type != t_data) {
continue;
}
const std::string bname = basename(it.file);
if (bname.size() < 4 || bname.substr(bname.size() - 4) != ".men") continue;
if (bname.size() < 4 || bname.substr(bname.size() - 4) != ".men") {
continue;
}
auto bytes = ResourceHelper::loadFile(it.file);
if (bytes.empty()) continue;
if (bytes.empty()) {
continue;
}
Menu *m = new Menu(renderer_, "");
m->loadFromBytes(bytes, bname);
const std::string s = stem(it.file);
@@ -166,7 +194,7 @@ void Resource::preloadAll() {
}
}
Texture *Resource::getTexture(const std::string &name) {
auto Resource::getTexture(const std::string &name) -> Texture * {
auto it = textures_.find(name);
if (it == textures_.end()) {
std::cerr << "Resource::getTexture: missing " << name << '\n';
@@ -175,7 +203,7 @@ Texture *Resource::getTexture(const std::string &name) {
return it->second;
}
JA_Sound_t *Resource::getSound(const std::string &name) {
auto Resource::getSound(const std::string &name) -> JA_Sound_t * {
auto it = sounds_.find(name);
if (it == sounds_.end()) {
std::cerr << "Resource::getSound: missing " << name << '\n';
@@ -184,7 +212,7 @@ JA_Sound_t *Resource::getSound(const std::string &name) {
return it->second;
}
JA_Music_t *Resource::getMusic(const std::string &name) {
auto Resource::getMusic(const std::string &name) -> JA_Music_t * {
auto it = musics_.find(name);
if (it == musics_.end()) {
std::cerr << "Resource::getMusic: missing " << name << '\n';
@@ -193,7 +221,7 @@ JA_Music_t *Resource::getMusic(const std::string &name) {
return it->second;
}
std::vector<std::string> &Resource::getAnimationLines(const std::string &name) {
auto Resource::getAnimationLines(const std::string &name) -> std::vector<std::string> & {
auto it = animationLines_.find(name);
if (it == animationLines_.end()) {
static std::vector<std::string> empty;
@@ -203,7 +231,7 @@ std::vector<std::string> &Resource::getAnimationLines(const std::string &name) {
return it->second;
}
Text *Resource::getText(const std::string &name) {
auto Resource::getText(const std::string &name) -> Text * {
auto it = texts_.find(name);
if (it == texts_.end()) {
std::cerr << "Resource::getText: missing " << name << '\n';
@@ -212,7 +240,7 @@ Text *Resource::getText(const std::string &name) {
return it->second;
}
Menu *Resource::getMenu(const std::string &name) {
auto Resource::getMenu(const std::string &name) -> Menu * {
auto it = menus_.find(name);
if (it == menus_.end()) {
std::cerr << "Resource::getMenu: missing " << name << '\n';
+8 -8
View File
@@ -19,15 +19,15 @@ class Resource {
public:
static void init(SDL_Renderer *renderer);
static void destroy();
static Resource *get();
static auto get() -> Resource *;
Texture *getTexture(const std::string &name);
JA_Sound_t *getSound(const std::string &name);
JA_Music_t *getMusic(const std::string &name);
std::vector<std::string> &getAnimationLines(const std::string &name);
Text *getText(const std::string &name); // name sin extensión: "smb2", "nokia2", ...
Menu *getMenu(const std::string &name); // name sin extensión: "title", "options", ...
const std::vector<uint8_t> &getDemoBytes() const { return demoBytes_; }
auto getTexture(const std::string &name) -> Texture *;
auto getSound(const std::string &name) -> JA_Sound_t *;
auto getMusic(const std::string &name) -> JA_Music_t *;
auto getAnimationLines(const std::string &name) -> std::vector<std::string> &;
auto getText(const std::string &name) -> Text *; // name sin extensión: "smb2", "nokia2", ...
auto getMenu(const std::string &name) -> Menu *; // name sin extensión: "title", "options", ...
auto getDemoBytes() const -> const std::vector<uint8_t> & { return demoBytes_; }
private:
explicit Resource(SDL_Renderer *renderer);
+5 -5
View File
@@ -10,7 +10,7 @@
namespace ResourceHelper {
static bool resource_system_initialized = false;
bool initializeResourceSystem(const std::string& pack_file, bool enable_fallback) {
auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback) -> bool {
auto& loader = ResourceLoader::getInstance();
bool ok = loader.initialize(pack_file, enable_fallback);
resource_system_initialized = ok;
@@ -31,7 +31,7 @@ namespace ResourceHelper {
}
}
std::vector<uint8_t> loadFile(const std::string& filepath) {
auto loadFile(const std::string& filepath) -> std::vector<uint8_t> {
if (resource_system_initialized && shouldUseResourcePack(filepath)) {
auto& loader = ResourceLoader::getInstance();
std::string pack_path = getPackPath(filepath);
@@ -58,14 +58,14 @@ namespace ResourceHelper {
return data;
}
bool shouldUseResourcePack(const std::string& filepath) {
auto shouldUseResourcePack(const std::string& filepath) -> bool {
// Solo entran al pack los ficheros dentro de data/
return filepath.find("data/") != std::string::npos;
}
std::string getPackPath(const std::string& asset_path) {
auto getPackPath(const std::string& asset_path) -> std::string {
std::string pack_path = asset_path;
std::replace(pack_path.begin(), pack_path.end(), '\\', '/');
std::ranges::replace(pack_path, '\\', '/');
// Toma la última aparición de "data/" como prefijo a quitar
size_t last_data = pack_path.rfind("data/");
+4 -4
View File
@@ -5,11 +5,11 @@
#include <vector>
namespace ResourceHelper {
bool initializeResourceSystem(const std::string& pack_file = "resources.pack", bool enable_fallback = true);
auto initializeResourceSystem(const std::string& pack_file = "resources.pack", bool enable_fallback = true) -> bool;
void shutdownResourceSystem();
std::vector<uint8_t> loadFile(const std::string& filepath);
auto loadFile(const std::string& filepath) -> std::vector<uint8_t>;
bool shouldUseResourcePack(const std::string& filepath);
std::string getPackPath(const std::string& asset_path);
auto shouldUseResourcePack(const std::string& filepath) -> bool;
auto getPackPath(const std::string& asset_path) -> std::string;
} // namespace ResourceHelper
+10 -12
View File
@@ -9,11 +9,9 @@
std::unique_ptr<ResourceLoader> ResourceLoader::instance = nullptr;
ResourceLoader::ResourceLoader()
: resource_pack_(nullptr),
fallback_to_files_(true) {}
ResourceLoader::ResourceLoader() = default;
ResourceLoader& ResourceLoader::getInstance() {
auto ResourceLoader::getInstance() -> ResourceLoader& {
if (!instance) {
instance = std::unique_ptr<ResourceLoader>(new ResourceLoader());
}
@@ -24,7 +22,7 @@ ResourceLoader::~ResourceLoader() {
shutdown();
}
bool ResourceLoader::initialize(const std::string& pack_file, bool enable_fallback) {
auto ResourceLoader::initialize(const std::string& pack_file, bool enable_fallback) -> bool {
shutdown();
fallback_to_files_ = enable_fallback;
@@ -55,7 +53,7 @@ void ResourceLoader::shutdown() {
}
}
std::vector<uint8_t> ResourceLoader::loadResource(const std::string& filename) {
auto ResourceLoader::loadResource(const std::string& filename) -> std::vector<uint8_t> {
if ((resource_pack_ != nullptr) && resource_pack_->hasResource(filename)) {
return resource_pack_->getResource(filename);
}
@@ -68,7 +66,7 @@ std::vector<uint8_t> ResourceLoader::loadResource(const std::string& filename) {
return {};
}
bool ResourceLoader::resourceExists(const std::string& filename) {
auto ResourceLoader::resourceExists(const std::string& filename) -> bool {
if ((resource_pack_ != nullptr) && resource_pack_->hasResource(filename)) {
return true;
}
@@ -81,7 +79,7 @@ bool ResourceLoader::resourceExists(const std::string& filename) {
return false;
}
std::vector<uint8_t> ResourceLoader::loadFromFile(const std::string& filename) {
auto ResourceLoader::loadFromFile(const std::string& filename) -> std::vector<uint8_t> {
std::string full_path = getDataPath(filename);
std::ifstream file(full_path, std::ios::binary | std::ios::ate);
@@ -102,18 +100,18 @@ std::vector<uint8_t> ResourceLoader::loadFromFile(const std::string& filename) {
return data;
}
std::string ResourceLoader::getDataPath(const std::string& filename) {
auto ResourceLoader::getDataPath(const std::string& filename) -> std::string {
return "data/" + filename;
}
size_t ResourceLoader::getLoadedResourceCount() const {
auto ResourceLoader::getLoadedResourceCount() const -> size_t {
if (resource_pack_ != nullptr) {
return resource_pack_->getResourceCount();
}
return 0;
}
std::vector<std::string> ResourceLoader::getAvailableResources() const {
auto ResourceLoader::getAvailableResources() const -> std::vector<std::string> {
if (resource_pack_ != nullptr) {
return resource_pack_->getResourceList();
}
@@ -123,7 +121,7 @@ std::vector<std::string> ResourceLoader::getAvailableResources() const {
for (const auto& entry : std::filesystem::recursive_directory_iterator("data")) {
if (entry.is_regular_file()) {
std::string filename = std::filesystem::relative(entry.path(), "data").string();
std::replace(filename.begin(), filename.end(), '\\', '/');
std::ranges::replace(filename, '\\', '/');
result.push_back(filename);
}
}
+11 -11
View File
@@ -11,29 +11,29 @@ class ResourcePack;
class ResourceLoader {
private:
static std::unique_ptr<ResourceLoader> instance;
ResourcePack* resource_pack_;
ResourcePack* resource_pack_{nullptr};
std::string pack_path_;
bool fallback_to_files_;
bool fallback_to_files_{true};
ResourceLoader();
public:
static ResourceLoader& getInstance();
static auto getInstance() -> ResourceLoader&;
~ResourceLoader();
bool initialize(const std::string& pack_file, bool enable_fallback = true);
auto initialize(const std::string& pack_file, bool enable_fallback = true) -> bool;
void shutdown();
std::vector<uint8_t> loadResource(const std::string& filename);
bool resourceExists(const std::string& filename);
auto loadResource(const std::string& filename) -> std::vector<uint8_t>;
auto resourceExists(const std::string& filename) -> bool;
void setFallbackToFiles(bool enable) { fallback_to_files_ = enable; }
bool getFallbackToFiles() const { return fallback_to_files_; }
[[nodiscard]] auto getFallbackToFiles() const -> bool { return fallback_to_files_; }
size_t getLoadedResourceCount() const;
std::vector<std::string> getAvailableResources() const;
[[nodiscard]] auto getLoadedResourceCount() const -> size_t;
[[nodiscard]] auto getAvailableResources() const -> std::vector<std::string>;
private:
static std::vector<uint8_t> loadFromFile(const std::string& filename);
static std::string getDataPath(const std::string& filename);
static auto loadFromFile(const std::string& filename) -> std::vector<uint8_t>;
static auto getDataPath(const std::string& filename) -> std::string;
};
+16 -15
View File
@@ -10,19 +10,20 @@
const std::string ResourcePack::DEFAULT_ENCRYPT_KEY = "CCRS_RESOURCES__2026";
ResourcePack::ResourcePack()
: loaded_(false) {}
ResourcePack::ResourcePack() = default;
ResourcePack::~ResourcePack() {
clear();
}
uint32_t ResourcePack::calculateChecksum(const std::vector<uint8_t>& data) {
auto ResourcePack::calculateChecksum(const std::vector<uint8_t>& data) -> uint32_t {
return std::accumulate(data.begin(), data.end(), uint32_t(0x12345678), [](uint32_t acc, uint8_t b) { return ((acc << 5) + acc) + b; });
}
void ResourcePack::encryptData(std::vector<uint8_t>& data, const std::string& key) {
if (key.empty()) return;
if (key.empty()) {
return;
}
for (size_t i = 0; i < data.size(); ++i) {
data[i] ^= key[i % key.length()];
}
@@ -32,7 +33,7 @@ void ResourcePack::decryptData(std::vector<uint8_t>& data, const std::string& ke
encryptData(data, key);
}
bool ResourcePack::loadPack(const std::string& pack_file) {
auto ResourcePack::loadPack(const std::string& pack_file) -> bool {
std::ifstream file(pack_file, std::ios::binary);
if (!file) {
std::cerr << "Error: Could not open pack file: " << pack_file << '\n';
@@ -87,7 +88,7 @@ bool ResourcePack::loadPack(const std::string& pack_file) {
return true;
}
bool ResourcePack::savePack(const std::string& pack_file) {
auto ResourcePack::savePack(const std::string& pack_file) -> bool {
std::ofstream file(pack_file, std::ios::binary);
if (!file) {
std::cerr << "Error: Could not create pack file: " << pack_file << '\n';
@@ -99,11 +100,11 @@ bool ResourcePack::savePack(const std::string& pack_file) {
uint32_t version = 1;
file.write(reinterpret_cast<const char*>(&version), sizeof(version));
uint32_t resource_count = static_cast<uint32_t>(resources_.size());
auto resource_count = static_cast<uint32_t>(resources_.size());
file.write(reinterpret_cast<const char*>(&resource_count), sizeof(resource_count));
for (const auto& [filename, entry] : resources_) {
uint32_t filename_length = static_cast<uint32_t>(filename.length());
auto filename_length = static_cast<uint32_t>(filename.length());
file.write(reinterpret_cast<const char*>(&filename_length), sizeof(filename_length));
file.write(filename.c_str(), filename_length);
@@ -122,7 +123,7 @@ bool ResourcePack::savePack(const std::string& pack_file) {
return true;
}
bool ResourcePack::addFile(const std::string& filename, const std::string& filepath) {
auto ResourcePack::addFile(const std::string& filename, const std::string& filepath) -> bool {
std::ifstream file(filepath, std::ios::binary | std::ios::ate);
if (!file) {
std::cerr << "Error: Could not open file: " << filepath << '\n';
@@ -150,7 +151,7 @@ bool ResourcePack::addFile(const std::string& filename, const std::string& filep
return true;
}
bool ResourcePack::addDirectory(const std::string& directory) {
auto ResourcePack::addDirectory(const std::string& directory) -> bool {
if (!std::filesystem::exists(directory)) {
std::cerr << "Error: Directory does not exist: " << directory << '\n';
return false;
@@ -162,7 +163,7 @@ bool ResourcePack::addDirectory(const std::string& directory) {
std::string filepath = entry.path().string();
std::string filename = std::filesystem::relative(entry.path(), directory).string();
std::replace(filename.begin(), filename.end(), '\\', '/');
std::ranges::replace(filename, '\\', '/');
if (!addFile(filename, filepath)) {
return false;
@@ -173,7 +174,7 @@ bool ResourcePack::addDirectory(const std::string& directory) {
return true;
}
std::vector<uint8_t> ResourcePack::getResource(const std::string& filename) {
auto ResourcePack::getResource(const std::string& filename) -> std::vector<uint8_t> {
auto it = resources_.find(filename);
if (it == resources_.end()) {
std::cerr << "Error: Resource not found: " << filename << '\n';
@@ -197,7 +198,7 @@ std::vector<uint8_t> ResourcePack::getResource(const std::string& filename) {
return result;
}
bool ResourcePack::hasResource(const std::string& filename) const {
auto ResourcePack::hasResource(const std::string& filename) const -> bool {
return resources_.find(filename) != resources_.end();
}
@@ -207,11 +208,11 @@ void ResourcePack::clear() {
loaded_ = false;
}
size_t ResourcePack::getResourceCount() const {
auto ResourcePack::getResourceCount() const -> size_t {
return resources_.size();
}
std::vector<std::string> ResourcePack::getResourceList() const {
auto ResourcePack::getResourceList() const -> std::vector<std::string> {
std::vector<std::string> result;
result.reserve(resources_.size());
for (const auto& [filename, entry] : resources_) {
+10 -10
View File
@@ -17,9 +17,9 @@ class ResourcePack {
private:
std::unordered_map<std::string, ResourceEntry> resources_;
std::vector<uint8_t> data_;
bool loaded_;
bool loaded_{false};
static uint32_t calculateChecksum(const std::vector<uint8_t>& data);
static auto calculateChecksum(const std::vector<uint8_t>& data) -> uint32_t;
static void encryptData(std::vector<uint8_t>& data, const std::string& key);
static void decryptData(std::vector<uint8_t>& data, const std::string& key);
@@ -27,18 +27,18 @@ class ResourcePack {
ResourcePack();
~ResourcePack();
bool loadPack(const std::string& pack_file);
bool savePack(const std::string& pack_file);
auto loadPack(const std::string& pack_file) -> bool;
auto savePack(const std::string& pack_file) -> bool;
bool addFile(const std::string& filename, const std::string& filepath);
bool addDirectory(const std::string& directory);
auto addFile(const std::string& filename, const std::string& filepath) -> bool;
auto addDirectory(const std::string& directory) -> bool;
std::vector<uint8_t> getResource(const std::string& filename);
bool hasResource(const std::string& filename) const;
auto getResource(const std::string& filename) -> std::vector<uint8_t>;
auto hasResource(const std::string& filename) const -> bool;
void clear();
size_t getResourceCount() const;
std::vector<std::string> getResourceList() const;
auto getResourceCount() const -> size_t;
auto getResourceList() const -> std::vector<std::string>;
static const std::string DEFAULT_ENCRYPT_KEY;
};
+11 -11
View File
@@ -96,16 +96,16 @@ class Menu {
std::string font_txt;
// Carga la configuración del menu desde un archivo de texto
bool load(const std::string &file_path);
auto load(const std::string &file_path) -> bool;
// Parser compartido (recibe cualquier istream)
bool parseFromStream(std::istream &file, const std::string &filename);
auto parseFromStream(std::istream &file, const std::string &filename) -> bool;
// Asigna variables a partir de dos cadenas
bool setVars(const std::string &var, const std::string &value);
auto setVars(const std::string &var, const std::string &value) -> bool;
// Asigna variables a partir de dos cadenas
bool setItem(item_t *item, const std::string &var, const std::string &value);
auto setItem(item_t *item, const std::string &var, const std::string &value) -> bool;
// Actualiza el menu para recolocarlo correctamente y establecer el tamaño
void reorganize();
@@ -120,22 +120,22 @@ class Menu {
void updateSelector();
// Obtiene la anchura del elemento más ancho del menu
int getWidestItem();
auto getWidestItem() -> int;
// Gestiona la entrada de teclado y mando durante el menu
void checkMenuInput(Menu *menu);
// Calcula el ancho del menu
int findWidth();
auto findWidth() -> int;
// Calcula el alto del menu
int findHeight();
auto findHeight() -> int;
// Recoloca los elementos del menu en el eje Y
void replaceElementsOnY();
// Calcula la altura del selector
int getSelectorHeight(int value);
auto getSelectorHeight(int value) -> int;
// Calcula los colores del selector para el degradado
void setSelectorItemColors();
@@ -148,16 +148,16 @@ class Menu {
~Menu();
// Carga el menu desde bytes en memoria
bool loadFromBytes(const std::vector<uint8_t> &bytes, const std::string &nameForLogs = "");
auto loadFromBytes(const std::vector<uint8_t> &bytes, const std::string &nameForLogs = "") -> bool;
// Carga los ficheros de audio
void loadAudioFile(const std::string &file, int sound);
// Obtiene el nombre del menu
const std::string &getName() const;
[[nodiscard]] auto getName() const -> const std::string &;
// Obtiene el valor de la variable
int getItemSelected();
auto getItemSelected() -> int;
// Deja el menu apuntando al primer elemento
void reset();