Implement FullScreen and FPS opts

This commit is contained in:
2024-01-29 16:41:13 +01:00
parent ed1815eddc
commit a633c9cbdf
7 changed files with 76 additions and 47 deletions

2
.gitignore vendored
View File

@@ -10,3 +10,5 @@ venv/
scripts/__pycache__/ scripts/__pycache__/
imgui.ini imgui.ini
settings.ini
game_data.ini

View File

@@ -15,7 +15,7 @@ typedef enum Player {
// defined in main.c // defined in main.c
extern const char *SETTINGS_PATH; extern const char *GAME_DATA_SAVE_PATH;
#endif //PIXELDEFENSE_CONSTANTS_H #endif //PIXELDEFENSE_CONSTANTS_H

View File

@@ -26,23 +26,30 @@ typedef struct DrawData {
typedef struct Options { typedef struct Options {
// Video // Video
bool fullscreen; bool fullscreen;
bool vsync; bool limitFps;
// Audio // Audio
f32 master; f32 master;
f32 music; f32 music;
f32 sound; f32 sound;
} Options; } Options;
static Options getDefaultOptions() { typedef struct GameData {
return (Options) { Options options;
.fullscreen = false, } GameData;
.vsync = false,
.master = 5.0f, static GameData getDefaultGameData() {
.music = 5.0f, return (GameData) {
.sound = 5.0f, .options = {
.fullscreen = false,
.limitFps = true,
.master = 0.5f,
.music = 0.5f,
.sound = 0.5f
}
}; };
} }
typedef struct PlayerResources { typedef struct PlayerResources {
i64 wood; i64 wood;
i64 food; i64 food;
@@ -63,7 +70,7 @@ typedef struct Game {
Font font; Font font;
Options options; GameData gameData;
PlayerResources playerResources[PLAYER_COUNT]; PlayerResources playerResources[PLAYER_COUNT];
Player player; Player player;

View File

@@ -18,7 +18,7 @@
#include "sounds.h" #include "sounds.h"
// Constants // Constants
const char *SETTINGS_PATH = "settings.ini"; const char *GAME_DATA_SAVE_PATH = "game_data.ini";
// Constants end // Constants end
ECS_COMPONENT_DECLARE(Game); ECS_COMPONENT_DECLARE(Game);
@@ -99,7 +99,7 @@ int cmpDrawData(const void *a, const void *b) {
} }
bool serializeOptions(const char *path, const Options *opts) { bool serializeGameData(const char *path, const GameData *gameData) {
#ifdef EMSCRIPTEN #ifdef EMSCRIPTEN
char buf[4096]; char buf[4096];
@@ -109,7 +109,7 @@ bool serializeOptions(const char *path, const Options *opts) {
bzLogInfo("write path: %s", path); bzLogInfo("write path: %s", path);
FILE *f = fopen(path, "w"); FILE *f = fopen(path, "w");
if (!f) return false; if (!f) return false;
size_t numWritten = fwrite(opts, sizeof(*opts), 1, f); size_t numWritten = fwrite(gameData, sizeof(*gameData), 1, f);
fclose(f); fclose(f);
#ifdef EMSCRIPTEN #ifdef EMSCRIPTEN
// Sync FS // Sync FS
@@ -122,7 +122,7 @@ bool serializeOptions(const char *path, const Options *opts) {
return numWritten == 1; return numWritten == 1;
} }
bool deserializeOptions(const char *path, Options *optsOut) { bool deserializeGameData(const char *path, GameData *gameData) {
#ifdef EMSCRIPTEN #ifdef EMSCRIPTEN
char buf[4096]; char buf[4096];
snprintf(buf, sizeof(buf), "%s%s", "/game/", path); snprintf(buf, sizeof(buf), "%s%s", "/game/", path);
@@ -134,15 +134,29 @@ bool deserializeOptions(const char *path, Options *optsOut) {
bzLogInfo("start reading"); bzLogInfo("start reading");
if (!f) return false; if (!f) return false;
bzLogInfo("reading"); bzLogInfo("reading");
Options opts; GameData data;
size_t numRead = fread(&opts, sizeof(opts), 1, f); size_t numRead = fread(&data, sizeof(data), 1, f);
fclose(f); fclose(f);
if (numRead == 1) { if (numRead == 1) {
*optsOut = opts; *gameData = data;
return true; return true;
} }
return false; return false;
} }
void applyOptions(const Options *options) {
SoundState *sounds = ecs_singleton_get_mut(ECS, SoundState);
soundsApplyVolume(sounds, options->master, options->music, options->sound);
bool isFullscreen = IsWindowFullscreen();
bool wantFullscreen = options->fullscreen;
if (isFullscreen != wantFullscreen)
ToggleFullscreen();
if (options->limitFps)
SetTargetFPS(60);
else
SetTargetFPS(0);
}
bool init(void *userData) { bool init(void *userData) {
// Center window // Center window
@@ -333,7 +347,7 @@ void deinit(void *userData) {
InputState *input = ecs_singleton_get_mut(ECS, InputState); InputState *input = ecs_singleton_get_mut(ECS, InputState);
SoundState *sounds = ecs_singleton_get_mut(ECS, SoundState); SoundState *sounds = ecs_singleton_get_mut(ECS, SoundState);
serializeOptions(SETTINGS_PATH, &game->options); serializeGameData(GAME_DATA_SAVE_PATH, &game->gameData);
unloadMap(game); unloadMap(game);
@@ -379,25 +393,23 @@ void update(float dt, void *userData) {
char titleBuf[32]; char titleBuf[32];
snprintf(titleBuf, sizeof(titleBuf), "FPS: %d | %.2f ms", GetFPS(), GetFrameTime() * 1000); snprintf(titleBuf, sizeof(titleBuf), "FPS: %d | %.2f ms", GetFPS(), GetFrameTime() * 1000);
//SetWindowTitle(titleBuf); SetWindowTitle(titleBuf);
Game *game = ecs_singleton_get_mut(ECS, Game); Game *game = ecs_singleton_get_mut(ECS, Game);
InputState *input = ecs_singleton_get_mut(ECS, InputState); InputState *input = ecs_singleton_get_mut(ECS, InputState);
{ {
static bool optsLoaded = false; static bool gameDataLoaded = false;
if (!optsLoaded) { if (!gameDataLoaded) {
// Load settings // Load settings
const char *path = SETTINGS_PATH; const char *path = GAME_DATA_SAVE_PATH;
Options opts; GameData gameData = getDefaultGameData();
if (deserializeOptions(path, &opts)) { if (deserializeGameData(path, &gameData)) {
game->options = opts; bzLogWarning("Failed to read game data: %s.", path);
} else {
game->options = getDefaultOptions();
} }
SoundState *sounds = ecs_singleton_get_mut(ECS, SoundState); game->gameData = gameData;
soundsApplyVolume(sounds, opts.master, opts.music, opts.sound); applyOptions(&gameData.options);
optsLoaded = true; gameDataLoaded = true;
} }
} }
@@ -719,9 +731,16 @@ void imguiRender(float dt, void *userData) {
} }
if (igCollapsingHeader_TreeNodeFlags("Resources", 0)) { if (igCollapsingHeader_TreeNodeFlags("Resources", 0)) {
PlayerResources resources = game->playerResources[game->player]; PlayerResources resources = game->playerResources[game->player];
igText("Wood: %lld", resources.wood); i32 wood = resources.wood;
igText("Food: %lld", resources.food); i32 food = resources.food;
igText("Gold: %lld", resources.gold); i32 gold = resources.gold;
igSliderInt("Wood: ", &wood, 0, 10000, "%d", 0);
igSliderInt("Food: ", &food, 0, 10000, "%d", 0);
igSliderInt("Gold: ", &gold, 0, 10000, "%d", 0);
resources.wood = wood;
resources.food = food;
resources.gold = gold;
game->playerResources[game->player] = resources;
igText("Pop: %lld", resources.pop); igText("Pop: %lld", resources.pop);
igText("Pop Capacity: %lld", resources.pop); igText("Pop Capacity: %lld", resources.pop);
} }

View File

@@ -278,17 +278,18 @@ void drawSettingsUI(Game *game, f32 dt) {
.type = BZ_UI_LAYOUT_FLEX_BOX, .type = BZ_UI_LAYOUT_FLEX_BOX,
.flags = BZ_UI_FLEX_DIR_COLUMN | BZ_UI_FLEX_JUSTIFY_CENTER | BZ_UI_FLEX_ALIGN_CENTER .flags = BZ_UI_FLEX_DIR_COLUMN | BZ_UI_FLEX_JUSTIFY_CENTER | BZ_UI_FLEX_ALIGN_CENTER
}); });
static Options opts; static GameData gameData = {};
if (game->screenPrevFrame != SCREEN_SETTINGS) if (game->screenPrevFrame != SCREEN_SETTINGS)
opts = game->options; gameData = game->gameData;
uiSettingsLabel("Video"); uiSettingsLabel("Video");
uiSettingsCheckbox("Fullscreen", &opts.fullscreen); uiSettingsCheckbox("Fullscreen", &gameData.options.fullscreen);
uiSettingsCheckbox("V-Sync", &opts.vsync); uiSettingsCheckbox("Limit FPS", &gameData.options.limitFps);
//uiSettingsCheckbox("V-Sync", &opts.vsync);
uiSettingsLabel("Audio"); uiSettingsLabel("Audio");
uiSettingsSlider("Master: ", &opts.master); uiSettingsSlider("Master: ", &gameData.options.master);
uiSettingsSlider("Music: ", &opts.music); uiSettingsSlider("Music: ", &gameData.options.music);
uiSettingsSlider("Sound: ", &opts.sound); uiSettingsSlider("Sound: ", &gameData.options.sound);
bzUIPopParent(UI); bzUIPopParent(UI);
bzUIPushDiv(UI, (BzUISize) {BZ_UI_SIZE_REL_PARENT, 0.8f}, bzUIPushDiv(UI, (BzUISize) {BZ_UI_SIZE_REL_PARENT, 0.8f},
@@ -302,13 +303,12 @@ void drawSettingsUI(Game *game, f32 dt) {
setScreen(game, SCREEN_MAIN_MENU); setScreen(game, SCREEN_MAIN_MENU);
} }
if (uiSettingsButton("Reset")) { if (uiSettingsButton("Reset")) {
opts = game->options; gameData = game->gameData;
} }
if (uiSettingsButton("Apply")) { if (uiSettingsButton("Apply")) {
serializeOptions(SETTINGS_PATH, &opts); serializeGameData(GAME_DATA_SAVE_PATH, &gameData);
game->options = opts; game->gameData = gameData;
SoundState *sounds = ecs_singleton_get_mut(ECS, SoundState); applyOptions(&game->gameData.options);
soundsApplyVolume(sounds, opts.master, opts.music, opts.sound);
setScreen(game, SCREEN_MAIN_MENU); setScreen(game, SCREEN_MAIN_MENU);
} }

View File

@@ -19,7 +19,8 @@ static Rectangle getCameraBounds(Camera2D camera) {
} }
// Implemented in main.c // Implemented in main.c
bool serializeOptions(const char *path, const Options *opts); bool serializeGameData(const char *path, const GameData *gameData);
bool deserializeOptions(const char *path, Options *optsOut); bool deserializeGameData(const char *path, GameData *gameData);
void applyOptions(const Options *options);
#endif //PIXELDEFENSE_UTILS_H #endif //PIXELDEFENSE_UTILS_H

Binary file not shown.