more transforms; fix first update-ordering crash :-)

This commit is contained in:
Josh Deprez 2021-09-01 09:48:01 +10:00
parent 400552e742
commit 6155e64c60
10 changed files with 58 additions and 31 deletions

Binary file not shown.

View file

@ -16,6 +16,7 @@ type AnimFrame struct {
} }
// Anim is n animation being displayed, together with the current state. // Anim is n animation being displayed, together with the current state.
// A nil *Anim can be used, but always returns 0 for the current frame.
type Anim struct { type Anim struct {
Frames []AnimFrame Frames []AnimFrame
OneShot bool OneShot bool
@ -25,18 +26,34 @@ type Anim struct {
// Copy makes a shallow copy of the anim. // Copy makes a shallow copy of the anim.
func (a *Anim) Copy() *Anim { func (a *Anim) Copy() *Anim {
if a == nil {
return nil
}
a2 := *a a2 := *a
return &a2 return &a2
} }
// CurrentFrame returns the frame number for the current index. // CurrentFrame returns the frame number for the current index.
func (a *Anim) CurrentFrame() int { return a.Frames[a.Index].Frame } func (a *Anim) CurrentFrame() int {
if a == nil {
return 0
}
return a.Frames[a.Index].Frame
}
// Reset resets both Index and Ticks to 0. // Reset resets both Index and Ticks to 0.
func (a *Anim) Reset() { a.Index, a.Ticks = 0, 0 } func (a *Anim) Reset() {
if a == nil {
return
}
a.Index, a.Ticks = 0, 0
}
// Update increments the tick count and advances the frame if necessary. // Update increments the tick count and advances the frame if necessary.
func (a *Anim) Update() error { func (a *Anim) Update() error {
if a == nil {
return nil
}
a.Ticks++ a.Ticks++
if a.OneShot && a.Index == len(a.Frames)-1 { if a.OneShot && a.Index == len(a.Frames)-1 {
// on the last frame of a one shot so remain on final frame // on the last frame of a one shot so remain on final frame

View file

@ -30,13 +30,14 @@ type Billboard struct {
} }
// Draw draws the image. // Draw draws the image.
func (b *Billboard) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) { func (b *Billboard) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
var geom ebiten.GeoM screen.DrawImage(b.Src.Image(), opts)
geom.Translate(float64(b.Pos.X), float64(b.Pos.Y))
geom.Concat(opts.GeoM)
opts.GeoM = geom
screen.DrawImage(b.Src.Image(), &opts)
} }
// Scan returns a slice containing Src. // Scan returns a slice containing Src.
func (b *Billboard) Scan() []interface{} { return []interface{}{&b.Src} } func (b *Billboard) Scan() []interface{} { return []interface{}{&b.Src} }
func (b *Billboard) Transform() (opts ebiten.DrawImageOptions) {
opts.GeoM.Translate(float2(b.Pos))
return opts
}

View file

@ -10,12 +10,21 @@ import (
"github.com/hajimehoshi/ebiten/v2/ebitenutil" "github.com/hajimehoshi/ebiten/v2/ebitenutil"
) )
var _ interface { var (
Drawer _ interface {
Hider Drawer
} = &PerfDisplay{} Hider
} = &PerfDisplay{}
_ interface {
Drawer
Hider
Updater
} = &DebugToast{}
)
func init() { func init() {
gob.Register(&DebugToast{})
gob.Register(&PerfDisplay{}) gob.Register(&PerfDisplay{})
} }
@ -28,7 +37,7 @@ type DebugToast struct {
Text string Text string
} }
func (d *DebugToast) Draw(screen *ebiten.Image, _ ebiten.DrawImageOptions) { func (d *DebugToast) Draw(screen *ebiten.Image, _ *ebiten.DrawImageOptions) {
ebitenutil.DebugPrintAt(screen, d.Text, d.Pos.X, d.Pos.Y) ebitenutil.DebugPrintAt(screen, d.Text, d.Pos.X, d.Pos.Y)
} }
@ -54,7 +63,7 @@ type PerfDisplay struct {
Hidden Hidden
} }
func (p PerfDisplay) Draw(screen *ebiten.Image, _ ebiten.DrawImageOptions) { func (p PerfDisplay) Draw(screen *ebiten.Image, _ *ebiten.DrawImageOptions) {
ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f FPS: %0.2f", ebiten.CurrentTPS(), ebiten.CurrentFPS())) ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f FPS: %0.2f", ebiten.CurrentTPS(), ebiten.CurrentFPS()))
} }

