Implement FullScreen and FPS opts
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -10,3 +10,5 @@ venv/
|
|||||||
scripts/__pycache__/
|
scripts/__pycache__/
|
||||||
|
|
||||||
imgui.ini
|
imgui.ini
|
||||||
|
settings.ini
|
||||||
|
game_data.ini
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
65
game/main.c
65
game/main.c
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
BIN
settings.ini
BIN
settings.ini
Binary file not shown.
Reference in New Issue
Block a user