Lazily load sprite image data
This cuts memory use significantly, since many sprites in an object are never used. We can get savings over time by evicting sprites when they go out of scope, but that's, well, out of scope. To achieve this, I introduce an assetstore package that is in charge of loading things from the filesystem. This also allows some lingering case-sensitivity issues to be handled cleanly. I'd hoped that creating fewer ebiten.Image instances would help CPU usage, but that doesn't seem to be the case.
This commit is contained in:
89
internal/assetstore/map.go
Normal file
89
internal/assetstore/map.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package assetstore
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"image"
|
||||
|
||||
"code.ur.gs/lupine/ordoor/internal/maps"
|
||||
)
|
||||
|
||||
type Map struct {
|
||||
assets *AssetStore
|
||||
set *Set
|
||||
Rect image.Rectangle
|
||||
|
||||
raw *maps.GameMap
|
||||
}
|
||||
|
||||
// Map loads a game map with the given name (e.g. "Chapter01")
|
||||
func (a *AssetStore) Map(name string) (*Map, error) {
|
||||
name = canonical(name)
|
||||
|
||||
if m, ok := a.maps[name]; ok {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
mapFile, err := a.lookup(name, "map", "Maps", "MultiMaps")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txtFile, err := a.lookup(name, "txt", "Maps", "MultiMaps")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
raw, err := maps.LoadGameMapByFiles(mapFile, txtFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The set for a map is small and frequently referenced, so load it here
|
||||
set, err := a.Set(raw.MapSetName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m := &Map{
|
||||
Rect: image.Rect(
|
||||
int(raw.MinWidth),
|
||||
int(raw.MinLength),
|
||||
int(raw.MaxWidth),
|
||||
int(raw.MaxLength),
|
||||
),
|
||||
assets: a,
|
||||
raw: raw,
|
||||
set: set,
|
||||
}
|
||||
|
||||
a.maps[canonical(name)] = m
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// ImagesForCell returns the sprites needed to correctly render this cell.
|
||||
// They should be rendered from first to last to get the correct ordering
|
||||
func (m *Map) ImagesForCell(x, y, z int) ([]*ebiten.Image, error) {
|
||||
cell := m.raw.At(x, y, z)
|
||||
images := make([]*ebiten.Image, 0, 4)
|
||||
|
||||
for _, ref := range []maps.ObjRef{cell.Surface, cell.Center, cell.Left, cell.Right} {
|
||||
if !ref.IsActive() {
|
||||
continue
|
||||
}
|
||||
|
||||
obj, err := m.set.Object(ref.Index())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
img, err := obj.Image(ref.Sprite())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
images = append(images, img)
|
||||
}
|
||||
|
||||
return images, nil
|
||||
}
|
Reference in New Issue
Block a user