ichigo/engine/interface.go

164 lines
4.8 KiB
Go
Raw Normal View History

2021-08-05 12:26:41 +10:00
package engine
2021-08-05 12:33:23 +10:00
import (
"image"
2021-08-23 10:09:49 +10:00
"io/fs"
2021-08-27 15:39:10 +10:00
"reflect"
2021-08-05 12:33:23 +10:00
2021-09-08 20:08:57 +10:00
"drjosh.dev/gurgle/geom"
2021-08-05 12:33:23 +10:00
"github.com/hajimehoshi/ebiten/v2"
)
2021-08-27 15:39:10 +10:00
// Reflection types used for queries... Is there a better way?
var (
// TypeOf(pointer to interface).Elem() is "idiomatic" -
// see https://pkg.go.dev/reflect#example-TypeOf
2021-09-10 17:18:20 +10:00
BoundingRecterType = reflect.TypeOf((*BoundingRecter)(nil)).Elem()
BoundingBoxerType = reflect.TypeOf((*BoundingBoxer)(nil)).Elem()
ColliderType = reflect.TypeOf((*Collider)(nil)).Elem()
DisablerType = reflect.TypeOf((*Disabler)(nil)).Elem()
2021-09-20 14:24:32 +10:00
DrawLayerType = reflect.TypeOf((*DrawLayer)(nil)).Elem()
2021-09-10 17:18:20 +10:00
DrawerType = reflect.TypeOf((*Drawer)(nil)).Elem()
2021-09-20 14:24:32 +10:00
DrawBoxerType = reflect.TypeOf((*DrawBoxer)(nil)).Elem()
DrawOrdererType = reflect.TypeOf((*DrawOrderer)(nil)).Elem()
2021-09-10 17:18:20 +10:00
HiderType = reflect.TypeOf((*Hider)(nil)).Elem()
IdentifierType = reflect.TypeOf((*Identifier)(nil)).Elem()
LoaderType = reflect.TypeOf((*Loader)(nil)).Elem()
PrepperType = reflect.TypeOf((*Prepper)(nil)).Elem()
ScannerType = reflect.TypeOf((*Scanner)(nil)).Elem()
SaverType = reflect.TypeOf((*Saver)(nil)).Elem()
TransformerType = reflect.TypeOf((*Transformer)(nil)).Elem()
UpdaterType = reflect.TypeOf((*Updater)(nil)).Elem()
2021-08-27 15:39:10 +10:00
// Behaviours lists all the behaviours that can be queried with Game.Query.
Behaviours = []reflect.Type{
2021-09-10 17:18:20 +10:00
BoundingRecterType,
BoundingBoxerType,
2021-08-27 15:39:10 +10:00
ColliderType,
DisablerType,
2021-09-20 14:24:32 +10:00
DrawLayerType,
2021-08-27 15:39:10 +10:00
DrawerType,
2021-09-20 14:24:32 +10:00
DrawBoxerType,
DrawOrdererType,
2021-08-27 15:39:10 +10:00
HiderType,
IdentifierType,
LoaderType,
PrepperType,
ScannerType,
SaverType,
2021-08-31 18:19:14 +10:00
TransformerType,
2021-08-27 15:39:10 +10:00
UpdaterType,
}
)
2021-09-10 17:18:20 +10:00
// BoundingRecter components have a bounding rectangle.
type BoundingRecter interface {
2021-08-23 10:34:56 +10:00
BoundingRect() image.Rectangle
}
2021-09-10 17:18:20 +10:00
// BoundingBoxer components have a bounding box.
type BoundingBoxer interface {
BoundingBox() geom.Box
}
2021-08-05 12:33:23 +10:00
// Collider components have tangible form.
type Collider interface {
2021-09-08 20:08:57 +10:00
CollidesWith(geom.Box) bool
2021-08-05 12:33:23 +10:00
}
2021-08-05 12:26:41 +10:00
2021-08-23 11:10:46 +10:00
// Disabler components can be disabled.
type Disabler interface {
2021-09-13 16:50:35 +10:00
Disabled() bool
2021-08-23 11:10:46 +10:00
Disable()
Enable()
}
2021-09-20 12:18:03 +10:00
// DrawLayer is a component responsible for calling Draw on all Drawer
// components beneath it, except those beneath another DrawLayer (it calls
// DrawAll on those).
type DrawLayer interface {
DrawAll(*ebiten.Image, *ebiten.DrawImageOptions)
}
// Drawer components can draw themselves. Draw is called often. Draw is not
// requierd to call Draw on subcomponents, if they are known to the engine
// (as part of a DrawManager).
2021-08-05 12:26:41 +10:00
type Drawer interface {
2021-09-11 13:00:23 +10:00
Draw(*ebiten.Image, *ebiten.DrawImageOptions)
2021-09-17 14:56:00 +10:00
}
2021-09-20 12:18:03 +10:00
// DrawBoxer components can both draw and have a bounding box (used for draw
// ordering).
type DrawBoxer interface {
BoundingBoxer
Drawer
}
2021-09-17 14:56:00 +10:00
// DrawOrderer components have more specific ideas about draw ordering than
// merely "my Z is bigger than yours".
type DrawOrderer interface {
2021-09-11 13:00:23 +10:00
DrawAfter(Drawer) bool
DrawBefore(Drawer) bool
2021-08-18 14:25:51 +10:00
}
2021-08-23 10:34:56 +10:00
// Hider components can be hidden.
type Hider interface {
2021-09-13 16:50:35 +10:00
Hidden() bool
2021-08-23 10:34:56 +10:00
Hide()
Show()
}
2021-08-05 12:26:41 +10:00
// Identifier components have a sense of self. This makes it easier for
2021-09-16 10:34:54 +10:00
// components to find and interact with one another. Returning the empty string
// is treated as having no identifier.
2021-08-05 12:26:41 +10:00
type Identifier interface {
Ident() string
}
2021-08-20 15:01:31 +10:00
// Loader components get the chance to load themselves. This happens
// before preparation.
type Loader interface {
2021-08-23 10:09:49 +10:00
Load(fs.FS) error
2021-08-20 15:01:31 +10:00
}
2021-08-05 12:26:41 +10:00
// Prepper components can be prepared. It is called after the component
// database has been populated but before the game is run. The component can
// store the reference to game, if needed, and also query the component database.
type Prepper interface {
2021-08-27 14:52:24 +10:00
Prepare(game *Game) error
2021-08-05 12:26:41 +10:00
}
// Scanner components can be scanned. It is called when the game tree is walked
// (such as when the game component database is constructed).
// Scan should return a slice containing all immediate subcomponents.
type Scanner interface {
Scan() []interface{}
}
2021-08-25 16:46:30 +10:00
// Saver components can be saved to disk.
type Saver interface {
Save() error
}
2021-09-07 14:00:50 +10:00
// Transformer components can provide draw options to apply to themselves and
// any child components. The opts passed to Draw of a component c will be the
// cumulative opts of all parents of c plus the value returned from c.Transform.
2021-08-31 18:19:14 +10:00
type Transformer interface {
2021-09-07 14:00:50 +10:00
Transform() ebiten.DrawImageOptions
2021-08-31 18:19:14 +10:00
}
2021-09-01 09:32:36 +10:00
// Updater components can update themselves. Update is called repeatedly. Each
// component must call Update on any internal components not known to the engine
// (i.e. not passed to Game.Register or returned from Scan).
2021-08-05 12:26:41 +10:00
type Updater interface {
Update() error
}
2021-09-11 17:53:31 +10:00
// ZPositioner components opt into a simpler method of determining draw order
// than DrawAfter/DrawBefore. Drawer implementations should handle the
// ZPositioner case as though the component were a flat infinite plane given by
// z = ZPos().
type ZPositioner interface {
ZPos() int
}