From cd7b0fae998d5f423c025a33c1420a0d539ccfc5 Mon Sep 17 00:00:00 2001 From: Josh Deprez Date: Sun, 1 Aug 2021 16:41:10 +1000 Subject: [PATCH] change how walk works --- engine/debug.go | 25 ++++++++++++++++++++----- engine/game.go | 36 ++++++++++++++++++++---------------- main.go | 7 +++++++ 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/engine/debug.go b/engine/debug.go index 2f878dd..aaf1e25 100644 --- a/engine/debug.go +++ b/engine/debug.go @@ -2,6 +2,7 @@ package engine import ( "encoding/gob" + "errors" "fmt" "math" "os" @@ -12,6 +13,7 @@ import ( ) func init() { + gob.Register(GobDumper{}) gob.Register(PerfDisplay{}) } @@ -30,19 +32,32 @@ func (PerfDisplay) Z() float64 { // GobDumper waits for a given key combo, then dumps the game into a gob file // in the current directory. type GobDumper struct { - combo []ebiten.Key - game ebiten.Game + KeyCombo []ebiten.Key + + game *Game } -func (d GobDumper) Update() error { - for _, key := range d.combo { +func (d *GobDumper) Scan(g *Game) []interface{} { + d.game = g + return nil +} + +func (d *GobDumper) Update() error { + for _, key := range d.KeyCombo { if !ebiten.IsKeyPressed(key) { return nil } } + if d.game == nil { + return errors.New("nil d.game in GobDumper.Update") + } f, err := os.Create(time.Now().Format("20060102030405.gob")) if err != nil { return err } - return gob.NewEncoder(f).Encode(d.game) + defer f.Close() + if err := gob.NewEncoder(f).Encode(d.game); err != nil { + return err + } + return f.Close() } diff --git a/engine/game.go b/engine/game.go index fc26b3d..f2caf65 100644 --- a/engine/game.go +++ b/engine/game.go @@ -29,7 +29,6 @@ type Game struct { ScreenHeight int Scene *Scene - allComponents []interface{} componentsByID map[string]interface{} } @@ -51,11 +50,21 @@ func (g *Game) Update() error { // Component returns the component with a given ID. func (g *Game) Component(id string) interface{} { return g.componentsByID[id] } -// Walk calls visit with every component, for as long as visit returns true. -func (g *Game) Walk(visit func(interface{}) bool) { - for _, c := range g.allComponents { - if !visit(c) { - return +// Walk calls v with every component, for as long as visit returns true. +func (g *Game) Walk(v func(interface{}) bool) { + g.walk(g.Scene, v) +} + +func (g *Game) walk(c interface{}, v func(interface{}) bool) { + if !v(c) { + return + } + if sc, ok := c.(Scanner); ok { + for _, c := range sc.Scan(g) { + if !v(c) { + return + } + g.walk(c, v) } } } @@ -63,16 +72,11 @@ func (g *Game) Walk(visit func(interface{}) bool) { // Build builds the component database. func (g *Game) Build() { byID := make(map[string]interface{}) - all := []interface{}{g.Scene} - for offset := 0; offset < len(all); offset++ { - head := all[offset] - if id, ok := head.(IDer); ok { - byID[id.ID()] = head + g.walk(g.Scene, func(c interface{}) bool { + if id, ok := c.(IDer); ok { + byID[id.ID()] = c } - if sc, ok := head.(Scanner); ok { - all = append(all, sc.Scan(g)) - } - } - g.allComponents = all + return true + }) g.componentsByID = byID } diff --git a/main.go b/main.go index 335df59..a9ed90a 100644 --- a/main.go +++ b/main.go @@ -75,6 +75,12 @@ func main() { ScreenWidth: screenWidth, Scene: &engine.Scene{ Components: []interface{}{ + &engine.GobDumper{ + KeyCombo: []ebiten.Key{ + ebiten.KeyControl, + ebiten.KeyD, + }, + }, &engine.Tilemap{ Map: tiles, Src: engine.ImageRef{Path: "assets/boxes.png"}, @@ -84,6 +90,7 @@ func main() { }, }, } + game.Build() if err := ebiten.RunGame(game); err != nil { log.Fatalf("Game error: %v", err)