Respect sprite X and Y offsets
This makes menus display more correctly, and also fixes trees and other objects on the main map, although it messes up bounds clipping (sigh).
This commit is contained in:
@@ -4,8 +4,6 @@ import (
|
||||
"image"
|
||||
"log"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
|
||||
"code.ur.gs/lupine/ordoor/internal/maps"
|
||||
)
|
||||
|
||||
@@ -64,11 +62,11 @@ func (a *AssetStore) Map(name string) (*Map, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// ImagesForCell returns the sprites needed to correctly render this cell.
|
||||
// SpritesForCell 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) {
|
||||
func (m *Map) SpritesForCell(x, y, z int) ([]*Sprite, error) {
|
||||
cell := m.raw.At(x, y, z)
|
||||
images := make([]*ebiten.Image, 0, 4)
|
||||
sprites := make([]*Sprite, 0, 4)
|
||||
|
||||
for _, ref := range []maps.ObjRef{cell.Surface, cell.Right, cell.Left, cell.Center} {
|
||||
if !ref.IsActive() {
|
||||
@@ -80,13 +78,13 @@ func (m *Map) ImagesForCell(x, y, z int) ([]*ebiten.Image, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
img, err := obj.Image(ref.Sprite())
|
||||
sprite, err := obj.Sprite(ref.Sprite())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
images = append(images, img)
|
||||
sprites = append(sprites, sprite)
|
||||
}
|
||||
|
||||
return images, nil
|
||||
return sprites, nil
|
||||
}
|
||||
|
@@ -9,12 +9,23 @@ import (
|
||||
)
|
||||
|
||||
type Object struct {
|
||||
assets *AssetStore
|
||||
images []*ebiten.Image
|
||||
assets *AssetStore
|
||||
sprites []*Sprite
|
||||
|
||||
raw *data.Object
|
||||
}
|
||||
|
||||
type Sprite struct {
|
||||
obj *Object
|
||||
|
||||
XOffset int
|
||||
YOffset int
|
||||
Width int
|
||||
Height int
|
||||
|
||||
Image *ebiten.Image
|
||||
}
|
||||
|
||||
func (a *AssetStore) Object(name string) (*Object, error) {
|
||||
name = canonical(name)
|
||||
|
||||
@@ -35,9 +46,9 @@ func (a *AssetStore) Object(name string) (*Object, error) {
|
||||
raw.Name = name
|
||||
|
||||
obj := &Object{
|
||||
assets: a,
|
||||
images: make([]*ebiten.Image, int(raw.NumSprites)),
|
||||
raw: raw,
|
||||
assets: a,
|
||||
sprites: make([]*Sprite, int(raw.NumSprites)),
|
||||
raw: raw,
|
||||
}
|
||||
a.objs[name] = obj
|
||||
|
||||
@@ -45,11 +56,11 @@ func (a *AssetStore) Object(name string) (*Object, error) {
|
||||
}
|
||||
|
||||
// Filled lazily
|
||||
func (o *Object) Image(idx int) (*ebiten.Image, error) {
|
||||
if img := o.images[idx]; img != nil {
|
||||
return img, nil
|
||||
func (o *Object) Sprite(idx int) (*Sprite, error) {
|
||||
if sprite := o.sprites[idx]; sprite != nil {
|
||||
return sprite, nil
|
||||
}
|
||||
log.Printf("Loading sprite %v %v", o.raw.Name, idx)
|
||||
log.Printf("Loading sprite %v:%v", o.raw.Name, idx)
|
||||
|
||||
if o.raw.Sprites[idx] == nil {
|
||||
if err := o.raw.LoadSprite(idx); err != nil {
|
||||
@@ -57,13 +68,22 @@ func (o *Object) Image(idx int) (*ebiten.Image, error) {
|
||||
}
|
||||
}
|
||||
|
||||
stdImg := o.raw.Sprites[idx].ToImage()
|
||||
img, err := ebiten.NewImageFromImage(stdImg, ebiten.FilterDefault)
|
||||
raw := o.raw.Sprites[idx]
|
||||
img, err := ebiten.NewImageFromImage(raw.ToImage(), ebiten.FilterDefault)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
o.images[idx] = img
|
||||
sprite := &Sprite{
|
||||
obj: o,
|
||||
Width: int(raw.Width),
|
||||
Height: int(raw.Width),
|
||||
XOffset: int(raw.XOffset),
|
||||
YOffset: int(raw.YOffset),
|
||||
Image: img,
|
||||
}
|
||||
|
||||
return img, nil
|
||||
o.sprites[idx] = sprite
|
||||
|
||||
return sprite, nil
|
||||
}
|
||||
|
@@ -11,8 +11,10 @@ import (
|
||||
// * Width & height now stored using int
|
||||
// * Colour data is now 32-bit rather than using a palette
|
||||
type Sprite struct {
|
||||
Width int
|
||||
Height int
|
||||
XOffset int
|
||||
YOffset int
|
||||
Width int
|
||||
Height int
|
||||
|
||||
Image *ebiten.Image
|
||||
}
|
||||
@@ -39,14 +41,18 @@ func ConvertObject(rawObj *data.Object, name string) (*Object, error) {
|
||||
}
|
||||
|
||||
for i, rawSpr := range rawObj.Sprites {
|
||||
w := int(rawSpr.Width)
|
||||
h := int(rawSpr.Height)
|
||||
ebitenImage, err := ebiten.NewImageFromImage(rawSpr.ToImage(), ebiten.FilterDefault)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out.Sprites[i] = &Sprite{Width: w, Height: h, Image: ebitenImage}
|
||||
out.Sprites[i] = &Sprite{
|
||||
XOffset: int(rawSpr.XOffset),
|
||||
YOffset: int(rawSpr.YOffset),
|
||||
Width: int(rawSpr.Width),
|
||||
Height: int(rawSpr.Height),
|
||||
Image: ebitenImage,
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
|
@@ -14,7 +14,8 @@ import (
|
||||
)
|
||||
|
||||
type SpriteHeader struct {
|
||||
Unknown0 uint32
|
||||
XOffset uint16
|
||||
YOffset uint16
|
||||
Width uint16
|
||||
Height uint16
|
||||
Padding1 uint32 // I don't think this is used. Could be wrong.
|
||||
|
@@ -15,6 +15,9 @@ import (
|
||||
var (
|
||||
screenScale = flag.Float64("screen-scale", 1.0, "Scale the window by this factor")
|
||||
|
||||
winX = flag.Int("win-x", 1280, "Pre-scaled window X dimension")
|
||||
winY = flag.Int("win-y", 1024, "Pre-scaled window Y dimension")
|
||||
|
||||
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
|
||||
)
|
||||
|
||||
@@ -27,7 +30,7 @@ type Window struct {
|
||||
updateFn func() error
|
||||
drawFn func(*ebiten.Image) error
|
||||
|
||||
debug bool
|
||||
debug bool
|
||||
firstRun bool
|
||||
}
|
||||
|
||||
@@ -103,16 +106,16 @@ func (w *Window) Run(updateFn func() error, drawFn func(*ebiten.Image) error) er
|
||||
w.drawFn = drawFn
|
||||
|
||||
if *cpuprofile != "" {
|
||||
f, err := os.Create(*cpuprofile)
|
||||
if err != nil {
|
||||
log.Fatal("could not create CPU profile: ", err)
|
||||
}
|
||||
defer f.Close() // error handling omitted for example
|
||||
if err := pprof.StartCPUProfile(f); err != nil {
|
||||
log.Fatal("could not start CPU profile: ", err)
|
||||
}
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
f, err := os.Create(*cpuprofile)
|
||||
if err != nil {
|
||||
log.Fatal("could not create CPU profile: ", err)
|
||||
}
|
||||
defer f.Close() // error handling omitted for example
|
||||
if err := pprof.StartCPUProfile(f); err != nil {
|
||||
log.Fatal("could not start CPU profile: ", err)
|
||||
}
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
return ebiten.Run(w.run, 640, 480, 1, w.Title) // Native game resolution: 640x480
|
||||
return ebiten.Run(w.run, *winX, *winY, 1, w.Title) // Native game resolution: 640x480
|
||||
}
|
||||
|
Reference in New Issue
Block a user