From 3d75693cc210d68948596450abb1873c8070f427 Mon Sep 17 00:00:00 2001 From: Josh Deprez Date: Mon, 2 Aug 2021 12:16:10 +1000 Subject: [PATCH] Split Scan and Build --- engine/debug.go | 17 +++++++++++------ engine/game.go | 21 ++++++++++++++++----- engine/scene.go | 2 +- main.go | 2 +- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/engine/debug.go b/engine/debug.go index 6879712..fb8a60c 100644 --- a/engine/debug.go +++ b/engine/debug.go @@ -1,6 +1,7 @@ package engine import ( + "compress/gzip" "encoding/gob" "errors" "fmt" @@ -42,11 +43,10 @@ type GobDumper struct { game *Game } -func (d *GobDumper) Scan(g *Game) []interface{} { - d.game = g - return nil -} +// Build simply stores the reference to the Game. +func (d *GobDumper) Build(g *Game) { d.game = g } +// Update waits for the key combo, then dumps the game state into a gzipped gob. func (d *GobDumper) Update() error { for _, key := range d.KeyCombo { if !ebiten.IsKeyPressed(key) { @@ -56,12 +56,17 @@ func (d *GobDumper) Update() error { if d.game == nil { return errors.New("nil d.game in GobDumper.Update") } - f, err := os.Create(time.Now().Format("20060102030405.gob")) + f, err := os.Create(time.Now().Format("20060102030405.gob.gz")) if err != nil { return err } defer f.Close() - if err := gob.NewEncoder(f).Encode(d.game); err != nil { + gz := gzip.NewWriter(f) + defer gz.Close() + if err := gob.NewEncoder(gz).Encode(d.game); err != nil { + return err + } + if err := gz.Close(); err != nil { return err } return f.Close() diff --git a/engine/game.go b/engine/game.go index 13d50fe..d26cfa5 100644 --- a/engine/game.go +++ b/engine/game.go @@ -16,11 +16,18 @@ type Identifier interface { Ident() string } -// Scanner components can be scanned. It is called when the game +// Builder components can be built. It is called when the game // component database is being constructed. It should store the Game reference -// (if needed later on), and return a slice of all subcomponents. +// (if needed later on). +type Builder interface { + Build(game *Game) +} + +// Scanner components can be scanned. It is called when the game tree is walked +// (such as when the game component database is constructed). +// Scan should return a slice containing all subcomponents. type Scanner interface { - Scan(game *Game) []interface{} + Scan() []interface{} } // Game implements the ebiten methods using a collection of components. @@ -77,7 +84,8 @@ func (g *Game) UnregisterComponent(c interface{}) { // Component returns the component with a given ID, or nil if there is none. func (g *Game) Component(id string) interface{} { return g.componentsByID[id] } -// Walk calls v with every component, for as long as visit returns true. +// Walk calls v with every component reachable via Scan, for as long as visit +// returns true. func (g *Game) Walk(v func(interface{}) bool) { g.walk(g.Scene, v) } @@ -87,7 +95,7 @@ func (g *Game) walk(c interface{}, v func(interface{}) bool) { return } if sc, ok := c.(Scanner); ok { - for _, c := range sc.Scan(g) { + for _, c := range sc.Scan() { if !v(c) { return } @@ -100,6 +108,9 @@ func (g *Game) walk(c interface{}, v func(interface{}) bool) { func (g *Game) Build() { g.componentsByID = make(map[string]interface{}) g.Walk(func(c interface{}) bool { + if b, ok := c.(Builder); ok { + b.Build(g) + } g.RegisterComponent(c) return true }) diff --git a/engine/scene.go b/engine/scene.go index 3002b70..317c9e1 100644 --- a/engine/scene.go +++ b/engine/scene.go @@ -65,7 +65,7 @@ func (s *Scene) sortByZ() { } // Scan returns all subcomponents. -func (s *Scene) Scan(g *Game) []interface{} { return s.Components } +func (s *Scene) Scan() []interface{} { return s.Components } // Update calls Update on all Updater components. func (s *Scene) Update() error { diff --git a/main.go b/main.go index f36e450..1d57092 100644 --- a/main.go +++ b/main.go @@ -74,7 +74,7 @@ func main() { ScreenHeight: screenHeight, ScreenWidth: screenWidth, Scene: &engine.Scene{ - ID: "root_scene", + ID: "root", Components: []interface{}{ &engine.GobDumper{ KeyCombo: []ebiten.Key{ebiten.KeyControl, ebiten.KeyD},