better drawordering?

This commit is contained in:
Josh Deprez 2021-09-09 19:11:25 +10:00
parent 724b5af8a3
commit 5afa3a9b00
8 changed files with 35 additions and 27 deletions

View file

@ -41,9 +41,9 @@ func (d *DebugToast) Draw(screen *ebiten.Image, _ *ebiten.DrawImageOptions) {
ebitenutil.DebugPrintAt(screen, d.Text, d.Pos.X, d.Pos.Y)
}
func (d *DebugToast) DrawOrder() (int, int) {
func (d *DebugToast) DrawOrder() float64 {
// Always draw on top
return math.MaxInt, 0
return math.MaxFloat64
}
func (d *DebugToast) Toast(text string) {
@ -68,7 +68,7 @@ func (p PerfDisplay) Draw(screen *ebiten.Image, _ *ebiten.DrawImageOptions) {
ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f FPS: %0.2f", ebiten.CurrentTPS(), ebiten.CurrentFPS()))
}
func (PerfDisplay) DrawOrder() (int, int) {
func (PerfDisplay) DrawOrder() float64 {
// Always draw on top
return math.MaxInt, 0
return math.MaxFloat64
}

View file

@ -431,17 +431,12 @@ type tombstone struct{}
func (tombstone) Draw(*ebiten.Image, *ebiten.DrawImageOptions) {}
func (tombstone) DrawOrder() (int, int) { return math.MaxInt, math.MaxInt }
func (tombstone) DrawOrder() float64 { return math.Inf(1) }
type drawList []Drawer
func (d drawList) Less(i, j int) bool {
a0, a1 := d[i].DrawOrder()
b0, b1 := d[j].DrawOrder()
if a0 == b0 {
return a1 < b1
}
return a0 < b0
return d[i].DrawOrder() < d[j].DrawOrder()
}
func (d drawList) Len() int { return len(d) }

View file

@ -65,7 +65,7 @@ type Disabler interface {
// passed to Game.Register or returned from Scan).
type Drawer interface {
Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions)
DrawOrder() (z, bias int)
DrawOrder() float64
}
// Hider components can be hidden.

View file

@ -40,8 +40,8 @@ func (h *Hidden) Hide() { *h = true }
// Show sets h to false.
func (h *Hidden) Show() { *h = false }
// ZOrder implements DrawOrder (in Drawer) directly (as an int value).
type ZOrder int
// ZOrder implements DrawOrder (in Drawer) directly (as a numeric value).
type ZOrder float64
// DrawOrder returns z as a int with 0 bias.
func (z ZOrder) DrawOrder() (int, int) { return int(z), 0 }
// DrawOrder returns z.
func (z ZOrder) DrawOrder() float64 { return float64(z) }

View file

@ -149,9 +149,8 @@ func (p *Prism) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
screen.DrawImage(p.m.Sheet.SubImage(p.Cell), opts)
}
func (p *Prism) DrawOrder() (int, int) {
return p.m.PosToWorld.Apply(p.pos).Z,
geom.Dot(p.pos.XY(), image.Point(p.m.game.Projection).Mul(-1))
func (p *Prism) DrawOrder() float64 {
return p.m.game.Projection.DrawOrder(p.m.PosToWorld.Apply(p.pos))
}
func (p *Prism) Transform() (opts ebiten.DrawImageOptions) {

View file

@ -35,9 +35,9 @@ func (s *Sprite) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
screen.DrawImage(s.Sheet.SubImage(s.anim.Cell()), opts)
}
// DrawOrder returns the Z position from Actor.Pos, and 0 bias.
func (s *Sprite) DrawOrder() (int, int) {
return s.Actor.Pos.Z, 0
// DrawOrder returns the projected draw order.
func (s *Sprite) DrawOrder() float64 {
return s.Actor.game.Projection.DrawOrder(s.Actor.Pos)
}
// Scan returns the Actor and the Sheet.

View file

@ -265,11 +265,11 @@ func Level1() *engine.Scene {
CollisionDomain: "level_1",
Pos: geom.Pt3(100, -64, 100),
Bounds: geom.Box{
Min: geom.Pt3(-4, -16, -1),
Max: geom.Pt3(4, 0, 1),
Min: geom.Pt3(-4, -15, -1),
Max: geom.Pt3(4, 1, 1),
},
},
DrawOffset: image.Pt(-5, -16),
DrawOffset: image.Pt(-5, -15),
Sheet: engine.Sheet{
AnimDefs: map[string]*engine.AnimDef{
"idle_left": {Steps: []engine.AnimStep{

View file

@ -17,8 +17,8 @@ func (π IntProjection) Project(p Int3) image.Point {
Dividing is used because there's little reason for an isometric
projection in a game to exaggerate the Z position.
Integers are used to preserve that "pixel perfect" calculation in case
you are making the next Celeste.
Integers are used to preserve "pixel perfect" calculation in case you
are making the next Celeste.
*/
q := p.XY()
if π.X != 0 {
@ -29,3 +29,17 @@ func (π IntProjection) Project(p Int3) image.Point {
}
return q
}
// DrawOrder computes a draw-order value for a point under this projection.
// Each projection has an implied camera angle - Z alone is insufficient to
// order things properly.
func (π IntProjection) DrawOrder(p Int3) float64 {
z := float64(p.Z)
if π.X != 0 {
z -= float64(p.X) / float64(π.X)
}
if π.Y != 0 {
z -= float64(p.Y) / float64(π.Y)
}
return z
}