diff --git a/engine/asset.go b/engine/asset.go index 3cf7c57..a2ed7c7 100644 --- a/engine/asset.go +++ b/engine/asset.go @@ -1,7 +1,6 @@ package engine import ( - "compress/gzip" "encoding/gob" "image" "io/fs" @@ -16,7 +15,7 @@ var ( // TODO: put in Game AnimDefs map[string]*AnimDef - imageCache = make(map[string]*ebiten.Image) + imageCache = make(map[assetKey]*ebiten.Image) // Ensure ref types satisfy interfaces. _ Loader = &ImageRef{} @@ -30,6 +29,11 @@ func init() { gob.Register(SceneRef{}) } +type assetKey struct { + assets fs.FS + path string +} + // AnimRef manages an Anim using a premade AnimDef from the cache. type AnimRef struct { Key string @@ -72,7 +76,7 @@ func (r *ImageRef) Image() *ebiten.Image { // the same image. func (r *ImageRef) Load(assets fs.FS) error { // Fast path load from cache - r.image = imageCache[r.Path] + r.image = imageCache[assetKey{assets, r.Path}] if r.image != nil { return nil } @@ -87,76 +91,6 @@ func (r *ImageRef) Load(assets fs.FS) error { return err } r.image = ebiten.NewImageFromImage(i) - imageCache[r.Path] = r.image + imageCache[assetKey{assets, r.Path}] = r.image return nil } - -// 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 - - scene *Scene // not exported for gob reasons -} - -// Load loads the scene from the file. -func (r *SceneRef) Load(assets fs.FS) error { - f, err := assets.Open(r.Path) - if err != nil { - return err - } - defer f.Close() - - gz, err := gzip.NewReader(f) - if err != nil { - return err - } - sc := new(Scene) - if err := gob.NewDecoder(gz).Decode(sc); err != nil { - return err - } - r.scene = sc - return nil -} - -// The rest of the methods forward to r.scene, as such they will -// panic if the scene isn't loaded. - -// BoundingRect returns the Bounds from the scene. -func (r SceneRef) BoundingRect() image.Rectangle { return r.scene.BoundingRect() } - -// 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() } - -// IsHidden returns the value of IsHidden from the scene. -func (r SceneRef) IsHidden() bool { return r.scene.IsHidden() } - -// Hide calls Hide on the scene. -func (r SceneRef) Hide() { r.scene.Hide() } - -// Show calls Show on the scene. -func (r SceneRef) Show() { r.scene.Show() } - -// 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() } diff --git a/engine/sceneref.go b/engine/sceneref.go new file mode 100644 index 0000000..2d51df0 --- /dev/null +++ b/engine/sceneref.go @@ -0,0 +1,80 @@ +package engine + +import ( + "compress/gzip" + "encoding/gob" + "image" + "io/fs" + + "github.com/hajimehoshi/ebiten/v2" +) + +// 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 + + scene *Scene // not exported for gob reasons +} + +// Load loads the scene from the file. +func (r *SceneRef) Load(assets fs.FS) error { + f, err := assets.Open(r.Path) + if err != nil { + return err + } + defer f.Close() + + gz, err := gzip.NewReader(f) + if err != nil { + return err + } + sc := new(Scene) + if err := gob.NewDecoder(gz).Decode(sc); err != nil { + return err + } + r.scene = sc + return nil +} + +// The rest of the methods forward to r.scene, as such they will +// panic if the scene isn't loaded. + +// BoundingRect returns the Bounds from the scene. +func (r SceneRef) BoundingRect() image.Rectangle { return r.scene.BoundingRect() } + +// 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() } + +// IsHidden returns the value of IsHidden from the scene. +func (r SceneRef) IsHidden() bool { return r.scene.IsHidden() } + +// Hide calls Hide on the scene. +func (r SceneRef) Hide() { r.scene.Hide() } + +// Show calls Show on the scene. +func (r SceneRef) Show() { r.scene.Show() } + +// 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() } diff --git a/engine/tiles.go b/engine/tiles.go index d586806..eed40bf 100644 --- a/engine/tiles.go +++ b/engine/tiles.go @@ -13,6 +13,7 @@ var ( _ Collider = &Tilemap{} _ Drawer = &Tilemap{} _ DrawOrderer = &Tilemap{} + _ Hider = &Tilemap{} _ Scanner = &Tilemap{} _ Updater = &Tilemap{} ) @@ -25,10 +26,10 @@ func init() { // Tilemap renders a grid of tiles. type Tilemap struct { + ID Disabled bool ZOrder - Hidden bool - ID + Hidden Map map[image.Point]Tile Ersatz bool // "fake wall" Offset image.Point // world coordinates