ImageRef implements Loader
This commit is contained in:
parent
af89c01dbd
commit
245d939f2c
4 changed files with 33 additions and 12 deletions
|
@ -20,7 +20,8 @@ var (
|
||||||
|
|
||||||
imageCache = make(map[string]*ebiten.Image)
|
imageCache = make(map[string]*ebiten.Image)
|
||||||
|
|
||||||
// Ensure SceneRef does the same stuff as Scene.
|
// Ensure ref types satisfy interfaces.
|
||||||
|
_ Loader = &ImageRef{}
|
||||||
_ Scener = &SceneRef{}
|
_ Scener = &SceneRef{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -52,36 +53,43 @@ func (r *AnimRef) Anim() *Anim {
|
||||||
|
|
||||||
// ImageRef loads images from the AssetFS into *ebiten.Image form.
|
// ImageRef loads images from the AssetFS into *ebiten.Image form.
|
||||||
// It is your responsibility to import _ "image/..." for whatever
|
// It is your responsibility to import _ "image/..." for whatever
|
||||||
// format the files are in.
|
// format the files are in, and to load it (either return it as a
|
||||||
|
// subcomponent from Scan so that Game will Load it, or call Load
|
||||||
|
// yourself).
|
||||||
type ImageRef struct {
|
type ImageRef struct {
|
||||||
Path string
|
Path string
|
||||||
|
|
||||||
image *ebiten.Image
|
image *ebiten.Image
|
||||||
}
|
}
|
||||||
|
|
||||||
// Image returns the image. If it hasn't been loaded yet, it loads.
|
// Image returns the image, or nil if not loaded.
|
||||||
// Multiple distinct ImageRefs can use the same path.
|
// Multiple distinct ImageRefs can use the same path.
|
||||||
// TODO: adopt Loader?
|
|
||||||
func (r *ImageRef) Image() *ebiten.Image {
|
func (r *ImageRef) Image() *ebiten.Image {
|
||||||
if r.image != nil {
|
return r.image
|
||||||
return r.image
|
}
|
||||||
}
|
|
||||||
|
// Load loads the image. Load is required before Image returns.
|
||||||
|
// Loading the same path multiple times uses a cache to return
|
||||||
|
// the same image.
|
||||||
|
func (r *ImageRef) Load() error {
|
||||||
|
// Fast path load from cache
|
||||||
r.image = imageCache[r.Path]
|
r.image = imageCache[r.Path]
|
||||||
if r.image != nil {
|
if r.image != nil {
|
||||||
return r.image
|
return nil
|
||||||
}
|
}
|
||||||
|
// Slow path
|
||||||
f, err := AssetFS.Open(r.Path)
|
f, err := AssetFS.Open(r.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Couldn't open asset: %v", err)
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
i, _, err := image.Decode(f)
|
i, _, err := image.Decode(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Couldn't decode asset: %v", err)
|
return err
|
||||||
}
|
}
|
||||||
r.image = ebiten.NewImageFromImage(i)
|
r.image = ebiten.NewImageFromImage(i)
|
||||||
imageCache[r.Path] = r.image
|
imageCache[r.Path] = r.image
|
||||||
return r.image
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SceneRef loads a gzipped, gob-encoded Scene from the asset FS.
|
// SceneRef loads a gzipped, gob-encoded Scene from the asset FS.
|
||||||
|
|
|
@ -13,6 +13,7 @@ var (
|
||||||
_ Drawer = &Image{}
|
_ Drawer = &Image{}
|
||||||
_ DrawOrderer = &Image{}
|
_ DrawOrderer = &Image{}
|
||||||
_ ParallaxScaler = &Image{}
|
_ ParallaxScaler = &Image{}
|
||||||
|
_ Scanner = &Image{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -36,3 +37,6 @@ func (i *Image) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) {
|
||||||
opts.GeoM = geom
|
opts.GeoM = geom
|
||||||
screen.DrawImage(i.Src.Image(), &opts)
|
screen.DrawImage(i.Src.Image(), &opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scan returns a slice containing Src.
|
||||||
|
func (i *Image) Scan() []interface{} { return []interface{}{&i.Src} }
|
||||||
|
|
|
@ -51,7 +51,12 @@ func (s *Sprite) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) {
|
||||||
screen.DrawImage(src.SubImage(image.Rectangle{sp, sp.Add(s.FrameSize)}).(*ebiten.Image), &opts)
|
screen.DrawImage(src.SubImage(image.Rectangle{sp, sp.Add(s.FrameSize)}).(*ebiten.Image), &opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Sprite) Scan() []interface{} { return []interface{}{&s.Actor} }
|
func (s *Sprite) Scan() []interface{} {
|
||||||
|
return []interface{}{
|
||||||
|
&s.Actor,
|
||||||
|
&s.Src,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Sprite) SetAnim(a *Anim) {
|
func (s *Sprite) SetAnim(a *Anim) {
|
||||||
if s.anim != a {
|
if s.anim != a {
|
||||||
|
|
|
@ -13,6 +13,7 @@ var (
|
||||||
_ Collider = &Tilemap{}
|
_ Collider = &Tilemap{}
|
||||||
_ Drawer = &Tilemap{}
|
_ Drawer = &Tilemap{}
|
||||||
_ DrawOrderer = &Tilemap{}
|
_ DrawOrderer = &Tilemap{}
|
||||||
|
_ Scanner = &Tilemap{}
|
||||||
_ Updater = &Tilemap{}
|
_ Updater = &Tilemap{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -86,6 +87,9 @@ func (t *Tilemap) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scan returns a slice containing Src.
|
||||||
|
func (t *Tilemap) Scan() []interface{} { return []interface{}{&t.Src} }
|
||||||
|
|
||||||
// Update calls Update on any tiles that are Updaters, e.g. AnimatedTile.
|
// Update calls Update on any tiles that are Updaters, e.g. AnimatedTile.
|
||||||
func (t *Tilemap) Update() error {
|
func (t *Tilemap) Update() error {
|
||||||
if t.Disabled {
|
if t.Disabled {
|
||||||
|
|
Loading…
Reference in a new issue