afegida persistencia i fuck yamal
This commit is contained in:
@@ -35,6 +35,14 @@ All engine modules are flat C-style APIs (no classes), prefixed by subsystem:
|
|||||||
- **JF** (`source/core/jfile`) — File I/O: supports loading from filesystem folder or a packed resource file (`.jrf`). Currently uses folder mode (`data/`)
|
- **JF** (`source/core/jfile`) — File I/O: supports loading from filesystem folder or a packed resource file (`.jrf`). Currently uses folder mode (`data/`)
|
||||||
- **shader** (`source/core/jshader`) — OpenGL post-processing shader (CRT effect) applied to the back buffer
|
- **shader** (`source/core/jshader`) — OpenGL post-processing shader (CRT effect) applied to the back buffer
|
||||||
|
|
||||||
|
### Configuration System (`source/game/`)
|
||||||
|
|
||||||
|
Follows the pattern from `jaildoctors_dilemma`:
|
||||||
|
|
||||||
|
- **defines.hpp** <20><> Game-wide constants (window title, version, screen dimensions)
|
||||||
|
- **defaults.hpp** — Default values for all persistent options (audio, game)
|
||||||
|
- **options.hpp/cpp** — `Options` namespace with structs, inline globals, and YAML load/save API. Config persists to `~/.config/jailgames/aee/config.yaml` (Linux), `%APPDATA%/jailgames/aee/` (Windows)
|
||||||
|
|
||||||
### Game Modules (`source/game/`)
|
### Game Modules (`source/game/`)
|
||||||
|
|
||||||
- **ModuleSequence** — Non-gameplay screens: intro, menu, slides, banners, credits, death screen. State machine entry point (state=1)
|
- **ModuleSequence** — Non-gameplay screens: intro, menu, slides, banners, credits, death screen. State machine entry point (state=1)
|
||||||
@@ -51,6 +59,7 @@ All engine modules are flat C-style APIs (no classes), prefixed by subsystem:
|
|||||||
|
|
||||||
- `gif.h` — Header-only GIF decoder
|
- `gif.h` — Header-only GIF decoder
|
||||||
- `stb_vorbis.h` — stb single-header OGG decoder
|
- `stb_vorbis.h` — stb single-header OGG decoder
|
||||||
|
- `fkyaml_node.hpp` — Header-only YAML parser (fkYAML v0.4.2)
|
||||||
|
|
||||||
### Main Loop (`source/main.cpp`)
|
### Main Loop (`source/main.cpp`)
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ set(APP_SOURCES
|
|||||||
source/core/jshader.cpp
|
source/core/jshader.cpp
|
||||||
|
|
||||||
# Game
|
# Game
|
||||||
|
source/game/options.cpp
|
||||||
source/game/bola.cpp
|
source/game/bola.cpp
|
||||||
source/game/engendro.cpp
|
source/game/engendro.cpp
|
||||||
source/game/info.cpp
|
source/game/info.cpp
|
||||||
|
|||||||
@@ -139,7 +139,8 @@ char *file_getfilebuffer(const char *resourcename, int& filesize, const bool zer
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea la carpeta del sistema donde guardar datos
|
// Crea la carpeta del sistema donde guardar datos.
|
||||||
|
// Acepta rutas con subdirectorios (ej: "jailgames/aee") y crea toda la jerarquía.
|
||||||
void file_setconfigfolder(const char *foldername)
|
void file_setconfigfolder(const char *foldername)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -151,28 +152,15 @@ void file_setconfigfolder(const char *foldername)
|
|||||||
#elif __linux__
|
#elif __linux__
|
||||||
struct passwd *pw = getpwuid(getuid());
|
struct passwd *pw = getpwuid(getuid());
|
||||||
const char *homedir = pw->pw_dir;
|
const char *homedir = pw->pw_dir;
|
||||||
config_folder = std::string(homedir) + "/." + foldername;
|
config_folder = std::string(homedir) + "/.config/" + foldername;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct stat st = {0};
|
std::filesystem::create_directories(config_folder);
|
||||||
if (stat(config_folder.c_str(), &st) == -1)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
int ret = mkdir(config_folder.c_str());
|
|
||||||
#else
|
|
||||||
int ret = mkdir(config_folder.c_str(), S_IRWXU);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
printf("ERROR CREATING CONFIG FOLDER.");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *file_getconfigfolder() {
|
const char *file_getconfigfolder() {
|
||||||
std::string folder = config_folder + "/";
|
static std::string folder;
|
||||||
|
folder = config_folder + "/";
|
||||||
return folder.c_str();
|
return folder.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
14726
source/external/fkyaml_node.hpp
vendored
Normal file
14726
source/external/fkyaml_node.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
15
source/game/defaults.hpp
Normal file
15
source/game/defaults.hpp
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Defaults::Audio {
|
||||||
|
constexpr float VOLUME = 1.0F;
|
||||||
|
constexpr bool MUSIC_ENABLED = true;
|
||||||
|
constexpr float MUSIC_VOLUME = 0.8F;
|
||||||
|
constexpr bool SOUND_ENABLED = true;
|
||||||
|
constexpr float SOUND_VOLUME = 1.0F;
|
||||||
|
} // namespace Defaults::Audio
|
||||||
|
|
||||||
|
namespace Defaults::Game {
|
||||||
|
constexpr int HABITACIO_INICIAL = 1;
|
||||||
|
constexpr int PIRAMIDE_INICIAL = 255;
|
||||||
|
constexpr int VIDES = 5;
|
||||||
|
} // namespace Defaults::Game
|
||||||
14
source/game/defines.hpp
Normal file
14
source/game/defines.hpp
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Textos
|
||||||
|
namespace Texts {
|
||||||
|
constexpr const char* WINDOW_TITLE = "Aventures En Egipte";
|
||||||
|
constexpr const char* VERSION = "1.00";
|
||||||
|
} // namespace Texts
|
||||||
|
|
||||||
|
// Resolución del juego
|
||||||
|
namespace Screen {
|
||||||
|
constexpr int WIDTH = 320;
|
||||||
|
constexpr int HEIGHT = 200;
|
||||||
|
constexpr int BUFFER_SIZE = WIDTH * HEIGHT; // 64000
|
||||||
|
} // namespace Screen
|
||||||
146
source/game/options.cpp
Normal file
146
source/game/options.cpp
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
#include "game/options.hpp"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "external/fkyaml_node.hpp"
|
||||||
|
#include "game/defaults.hpp"
|
||||||
|
#include "game/defines.hpp"
|
||||||
|
|
||||||
|
namespace Options {
|
||||||
|
|
||||||
|
// Estableix la ruta del fitxer de configuració
|
||||||
|
void setConfigFile(const std::string& path) {
|
||||||
|
config_file_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Funcions helper de càrrega ---
|
||||||
|
|
||||||
|
static void loadAudioConfigFromYaml(const fkyaml::node& yaml) {
|
||||||
|
if (!yaml.contains("audio")) return;
|
||||||
|
const auto& node = yaml["audio"];
|
||||||
|
|
||||||
|
if (node.contains("volume"))
|
||||||
|
audio.volume = node["volume"].get_value<float>();
|
||||||
|
|
||||||
|
if (node.contains("music")) {
|
||||||
|
const auto& music = node["music"];
|
||||||
|
if (music.contains("enabled"))
|
||||||
|
audio.music_enabled = music["enabled"].get_value<bool>();
|
||||||
|
if (music.contains("volume"))
|
||||||
|
audio.music_volume = music["volume"].get_value<float>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.contains("sound")) {
|
||||||
|
const auto& sound = node["sound"];
|
||||||
|
if (sound.contains("enabled"))
|
||||||
|
audio.sound_enabled = sound["enabled"].get_value<bool>();
|
||||||
|
if (sound.contains("volume"))
|
||||||
|
audio.sound_volume = sound["volume"].get_value<float>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void loadGameConfigFromYaml(const fkyaml::node& yaml) {
|
||||||
|
if (!yaml.contains("game")) return;
|
||||||
|
const auto& node = yaml["game"];
|
||||||
|
|
||||||
|
if (node.contains("habitacio_inicial"))
|
||||||
|
game.habitacio_inicial = node["habitacio_inicial"].get_value<int>();
|
||||||
|
if (node.contains("piramide_inicial"))
|
||||||
|
game.piramide_inicial = node["piramide_inicial"].get_value<int>();
|
||||||
|
if (node.contains("vides"))
|
||||||
|
game.vides = node["vides"].get_value<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Carrega les opcions des del fitxer configurat
|
||||||
|
auto loadFromFile() -> bool {
|
||||||
|
const std::string CONFIG_VERSION = Texts::VERSION;
|
||||||
|
version = "";
|
||||||
|
|
||||||
|
std::ifstream file(config_file_path);
|
||||||
|
if (!file.good()) {
|
||||||
|
std::cout << "Config file not found, creating default: " << config_file_path << '\n';
|
||||||
|
saveToFile();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::cout << "Reading config file: " << config_file_path << '\n';
|
||||||
|
|
||||||
|
auto yaml = fkyaml::node::deserialize(content);
|
||||||
|
|
||||||
|
if (yaml.contains("version")) {
|
||||||
|
version = yaml["version"].get_value<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CONFIG_VERSION != version) {
|
||||||
|
std::cout << "Config version mismatch (expected: " << CONFIG_VERSION
|
||||||
|
<< ", got: " << version << "), creating new config\n";
|
||||||
|
saveToFile();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadAudioConfigFromYaml(yaml);
|
||||||
|
loadGameConfigFromYaml(yaml);
|
||||||
|
|
||||||
|
std::cout << "Config file loaded successfully\n\n";
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (const fkyaml::exception& e) {
|
||||||
|
std::cerr << "Error parsing YAML config: " << e.what() << '\n';
|
||||||
|
std::cerr << "Creating new config with defaults\n";
|
||||||
|
saveToFile();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Guarda les opcions al fitxer configurat
|
||||||
|
auto saveToFile() -> bool {
|
||||||
|
std::ofstream file(config_file_path);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
std::cerr << "Error: Unable to open file " << config_file_path << " for writing\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Writing config file: " << config_file_path << '\n';
|
||||||
|
|
||||||
|
file << "# Aventures En Egipte - Configuration File\n";
|
||||||
|
file << "# \n";
|
||||||
|
file << "# This file is automatically generated and managed by the game.\n";
|
||||||
|
file << "# Manual edits are preserved if valid.\n";
|
||||||
|
file << "\n";
|
||||||
|
|
||||||
|
// VERSION
|
||||||
|
file << "version: \"" << Texts::VERSION << "\"\n";
|
||||||
|
file << "\n";
|
||||||
|
|
||||||
|
// AUDIO
|
||||||
|
file << "# AUDIO\n";
|
||||||
|
file << "audio:\n";
|
||||||
|
file << " volume: " << audio.volume << "\n";
|
||||||
|
file << " music:\n";
|
||||||
|
file << " enabled: " << (audio.music_enabled ? "true" : "false") << "\n";
|
||||||
|
file << " volume: " << audio.music_volume << "\n";
|
||||||
|
file << " sound:\n";
|
||||||
|
file << " enabled: " << (audio.sound_enabled ? "true" : "false") << "\n";
|
||||||
|
file << " volume: " << audio.sound_volume << "\n";
|
||||||
|
file << "\n";
|
||||||
|
|
||||||
|
// GAME
|
||||||
|
file << "# GAME\n";
|
||||||
|
file << "game:\n";
|
||||||
|
file << " habitacio_inicial: " << game.habitacio_inicial << "\n";
|
||||||
|
file << " piramide_inicial: " << game.piramide_inicial << "\n";
|
||||||
|
file << " vides: " << game.vides << "\n";
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
std::cout << "Config file saved successfully\n\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Options
|
||||||
37
source/game/options.hpp
Normal file
37
source/game/options.hpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "game/defaults.hpp"
|
||||||
|
#include "game/defines.hpp"
|
||||||
|
|
||||||
|
namespace Options {
|
||||||
|
|
||||||
|
// Opcions d'àudio
|
||||||
|
struct Audio {
|
||||||
|
bool music_enabled{Defaults::Audio::MUSIC_ENABLED};
|
||||||
|
float music_volume{Defaults::Audio::MUSIC_VOLUME};
|
||||||
|
bool sound_enabled{Defaults::Audio::SOUND_ENABLED};
|
||||||
|
float sound_volume{Defaults::Audio::SOUND_VOLUME};
|
||||||
|
float volume{Defaults::Audio::VOLUME};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Opcions de joc
|
||||||
|
struct Game {
|
||||||
|
int habitacio_inicial{Defaults::Game::HABITACIO_INICIAL};
|
||||||
|
int piramide_inicial{Defaults::Game::PIRAMIDE_INICIAL};
|
||||||
|
int vides{Defaults::Game::VIDES};
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Variables globals ---
|
||||||
|
inline std::string version{};
|
||||||
|
inline Audio audio{};
|
||||||
|
inline Game game{};
|
||||||
|
inline std::string config_file_path{};
|
||||||
|
|
||||||
|
// --- API ---
|
||||||
|
void setConfigFile(const std::string& path);
|
||||||
|
auto loadFromFile() -> bool;
|
||||||
|
auto saveToFile() -> bool;
|
||||||
|
|
||||||
|
} // namespace Options
|
||||||
@@ -2,46 +2,32 @@
|
|||||||
#include "core/jdraw8.hpp"
|
#include "core/jdraw8.hpp"
|
||||||
#include "core/jail_audio.hpp"
|
#include "core/jail_audio.hpp"
|
||||||
#include "core/jfile.hpp"
|
#include "core/jfile.hpp"
|
||||||
|
#include "game/defines.hpp"
|
||||||
#include "game/info.hpp"
|
#include "game/info.hpp"
|
||||||
#include "game/modulegame.hpp"
|
#include "game/modulegame.hpp"
|
||||||
#include "game/modulesequence.hpp"
|
#include "game/modulesequence.hpp"
|
||||||
|
#include "game/options.hpp"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
/*
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <libgen.h>
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
|
|
||||||
int main( int argc, char* args[] ) {
|
int main( int argc, char* args[] ) {
|
||||||
|
|
||||||
//file_setresourcefilename("data.jrf");
|
|
||||||
/*#ifdef WIN32
|
|
||||||
JF_SetResourceFile("data.jrf");
|
|
||||||
#else
|
|
||||||
char res_file[255] = "";
|
|
||||||
strcpy(res_file, dirname(args[0]));
|
|
||||||
#ifdef __APPLE__
|
|
||||||
strcat(res_file, "/../Resources/data.jrf");
|
|
||||||
#else
|
|
||||||
strcat(res_file, "/data.jrf");
|
|
||||||
#endif
|
|
||||||
printf("ARXIU DE RECURSOS: %s\n", res_file);
|
|
||||||
JF_SetResourceFile(res_file);
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
srand( unsigned(time(NULL)) );
|
srand( unsigned(time(NULL)) );
|
||||||
|
|
||||||
|
// Crea la carpeta de configuració i carrega les opcions
|
||||||
|
file_setconfigfolder("jailgames/aee");
|
||||||
|
Options::setConfigFile(std::string(file_getconfigfolder()) + "config.yaml");
|
||||||
|
Options::loadFromFile();
|
||||||
|
|
||||||
JG_Init();
|
JG_Init();
|
||||||
JD8_Init("Aventures En Egipte");
|
JD8_Init(Texts::WINDOW_TITLE);
|
||||||
JA_Init(48000, SDL_AUDIO_S16, 2);
|
JA_Init(48000, SDL_AUDIO_S16, 2);
|
||||||
|
|
||||||
info::num_habitacio = 1;
|
info::num_habitacio = Options::game.habitacio_inicial;
|
||||||
info::num_piramide = 255;
|
info::num_piramide = Options::game.piramide_inicial;
|
||||||
info::diners = 0;
|
info::diners = 0;
|
||||||
info::diamants = 0;
|
info::diamants = 0;
|
||||||
info::vida = 5;
|
info::vida = Options::game.vides;
|
||||||
info::momies = 0;
|
info::momies = 0;
|
||||||
info::nou_personatge = false;
|
info::nou_personatge = false;
|
||||||
info::pepe_activat = false;
|
info::pepe_activat = false;
|
||||||
@@ -71,10 +57,11 @@ int main( int argc, char* args[] ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Options::saveToFile();
|
||||||
|
|
||||||
JA_Quit();
|
JA_Quit();
|
||||||
JD8_Quit();
|
JD8_Quit();
|
||||||
JG_Finalize();
|
JG_Finalize();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user