progress on draw ordering
This commit is contained in:
parent
550cb5ef73
commit
bdb8e6775e
17 changed files with 182 additions and 76 deletions
|
@ -7,7 +7,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ensure Actor satisfies interfaces.
|
// Ensure Actor satisfies interfaces.
|
||||||
var _ Prepper = &Actor{}
|
var _ interface {
|
||||||
|
BoundingBoxer
|
||||||
|
Prepper
|
||||||
|
} = &Actor{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
gob.Register(&Actor{})
|
gob.Register(&Actor{})
|
||||||
|
@ -26,6 +29,7 @@ type Actor struct {
|
||||||
game *Game
|
game *Game
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BoundingBox returns the box Bounds.Add(Pos).
|
||||||
func (a *Actor) BoundingBox() geom.Box {
|
func (a *Actor) BoundingBox() geom.Box {
|
||||||
return a.Bounds.Add(a.Pos)
|
return a.Bounds.Add(a.Pos)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ type Billboard struct {
|
||||||
Hidden
|
Hidden
|
||||||
Pos image.Point
|
Pos image.Point
|
||||||
Src ImageRef
|
Src ImageRef
|
||||||
ZOrder
|
ZPosition
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw draws the image.
|
// Draw draws the image.
|
||||||
|
|
|
@ -39,7 +39,7 @@ type Camera struct {
|
||||||
// for the bounds of the child component (if available).
|
// for the bounds of the child component (if available).
|
||||||
func (c *Camera) PointAt(centre geom.Int3, zoom float64) {
|
func (c *Camera) PointAt(centre geom.Int3, zoom float64) {
|
||||||
// Special sauce: if Child has a BoundingRect, make some adjustments
|
// Special sauce: if Child has a BoundingRect, make some adjustments
|
||||||
bnd, ok := c.Child.(Bounder)
|
bnd, ok := c.Child.(BoundingRecter)
|
||||||
if !ok {
|
if !ok {
|
||||||
c.Centre = c.game.Projection.Project(centre)
|
c.Centre = c.game.Projection.Project(centre)
|
||||||
c.Zoom = zoom
|
c.Zoom = zoom
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"math"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
||||||
|
@ -41,9 +40,9 @@ 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 (d *DebugToast) DrawOrder() float64 {
|
func (DebugToast) DrawAfter(x Drawer) bool {
|
||||||
// Always draw on top
|
// Always draw on top
|
||||||
return math.MaxFloat64
|
return x != Tombstone{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DebugToast) Toast(text string) {
|
func (d *DebugToast) Toast(text string) {
|
||||||
|
@ -68,7 +67,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()))
|
ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f FPS: %0.2f", ebiten.CurrentTPS(), ebiten.CurrentFPS()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (PerfDisplay) DrawOrder() float64 {
|
func (PerfDisplay) DrawAfter(x Drawer) bool {
|
||||||
// Always draw on top
|
// Always draw on top
|
||||||
return math.MaxFloat64
|
return x != Tombstone{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ type Fill struct {
|
||||||
ID
|
ID
|
||||||
Color color.Color
|
Color color.Color
|
||||||
Hidden
|
Hidden
|
||||||
ZOrder
|
ZPosition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Fill) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
func (f *Fill) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"image"
|
"image"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"math"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -180,7 +179,7 @@ func (g *Game) Update() error {
|
||||||
sort.Stable(g.drawList)
|
sort.Stable(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{}) {
|
||||||
g.drawList = g.drawList[:i]
|
g.drawList = g.drawList[:i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -408,7 +407,7 @@ func (g *Game) unregister(component interface{}) {
|
||||||
// unregister from g.drawList
|
// unregister from g.drawList
|
||||||
for i, d := range g.drawList {
|
for i, d := range g.drawList {
|
||||||
if d == component {
|
if d == component {
|
||||||
g.drawList[i] = tombstone{}
|
g.drawList[i] = Tombstone{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,25 +424,23 @@ type abKey struct {
|
||||||
behaviour reflect.Type
|
behaviour reflect.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Drawer = tombstone{}
|
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) DrawAfter(x Drawer) bool {
|
||||||
|
return x != Tombstone{}
|
||||||
|
}
|
||||||
|
|
||||||
type drawList []Drawer
|
type drawList []Drawer
|
||||||
|
|
||||||
func (d drawList) Less(i, j int) bool {
|
func (d drawList) Less(i, j int) bool { return d[j].DrawAfter(d[i]) }
|
||||||
return d[i].DrawOrder() < d[j].DrawOrder()
|
|
||||||
}
|
|
||||||
|
|
||||||
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] }
|
||||||
|
|
||||||
// ConcatOpts returns the combined options (as though a was applied and then
|
// ConcatOpts returns the combined options (as though a was applied and then b).
|
||||||
// b).
|
|
||||||
func ConcatOpts(a, b ebiten.DrawImageOptions) ebiten.DrawImageOptions {
|
func ConcatOpts(a, b ebiten.DrawImageOptions) ebiten.DrawImageOptions {
|
||||||
a.ColorM.Concat(b.ColorM)
|
a.ColorM.Concat(b.ColorM)
|
||||||
a.GeoM.Concat(b.GeoM)
|
a.GeoM.Concat(b.GeoM)
|
||||||
|
|
|
@ -13,7 +13,8 @@ import (
|
||||||
var (
|
var (
|
||||||
// TypeOf(pointer to interface).Elem() is "idiomatic" -
|
// TypeOf(pointer to interface).Elem() is "idiomatic" -
|
||||||
// see https://pkg.go.dev/reflect#example-TypeOf
|
// see https://pkg.go.dev/reflect#example-TypeOf
|
||||||
BounderType = reflect.TypeOf((*Bounder)(nil)).Elem()
|
BoundingRecterType = reflect.TypeOf((*BoundingRecter)(nil)).Elem()
|
||||||
|
BoundingBoxerType = reflect.TypeOf((*BoundingBoxer)(nil)).Elem()
|
||||||
ColliderType = reflect.TypeOf((*Collider)(nil)).Elem()
|
ColliderType = reflect.TypeOf((*Collider)(nil)).Elem()
|
||||||
DisablerType = reflect.TypeOf((*Disabler)(nil)).Elem()
|
DisablerType = reflect.TypeOf((*Disabler)(nil)).Elem()
|
||||||
DrawerType = reflect.TypeOf((*Drawer)(nil)).Elem()
|
DrawerType = reflect.TypeOf((*Drawer)(nil)).Elem()
|
||||||
|
@ -28,7 +29,8 @@ var (
|
||||||
|
|
||||||
// Behaviours lists all the behaviours that can be queried with Game.Query.
|
// Behaviours lists all the behaviours that can be queried with Game.Query.
|
||||||
Behaviours = []reflect.Type{
|
Behaviours = []reflect.Type{
|
||||||
BounderType,
|
BoundingRecterType,
|
||||||
|
BoundingBoxerType,
|
||||||
ColliderType,
|
ColliderType,
|
||||||
DisablerType,
|
DisablerType,
|
||||||
DrawerType,
|
DrawerType,
|
||||||
|
@ -43,11 +45,16 @@ var (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bounder components have a bounding rectangle.
|
// BoundingRecter components have a bounding rectangle.
|
||||||
type Bounder interface {
|
type BoundingRecter interface {
|
||||||
BoundingRect() image.Rectangle
|
BoundingRect() image.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BoundingBoxer components have a bounding box.
|
||||||
|
type BoundingBoxer interface {
|
||||||
|
BoundingBox() geom.Box
|
||||||
|
}
|
||||||
|
|
||||||
// Collider components have tangible form.
|
// Collider components have tangible form.
|
||||||
type Collider interface {
|
type Collider interface {
|
||||||
CollidesWith(geom.Box) bool
|
CollidesWith(geom.Box) bool
|
||||||
|
@ -65,7 +72,7 @@ type Disabler interface {
|
||||||
// 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
|
DrawAfter(x Drawer) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hider components can be hidden.
|
// Hider components can be hidden.
|
||||||
|
|
|
@ -40,8 +40,22 @@ func (h *Hidden) Hide() { *h = true }
|
||||||
// Show sets h to false.
|
// Show sets h to false.
|
||||||
func (h *Hidden) Show() { *h = false }
|
func (h *Hidden) Show() { *h = false }
|
||||||
|
|
||||||
// ZOrder implements DrawOrder (in Drawer) directly (as a numeric value).
|
// ZPosition implements DrawAfter and DrawPosition as a simple Z coordinate.
|
||||||
type ZOrder float64
|
type ZPosition int
|
||||||
|
|
||||||
// DrawOrder returns z.
|
// DrawAfter reports if z > x.Z.
|
||||||
func (z ZOrder) DrawOrder() float64 { return float64(z) }
|
func (z ZPosition) DrawAfter(x Drawer) bool {
|
||||||
|
switch d := x.(type) {
|
||||||
|
case BoundingBoxer:
|
||||||
|
return int(z) > d.BoundingBox().Max.Z
|
||||||
|
case zpositioner:
|
||||||
|
return z.zposition() > d.zposition()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z ZPosition) zposition() int { return int(z) }
|
||||||
|
|
||||||
|
type zpositioner interface {
|
||||||
|
zposition() int
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
|
"log"
|
||||||
|
|
||||||
"drjosh.dev/gurgle/geom"
|
"drjosh.dev/gurgle/geom"
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
@ -20,6 +21,7 @@ var (
|
||||||
} = &PrismMap{}
|
} = &PrismMap{}
|
||||||
|
|
||||||
_ interface {
|
_ interface {
|
||||||
|
BoundingBoxer
|
||||||
Drawer
|
Drawer
|
||||||
Transformer
|
Transformer
|
||||||
} = &Prism{}
|
} = &Prism{}
|
||||||
|
@ -142,9 +144,64 @@ func (p *Prism) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
screen.DrawImage(p.m.Sheet.SubImage(p.Cell), opts)
|
screen.DrawImage(p.m.Sheet.SubImage(p.Cell), opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawOrder returns the projected draw distance.
|
func (p *Prism) logue(c Drawer, s string) {
|
||||||
func (p *Prism) DrawOrder() float64 {
|
if p.pos.Y != -16 {
|
||||||
return p.m.game.Projection.DrawOrder(p.pos)
|
return
|
||||||
|
}
|
||||||
|
if _, ok := c.(*Sprite); ok {
|
||||||
|
log.Print(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrawAfter reports if the prism should be drawn after x.
|
||||||
|
func (p *Prism) DrawAfter(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()
|
||||||
|
/*// No X overlap - no comparison needed
|
||||||
|
if pb.Max.X <= xb.Min.X || pb.Min.X >= xb.Max.X {
|
||||||
|
p.logue(x, "no x overlap")
|
||||||
|
return false
|
||||||
|
}*/
|
||||||
|
// Z ?
|
||||||
|
if pb.Min.Z >= xb.Max.Z { // p is unambiguously in front
|
||||||
|
p.logue(x, "prism unambiguously in front")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if pb.Max.Z <= xb.Min.Z { // p is unambiguously behind
|
||||||
|
p.logue(x, "prism unambiguously behind")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Y ? (NB: up is negative)
|
||||||
|
if pb.Max.Y <= xb.Min.Y { // p is above
|
||||||
|
p.logue(x, "prism unambiguously above")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if pb.Min.Y >= xb.Max.Y { // p is below
|
||||||
|
p.logue(x, "prism unambiguously below")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Try Z again
|
||||||
|
if pb.Min.Z+8 >= xb.Max.Z {
|
||||||
|
p.logue(x, "prism midsection after max Z")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if pb.Min.Z+8 <= xb.Min.Z {
|
||||||
|
p.logue(x, "prism midsection before min Z")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case zpositioner:
|
||||||
|
p.logue(x, "zpositioner test??")
|
||||||
|
return pb.Min.Z > int(d.zposition())
|
||||||
|
}
|
||||||
|
p.logue(x, "no tests at all???")
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform returns a translation by the projected position.
|
// Transform returns a translation by the projected position.
|
||||||
|
|
|
@ -40,6 +40,8 @@ func (g *Game) REPL(src io.Reader, dst io.Writer, assets fs.FS) error {
|
||||||
g.cmdHide(dst, argv)
|
g.cmdHide(dst, argv)
|
||||||
case "show":
|
case "show":
|
||||||
g.cmdShow(dst, argv)
|
g.cmdShow(dst, argv)
|
||||||
|
case "print":
|
||||||
|
g.cmdPrint(dst, argv)
|
||||||
}
|
}
|
||||||
fmt.Fprint(dst, prompt)
|
fmt.Fprint(dst, prompt)
|
||||||
}
|
}
|
||||||
|
@ -184,3 +186,11 @@ func (g *Game) cmdShow(dst io.Writer, argv []string) {
|
||||||
}
|
}
|
||||||
h.Show()
|
h.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *Game) cmdPrint(dst io.Writer, argv []string) {
|
||||||
|
c := g.cmdutilComponentArg1(dst, argv)
|
||||||
|
if c == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Fprintf(dst, "%#v\n", c)
|
||||||
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type scener interface {
|
type scener interface {
|
||||||
Bounder
|
BoundingRecter
|
||||||
Disabler
|
Disabler
|
||||||
Hider
|
Hider
|
||||||
Identifier
|
Identifier
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
// Ensure Sprite satisfies interfaces.
|
// Ensure Sprite satisfies interfaces.
|
||||||
var _ interface {
|
var _ interface {
|
||||||
|
BoundingBoxer
|
||||||
Drawer
|
Drawer
|
||||||
Scanner
|
Scanner
|
||||||
Transformer
|
Transformer
|
||||||
|
@ -30,14 +31,42 @@ type Sprite struct {
|
||||||
anim *Anim
|
anim *Anim
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BoundingBox forwards the call to Actor.
|
||||||
|
func (s *Sprite) BoundingBox() geom.Box { return s.Actor.BoundingBox() }
|
||||||
|
|
||||||
// Draw draws the current cell to the screen.
|
// Draw draws the current cell to the screen.
|
||||||
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.Cell()), opts)
|
screen.DrawImage(s.Sheet.SubImage(s.anim.Cell()), opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawOrder returns the projected draw order.
|
// DrawAfter reports if the sprite must be drawn after x.
|
||||||
func (s *Sprite) DrawOrder() float64 {
|
func (s *Sprite) DrawAfter(x Drawer) bool {
|
||||||
return s.Actor.game.Projection.DrawOrder(s.Actor.Pos)
|
sb := s.BoundingBox()
|
||||||
|
switch d := x.(type) {
|
||||||
|
case BoundingBoxer:
|
||||||
|
xb := d.BoundingBox()
|
||||||
|
/*// No X overlap - no comparison needed
|
||||||
|
if sb.Max.X <= xb.Min.X || sb.Min.X >= xb.Max.X {
|
||||||
|
return false
|
||||||
|
}*/
|
||||||
|
// Z ?
|
||||||
|
if sb.Min.Z >= xb.Max.Z { // s is unambiguously in front
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if sb.Max.Z <= xb.Min.Z { // s is unambiguously behind
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Y ? (NB: up is negative)
|
||||||
|
if sb.Max.Y <= xb.Min.Y { // s is unambiguously above
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if sb.Min.Y >= xb.Max.Y { // s is unambiguously below
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case zpositioner:
|
||||||
|
return sb.Min.Z > int(d.zposition())
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan returns the Actor and the Sheet.
|
// Scan returns the Actor and the Sheet.
|
||||||
|
|
|
@ -44,7 +44,7 @@ type Tilemap struct {
|
||||||
Ersatz bool // disables collisions ("fake wall")
|
Ersatz bool // disables collisions ("fake wall")
|
||||||
Offset image.Point // world coordinates
|
Offset image.Point // world coordinates
|
||||||
Sheet Sheet
|
Sheet Sheet
|
||||||
ZOrder
|
ZPosition
|
||||||
}
|
}
|
||||||
|
|
||||||
// CollidesWith implements Collider.
|
// CollidesWith implements Collider.
|
||||||
|
|
|
@ -92,7 +92,7 @@ type WallUnit struct {
|
||||||
Disabled
|
Disabled
|
||||||
Hidden
|
Hidden
|
||||||
Tile Tile // chooses which cell in wall.Sheet to draw
|
Tile Tile // chooses which cell in wall.Sheet to draw
|
||||||
ZOrder
|
ZPosition
|
||||||
|
|
||||||
pos image.Point // tilespace coordinates
|
pos image.Point // tilespace coordinates
|
||||||
wall *Wall
|
wall *Wall
|
||||||
|
|
|
@ -17,13 +17,13 @@ func Level1() *engine.Scene {
|
||||||
&engine.Fill{
|
&engine.Fill{
|
||||||
ID: "bg_fill",
|
ID: "bg_fill",
|
||||||
Color: color.Gray{100},
|
Color: color.Gray{100},
|
||||||
ZOrder: -1000,
|
ZPosition: -1000,
|
||||||
},
|
},
|
||||||
&engine.Parallax{
|
&engine.Parallax{
|
||||||
CameraID: "game_camera",
|
CameraID: "game_camera",
|
||||||
Child: &engine.Billboard{
|
Child: &engine.Billboard{
|
||||||
ID: "bg_image",
|
ID: "bg_image",
|
||||||
ZOrder: -900,
|
ZPosition: -900,
|
||||||
Pos: image.Pt(-160, -120),
|
Pos: image.Pt(-160, -120),
|
||||||
Src: engine.ImageRef{Path: "assets/space.png"},
|
Src: engine.ImageRef{Path: "assets/space.png"},
|
||||||
},
|
},
|
||||||
|
@ -31,7 +31,6 @@ func Level1() *engine.Scene {
|
||||||
},
|
},
|
||||||
&engine.PrismMap{
|
&engine.PrismMap{
|
||||||
ID: "hexagons",
|
ID: "hexagons",
|
||||||
//DrawOrderBias: image.Pt(0, -1), // draw higher Y after lower Y
|
|
||||||
PosToWorld: geom.IntMatrix3x4{
|
PosToWorld: geom.IntMatrix3x4{
|
||||||
// For each tile in the X direction, go right by 24 and
|
// For each tile in the X direction, go right by 24 and
|
||||||
// forward by 8, etc
|
// forward by 8, etc
|
||||||
|
|
|
@ -54,9 +54,13 @@ func PolygonRectOverlap(convex []image.Point, rect image.Rectangle) bool {
|
||||||
if PolygonContains(convex, rect.Min) {
|
if PolygonContains(convex, rect.Min) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reduced Max (to the inclusive bound).
|
// Reduced Max (to the inclusive bound).
|
||||||
rmax := rect.Max.Sub(image.Pt(1, 1))
|
rmax := rect.Max.Sub(image.Pt(1, 1))
|
||||||
|
// Since we went to the trouble of computing another point...
|
||||||
|
// TODO: this shouldn't be necessary
|
||||||
|
if PolygonContains(convex, rmax) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Only remaining cases involve line intersection between the rect and poly
|
// Only remaining cases involve line intersection between the rect and poly
|
||||||
// having eliminated the possibility that one is entirely within another.
|
// having eliminated the possibility that one is entirely within another.
|
||||||
|
|
|
@ -29,17 +29,3 @@ func (π IntProjection) Project(p Int3) image.Point {
|
||||||
}
|
}
|
||||||
return q
|
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
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue