bubbleless topsort working
This commit is contained in:
parent
17de1d6b97
commit
091d36094b
8 changed files with 81 additions and 26 deletions
|
@ -2,6 +2,7 @@ package engine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"drjosh.dev/gurgle/geom"
|
"drjosh.dev/gurgle/geom"
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
@ -75,6 +76,10 @@ func (b *Billboard) Prepare(g *Game) error {
|
||||||
// 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) String() string {
|
||||||
|
return fmt.Sprintf("Billboard@%v", b.Pos)
|
||||||
|
}
|
||||||
|
|
||||||
// Transform returns a translation by the projected position.
|
// Transform returns a translation by the projected position.
|
||||||
func (b *Billboard) Transform() (opts ebiten.DrawImageOptions) {
|
func (b *Billboard) Transform() (opts ebiten.DrawImageOptions) {
|
||||||
opts.GeoM.Translate(geom.CFloat(
|
opts.GeoM.Translate(geom.CFloat(
|
||||||
|
|
|
@ -41,8 +41,20 @@ func (d *DebugToast) Draw(screen *ebiten.Image, _ *ebiten.DrawImageOptions) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw last.
|
// Draw last.
|
||||||
func (DebugToast) DrawAfter(Drawer) bool { return true }
|
func (DebugToast) DrawAfter(x Drawer) bool {
|
||||||
func (DebugToast) DrawBefore(Drawer) bool { return false }
|
switch x.(type) {
|
||||||
|
case *DebugToast, PerfDisplay, tombstone:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
func (DebugToast) DrawBefore(x Drawer) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DebugToast) String() string {
|
||||||
|
return fmt.Sprintf("DebugToast@%v", d.Pos)
|
||||||
|
}
|
||||||
|
|
||||||
func (d *DebugToast) Toast(text string) {
|
func (d *DebugToast) Toast(text string) {
|
||||||
d.Text = text
|
d.Text = text
|
||||||
|
@ -67,5 +79,16 @@ func (p PerfDisplay) Draw(screen *ebiten.Image, _ *ebiten.DrawImageOptions) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw last.
|
// Draw last.
|
||||||
func (PerfDisplay) DrawAfter(Drawer) bool { return true }
|
func (PerfDisplay) DrawAfter(x Drawer) bool {
|
||||||
func (PerfDisplay) DrawBefore(Drawer) bool { return false }
|
switch x.(type) {
|
||||||
|
case *DebugToast, PerfDisplay, tombstone:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (PerfDisplay) DrawBefore(Drawer) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (PerfDisplay) String() string { return "PerfDisplay" }
|
||||||
|
|
|
@ -17,6 +17,8 @@ func (tombstone) Draw(*ebiten.Image, *ebiten.DrawImageOptions) {}
|
||||||
func (tombstone) DrawAfter(x Drawer) bool { return x != tombstone{} }
|
func (tombstone) DrawAfter(x Drawer) bool { return x != tombstone{} }
|
||||||
func (tombstone) DrawBefore(Drawer) bool { return false }
|
func (tombstone) DrawBefore(Drawer) bool { return false }
|
||||||
|
|
||||||
|
func (tombstone) String() string { return "tombstone" }
|
||||||
|
|
||||||
type drawList struct {
|
type drawList struct {
|
||||||
list []Drawer
|
list []Drawer
|
||||||
rev map[Drawer]int
|
rev map[Drawer]int
|
||||||
|
@ -80,9 +82,10 @@ func (d drawList) Swap(i, j int) {
|
||||||
|
|
||||||
// Bad, slow, topological sort
|
// Bad, slow, topological sort
|
||||||
func (d *drawList) topsort() error {
|
func (d *drawList) topsort() error {
|
||||||
// Count indegrees
|
// Count indegrees - O(|V|^2)
|
||||||
indegree := make(map[Drawer]int)
|
indegree := make(map[Drawer]int)
|
||||||
for _, u := range d.list {
|
for _, u := range d.list {
|
||||||
|
indegree[u] += 0
|
||||||
for _, v := range d.list {
|
for _, v := range d.list {
|
||||||
if u == v {
|
if u == v {
|
||||||
continue
|
continue
|
||||||
|
@ -92,6 +95,7 @@ func (d *drawList) topsort() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//log.Printf("indegree: %v", indegree)
|
||||||
// Sort into new list
|
// Sort into new list
|
||||||
list := make([]Drawer, 0, len(d.list))
|
list := make([]Drawer, 0, len(d.list))
|
||||||
for len(indegree) > 0 {
|
for len(indegree) > 0 {
|
||||||
|
@ -99,10 +103,11 @@ func (d *drawList) topsort() error {
|
||||||
for v, n := range indegree {
|
for v, n := range indegree {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
bag = append(bag, v)
|
bag = append(bag, v)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//log.Printf("zero indegree vertices: %v", bag)
|
||||||
if len(bag) == 0 {
|
if len(bag) == 0 {
|
||||||
|
//log.Printf("remaining vertices: %v", indegree)
|
||||||
return errors.New("no vertices with zero indegree")
|
return errors.New("no vertices with zero indegree")
|
||||||
}
|
}
|
||||||
list = append(list, bag...)
|
list = append(list, bag...)
|
||||||
|
|
|
@ -31,3 +31,5 @@ type Fill struct {
|
||||||
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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Fill) String() string { return "Fill" }
|
||||||
|
|
|
@ -237,6 +237,10 @@ func (p *Prism) DrawBefore(x Drawer) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Prism) String() string {
|
||||||
|
return fmt.Sprintf("Prism(%d)@%v", p.Cell, p.pos)
|
||||||
|
}
|
||||||
|
|
||||||
// Transform returns a translation by the projected position.
|
// Transform returns a translation by the projected position.
|
||||||
func (p *Prism) Transform() (opts ebiten.DrawImageOptions) {
|
func (p *Prism) Transform() (opts ebiten.DrawImageOptions) {
|
||||||
opts.GeoM.Translate(geom.CFloat(
|
opts.GeoM.Translate(geom.CFloat(
|
||||||
|
|
|
@ -2,6 +2,7 @@ package engine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
|
|
||||||
"drjosh.dev/gurgle/geom"
|
"drjosh.dev/gurgle/geom"
|
||||||
|
@ -108,6 +109,10 @@ func (s *Sprite) SetAnim(a *Anim) {
|
||||||
s.anim = a
|
s.anim = a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Sprite) String() string {
|
||||||
|
return fmt.Sprintf("Sprite@%v", s.Actor.Pos)
|
||||||
|
}
|
||||||
|
|
||||||
// Transform returns a translation by the DrawOffset and Actor.Pos projected
|
// Transform returns a translation by the DrawOffset and Actor.Pos projected
|
||||||
func (s *Sprite) Transform() (opts ebiten.DrawImageOptions) {
|
func (s *Sprite) Transform() (opts ebiten.DrawImageOptions) {
|
||||||
opts.GeoM.Translate(geom.CFloat(
|
opts.GeoM.Translate(geom.CFloat(
|
||||||
|
|
46
game/aw.go
46
game/aw.go
|
@ -109,29 +109,31 @@ func (aw *Awakeman) realUpdate() error {
|
||||||
bubblePeriod = 6
|
bubblePeriod = 6
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add a bubble?
|
if false {
|
||||||
aw.bubbleTimer--
|
// Add a bubble?
|
||||||
if aw.bubbleTimer <= 0 {
|
aw.bubbleTimer--
|
||||||
aw.bubbleTimer = bubblePeriod
|
if aw.bubbleTimer <= 0 {
|
||||||
bubble := NewBubble(aw.Sprite.Actor.Pos.Add(geom.Pt3(1, -15, -1)))
|
aw.bubbleTimer = bubblePeriod
|
||||||
if err := engine.PreorderWalk(bubble, func(c, _ interface{}) error {
|
bubble := NewBubble(aw.Sprite.Actor.Pos.Add(geom.Pt3(1, -15, -1)))
|
||||||
if p, ok := c.(engine.Loader); ok {
|
if err := engine.PreorderWalk(bubble, func(c, _ interface{}) error {
|
||||||
return p.Load(Assets)
|
if p, ok := c.(engine.Loader); ok {
|
||||||
|
return p.Load(Assets)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
aw.game.Register(bubble, aw.game.Parent(aw))
|
||||||
}); err != nil {
|
if err := engine.PreorderWalk(bubble, func(c, _ interface{}) error {
|
||||||
return err
|
if p, ok := c.(engine.Prepper); ok {
|
||||||
}
|
return p.Prepare(aw.game)
|
||||||
aw.game.Register(bubble, aw.game.Parent(aw))
|
}
|
||||||
if err := engine.PreorderWalk(bubble, func(c, _ interface{}) error {
|
return nil
|
||||||
if p, ok := c.(engine.Prepper); ok {
|
}); err != nil {
|
||||||
return p.Prepare(aw.game)
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
bubble.Sprite.SetAnim(bubble.Sprite.Sheet.NewAnim("bubble"))
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
bubble.Sprite.SetAnim(bubble.Sprite.Sheet.NewAnim("bubble"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fell below some threshold?
|
// Fell below some threshold?
|
||||||
|
@ -265,3 +267,7 @@ func (aw *Awakeman) Prepare(game *engine.Game) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (aw *Awakeman) Scan() []interface{} { return []interface{}{&aw.Sprite} }
|
func (aw *Awakeman) Scan() []interface{} { return []interface{}{&aw.Sprite} }
|
||||||
|
|
||||||
|
func (aw *Awakeman) String() string {
|
||||||
|
return fmt.Sprintf("Awakeman@%v", aw.Sprite.Actor.Pos)
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package game
|
package game
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
||||||
|
@ -52,6 +53,10 @@ func (b *Bubble) Scan() []interface{} {
|
||||||
return []interface{}{&b.Sprite}
|
return []interface{}{&b.Sprite}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bubble) String() string {
|
||||||
|
return fmt.Sprintf("Bubble@%v", b.Sprite.Actor.Pos)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Bubble) Prepare(g *engine.Game) error {
|
func (b *Bubble) Prepare(g *engine.Game) error {
|
||||||
b.game = g
|
b.game = g
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in a new issue