query takes ids; game has an id

This commit is contained in:
Josh Deprez 2021-08-28 18:14:37 +10:00
parent 3452a32ddb
commit b0520114ee
3 changed files with 23 additions and 13 deletions

View file

@ -81,7 +81,7 @@ func (a *Actor) MoveY(dy float64, onCollide func()) {
} }
func (a *Actor) Prepare(g *Game) error { func (a *Actor) Prepare(g *Game) error {
cs := g.Query(g.Component(a.CollisionDomain), ColliderType) cs := g.Query(a.CollisionDomain, ColliderType)
a.collisionDomain = make([]Collider, 0, len(cs)) a.collisionDomain = make([]Collider, 0, len(cs))
for _, c := range cs { for _, c := range cs {
a.collisionDomain = append(a.collisionDomain, c.(Collider)) a.collisionDomain = append(a.collisionDomain, c.(Collider))

View file

@ -10,6 +10,14 @@ import (
"github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2"
) )
var _ interface {
Disabler
Hider
Identifier
Updater
Scanner
} = &Game{}
func init() { func init() {
gob.Register(&Game{}) gob.Register(&Game{})
} }
@ -30,7 +38,7 @@ type Game struct {
} }
type dexKey struct { type dexKey struct {
ancestor interface{} ancestor string
behaviour reflect.Type behaviour reflect.Type
} }
@ -55,6 +63,9 @@ func (g *Game) Update() error {
return g.Root.Update() return g.Root.Update()
} }
// Ident returns "__GAME__".
func (g *Game) Ident() string { return "__GAME__" }
// Component returns the component with a given ID, or nil if there is none. // Component returns the component with a given ID, or nil if there is none.
// This only returns sensible values after LoadAndPrepare. // This only returns sensible values after LoadAndPrepare.
func (g *Game) Component(id string) Identifier { func (g *Game) Component(id string) Identifier {
@ -66,10 +77,10 @@ func (g *Game) Component(id string) Identifier {
// Query looks for components having both a given ancestor and implementing // Query looks for components having both a given ancestor and implementing
// a given behaviour (see Behaviors in interface.go). This only returns sensible // a given behaviour (see Behaviors in interface.go). This only returns sensible
// values after LoadAndPrepare. Note that every component is its own ancestor. // values after LoadAndPrepare. Note that every component is its own ancestor.
func (g *Game) Query(ancestor interface{}, behaviour reflect.Type) []interface{} { func (g *Game) Query(ancestorID string, behaviour reflect.Type) []interface{} {
g.dbmu.RLock() g.dbmu.RLock()
defer g.dbmu.RUnlock() defer g.dbmu.RUnlock()
return g.dex[dexKey{ancestor, behaviour}] return g.dex[dexKey{ancestorID, behaviour}]
} }
// Scan implements Scanner. // Scan implements Scanner.
@ -123,7 +134,7 @@ func (g *Game) LoadAndPrepare(assets fs.FS) error {
g.dbmu.Unlock() g.dbmu.Unlock()
// Prepare all the Preppers // Prepare all the Preppers
for _, p := range g.Query(g, PrepperType) { for _, p := range g.Query(g.Ident(), PrepperType) {
if err := p.(Prepper).Prepare(g); err != nil { if err := p.(Prepper).Prepare(g); err != nil {
return err return err
} }
@ -140,7 +151,11 @@ func (g *Game) registerComponent(c interface{}, path []interface{}) error {
} }
// TODO: sub-quadratic? // TODO: sub-quadratic?
for _, p := range append(path, c) { for _, p := range append(path, c) {
k := dexKey{p, b} i, ok := p.(Identifier)
if !ok || i.Ident() == "" {
continue
}
k := dexKey{i.Ident(), b}
g.dex[k] = append(g.dex[k], c) g.dex[k] = append(g.dex[k], c)
} }
} }

View file

@ -117,14 +117,9 @@ func (g *Game) cmdQuery(dst io.Writer, argv []string) {
fmt.Fprintf(dst, "Unknown behaviour %q\n", argv[1]) fmt.Fprintf(dst, "Unknown behaviour %q\n", argv[1])
} }
ances := interface{}(g) ances := g.Ident()
if len(argv) == 3 { if len(argv) == 3 {
id := argv[2] ances = argv[2]
ances = g.Component(id)
if ances == nil {
fmt.Fprintf(dst, "Component %q not found\n", id)
return
}
} }
x := g.Query(ances, behav) x := g.Query(ances, behav)