WIP: paradigm change

This commit is contained in:
Josh Deprez 2021-08-31 17:03:43 +10:00
parent b443ca3bd3
commit d3284f808d
2 changed files with 56 additions and 7 deletions

View file

@ -5,7 +5,9 @@ import (
"errors" "errors"
"fmt" "fmt"
"io/fs" "io/fs"
"math"
"reflect" "reflect"
"sort"
"sync" "sync"
"github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2"
@ -41,6 +43,7 @@ type Game struct {
dbmu sync.RWMutex dbmu sync.RWMutex
byID map[string]Identifier // Named components by ID byID map[string]Identifier // Named components by ID
byAB map[abKey]map[interface{}]struct{} // Ancestor/behaviour index byAB map[abKey]map[interface{}]struct{} // Ancestor/behaviour index
drawList drawers // draw list :|
par map[interface{}]interface{} // par[x] is parent of x par map[interface{}]interface{} // par[x] is parent of x
} }
@ -49,12 +52,33 @@ type abKey struct {
behaviour reflect.Type behaviour reflect.Type
} }
var _ Drawer = tombstone{}
type tombstone struct{}
func (tombstone) Draw(*ebiten.Image, ebiten.DrawImageOptions) {}
func (tombstone) DrawOrder() float64 { return math.Inf(1) }
type drawers []Drawer
func (d drawers) Less(i, j int) bool { return d[i].DrawOrder() < d[j].DrawOrder() }
func (d drawers) Len() int { return len(d) }
func (d drawers) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
// Draw draws the entire thing, with default draw options. // Draw draws the entire thing, with default draw options.
func (g *Game) Draw(screen *ebiten.Image) { func (g *Game) Draw(screen *ebiten.Image) {
if g.Hidden { if g.Hidden {
return return
} }
g.Root.Draw(screen, ebiten.DrawImageOptions{}) //g.Root.Draw(screen, ebiten.DrawImageOptions{})
// draw everything
for _, d := range g.drawList {
if h, ok := d.(Hider); ok && h.IsHidden() {
continue
}
d.Draw(screen, ebiten.DrawImageOptions{})
}
} }
// Layout returns the configured screen width/height. // Layout returns the configured screen width/height.
@ -67,7 +91,20 @@ func (g *Game) Update() error {
if g.Disabled { if g.Disabled {
return nil return nil
} }
return g.Root.Update()
if err := g.Root.Update(); err != nil {
return err
}
// sort the draw list (yes, on every frame)
sort.Stable(g.drawList)
// slice out any tombstones
for i := len(g.drawList) - 1; i >= 0; i-- {
if g.drawList[i] == (tombstone{}) {
g.drawList = g.drawList[:i]
}
}
return nil
} }
// Ident returns "__GAME__". // Ident returns "__GAME__".
@ -181,6 +218,11 @@ func (g *Game) register(component, parent interface{}) error {
g.par[component] = parent g.par[component] = parent
} }
// register in g.drawList
if d, ok := component.(Drawer); ok {
g.drawList = append(g.drawList, d)
}
// register in g.byAB // register in g.byAB
ct := reflect.TypeOf(component) ct := reflect.TypeOf(component)
for _, b := range Behaviours { for _, b := range Behaviours {
@ -248,6 +290,13 @@ func (g *Game) unregister(component interface{}) {
// unregister from g.par // unregister from g.par
delete(g.par, component) delete(g.par, component)
// unregister from g.drawList
for i, d := range g.drawList {
if d == component {
g.drawList[i] = tombstone{}
}
}
// unregister from g.byID if needed // unregister from g.byID if needed
i, ok := component.(Identifier) i, ok := component.(Identifier)
if !ok { if !ok {

View file

@ -16,7 +16,7 @@ import (
func main() { func main() {
// Change to true to enable cpu profile // Change to true to enable cpu profile
if false && runtime.GOOS != "js" { if true && runtime.GOOS != "js" {
f, err := os.Create("cpuprofile.pprof") f, err := os.Create("cpuprofile.pprof")
if err != nil { if err != nil {
log.Fatal("could not create CPU profile: ", err) log.Fatal("could not create CPU profile: ", err)