sets of interface{}, lol

This commit is contained in:
Josh Deprez 2021-08-30 15:03:22 +10:00
parent b82ed8d336
commit f923bf7164
3 changed files with 16 additions and 17 deletions

View file

@ -20,20 +20,20 @@ func init() {
// Actor handles basic movement. // Actor handles basic movement.
type Actor struct { type Actor struct {
CollisionDomain string CollisionDomain string // id of component to look for colliders inside of
Pos image.Point Pos image.Point
Size image.Point Size image.Point
collisionDomain []Collider xRem, yRem float64
xRem, yRem float64 game *Game
} }
func (a *Actor) BoundingRect() image.Rectangle { return image.Rectangle{a.Pos, a.Pos.Add(a.Size)} } func (a *Actor) BoundingRect() image.Rectangle { return image.Rectangle{a.Pos, a.Pos.Add(a.Size)} }
func (a *Actor) CollidesAt(p image.Point) bool { func (a *Actor) CollidesAt(p image.Point) bool {
bounds := image.Rectangle{Min: p, Max: p.Add(a.Size)} bounds := image.Rectangle{Min: p, Max: p.Add(a.Size)}
for _, c := range a.collisionDomain { for c := range a.game.Query(a.CollisionDomain, ColliderType) {
if c.CollidesWith(bounds) { if c.(Collider).CollidesWith(bounds) {
return true return true
} }
} }
@ -81,11 +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(a.CollisionDomain, ColliderType) a.game = g
a.collisionDomain = make([]Collider, 0, len(cs))
for _, c := range cs {
a.collisionDomain = append(a.collisionDomain, c.(Collider))
}
return nil return nil
} }

View file

@ -33,8 +33,8 @@ type Game struct {
Root DrawUpdater // typically a *Scene or SceneRef though Root DrawUpdater // typically a *Scene or SceneRef though
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][]interface{} // Ancestor/behaviour index byAB map[abKey]map[interface{}]struct{} // Ancestor/behaviour index
} }
type abKey struct { type abKey struct {
@ -77,7 +77,7 @@ 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(ancestorID string, behaviour reflect.Type) []interface{} { func (g *Game) Query(ancestorID string, behaviour reflect.Type) map[interface{}]struct{} {
g.dbmu.RLock() g.dbmu.RLock()
defer g.dbmu.RUnlock() defer g.dbmu.RUnlock()
return g.byAB[abKey{ancestorID, behaviour}] return g.byAB[abKey{ancestorID, behaviour}]
@ -127,14 +127,14 @@ func (g *Game) LoadAndPrepare(assets fs.FS) error {
// Build the component databases // Build the component databases
g.dbmu.Lock() g.dbmu.Lock()
g.byID = make(map[string]Identifier) g.byID = make(map[string]Identifier)
g.byAB = make(map[abKey][]interface{}) g.byAB = make(map[abKey]map[interface{}]struct{})
if err := Walk(g, g.registerComponent); err != nil { if err := Walk(g, g.registerComponent); err != nil {
return err return err
} }
g.dbmu.Unlock() g.dbmu.Unlock()
// Prepare all the Preppers // Prepare all the Preppers
for _, p := range g.Query(g.Ident(), 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
} }
@ -156,7 +156,10 @@ func (g *Game) registerComponent(c interface{}, path []interface{}) error {
continue continue
} }
k := abKey{i.Ident(), b} k := abKey{i.Ident(), b}
g.byAB[k] = append(g.byAB[k], c) if g.byAB[k] == nil {
g.byAB[k] = make(map[interface{}]struct{})
}
g.byAB[k][c] = struct{}{}
} }
} }

View file

@ -134,7 +134,7 @@ func (g *Game) cmdQuery(dst io.Writer, argv []string) {
return return
} }
for _, c := range x { for c := range x {
i, ok := c.(Identifier) i, ok := c.(Identifier)
if ok { if ok {
fmt.Fprintf(dst, "%T %s\n", c, i.Ident()) fmt.Fprintf(dst, "%T %s\n", c, i.Ident())