Persist settings

main
En Yi 2025-09-03 23:11:19 +08:00
parent 3098926e21
commit f67f9e26e2
5 changed files with 82 additions and 0 deletions

1
.gitignore vendored
View File

@ -6,3 +6,4 @@ compile_commands.json
.gdb_history
heaptrack.*
save.dat
settings.dat

View File

@ -3,6 +3,8 @@
#include <math.h>
#define SETTINGS_FILE "settings.dat"
void init_engine(GameEngine_t* engine, Vector2 starting_win_size)
{
InitAudioDevice();
@ -48,6 +50,77 @@ int get_keybind_or_default(GameEngine_t* engine, ActionType_t action, int defaul
return key;
}
#define PAIR_SIZE(a,b) (sizeof(a) + sizeof(b))
int load_keybinds(GameEngine_t* engine)
{
int len = 0;
float volume = 1.0f;
unsigned char* data = LoadFileData(SETTINGS_FILE, &len);
if (data != NULL)
{
if (len >= 4)
{
memcpy(&volume, data, sizeof(volume));
SetMasterVolume(volume);
len -= 4;
}
len /= 2; // 2 bytes for each key and actions
len /= 2; // key-action pair
unsigned char* keybind_data = data + sizeof(volume);
for (int i = 0; i < len; ++i)
{
uint16_t key = 0;
uint16_t action = 0;
memcpy(&key, keybind_data + i * PAIR_SIZE(key, action), sizeof(key));
memcpy(&action, keybind_data + i * PAIR_SIZE(key, action)+ sizeof(key), sizeof(action));
sc_map_get_64(&engine->keybinds, key);
if (sc_map_found(&engine->keybinds))
{
sc_map_put_64(&engine->keybinds, key, (ActionType_t)(action));
}
}
UnloadFileData(data);
}
else
{
// Create the file if not found
writeout_keybinds(engine);
}
return 0;
}
int writeout_keybinds(GameEngine_t* engine)
{
uint16_t key = 0;
uint16_t action = 0;
float volume = GetMasterVolume();
unsigned int n_keys = sc_map_size_64(&engine->keybinds);
uint32_t n_bytes = sizeof(volume) + PAIR_SIZE(key, action) * n_keys;
uint8_t* buf = RL_MALLOC(n_bytes);
if (buf == NULL)
{
return 1;
}
memcpy(buf, &volume, sizeof(volume));
int i = 0;
uint8_t* keybind_buf = buf + sizeof(volume);
sc_map_foreach(&engine->keybinds, key, action)
{
memcpy(keybind_buf + i * PAIR_SIZE(key, action), &key, sizeof(key));
memcpy(keybind_buf + i * PAIR_SIZE(key, action) + sizeof(key), &action, sizeof(action));
i++;
}
return SaveFileData(SETTINGS_FILE, buf, n_bytes)? 0 : 1;
RL_FREE(buf);
return 0;
}
void remap_scene_keys(GameEngine_t* engine)
{
// Assume all scene to be init'd

View File

@ -98,6 +98,11 @@ void process_inputs(GameEngine_t* engine, Scene_t* scene);
void register_keybind(GameEngine_t* engine, int key, ActionType_t action);
int get_keybind_or_default(GameEngine_t* engine, ActionType_t action, int default_key);
// You need to register the keybind first before loading them
// Otherwise, they will get ignored
int load_keybinds(GameEngine_t* engine);
int writeout_keybinds(GameEngine_t* engine);
// If a key bind gets changed, this must be called to update the
// key -> action mapping for all scene
void remap_scene_keys(GameEngine_t* engine);

1
main.c
View File

@ -47,6 +47,7 @@ int main(void)
register_keybind(&engine, KEY_Q, ACTION_EXIT);
register_keybind(&engine, KEY_Z, ACTION_LOOKAHEAD);
register_keybind(&engine, KEY_R, ACTION_RESTART);
load_keybinds(&engine);
load_sfx(&engine, "snd_jump", PLAYER_JMP_SFX);
load_sfx(&engine, "snd_land", PLAYER_LAND_SFX);

View File

@ -243,6 +243,8 @@ static void exec_component_function(Scene_t* scene, uint16_t sel)
scene->reset_function(scene);
data->curr_selection = sel + n_binds + 1;
data->old_volume_value = data->volume_value;
writeout_keybinds(scene->engine);
}
else
{