big Scener won

This commit is contained in:
Josh Deprez 2021-08-20 16:23:10 +10:00
parent b5792d3c8a
commit c352221606
5 changed files with 60 additions and 17 deletions

View file

@ -24,6 +24,12 @@ var (
_ Scener = &SceneRef{}
)
func init() {
gob.Register(AnimRef{})
gob.Register(ImageRef{})
gob.Register(SceneRef{})
}
// AnimRef manages an Anim using a premade AnimDef from the cache.
type AnimRef struct {
Key string
@ -80,6 +86,13 @@ func (r *ImageRef) Image() *ebiten.Image {
// SceneRef loads a gzipped, gob-encoded Scene from the asset FS.
// After Load, Scene is usable.
// This is mostly useful for scenes that refer to other scenes, e.g.
//
// var sc = &Scene{
// Components: []interface{}{
// SceneRef{Path: "assets/foo.gob.gz"}
// },
// }
type SceneRef struct {
Path string
@ -112,3 +125,26 @@ func (r *SceneRef) Load() error {
// Scene returns the loaded scene, or nil if not yet loaded.
func (r SceneRef) Scene() *Scene { return r.scene }
// The rest of the methods forward to r.scene, as such they will
// panic if the scene isn't loaded.
// Draw draws the scene.
func (r SceneRef) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) {
r.scene.Draw(screen, opts)
}
// DrawOrder returns the value of DrawOrder from the scene.
func (r SceneRef) DrawOrder() float64 { return r.scene.DrawOrder() }
// Ident returns the value of Ident from the scene.
func (r SceneRef) Ident() string { return r.scene.Ident() }
// Prepare prepares the scene.
func (r SceneRef) Prepare(g *Game) { r.scene.Prepare(g) }
// Scan returns the components in the scene.
func (r SceneRef) Scan() []interface{} { return r.scene.Scan() }
// Update updates the scene.
func (r SceneRef) Update() error { return r.scene.Update() }

View file

@ -24,11 +24,6 @@ func (g *Game) Draw(screen *ebiten.Image) {
g.Scene().Draw(screen, ebiten.DrawImageOptions{})
}
// Update updates the current scene.
func (g *Game) Update() error {
return g.Scene().Update()
}
// Layout returns the configured screen width/height.
func (g *Game) Layout(outsideWidth, outsideHeight int) (w, h int) {
return g.ScreenWidth, g.ScreenHeight
@ -88,7 +83,8 @@ func Walk(c interface{}, v func(interface{}) error) error {
// Prepare builds the component database (using Walk) and then calls
// Prepare on every Preparer. You must call Prepare before any calls
// to Component.
// to Component. You may call Prepare again (e.g. as an alternative to
// fastidiously calling RegisterComponent/UnregisterComponent).
func (g *Game) Prepare() {
g.componentsByID = make(map[string]interface{})
Walk(g, func(c interface{}) error {

View file

@ -57,7 +57,24 @@ type Scanner interface {
// Scener components are a scene (Scene or SceneRef).
type Scener interface {
// Q: Why not make Scener a small interface with just Scene() ?
// A: Everything in the engine would then need to type switch for Scener or SceneRef, i.e.
// switch x := i.(type) {
// case Drawer:
// i.Draw(screen, opts)
// case Scener:
// i.Scene().Draw(screen, opts)
// }
// It seems cleaner to let the engine assert only for the interface it needs at that moment.
Drawer
DrawOrderer
Identifier
Loader
Prepper
Scanner
Updater
Scene() *Scene
}

View file

@ -10,16 +10,7 @@ import (
)
// Ensure Scene satisfies Scener.
var (
_ Drawer = &Scene{}
_ DrawOrderer = &Scene{}
_ Identifier = &Scene{}
_ Loader = &Scene{}
_ Scanner = &Scene{}
_ Scener = &Scene{}
_ Prepper = &Scene{}
_ Updater = &Scene{}
)
var _ Scener = &Scene{}
func init() {
gob.Register(Scene{})
@ -48,7 +39,7 @@ func (s *Scene) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) {
}
}
// Load loads any components that need loading.
// Load loads any subcomponents that need loading.
func (s *Scene) Load() error {
for _, i := range s.Components {
l, ok := i.(Loader)

View file

@ -116,6 +116,9 @@ func main() {
},
},
}
if err := game.Load(); err != nil {
log.Fatalf("Loading error: %v", err)
}
game.Prepare()
if err := ebiten.RunGame(game); err != nil {