This commit is contained in:
Josh Deprez 2021-08-20 15:52:01 +10:00
parent 946b76df9a
commit b5792d3c8a
6 changed files with 35 additions and 32 deletions

View file

@ -55,6 +55,7 @@ type ImageRef struct {
// Image returns the image. If it hasn't been loaded yet, it loads.
// Multiple distinct ImageRefs can use the same path.
// TODO: adopt Loader?
func (r *ImageRef) Image() *ebiten.Image {
if r.image != nil {
return r.image
@ -78,6 +79,7 @@ func (r *ImageRef) Image() *ebiten.Image {
}
// SceneRef loads a gzipped, gob-encoded Scene from the asset FS.
// After Load, Scene is usable.
type SceneRef struct {
Path string
@ -101,17 +103,12 @@ func (r *SceneRef) Load() error {
if err := gob.NewDecoder(gz).Decode(sc); err != nil {
return err
}
if err := sc.Load(); err != nil {
return err
}
r.scene = sc
return sc.Load()
return nil
}
// Implement Scener by forwarding all the other calls to r.scene
func (r SceneRef) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) {
r.scene.Draw(screen, opts)
}
func (r SceneRef) DrawOrder() float64 { return r.scene.DrawOrder() }
func (r SceneRef) Ident() string { return r.scene.Ident() }
func (r SceneRef) Prepare(g *Game) { r.scene.Prepare(g) }
func (r SceneRef) Scan() []interface{} { return r.scene.Scan() }
func (r SceneRef) Update() error { return r.scene.Update() }
// Scene returns the loaded scene, or nil if not yet loaded.
func (r SceneRef) Scene() *Scene { return r.scene }

View file

@ -84,7 +84,7 @@ func (c *Camera) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) {
comm.Concat(opts.GeoM)
// Draw everything.
for _, i := range c.Scene.Components {
for _, i := range c.Scene.Scan() {
if d, ok := i.(Drawer); ok {
pf := 1.0
if s, ok := i.(ParallaxScaler); ok {
@ -106,5 +106,5 @@ func (c *Camera) Update() error { return c.Scene.Update() }
// Scan returns the only child (c.Scene).
func (c *Camera) Scan() []interface{} { return []interface{}{c.Scene} }
// Prepare grabs a copy of game.
// Prepare grabs a copy of game (needed for screen dimensions)
func (c *Camera) Prepare(game *Game) { c.game = game }

View file

@ -14,19 +14,19 @@ func init() {
type Game struct {
ScreenWidth int
ScreenHeight int
Scene *Scene
Scener
componentsByID map[string]interface{}
}
// Draw draws the entire thing, with default draw options.
func (g *Game) Draw(screen *ebiten.Image) {
g.Scene.Draw(screen, ebiten.DrawImageOptions{})
g.Scene().Draw(screen, ebiten.DrawImageOptions{})
}
// Update updates the current scene.
func (g *Game) Update() error {
return g.Scene.Update()
return g.Scene().Update()
}
// Layout returns the configured screen width/height.
@ -86,10 +86,10 @@ func Walk(c interface{}, v func(interface{}) error) error {
return nil
}
// PrepareToRun builds the component database (using Walk) and then calls
// Prepare on every Preparer. You must call PrepareToRun before passing to
// ebiten.RunGame.
func (g *Game) PrepareToRun() {
// Prepare builds the component database (using Walk) and then calls
// Prepare on every Preparer. You must call Prepare before any calls
// to Component.
func (g *Game) Prepare() {
g.componentsByID = make(map[string]interface{})
Walk(g, func(c interface{}) error {
g.RegisterComponent(c)

View file

@ -18,7 +18,7 @@ type Drawer interface {
Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions)
}
// DrawOrderer is used to reorder layers.
// DrawOrderer components can provide a number for determining draw order.
type DrawOrderer interface {
DrawOrder() float64
}
@ -55,16 +55,10 @@ type Scanner interface {
Scan() []interface{}
}
// Scener components do everything that a Scene can. The other implementation
// is SceneRef.
// Scener components are a scene (Scene or SceneRef).
type Scener interface {
Drawer
DrawOrderer
Identifier
Loader
Prepper
Scanner
Updater
Scene() *Scene
}
// Updater components can update themselves. Update is called repeatedly.

View file

@ -10,7 +10,16 @@ import (
)
// Ensure Scene satisfies Scener.
var _ Scener = &Scene{}
var (
_ Drawer = &Scene{}
_ DrawOrderer = &Scene{}
_ Identifier = &Scene{}
_ Loader = &Scene{}
_ Scanner = &Scene{}
_ Scener = &Scene{}
_ Prepper = &Scene{}
_ Updater = &Scene{}
)
func init() {
gob.Register(Scene{})
@ -73,6 +82,9 @@ func (s *Scene) sortByDrawOrder() {
// Scan returns all immediate subcomponents.
func (s *Scene) Scan() []interface{} { return s.Components }
// Scene returns itself.
func (s *Scene) Scene() *Scene { return s }
// Update calls Update on all Updater components.
func (s *Scene) Update() error {
if s.Disabled {

View file

@ -102,7 +102,7 @@ func main() {
game := &engine.Game{
ScreenHeight: 240,
ScreenWidth: 320,
Scene: &engine.Scene{
Scener: &engine.Scene{
ID: "root",
Components: []interface{}{
&engine.GobDumper{
@ -116,7 +116,7 @@ func main() {
},
},
}
game.PrepareToRun()
game.Prepare()
if err := ebiten.RunGame(game); err != nil {
log.Fatalf("Game error: %v", err)