re-un-re-refactor?

This commit is contained in:
Josh Deprez 2021-09-22 14:37:00 +10:00
parent d37a26eb70
commit 83c3182be1
19 changed files with 80 additions and 56 deletions

View file

@ -52,7 +52,7 @@ func (b *Billboard) Prepare(g *Game) error {
} }
// Scan returns a slice containing Src. // Scan returns a slice containing Src.
func (b *Billboard) Scan() Components { return Components{&b.Src} } func (b *Billboard) Scan() []interface{} { return []interface{}{&b.Src} }
func (b *Billboard) String() string { func (b *Billboard) String() string {
return fmt.Sprintf("Billboard@%v", b.Pos) return fmt.Sprintf("Billboard@%v", b.Pos)

View file

@ -86,7 +86,7 @@ func (c *Camera) Prepare(game *Game) error {
} }
// Scan returns s.Child. // Scan returns s.Child.
func (c *Camera) Scan() Components { return Components{c.Child} } func (c *Camera) Scan() []interface{} { return []interface{}{c.Child} }
// Transform returns the camera transform. // Transform returns the camera transform.
func (c *Camera) Transform() (opts ebiten.DrawImageOptions) { func (c *Camera) Transform() (opts ebiten.DrawImageOptions) {

45
engine/container.go Normal file
View file

@ -0,0 +1,45 @@
package engine
// Container contains many components.
type Container []interface{}
// Scan returns c.
func (c Container) Scan() []interface{} { return c }
// Register records component in the slice, if parent is the container.
func (c *Container) Register(component, parent interface{}) error {
if parent == c {
*c = append(*c, component)
}
return nil
}
// Unregister searches the slice for the component, and removes it by setting
// to nil. If the number of nil items is greater than half the slice, the slice
// is compacted.
func (c *Container) Unregister(component interface{}) {
free := 0
for i, x := range *c {
switch x {
case component:
(*c)[i] = nil
free++
case nil:
free++
}
}
if free > len(*c)/2 {
c.compact()
}
}
func (c *Container) compact() {
i := 0
for _, x := range *c {
if x != nil {
(*c)[i] = x
i++
}
}
*c = (*c)[:i]
}

View file

@ -25,7 +25,7 @@ var _ interface {
// the number of tests between components. // the number of tests between components.
type DrawDAG struct { type DrawDAG struct {
ChunkSize int ChunkSize int
Components Child interface{}
Hides Hides
*dag *dag
@ -114,6 +114,8 @@ func (d *DrawDAG) Prepare(game *Game) error {
return d.Register(d, nil) return d.Register(d, nil)
} }
func (d *DrawDAG) Scan() []interface{} { return []interface{}{d.Child} }
// Update checks for any changes to descendants, and updates its internal // Update checks for any changes to descendants, and updates its internal
// data structures accordingly. // data structures accordingly.
func (d *DrawDAG) Update() error { func (d *DrawDAG) Update() error {

View file

@ -13,7 +13,7 @@ var _ interface {
// through the game tree, without any extra sorting based on Z values or // through the game tree, without any extra sorting based on Z values or
// consideration for DrawOrderer). // consideration for DrawOrderer).
type DrawDFS struct { type DrawDFS struct {
Components Child interface{}
Hides Hides
} }
@ -21,9 +21,7 @@ func (d *DrawDFS) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
if d.Hidden() { if d.Hidden() {
return return
} }
for _, component := range d.Components { d.draw(d.Child, screen, *opts)
d.draw(component, screen, *opts)
}
} }
// exists to satisfy interface // exists to satisfy interface
@ -53,3 +51,5 @@ func (d *DrawDFS) draw(component interface{}, screen *ebiten.Image, opts ebiten.
} }
} }
} }
func (d *DrawDFS) Scan() []interface{} { return []interface{}{d.Child} }

View file

@ -167,7 +167,7 @@ func (g *Game) Query(ancestor interface{}, behaviour reflect.Type) map[interface
} }
// Scan returns g.Root. // Scan returns g.Root.
func (g *Game) Scan() Components { return Components{g.Root} } func (g *Game) Scan() []interface{} { return []interface{}{g.Root} }
// PreorderWalk calls visit with every component and its parent, reachable from // PreorderWalk calls visit with every component and its parent, reachable from
// the given component via Scan, for as long as visit returns nil. The parent // the given component via Scan, for as long as visit returns nil. The parent

