componentdb
This commit is contained in:
parent
facb9f8e91
commit
51d9a69a4b
3 changed files with 81 additions and 3 deletions
|
@ -4,6 +4,8 @@ import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
||||||
|
@ -24,3 +26,23 @@ func (PerfDisplay) Z() float64 {
|
||||||
// Always draw on top
|
// Always draw on top
|
||||||
return math.MaxFloat64
|
return math.MaxFloat64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d GobDumper) Update() error {
|
||||||
|
for _, key := range d.combo {
|
||||||
|
if !ebiten.IsKeyPressed(key) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f, err := os.Create(time.Now().Format("20060102030405.gob"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return gob.NewEncoder(f).Encode(d.game)
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,36 @@
|
||||||
package engine
|
package engine
|
||||||
|
|
||||||
import "github.com/hajimehoshi/ebiten/v2"
|
import (
|
||||||
|
"encoding/gob"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
gob.Register(Game{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// IDer components have a name. This makes it easier for components to
|
||||||
|
// find and interact with one another.
|
||||||
|
type IDer interface {
|
||||||
|
ID() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scanner components can be scanned. 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.
|
||||||
|
type Scanner interface {
|
||||||
|
Scan(game *Game) []interface{}
|
||||||
|
}
|
||||||
|
|
||||||
// Game implements the ebiten methods using a collection of components.
|
// Game implements the ebiten methods using a collection of components.
|
||||||
type Game struct {
|
type Game struct {
|
||||||
ScreenWidth int
|
ScreenWidth int
|
||||||
ScreenHeight int
|
ScreenHeight int
|
||||||
Scene *Scene
|
Scene *Scene
|
||||||
|
|
||||||
|
allComponents []interface{}
|
||||||
|
componentsByID map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw draws the entire thing.
|
// Draw draws the entire thing.
|
||||||
|
@ -23,3 +47,32 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (w, h int) {
|
||||||
func (g *Game) Update() error {
|
func (g *Game) Update() error {
|
||||||
return g.Scene.Update()
|
return g.Scene.Update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
if sc, ok := head.(Scanner); ok {
|
||||||
|
all = append(all, sc.Scan(g))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.allComponents = all
|
||||||
|
g.componentsByID = byID
|
||||||
|
}
|
||||||
|
|
|
@ -12,12 +12,12 @@ func init() {
|
||||||
gob.Register(Scene{})
|
gob.Register(Scene{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drawer is a component that can draw itself. Draw is called often.
|
// Drawer components can draw themselves. Draw is called often.
|
||||||
type Drawer interface {
|
type Drawer interface {
|
||||||
Draw(screen *ebiten.Image, geom ebiten.GeoM)
|
Draw(screen *ebiten.Image, geom ebiten.GeoM)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updater is a component that can update. Update is called repeatedly.
|
// Updater components can update themselves. Update is called repeatedly.
|
||||||
type Updater interface {
|
type Updater interface {
|
||||||
Update() error
|
Update() error
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,9 @@ func (s *Scene) sortByZ() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scan returns all subcomponents.
|
||||||
|
func (s *Scene) Scan(g *Game) []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 {
|
||||||
needsSort := false
|
needsSort := false
|
||||||
|
|
Loading…
Reference in a new issue