Split Scan and Build
This commit is contained in:
parent
1c8d054aff
commit
3d75693cc2
4 changed files with 29 additions and 13 deletions
|
@ -1,6 +1,7 @@
|
||||||
package engine
|
package engine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"compress/gzip"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -42,11 +43,10 @@ type GobDumper struct {
|
||||||
game *Game
|
game *Game
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *GobDumper) Scan(g *Game) []interface{} {
|
// Build simply stores the reference to the Game.
|
||||||
d.game = g
|
func (d *GobDumper) Build(g *Game) { d.game = g }
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Update waits for the key combo, then dumps the game state into a gzipped gob.
|
||||||
func (d *GobDumper) Update() error {
|
func (d *GobDumper) Update() error {
|
||||||
for _, key := range d.KeyCombo {
|
for _, key := range d.KeyCombo {
|
||||||
if !ebiten.IsKeyPressed(key) {
|
if !ebiten.IsKeyPressed(key) {
|
||||||
|
@ -56,12 +56,17 @@ func (d *GobDumper) Update() error {
|
||||||
if d.game == nil {
|
if d.game == nil {
|
||||||
return errors.New("nil d.game in GobDumper.Update")
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
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 err
|
||||||
}
|
}
|
||||||
return f.Close()
|
return f.Close()
|
||||||
|
|
|
@ -16,11 +16,18 @@ type Identifier interface {
|
||||||
Ident() string
|
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
|
// 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 {
|
type Scanner interface {
|
||||||
Scan(game *Game) []interface{}
|
Scan() []interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Game implements the ebiten methods using a collection of components.
|
// 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.
|
// 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] }
|
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) {
|
func (g *Game) Walk(v func(interface{}) bool) {
|
||||||
g.walk(g.Scene, v)
|
g.walk(g.Scene, v)
|
||||||
}
|
}
|
||||||
|
@ -87,7 +95,7 @@ func (g *Game) walk(c interface{}, v func(interface{}) bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if sc, ok := c.(Scanner); ok {
|
if sc, ok := c.(Scanner); ok {
|
||||||
for _, c := range sc.Scan(g) {
|
for _, c := range sc.Scan() {
|
||||||
if !v(c) {
|
if !v(c) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -100,6 +108,9 @@ func (g *Game) walk(c interface{}, v func(interface{}) bool) {
|
||||||
func (g *Game) Build() {
|
func (g *Game) Build() {
|
||||||
g.componentsByID = make(map[string]interface{})
|
g.componentsByID = make(map[string]interface{})
|
||||||
g.Walk(func(c interface{}) bool {
|
g.Walk(func(c interface{}) bool {
|
||||||
|
if b, ok := c.(Builder); ok {
|
||||||
|
b.Build(g)
|
||||||
|
}
|
||||||
g.RegisterComponent(c)
|
g.RegisterComponent(c)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
|
@ -65,7 +65,7 @@ func (s *Scene) sortByZ() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan returns all subcomponents.
|
// 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.
|
// Update calls Update on all Updater components.
|
||||||
func (s *Scene) Update() error {
|
func (s *Scene) Update() error {
|
||||||
|
|
2
main.go
2
main.go
|
@ -74,7 +74,7 @@ func main() {
|
||||||
ScreenHeight: screenHeight,
|
ScreenHeight: screenHeight,
|
||||||
ScreenWidth: screenWidth,
|
ScreenWidth: screenWidth,
|
||||||
Scene: &engine.Scene{
|
Scene: &engine.Scene{
|
||||||
ID: "root_scene",
|
ID: "root",
|
||||||
Components: []interface{}{
|
Components: []interface{}{
|
||||||
&engine.GobDumper{
|
&engine.GobDumper{
|
||||||
KeyCombo: []ebiten.Key{ebiten.KeyControl, ebiten.KeyD},
|
KeyCombo: []ebiten.Key{ebiten.KeyControl, ebiten.KeyD},
|
||||||
|
|
Loading…
Reference in a new issue