View file

@ -147,7 +147,7 @@ type Saver interface {
// (such as when the game component database is constructed). // (such as when the game component database is constructed).
// Scan should return a slice containing all immediate subcomponents. // Scan should return a slice containing all immediate subcomponents.
type Scanner interface { type Scanner interface {
Scan() Components Scan() []interface{}
} }
// Transformer components can provide draw options to apply to themselves and // Transformer components can provide draw options to apply to themselves and

View file

@ -39,9 +39,3 @@ func (h *Hides) Hide() { *h = true }
// Show sets h to false. // Show sets h to false.
func (h *Hides) Show() { *h = false } func (h *Hides) Show() { *h = false }
// Components implements Scan directly (as itself!)
type Components []interface{}
// Scan returns c.
func (c Components) Scan() Components { return c }

View file

@ -39,7 +39,7 @@ func (p *Parallax) Prepare(game *Game) error {
} }
// Scan returns the child component. // Scan returns the child component.
func (p *Parallax) Scan() Components { return Components{p.Child} } func (p *Parallax) Scan() []interface{} { return []interface{}{p.Child} }
// Transform returns a GeoM translation of Factor * camera.Centre. // Transform returns a GeoM translation of Factor * camera.Centre.
func (p *Parallax) Transform() (opts ebiten.DrawImageOptions) { func (p *Parallax) Transform() (opts ebiten.DrawImageOptions) {

View file

@ -113,8 +113,8 @@ func (m *PrismMap) Prepare(g *Game) error {
} }
// Scan returns the Sheet and all the Prisms. // Scan returns the Sheet and all the Prisms.
func (m *PrismMap) Scan() Components { func (m *PrismMap) Scan() []interface{} {
c := make(Components, 1, len(m.Map)+1) c := make([]interface{}, 1, len(m.Map)+1)
c[0] = &m.Sheet c[0] = &m.Sheet
for _, prism := range m.Map { for _, prism := range m.Map {
c = append(c, prism) c = append(c, prism)

View file

@ -21,7 +21,6 @@ type scener interface {
Disabler Disabler
Hider Hider
Identifier Identifier
Registrar
Scanner Scanner
} }
@ -30,30 +29,16 @@ func init() {
gob.Register(&SceneRef{}) gob.Register(&SceneRef{})
} }
// Scene gives an identity, bounds, and other properties to a collection of // Scene is a component for adding an identity, bounds, and other properties.
// components.
type Scene struct { type Scene struct {
ID ID
Bounds // world coordinates Bounds // world coordinates
Components Child interface{}
Disables Disables
Hides Hides
} }
func (s *Scene) Register(component, parent interface{}) error { func (s *Scene) Scan() []interface{} { return []interface{}{s.Child} }
if parent == s {
s.Components = append(s.Components, component)
}
return nil
}
func (s *Scene) Unregister(component interface{}) {
for i, c := range s.Components {
if c == component {
s.Components[i] = nil
}
}
}
// SceneRef loads a gzipped, gob-encoded Scene from the asset FS. // SceneRef loads a gzipped, gob-encoded Scene from the asset FS.
// After Load, Scene is usable. // After Load, Scene is usable.

View file

@ -47,7 +47,7 @@ func (s *Sheet) Prepare(*Game) error {
} }
// Scan returns the Src. // Scan returns the Src.
func (s *Sheet) Scan() Components { return Components{&s.Src} } func (s *Sheet) Scan() []interface{} { return []interface{}{&s.Src} }
// SubImage returns an *ebiten.Image corresponding to the given cell index. // SubImage returns an *ebiten.Image corresponding to the given cell index.
func (s *Sheet) SubImage(i int) *ebiten.Image { func (s *Sheet) SubImage(i int) *ebiten.Image {

View file

@ -41,8 +41,8 @@ func (s *Sprite) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
} }
// Scan returns the Actor and the Sheet. // Scan returns the Actor and the Sheet.
func (s *Sprite) Scan() Components { func (s *Sprite) Scan() []interface{} {
return Components{ return []interface{}{
&s.Actor, &s.Actor,
&s.Sheet, &s.Sheet,
} }

View file

@ -100,8 +100,8 @@ func (t *Tilemap) Load(fs.FS) error {
} }
// Scan returns a slice containing Src and all non-nil tiles. // Scan returns a slice containing Src and all non-nil tiles.
func (t *Tilemap) Scan() Components { func (t *Tilemap) Scan() []interface{} {
c := make(Components, 1, len(t.Map)+1) c := make([]interface{}, 1, len(t.Map)+1)
c[0] = &t.Sheet c[0] = &t.Sheet
for _, tile := range t.Map { for _, tile := range t.Map {
c = append(c, tile) c = append(c, tile)
@ -152,4 +152,4 @@ type AnimatedTile struct {
func (a *AnimatedTile) Cell() int { return a.anim.Cell() } func (a *AnimatedTile) Cell() int { return a.anim.Cell() }
// Scan returns a.anim. // Scan returns a.anim.
func (a *AnimatedTile) Scan() Components { return Components{a.anim} } func (a *AnimatedTile) Scan() []interface{} { return []interface{}{a.anim} }

View file

@ -61,8 +61,8 @@ func (w *Wall) CollidesWith(b geom.Box) bool {
} }
// Scan returns the Sheet and all WallUnits. // Scan returns the Sheet and all WallUnits.
func (w *Wall) Scan() Components { func (w *Wall) Scan() []interface{} {
c := make(Components, 1, len(w.Units)+1) c := make([]interface{}, 1, len(w.Units)+1)
c[0] = &w.Sheet c[0] = &w.Sheet
for _, unit := range w.Units { for _, unit := range w.Units {
c = append(c, unit) c = append(c, unit)
@ -103,7 +103,7 @@ func (u *WallUnit) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
} }
// Scan returns the Tile. // Scan returns the Tile.
func (u *WallUnit) Scan() Components { return Components{u.Tile} } func (u *WallUnit) Scan() []interface{} { return []interface{}{u.Tile} }
func (u *WallUnit) Transform() (opts ebiten.DrawImageOptions) { func (u *WallUnit) Transform() (opts ebiten.DrawImageOptions) {
opts.GeoM.Translate(geom.CFloat( opts.GeoM.Translate(geom.CFloat(

View file

@ -270,8 +270,8 @@ func (aw *Awakeman) Prepare(game *engine.Game) error {
return nil return nil
} }
func (aw *Awakeman) Scan() engine.Components { func (aw *Awakeman) Scan() []interface{} {
return engine.Components{&aw.Sprite} return []interface{}{&aw.Sprite}
} }
func (aw *Awakeman) String() string { func (aw *Awakeman) String() string {

View file

@ -55,8 +55,8 @@ func NewBubble(pos geom.Int3) *Bubble {
} }
} }
func (b *Bubble) Scan() engine.Components { func (b *Bubble) Scan() []interface{} {
return engine.Components{&b.Sprite} return []interface{}{&b.Sprite}
} }
func (b *Bubble) String() string { func (b *Bubble) String() string {

View file

@ -12,7 +12,7 @@ func Level1() *engine.Scene {
return &engine.Scene{ return &engine.Scene{
ID: "level_1", ID: "level_1",
Bounds: engine.Bounds(image.Rect(-32, -32, 320+32, 240+32)), Bounds: engine.Bounds(image.Rect(-32, -32, 320+32, 240+32)),
Components: engine.Components{ Child: &engine.Container{
&engine.Parallax{ &engine.Parallax{
CameraID: "game_camera", CameraID: "game_camera",
Child: &engine.Billboard{ Child: &engine.Billboard{

View file

@ -68,20 +68,18 @@ func main() {
Z: math.Sqrt(3), Z: math.Sqrt(3),
}, },
Root: &engine.DrawDFS{ Root: &engine.DrawDFS{
Components: engine.Components{ Child: &engine.Container{
&engine.Fill{ &engine.Fill{
ID: "bg_fill", ID: "bg_fill",
Color: color.Gray{100}, Color: color.Gray{100},
}, },
&engine.DrawDAG{ &engine.DrawDAG{
ChunkSize: 16, ChunkSize: 16,
Components: engine.Components{ Child: &engine.Camera{
&engine.Camera{
ID: "game_camera", ID: "game_camera",
Child: lev1, Child: lev1,
}, },
}, },
},
&engine.DebugToast{ID: "toast", Pos: image.Pt(0, 15)}, &engine.DebugToast{ID: "toast", Pos: image.Pt(0, 15)},
engine.PerfDisplay{}, engine.PerfDisplay{},
}, },