Added progress tracking.
This commit is contained in:
parent
8ef4e4ea3a
commit
1f26980ba3
@ -26,6 +26,7 @@ type Context struct {
|
||||
Textures map[string]texture
|
||||
Sprites map[string]sprite
|
||||
Levels map[string]levelPack
|
||||
Progress progress
|
||||
SpriteDrawer SpriteDrawer
|
||||
Settings settings
|
||||
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.DisplaySize = geom.Pt(disp.Width(), disp.Height())
|
||||
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 {
|
||||
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()
|
||||
if err != nil {
|
||||
log.Printf("Unable to store settings.")
|
||||
log.Printf("Unable to store settings; err: %v", err)
|
||||
}
|
||||
|
||||
log.Printf("Creating display.")
|
||||
|
@ -19,10 +19,15 @@ func (s *levelSelect) Enter(ctx *Context) error {
|
||||
s.ctx = ctx
|
||||
s.pack = s.ctx.Levels[s.packID]
|
||||
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 {
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
|
||||
"opslag.de/schobers/allg5"
|
||||
@ -60,7 +61,22 @@ func (l *playLevel) Leave() {}
|
||||
func (l *playLevel) onComplete() {
|
||||
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{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)
|
||||
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
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"opslag.de/schobers/allg5"
|
||||
)
|
||||
|
||||
@ -28,27 +24,11 @@ type settings struct {
|
||||
Video video
|
||||
}
|
||||
|
||||
func (s *settings) DefaultPath() (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 filepath.Join(dir, "settings.json"), nil
|
||||
}
|
||||
func (s *settings) DefaultPath() (string, error) { return userFile("settings.json") }
|
||||
|
||||
func (s *settings) Load(path string) error {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
var fromFile settings
|
||||
err = json.NewDecoder(f).Decode(&fromFile)
|
||||
err := decodeJSON(path, &fromFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -64,14 +44,7 @@ func (s *settings) LoadDefault() error {
|
||||
return s.Load(path)
|
||||
}
|
||||
|
||||
func (s *settings) Store(path string) error {
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
return json.NewEncoder(f).Encode(&s)
|
||||
}
|
||||
func (s *settings) Store(path string) error { return encodeJSON(path, s) }
|
||||
|
||||
func (s *settings) StoreDefault() error {
|
||||
path, err := s.DefaultPath()
|
||||
|
Loading…
Reference in New Issue
Block a user