View file

@ -28,6 +28,6 @@ type Fill struct {
ZOrder ZOrder
} }
func (f *Fill) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) { func (f *Fill) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
screen.Fill(opts.ColorM.Apply(f.Color)) screen.Fill(opts.ColorM.Apply(f.Color))
} }

View file

@ -104,7 +104,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
if st.hidden { if st.hidden {
continue continue
} }
d.Draw(screen, st.opts) d.Draw(screen, &st.opts)
} }
} }
@ -390,7 +390,7 @@ var _ Drawer = tombstone{}
type tombstone struct{} type tombstone struct{}
func (tombstone) Draw(*ebiten.Image, ebiten.DrawImageOptions) {} func (tombstone) Draw(*ebiten.Image, *ebiten.DrawImageOptions) {}
func (tombstone) DrawOrder() float64 { return math.Inf(1) } func (tombstone) DrawOrder() float64 { return math.Inf(1) }

View file

@ -79,7 +79,7 @@ type Disabler interface {
// must call Draw on any internal components not known to the engine (i.e. not // must call Draw on any internal components not known to the engine (i.e. not
// passed to Game.Register or returned from Scan). // passed to Game.Register or returned from Scan).
type Drawer interface { type Drawer interface {
Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions)
DrawOrder() float64 DrawOrder() float64
} }

View file

@ -30,8 +30,8 @@ type Sprite struct {
anim *Anim anim *Anim
} }
func (s *Sprite) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) { func (s *Sprite) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
screen.DrawImage(s.Sheet.SubImage(s.anim.CurrentFrame()), &opts) screen.DrawImage(s.Sheet.SubImage(s.anim.CurrentFrame()), opts)
} }
func (s *Sprite) Scan() []interface{} { func (s *Sprite) Scan() []interface{} {
@ -53,5 +53,6 @@ func (s *Sprite) Transform() (opts ebiten.DrawImageOptions) {
return opts return opts
} }
// anim isn't returned from Scan so we must update it ourselves // anim can change a bit so we don't tell Game about it, but that means it must
// be updated here.
func (s *Sprite) Update() error { return s.anim.Update() } func (s *Sprite) Update() error { return s.anim.Update() }

View file

@ -65,7 +65,7 @@ func (t *Tilemap) CollidesWith(r image.Rectangle) bool {
} }
// Draw draws the tilemap. // Draw draws the tilemap.
func (t *Tilemap) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) { func (t *Tilemap) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
og := opts.GeoM og := opts.GeoM
var geom ebiten.GeoM var geom ebiten.GeoM
for p, tile := range t.Map { for p, tile := range t.Map {
@ -78,7 +78,7 @@ func (t *Tilemap) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) {
opts.GeoM = geom opts.GeoM = geom
src := t.Sheet.SubImage(tile.CellIndex()) src := t.Sheet.SubImage(tile.CellIndex())
screen.DrawImage(src, &opts) screen.DrawImage(src, opts)
} }
} }

View file

@ -78,14 +78,8 @@ type WallUnit struct {
wall *Wall wall *Wall
} }
func (u *WallUnit) Draw(screen *ebiten.Image, opts ebiten.DrawImageOptions) { func (u *WallUnit) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
var geom ebiten.GeoM screen.DrawImage(u.wall.Sheet.SubImage(u.Tile.CellIndex()), opts)
geom.Translate(float2(mul2(u.Pos, u.wall.UnitSize).Add(u.wall.UnitOffset).Add(u.wall.Offset)))
geom.Concat(opts.GeoM)
opts.GeoM = geom
src := u.wall.Sheet.SubImage(u.Tile.CellIndex())
screen.DrawImage(src, &opts)
} }
func (u *WallUnit) Prepare(g *Game) error { func (u *WallUnit) Prepare(g *Game) error {
@ -95,3 +89,8 @@ func (u *WallUnit) Prepare(g *Game) error {
} }
func (u *WallUnit) Scan() []interface{} { return []interface{}{u.Tile} } func (u *WallUnit) Scan() []interface{} { return []interface{}{u.Tile} }
func (u *WallUnit) Transform() (opts ebiten.DrawImageOptions) {
opts.GeoM.Translate(float2(mul2(u.Pos, u.wall.UnitSize).Add(u.wall.UnitOffset).Add(u.wall.Offset)))
return opts
}