M12: ljud, inställningar och release v0.1.0
All checks were successful
release / build-release (push) Successful in 1m35s

tools/gensound syntetiserar 21 ljud: fyra stationsmelodier i klockklang
(en per station via melody-fältet eller banans id), ankomstjingel,
ding-dong vid inrullning, dörrsignal vid avgång, spärrens pip och
nekande, kiosk, toalett, lärt ord, bekräfta/varning, byte, personal,
vinst, förlust, flygplan, sorl och menymusik. sfx.go spelar effekter
utifrån vad som hänt i sim.Run sedan förra bildrutan. Ljudlagret har
huvudvolym × effekter/musik och byter inte slinga i onödan.
Inställningar (S på bankartan, sparas): volymer, språk sv/en som laddas
om direkt, fönsterskala, fullskärm (F11 överallt) och tangentöversikt.
Fönsterikon från genart. CHANGELOG.md. Tester för ljudfiler, melodival
och inställningar. Docs, wiki och skärmdumpar uppdaterade.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 08:31:38 +01:00
parent 36a45563ec
commit 86f8130735
47 changed files with 800 additions and 107 deletions

View File

@@ -42,6 +42,32 @@ type State struct {
Current *RunRef `json:"current,omitempty"`
NavMode string `json:"navMode,omitempty"` // "list" (standard) eller "signs"
Endless []EndlessRecord `json:"endless,omitempty"` // oändligt läge: bästa omgångarna, högst poäng först
Settings *Settings `json:"settings,omitempty"`
}
// Settings är spelarens inställningar (M12).
type Settings struct {
Master int `json:"master"` // 0–10
Effects int `json:"effects"` // 0–10
Music int `json:"music"` // 0–10 (musik och sorl)
Lang string `json:"lang"` // "sv" eller "en"
Scale int `json:"scale"` // fönsterskala 1–6, 0 = flaggan -scale
Fullscreen bool `json:"fullscreen"`
}
// DefaultSettings är standardinställningarna.
func DefaultSettings() *Settings { return &Settings{Master: 8, Effects: 8, Music: 6, Lang: "sv"} }
// normalize ser till att inställningarna är rimliga (saknade = standard).
func (s *Settings) normalize() {
clamp := func(v *int) { *v = max(0, min(10, *v)) }
clamp(&s.Master)
clamp(&s.Effects)
clamp(&s.Music)
if s.Lang != "sv" && s.Lang != "en" {
s.Lang = "sv"
}
s.Scale = max(0, min(6, s.Scale))
}
// EndlessRecord är en avslutad omgång i oändligt läge.
@@ -77,7 +103,7 @@ func (s *State) BestEndless() *EndlessRecord {
// New är ett nytt spel.
func New() *State {
return &State{Version: Version, Know: lang.NewKnowledge(), Wallet: sim.NewWallet(), Profile: &sim.Profile{}, Progress: progress.New()}
return &State{Version: Version, Know: lang.NewKnowledge(), Wallet: sim.NewWallet(), Profile: &sim.Profile{}, Progress: progress.New(), Settings: DefaultSettings()}
}
// DefaultPath är sparfilens plats: ~/.config/metro-puzzle-jp/save.json på
@@ -116,6 +142,10 @@ func migrate(s *State) error {
}
// Version 0 (saknat fält) och 1 har samma form; här läggs framtida steg.
s.Version = Version
if s.Settings == nil {
s.Settings = DefaultSettings()
}
s.Settings.normalize()
if s.Know == nil {
s.Know = lang.NewKnowledge()
}