draw ordering works now
This commit is contained in:
parent
ad2346f9ff
commit
f8dd02c072
6 changed files with 159 additions and 46 deletions
|
@ -40,10 +40,8 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (DebugToast) DrawAfter(x Drawer) bool {
|
func (DebugToast) DrawAfter(x Drawer) bool { return x != Tombstone{} }
|
||||||
// Always draw on top
|
func (DebugToast) DrawBefore(x Drawer) bool { return x == Tombstone{} }
|
||||||
return x != Tombstone{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DebugToast) Toast(text string) {
|
func (d *DebugToast) Toast(text string) {
|
||||||
d.Text = text
|
d.Text = text
|
||||||
|
@ -67,7 +65,5 @@ 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()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (PerfDisplay) DrawAfter(x Drawer) bool {
|
func (PerfDisplay) DrawAfter(x Drawer) bool { return x != Tombstone{} }
|
||||||
// Always draw on top
|
func (PerfDisplay) DrawBefore(x Drawer) bool { return x == Tombstone{} }
|
||||||
return x != Tombstone{}
|
|
||||||
}
|
|
||||||
|
|
|
@ -176,7 +176,8 @@ func (g *Game) Update() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort the draw list (on every frame - this isn't as bad as it sounds)
|
// Sort the draw list (on every frame - this isn't as bad as it sounds)
|
||||||
sort.Stable(g.drawList)
|
//sort.Stable(g.drawList)
|
||||||
|
sort.Sort(g.drawList)
|
||||||
// Truncate tombstones from the end.
|
// Truncate tombstones from the end.
|
||||||
for i := len(g.drawList) - 1; i >= 0; i-- {
|
for i := len(g.drawList) - 1; i >= 0; i-- {
|
||||||
if g.drawList[i] == (Tombstone{}) {
|
if g.drawList[i] == (Tombstone{}) {
|
||||||
|
@ -430,13 +431,14 @@ type Tombstone struct{}
|
||||||
|
|
||||||
func (Tombstone) Draw(*ebiten.Image, *ebiten.DrawImageOptions) {}
|
func (Tombstone) Draw(*ebiten.Image, *ebiten.DrawImageOptions) {}
|
||||||
|
|
||||||
func (Tombstone) DrawAfter(x Drawer) bool {
|
func (Tombstone) DrawAfter(x Drawer) bool { return x != Tombstone{} }
|
||||||
return x != Tombstone{}
|
func (Tombstone) DrawBefore(Drawer) bool { return false }
|
||||||
}
|
|
||||||
|
|
||||||
type drawList []Drawer
|
type drawList []Drawer
|
||||||
|
|
||||||
func (d drawList) Less(i, j int) bool { return d[j].DrawAfter(d[i]) }
|
func (d drawList) Less(i, j int) bool {
|
||||||
|
return d[i].DrawBefore(d[j]) || d[j].DrawAfter(d[i])
|
||||||
|
}
|
||||||
func (d drawList) Len() int { return len(d) }
|
func (d drawList) Len() int { return len(d) }
|
||||||
func (d drawList) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
|
func (d drawList) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,9 @@ 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(*ebiten.Image, *ebiten.DrawImageOptions)
|
||||||
DrawAfter(x Drawer) bool
|
DrawAfter(Drawer) bool
|
||||||
|
DrawBefore(Drawer) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hider components can be hidden.
|
// Hider components can be hidden.
|
||||||
|
|
|
@ -43,17 +43,28 @@ func (h *Hidden) Show() { *h = false }
|
||||||
// ZPosition implements DrawAfter and DrawPosition as a simple Z coordinate.
|
// ZPosition implements DrawAfter and DrawPosition as a simple Z coordinate.
|
||||||
type ZPosition int
|
type ZPosition int
|
||||||
|
|
||||||
// DrawAfter reports if z > x.Z.
|
// DrawAfter reports if z >= x.Max.Z.
|
||||||
func (z ZPosition) DrawAfter(x Drawer) bool {
|
func (z ZPosition) DrawAfter(x Drawer) bool {
|
||||||
switch d := x.(type) {
|
switch d := x.(type) {
|
||||||
case BoundingBoxer:
|
case BoundingBoxer:
|
||||||
return int(z) > d.BoundingBox().Max.Z
|
return int(z) >= d.BoundingBox().Max.Z
|
||||||
case zpositioner:
|
case zpositioner:
|
||||||
return z.zposition() > d.zposition()
|
return z.zposition() > d.zposition()
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DrawBefore reports if z < x.Min.Z.
|
||||||
|
func (z ZPosition) DrawBefore(x Drawer) bool {
|
||||||
|
switch d := x.(type) {
|
||||||
|
case BoundingBoxer:
|
||||||
|
return int(z) < d.BoundingBox().Min.Z
|
||||||
|
case zpositioner:
|
||||||
|
return z.zposition() < d.zposition()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (z ZPosition) zposition() int { return int(z) }
|
func (z ZPosition) zposition() int { return int(z) }
|
||||||
|
|
||||||
type zpositioner interface {
|
type zpositioner interface {
|
||||||
|
|
|
@ -147,31 +147,95 @@ func (p *Prism) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
func (p *Prism) DrawAfter(x Drawer) bool {
|
func (p *Prism) DrawAfter(x Drawer) bool {
|
||||||
pb := p.BoundingBox()
|
pb := p.BoundingBox()
|
||||||
switch d := x.(type) {
|
switch d := x.(type) {
|
||||||
|
case *Prism:
|
||||||
|
if p.pos.Z == d.pos.Z {
|
||||||
|
return p.pos.Y < d.pos.Y
|
||||||
|
}
|
||||||
|
return p.pos.Z > d.pos.Z
|
||||||
case BoundingBoxer:
|
case BoundingBoxer:
|
||||||
xb := d.BoundingBox()
|
xb := d.BoundingBox()
|
||||||
// Z ?
|
if pb.Max.Z <= xb.Min.Z { // p is behind x
|
||||||
if pb.Min.Z >= xb.Max.Z { // p is unambiguously in front
|
/*if _, ok := x.(*Sprite); ok && pb.Min.Y < 0 {
|
||||||
return true
|
log.Print("p.DrawAfter: prism is behind sprite")
|
||||||
}
|
}*/
|
||||||
if pb.Max.Z <= xb.Min.Z { // p is unambiguously behind
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Y ? (NB: up is negative)
|
if pb.Min.Z >= xb.Max.Z { // p is in front of x
|
||||||
if pb.Max.Y <= xb.Min.Y { // p is above
|
/*if _, ok := x.(*Sprite); ok && pb.Min.Y < 0 {
|
||||||
|
log.Print("p.DrawAfter: prism is in front of sprite")
|
||||||
|
}*/
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if pb.Min.Y >= xb.Max.Y { // p is below
|
if pb.Min.Y >= xb.Max.Y { // p is below x
|
||||||
|
/*if _, ok := x.(*Sprite); ok && pb.Min.Y < 0 {
|
||||||
|
log.Print("p.DrawAfter: prism is below sprite")
|
||||||
|
}*/
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if pb.Max.Y <= xb.Min.Y { // p is above x
|
||||||
|
/*if _, ok := x.(*Sprite); ok && pb.Min.Y < 0 {
|
||||||
|
log.Print("p.DrawAfter: prism is above sprite")
|
||||||
|
}*/
|
||||||
|
return true
|
||||||
|
}
|
||||||
// The hexagon special
|
// The hexagon special
|
||||||
if pb.Min.Z+8 >= xb.Max.Z {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if pb.Min.Z+8 <= xb.Min.Z {
|
if pb.Min.Z+8 <= xb.Min.Z {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if pb.Min.Z+8 >= xb.Max.Z {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
case zpositioner:
|
case zpositioner:
|
||||||
return pb.Min.Z > int(d.zposition())
|
return pb.Min.Z > int(d.zposition()) // p is after x
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrawBefore reports if the prism should be drawn before x.
|
||||||
|
func (p *Prism) DrawBefore(x Drawer) bool {
|
||||||
|
pb := p.BoundingBox()
|
||||||
|
switch d := x.(type) {
|
||||||
|
case *Prism:
|
||||||
|
if p.pos.Z == d.pos.Z {
|
||||||
|
return p.pos.Y > d.pos.Y
|
||||||
|
}
|
||||||
|
return p.pos.Z < d.pos.Z
|
||||||
|
case BoundingBoxer:
|
||||||
|
xb := d.BoundingBox()
|
||||||
|
if pb.Min.Z >= xb.Max.Z { // p is in front of x
|
||||||
|
/*if _, ok := x.(*Sprite); ok && pb.Min.Y < 0 {
|
||||||
|
log.Print("p.DrawBefore: prism is in front of sprite")
|
||||||
|
}*/
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if pb.Max.Z <= xb.Min.Z { // p is behind x
|
||||||
|
/*if _, ok := x.(*Sprite); ok && pb.Min.Y < 0 {
|
||||||
|
log.Print("p.DrawBefore: prism is behind sprite")
|
||||||
|
}*/
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if pb.Max.Y <= xb.Min.Y { // p is above x
|
||||||
|
/*if pb.Min.Y < 0 {
|
||||||
|
log.Print("p.DrawBefore: prism is above sprite")
|
||||||
|
}*/
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if pb.Min.Y >= xb.Max.Y { // p is below x
|
||||||
|
/*if pb.Min.Y < 0 {
|
||||||
|
log.Print("p.DrawBefore: prism is below sprite")
|
||||||
|
}*/
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// The hexagon special
|
||||||
|
if pb.Min.Z+8 >= xb.Max.Z {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if pb.Min.Z+8 <= xb.Min.Z {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case zpositioner:
|
||||||
|
return pb.Max.Z < int(d.zposition()) // p is before x
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,35 +39,74 @@ func (s *Sprite) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
screen.DrawImage(s.Sheet.SubImage(s.anim.Cell()), opts)
|
screen.DrawImage(s.Sheet.SubImage(s.anim.Cell()), opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawAfter reports if the sprite must be drawn after x.
|
// DrawAfter reports if the sprite should be drawn after x.
|
||||||
func (s *Sprite) DrawAfter(x Drawer) bool {
|
func (s *Sprite) DrawAfter(x Drawer) bool {
|
||||||
sb := s.BoundingBox()
|
sb := s.BoundingBox()
|
||||||
switch d := x.(type) {
|
switch d := x.(type) {
|
||||||
case BoundingBoxer:
|
case BoundingBoxer:
|
||||||
xb := d.BoundingBox()
|
xb := d.BoundingBox()
|
||||||
// Z ?
|
if sb.Max.Z <= xb.Min.Z { // s is behind x
|
||||||
if sb.Min.Z >= xb.Max.Z { // s is unambiguously in front
|
/*if xb.Min.Y < 0 {
|
||||||
return true
|
log.Print("s.DrawAfter: sprite is behind prism")
|
||||||
}
|
}*/
|
||||||
if sb.Max.Z <= xb.Min.Z { // s is unambiguously behind
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Y ? (NB: up is negative)
|
if sb.Min.Z >= xb.Max.Z { // s is in front of x
|
||||||
if sb.Max.Y <= xb.Min.Y { // s is unambiguously above
|
/*if xb.Min.Y < 0 {
|
||||||
|
log.Print("s.DrawAfter: sprite is in front of prism")
|
||||||
|
}*/
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if sb.Min.Y >= xb.Max.Y { // s is unambiguously below
|
if sb.Min.Y >= xb.Max.Y { // s is below x
|
||||||
|
/*if xb.Min.Y < 0 {
|
||||||
|
log.Print("s.DrawAfter: sprite is below prism")
|
||||||
|
}*/
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Hexagon special
|
if sb.Max.Y <= xb.Min.Y { // s is above x
|
||||||
if sb.Min.Z > xb.Min.Z+8 {
|
/*if xb.Min.Y < 0 {
|
||||||
|
log.Print("s.DrawAfter: sprite is above prism")
|
||||||
|
}*/
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if sb.Max.Z < sb.Min.Z+8 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
case zpositioner:
|
case zpositioner:
|
||||||
return sb.Min.Z > int(d.zposition())
|
return sb.Min.Z > int(d.zposition()) // s is after
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrawBefore reports if the sprite should be drawn before x.
|
||||||
|
func (s *Sprite) DrawBefore(x Drawer) bool {
|
||||||
|
sb := s.BoundingBox()
|
||||||
|
switch d := x.(type) {
|
||||||
|
case BoundingBoxer:
|
||||||
|
xb := d.BoundingBox()
|
||||||
|
if sb.Min.Z >= xb.Max.Z { // s is in front of x
|
||||||
|
/*if xb.Min.Y < 0 {
|
||||||
|
log.Print("s.DrawBefore: sprite is in front of prism")
|
||||||
|
}*/
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if sb.Max.Z <= xb.Min.Z { // s is behind x
|
||||||
|
/*if xb.Min.Y < 0 {
|
||||||
|
log.Print("s.DrawBefore: sprite is behind prism")
|
||||||
|
}*/
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if sb.Max.Y <= xb.Min.Y { // s is above x
|
||||||
|
/*if xb.Min.Y < 0 {
|
||||||
|
log.Print("s.DrawBefore: sprite is above prism")
|
||||||
|
}*/
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if sb.Min.Y >= xb.Max.Y { // s is below x
|
||||||
|
/*if xb.Min.Y < 0 {
|
||||||
|
log.Print("s.DrawBefore: sprite is below prism")
|
||||||
|
}*/
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case zpositioner:
|
||||||
|
return sb.Max.Z < int(d.zposition()) // s is before
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue