1
0
Fork 0

feat: implement persistant configuration

This commit is contained in:
Henrik Hautakoski 2025-10-28 06:35:14 +01:00
parent 30b194619f
commit 8a02249845
5 changed files with 82 additions and 0 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
/tetris /tetris
/tetris.exe /tetris.exe
/config.json

21
game/config.go Normal file
View file

@ -0,0 +1,21 @@
package game
import (
"io"
"tetris/game/config"
)
// Global config variable with default values.
var Config = &config.Config{
SoundVolume: 255,
}
func LoadConfig(configPath string) error {
cfg, err := config.LoadFromFile(configPath)
if err != nil && err != io.EOF {
return err
}
Config = cfg
return nil
}

45
game/config/config.go Normal file
View file

@ -0,0 +1,45 @@
package config
import (
"encoding/json"
"io"
"os"
)
type Config struct {
fd *os.File
SoundVolume byte `json:"sound_volume"`
}
func DefaultConfig(fd *os.File) *Config {
cfg := Config{
SoundVolume: 255,
}
cfg.fd = fd
return &cfg
}
func LoadFromFile(filename string) (*Config, error) {
fd, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0o644)
if err != nil {
return nil, err
}
cfg := DefaultConfig(fd)
err = json.NewDecoder(fd).Decode(cfg)
return cfg, err
}
func (c Config) Save() error {
if err := c.fd.Truncate(0); err != nil {
return err
}
if _, err := c.fd.Seek(0, io.SeekStart); err != nil {
return err
}
return json.NewEncoder(c.fd).Encode(c)
}
func (c Config) Close() error {
return c.fd.Close()
}

View file

@ -5,6 +5,7 @@ import (
"tetris/engine/audio" "tetris/engine/audio"
"tetris/engine/core" "tetris/engine/core"
"tetris/engine/render" "tetris/engine/render"
"tetris/game"
"tetris/game/state" "tetris/game/state"
"tetris/game/ui" "tetris/game/ui"
"tetris/game/ui/layouts" "tetris/game/ui/layouts"
@ -24,6 +25,10 @@ func soundVolumeChanged(widget *widgets.Slider) {
audio.SetVolume(value) audio.SetVolume(value)
audio.Play(assets.SFX_MENU_SOUND_VOLUME_SELECT) audio.Play(assets.SFX_MENU_SOUND_VOLUME_SELECT)
// Store in config and save
game.Config.SoundVolume = byte(widget.Value)
game.Config.Save()
} }
func NewOptionsMenu() *OptionsMenu { func NewOptionsMenu() *OptionsMenu {

View file

@ -1,10 +1,14 @@
package main package main
import ( import (
"fmt"
"tetris/assets" "tetris/assets"
"tetris/engine/audio" "tetris/engine/audio"
"tetris/engine/core"
"tetris/engine/graphics" "tetris/engine/graphics"
"tetris/engine/render" "tetris/engine/render"
"tetris/game"
"tetris/game/state/handlers" "tetris/game/state/handlers"
"tetris/game/state/machine" "tetris/game/state/machine"
@ -12,6 +16,10 @@ import (
) )
func main() { func main() {
if err := game.LoadConfig("./config.json"); err != nil {
fmt.Println("Failed to load config:", err)
}
render.Init(render.Config{ render.Init(render.Config{
Title: "Tetris", Title: "Tetris",
WindowWidth: 685, WindowWidth: 685,
@ -34,6 +42,8 @@ func main() {
audio.Init() audio.Init()
defer audio.Exit() defer audio.Exit()
// Set volume from config
audio.SetVolume(core.ByteToClampedFloat32(game.Config.SoundVolume))
audio.LoadLibrary(assets.LoadSound()) audio.LoadLibrary(assets.LoadSound())
// Load texture // Load texture