WIP: topological sort

This commit is contained in:
Josh Deprez 2021-09-16 21:32:03 +10:00
parent 43d95c0f65
commit 17de1d6b97
2 changed files with 57 additions and 3 deletions

View file

@ -1,6 +1,10 @@
package engine package engine
import "github.com/hajimehoshi/ebiten/v2" import (
"errors"
"github.com/hajimehoshi/ebiten/v2"
)
const commonDrawerComparisons = false const commonDrawerComparisons = false
@ -73,3 +77,51 @@ func (d drawList) Swap(i, j int) {
d.rev[d.list[i]], d.rev[d.list[j]] = j, i d.rev[d.list[i]], d.rev[d.list[j]] = j, i
d.list[i], d.list[j] = d.list[j], d.list[i] d.list[i], d.list[j] = d.list[j], d.list[i]
} }
// Bad, slow, topological sort
func (d *drawList) topsort() error {
// Count indegrees
indegree := make(map[Drawer]int)
for _, u := range d.list {
for _, v := range d.list {
if u == v {
continue
}
if u.DrawBefore(v) || v.DrawAfter(u) {
indegree[v]++
}
}
}
// Sort into new list
list := make([]Drawer, 0, len(d.list))
for len(indegree) > 0 {
var bag []Drawer
for v, n := range indegree {
if n == 0 {
bag = append(bag, v)
break
}
}
if len(bag) == 0 {
return errors.New("no vertices with zero indegree")
}
list = append(list, bag...)
for _, u := range bag {
delete(indegree, u)
}
for _, u := range bag {
for v := range indegree {
if u.DrawBefore(v) || v.DrawAfter(u) {
indegree[v]--
}
}
}
}
// Replace list
d.list = list
// Update rev
for i, v := range list {
d.rev[v] = i
}
return nil
}

View file

@ -8,7 +8,6 @@ import (
"io/fs" "io/fs"
"log" "log"
"reflect" "reflect"
"sort"
"sync" "sync"
"time" "time"
@ -183,7 +182,10 @@ 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)
if err := g.drawList.topsort(); err != nil {
return fmt.Errorf("drawList.topsort: %v", err)
}
// Truncate tombstones from the end. // Truncate tombstones from the end.
for i := g.drawList.Len() - 1; i >= 0; i-- { for i := g.drawList.Len() - 1; i >= 0; i-- {
if g.drawList.list[i] != (tombstone{}) { if g.drawList.list[i] != (tombstone{}) {