Added progress tracking.
This commit is contained in:
parent
8ef4e4ea3a
commit
1f26980ba3
@ -26,6 +26,7 @@ type Context struct {
|
|||||||
Textures map[string]texture
|
Textures map[string]texture
|
||||||
Sprites map[string]sprite
|
Sprites map[string]sprite
|
||||||
Levels map[string]levelPack
|
Levels map[string]levelPack
|
||||||
|
Progress progress
|
||||||
SpriteDrawer SpriteDrawer
|
SpriteDrawer SpriteDrawer
|
||||||
Settings settings
|
Settings settings
|
||||||
Palette *alui.Palette
|
Palette *alui.Palette
|
||||||
|
@ -196,6 +196,10 @@ func (g *game) Init(disp *allg5.Display, settings settings, res vfs.CopyDir, con
|
|||||||
g.ctx = &Context{Resources: res, Textures: map[string]texture{}, Settings: settings, Navigation: navigation{game: g}}
|
g.ctx = &Context{Resources: res, Textures: map[string]texture{}, Settings: settings, Navigation: navigation{game: g}}
|
||||||
g.ctx.DisplaySize = geom.Pt(disp.Width(), disp.Height())
|
g.ctx.DisplaySize = geom.Pt(disp.Width(), disp.Height())
|
||||||
g.ctx.SpriteDrawer.ctx = g.ctx
|
g.ctx.SpriteDrawer.ctx = g.ctx
|
||||||
|
err := g.ctx.Progress.load()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Unable to load previous progress.")
|
||||||
|
}
|
||||||
if err := g.initUI(disp, cons, fps); err != nil {
|
if err := g.initUI(disp, cons, fps); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
50
cmd/krampus19/io.go
Normal file
50
cmd/krampus19/io.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func decodeJSON(path string, v interface{}) error {
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
err = json.NewDecoder(f).Decode(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeJSON(path string, v interface{}) error {
|
||||||
|
f, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
return json.NewEncoder(f).Encode(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func userDir() (string, error) {
|
||||||
|
config, err := os.UserConfigDir()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
dir := filepath.Join(config, "krampus19")
|
||||||
|
err = os.MkdirAll(dir, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return dir, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func userFile(name string) (string, error) {
|
||||||
|
dir, err := userDir()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return filepath.Join(dir, name), nil
|
||||||
|
}
|
@ -48,7 +48,7 @@ func run() error {
|
|||||||
}
|
}
|
||||||
err = settings.StoreDefault()
|
err = settings.StoreDefault()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Unable to store settings.")
|
log.Printf("Unable to store settings; err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Creating display.")
|
log.Printf("Creating display.")
|
||||||
|
@ -19,10 +19,15 @@ func (s *levelSelect) Enter(ctx *Context) error {
|
|||||||
s.ctx = ctx
|
s.ctx = ctx
|
||||||
s.pack = s.ctx.Levels[s.packID]
|
s.pack = s.ctx.Levels[s.packID]
|
||||||
s.Init()
|
s.Init()
|
||||||
name := func(id string) string { return fmt.Sprintf("Level %s", id) }
|
name := func(id string, steps int) string {
|
||||||
|
if steps == 0 {
|
||||||
|
return fmt.Sprintf("Level %s", id)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Level %s (%d)", id, steps)
|
||||||
|
}
|
||||||
for _, id := range s.pack.order {
|
for _, id := range s.pack.order {
|
||||||
levelID := id
|
levelID := id
|
||||||
s.Add(name(levelID), func() {
|
s.Add(name(levelID, s.ctx.Progress.Level(s.packID, levelID).Steps), func() {
|
||||||
s.ctx.Navigation.PlayLevel(s.packID, levelID)
|
s.ctx.Navigation.PlayLevel(s.packID, levelID)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"opslag.de/schobers/allg5"
|
"opslag.de/schobers/allg5"
|
||||||
@ -60,7 +61,22 @@ func (l *playLevel) Leave() {}
|
|||||||
func (l *playLevel) onComplete() {
|
func (l *playLevel) onComplete() {
|
||||||
menu := alui.NewMenu()
|
menu := alui.NewMenu()
|
||||||
menu.AddChild(alui.NewMargins(&alui.Label{ControlBase: alui.ControlBase{Font: "header"}, Text: "Congratulations", TextAlign: allg5.AlignCenter}, 3*margin, 0, 2*margin))
|
menu.AddChild(alui.NewMargins(&alui.Label{ControlBase: alui.ControlBase{Font: "header"}, Text: "Congratulations", TextAlign: allg5.AlignCenter}, 3*margin, 0, 2*margin))
|
||||||
menu.AddChild(alui.NewMargins(&alui.Label{Text: fmt.Sprintf("You've completed the level in %d steps", l.state.steps), TextAlign: allg5.AlignCenter}, 0, 0, 2*margin))
|
menu.AddChild(alui.NewMargins(&alui.Label{Text: fmt.Sprintf("You've completed the level in %d steps.", l.state.steps), TextAlign: allg5.AlignCenter}, 0, 0, 2*margin))
|
||||||
|
|
||||||
|
progress := l.ctx.Progress.Level(l.packID, l.levelID)
|
||||||
|
if l.state.steps < progress.Steps || progress.Steps == 0 {
|
||||||
|
var improvement = progress.Steps - l.state.steps
|
||||||
|
if improvement > 0 { // first time it is lower than zero (no previous record).
|
||||||
|
menu.AddChild(alui.NewMargins(&alui.Label{Text: fmt.Sprintf("This is an improvement of %d steps.", improvement), TextAlign: allg5.AlignCenter}, 0, 0, 2*margin))
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.ctx.Progress.Update(l.packID, l.levelID, func(p *levelProgress) {
|
||||||
|
p.Steps = l.state.steps
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Unable to store progress; err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nextID, ok := l.state.pack.FindNext(l.levelID)
|
nextID, ok := l.state.pack.FindNext(l.levelID)
|
||||||
if ok {
|
if ok {
|
||||||
|
67
cmd/krampus19/progress.go
Normal file
67
cmd/krampus19/progress.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type progress struct {
|
||||||
|
Packs map[string]packProgress
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *progress) Pack(packID string) packProgress {
|
||||||
|
if p.Packs == nil {
|
||||||
|
p.Packs = map[string]packProgress{}
|
||||||
|
}
|
||||||
|
return p.Packs[packID]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *progress) Level(packID, levelID string) levelProgress {
|
||||||
|
pack := p.Pack(packID)
|
||||||
|
return pack.Level(levelID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *progress) Update(packID, levelID string, update func(*levelProgress)) error {
|
||||||
|
pack := p.Pack(packID)
|
||||||
|
pack.Update(levelID, update)
|
||||||
|
p.Packs[packID] = pack
|
||||||
|
return p.store()
|
||||||
|
}
|
||||||
|
|
||||||
|
type packProgress struct {
|
||||||
|
Levels map[string]levelProgress
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *packProgress) Level(id string) levelProgress {
|
||||||
|
if p.Levels == nil {
|
||||||
|
p.Levels = map[string]levelProgress{}
|
||||||
|
}
|
||||||
|
return p.Levels[id]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *packProgress) Update(id string, update func(*levelProgress)) {
|
||||||
|
level := p.Level(id)
|
||||||
|
update(&level)
|
||||||
|
p.Levels[id] = level
|
||||||
|
}
|
||||||
|
|
||||||
|
type levelProgress struct {
|
||||||
|
Steps int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *progress) store() error {
|
||||||
|
path, err := userFile("progress.json")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return encodeJSON(path, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *progress) load() error {
|
||||||
|
path, err := userFile("progress.json")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var fromFile progress
|
||||||
|
err = decodeJSON(path, &fromFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*p = fromFile
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,10 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"opslag.de/schobers/allg5"
|
"opslag.de/schobers/allg5"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,27 +24,11 @@ type settings struct {
|
|||||||
Video video
|
Video video
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *settings) DefaultPath() (string, error) {
|
func (s *settings) DefaultPath() (string, error) { return userFile("settings.json") }
|
||||||
config, err := os.UserConfigDir()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
dir := filepath.Join(config, "krampus19")
|
|
||||||
err = os.MkdirAll(dir, 0600)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return filepath.Join(dir, "settings.json"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *settings) Load(path string) error {
|
func (s *settings) Load(path string) error {
|
||||||
f, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
var fromFile settings
|
var fromFile settings
|
||||||
err = json.NewDecoder(f).Decode(&fromFile)
|
err := decodeJSON(path, &fromFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -64,14 +44,7 @@ func (s *settings) LoadDefault() error {
|
|||||||
return s.Load(path)
|
return s.Load(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *settings) Store(path string) error {
|
func (s *settings) Store(path string) error { return encodeJSON(path, s) }
|
||||||
f, err := os.Create(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
return json.NewEncoder(f).Encode(&s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *settings) StoreDefault() error {
|
func (s *settings) StoreDefault() error {
|
||||||
path, err := s.DefaultPath()
|
path, err := s.DefaultPath()
|
||||||
|
Loading…
Reference in New Issue
Block a user