Documentation ¶
Index ¶
- Constants
- Variables
- func LoadGobz(dst any, assets fs.FS, path string) error
- func SaveGobz(src any, name string) error
- type Actor
- func (a *Actor) BoundingBox() geom.Box
- func (a *Actor) CollidesAt(p geom.Int3) bool
- func (a *Actor) MoveX(x float64, onCollide func())
- func (a *Actor) MoveY(y float64, onCollide func())
- func (a *Actor) MoveZ(z float64, onCollide func())
- func (a *Actor) Prepare(g *Game) error
- func (a *Actor) String() string
- type Anim
- type AnimDef
- type AnimStep
- type AnimatedTile
- type Billboard
- func (b *Billboard) BoundingBox() geom.Box
- func (b *Billboard) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions)
- func (b *Billboard) Prepare(g *Game) error
- func (b *Billboard) Scan(visit VisitFunc) error
- func (b *Billboard) String() string
- func (b *Billboard) Transform() (opts ebiten.DrawImageOptions)
- type BoundingBoxer
- type BoundingRecter
- type Bounds
- type Camera
- type Collider
- type Container
- func (c *Container) Add(component any)
- func (c *Container) Contains(component any) bool
- func (c *Container) Element(i int) any
- func (c *Container) GobDecode(in []byte) error
- func (c *Container) GobEncode() ([]byte, error)
- func (c *Container) IndexOf(component any) (int, bool)
- func (c *Container) ItemCount() int
- func (c *Container) Len() int
- func (c *Container) Remove(component any)
- func (c *Container) Scan(visit VisitFunc) error
- func (c *Container) String() string
- func (c *Container) Swap(i, j int)
- type DebugToast
- type Disabler
- type Disables
- type DrawBoxer
- type DrawDAG
- func (d DrawDAG) Dot() string
- func (d *DrawDAG) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions)
- func (DrawDAG) ManagesDrawingSubcomponents()
- func (d *DrawDAG) Prepare(game *Game) error
- func (d *DrawDAG) Register(component, _ any) error
- func (d *DrawDAG) Scan(visit VisitFunc) error
- func (d *DrawDAG) String() string
- func (d *DrawDAG) Unregister(component any)
- func (d *DrawDAG) Update() error
- type DrawDFS
- type DrawManager
- type DrawOrderer
- type Drawer
- type DummyLoad
- type Fill
- type Game
- func (g *Game) Children(c any) *Container
- func (g *Game) Component(id string) Identifier
- func (g *Game) Draw(screen *ebiten.Image)
- func (g *Game) Ident() string
- func (g *Game) Layout(outsideWidth, outsideHeight int) (w, h int)
- func (g *Game) Load(component any, assets fs.FS) error
- func (g *Game) LoadAndPrepare(assets fs.FS) error
- func (g *Game) Parent(c any) any
- func (g *Game) Path(component any) []any
- func (g *Game) PathRegister(component, parent any) error
- func (g *Game) PathUnregister(component any)
- func (g *Game) Prepare(component any) error
- func (g *Game) Query(ancestor any, behaviour reflect.Type, visitPre, visitPost VisitFunc) error
- func (g *Game) REPL(src io.Reader, dst io.Writer, assets fs.FS) error
- func (g *Game) Register(component, parent any) error
- func (g *Game) ReversePath(component any) []any
- func (g *Game) Scan(visit VisitFunc) error
- func (g *Game) String() string
- func (g *Game) Unregister(component any)
- func (g *Game) Update() error
- type Hider
- type Hides
- type ID
- type Identifier
- type ImageRef
- type Loader
- type LoadingSwitch
- type Parallax
- type PerfDisplay
- type Prepper
- type Prism
- type PrismMap
- type Registrar
- type Saver
- type Scanner
- type Scene
- type SceneRef
- type Sheet
- type SolidRect
- type Sprite
- func (s *Sprite) Anim() *Anim
- func (s *Sprite) BoundingBox() geom.Box
- func (s *Sprite) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions)
- func (s *Sprite) Scan(visit VisitFunc) error
- func (s *Sprite) SetAnim(a *Anim)
- func (s *Sprite) String() string
- func (s *Sprite) Transform() (opts ebiten.DrawImageOptions)
- func (s *Sprite) Update() error
- type StaticTile
- type Tile
- type Tilemap
- func (t *Tilemap) CollidesWith(b geom.Box) bool
- func (t *Tilemap) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions)
- func (t *Tilemap) Load(fs.FS) error
- func (t *Tilemap) Scan(visit VisitFunc) error
- func (t *Tilemap) SetTileAt(wc image.Point, tile Tile)
- func (t *Tilemap) TileAt(wc image.Point) Tile
- func (t *Tilemap) TileBounds(wc image.Point) image.Rectangle
- func (t *Tilemap) Transform() (opts ebiten.DrawImageOptions)
- type Transformer
- type Updater
- type VisitFunc
- type Wall
- type WallUnit
Constants ¶
const Skip = skip("skip")
Skip is an "error" value that can be returned from visitor callbacks. It tells recursive methods of Game to skip processing the current item and its descendants, but will otherwise continue processing.
Variables ¶
var ( // TypeOf(pointer to interface).Elem() is "idiomatic" - // see https://pkg.go.dev/reflect#example-TypeOf BoundingBoxerType = reflect.TypeOf((*BoundingBoxer)(nil)).Elem() BoundingRecterType = reflect.TypeOf((*BoundingRecter)(nil)).Elem() ColliderType = reflect.TypeOf((*Collider)(nil)).Elem() DisablerType = reflect.TypeOf((*Disabler)(nil)).Elem() DrawBoxerType = reflect.TypeOf((*DrawBoxer)(nil)).Elem() DrawerType = reflect.TypeOf((*Drawer)(nil)).Elem() DrawManagerType = reflect.TypeOf((*DrawManager)(nil)).Elem() DrawOrdererType = reflect.TypeOf((*DrawOrderer)(nil)).Elem() HiderType = reflect.TypeOf((*Hider)(nil)).Elem() IdentifierType = reflect.TypeOf((*Identifier)(nil)).Elem() LoaderType = reflect.TypeOf((*Loader)(nil)).Elem() PrepperType = reflect.TypeOf((*Prepper)(nil)).Elem() RegistrarType = reflect.TypeOf((*Registrar)(nil)).Elem() SaverType = reflect.TypeOf((*Saver)(nil)).Elem() ScannerType = reflect.TypeOf((*Scanner)(nil)).Elem() TransformerType = reflect.TypeOf((*Transformer)(nil)).Elem() UpdaterType = reflect.TypeOf((*Updater)(nil)).Elem() // Behaviours lists all the behaviours that can be queried with Game.Query. Behaviours = []reflect.Type{ BoundingBoxerType, BoundingRecterType, ColliderType, DisablerType, DrawBoxerType, DrawerType, DrawManagerType, DrawOrdererType, HiderType, IdentifierType, LoaderType, PrepperType, RegistrarType, SaverType, ScannerType, TransformerType, UpdaterType, } )
Reflection types used for queries... Is there a better way?
Functions ¶
Types ¶
type Actor ¶
type Actor struct { CollisionDomain string // id of component to look for colliders inside of Pos geom.Int3 // in voxels; multiply by game.VoxelScale for regular Euclidean space Bounds geom.Box // in voxels; relative to Pos // contains filtered or unexported fields }
Actor handles basic movement.
func (*Actor) BoundingBox ¶
BoundingBox returns the box Bounds.Add(Pos).
func (*Actor) CollidesAt ¶
CollidesAt runs a collision test of the actor, supposing the actor is at a given position (not necessarily a.Pos).
func (*Actor) MoveX ¶
MoveX moves the actor x units in world space. It takes Game.VoxelScale into account (so MoveX(x) moves the actor x/VoxelScale.X voxel units). onCollide is called if a collision occurs, and the actor wil be in the colliding position during the call.
type Anim ¶
type Anim struct { Def *AnimDef Index int // current step index Ticks int // ticks spent at this step }
Anim is the current state of an animation being played (think of it as an instance of an AnimDef). nil *Anim can be used, but always returns 0 for the current frame.
type AnimatedTile ¶
type AnimatedTile struct { AnimKey string // contains filtered or unexported fields }
AnimatedTile uses an Anim to choose a tile index.
func (*AnimatedTile) Cell ¶
func (a *AnimatedTile) Cell() int
Cell returns the value of Cell provided by the animation.
type Billboard ¶
type Billboard struct { ID Hides Pos geom.Int3 Src ImageRef // contains filtered or unexported fields }
Billboard draws an image at a position.
func (*Billboard) BoundingBox ¶
BoundingBox returns a 0-depth box incorporating the image size.
func (*Billboard) Draw ¶
func (b *Billboard) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions)
Draw draws the image.
type BoundingBoxer ¶
BoundingBoxer components have a bounding box.
type BoundingRecter ¶
BoundingRecter components have a bounding rectangle.
type Bounds ¶
Bounds implements Bounder directly (as an image.Rectangle value).
func (Bounds) BoundingRect ¶
BoundingRect returns b as an image.Rectangle.
type Camera ¶
type Camera struct { ID Child any Disables Hides // Camera controls // These directly manipulate the camera. If you want to restrict the camera // view area to the child's bounding rectangle, use PointAt. Centre image.Point // voxel coordinates Rotation float64 // radians Zoom float64 // unitless // contains filtered or unexported fields }
Camera models a camera that is viewing something.
func (*Camera) PointAt ¶
PointAt points the camera at a particular centre point and zoom, but adjusts for the bounds of the child component (if available).
type Container ¶
type Container struct {
// contains filtered or unexported fields
}
Container is a component that contains many other components, in order. It can be used as both a component in its own right, or as an ordered set. A nil *Container contains no items and modifications will panic (like a map).
func MakeContainer ¶
MakeContainer puts the items into a new Container.
func (*Container) Add ¶
Add adds an item to the end of the container, if not already present. Adding nil, or a component already present in the container, does nothing. Add is _not_ safe to call on a nil *Container.
func (*Container) Contains ¶
Contains reports if an item exists in the container. Contains is safe to call on a nil *Container.
func (*Container) Element ¶
Element returns the item at index i, or nil for a free slot. Element is _not_ safe to call on a nil *Container.
func (*Container) GobEncode ¶
GobEncode encodes c as the slice of items. When called on a nil *Container, GobEncode returns a nil slice.
func (*Container) IndexOf ¶
IndexOf reports if an item exists in the container and returns the index if present. IndexOf is safe to call on a nil *Container.
func (*Container) ItemCount ¶
ItemCount returns the number of (non-nil) items in the container. ItemCount is safe to call on a nil *Container.
func (*Container) Len ¶
Len returns the number of items plus the number of nil slots in the container. Len is safe to call on a nil *Container.
func (*Container) Remove ¶
Remove replaces an item with nil. If the number of nil items is greater than half the slice, the slice is compacted (indexes of items will change). Removing an item not in the Container does nothing. Remove is safe to call on a nil *Container.
type DebugToast ¶
DebugToast debugprints a string for a while, then disappears.
func (*DebugToast) Draw ¶
func (d *DebugToast) Draw(screen *ebiten.Image, _ *ebiten.DrawImageOptions)
Draw uses DebugPrintAt to draw d.Text at the position d.Pos.
func (*DebugToast) String ¶
func (d *DebugToast) String() string
func (*DebugToast) Toast ¶
func (d *DebugToast) Toast(text string)
Toast sets the text to appear for 2 seconds.
func (*DebugToast) Update ¶
func (d *DebugToast) Update() error
Update hides the toast text once the timer is exhausted.
type Disabler ¶
type Disabler interface { Disabled() bool Disable() Enable() }
Disabler components can be disabled.
type DrawBoxer ¶
type DrawBoxer interface { BoundingBoxer Drawer }
DrawBoxer components can both draw and have a bounding box (used for draw ordering).
type DrawDAG ¶
type DrawDAG struct { ChunkSize int Child any Disables Hides // contains filtered or unexported fields }
DrawDAG is a DrawManager that organises DrawBoxer descendants in a directed acyclic graph (DAG), in order to draw them according to ordering constraints. It combines a DAG with a spatial index used when updating vertices to reduce the number of tests between components.
func (DrawDAG) Dot ¶
func (d DrawDAG) Dot() string
Dot returns a dot-syntax-like description of the graph.
func (*DrawDAG) Draw ¶
func (d *DrawDAG) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions)
Draw draws everything in the DAG in topological order.
func (DrawDAG) ManagesDrawingSubcomponents ¶
func (DrawDAG) ManagesDrawingSubcomponents()
ManagesDrawingSubcomponents is present so DrawDAG is recognised as a DrawManager.
func (*DrawDAG) Register ¶
Register recursively registers compponent and all descendants that are DrawBoxers into internal data structures (the DAG, etc) unless they are descendants of a different DrawManager.
func (*DrawDAG) Unregister ¶
Unregister unregisters the component and all subcomponents.
type DrawDFS ¶
DrawDFS is a DrawManager that does not add any structure. Components are drawn in the order in which they are encountered by a depth-first search through the game tree using Query, without any extra sorting based on Z values or consideration for DrawOrderer.
func (*DrawDFS) Draw ¶
func (d *DrawDFS) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions)
Draw draws all descendant components (that are not managed by some other DrawManager) in a pre-order traversal.
func (DrawDFS) ManagesDrawingSubcomponents ¶
func (DrawDFS) ManagesDrawingSubcomponents()
ManagesDrawingSubcomponents is present so DrawDFS is recognised as a DrawManager.
type DrawManager ¶
type DrawManager interface {
ManagesDrawingSubcomponents()
}
DrawManager is a component responsible for calling Draw on all Drawer components beneath it, except those beneath another DrawManager (it might call Draw on the DrawManager, but that's it).
type DrawOrderer ¶
DrawOrderer components have more specific ideas about draw ordering than merely "my Z is bigger than yours".
type Drawer ¶
type Drawer interface {
Draw(*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).
type Fill ¶
Fill fills the screen with a colour.
type Game ¶
type Game struct { Disables Hides Projection geom.Projector Root Drawer ScreenSize image.Point VoxelScale geom.Float3 // contains filtered or unexported fields }
Game implements the ebiten methods using a collection of components. One component must be the designated root component.
func (*Game) Children ¶
Children returns the direct subcomponents of the given component, or nil if there are none. This only returns sensible values for registered components.
func (*Game) Component ¶
func (g *Game) Component(id string) Identifier
Component returns the component with a given ID, or nil if there is none. This only returns sensible values for registered components (e.g. after LoadAndPrepare).
func (*Game) Load ¶
Load loads a component and all subcomponents recursively. Note that this method does not implement Loader itself.
func (*Game) LoadAndPrepare ¶
LoadAndPrepare first calls Load on all Loaders. Once loading is complete, it builds the component databases and then calls Prepare on every Preparer. LoadAndPrepare must be called before any calls to Component or Query.
func (*Game) Parent ¶
Parent returns the parent of a given component, or nil if there is none. This only returns sensible values for registered components.
func (*Game) Path ¶
Path returns a slice with the path of components to reach component from g (including g and component).
func (*Game) PathRegister ¶
PathRegister calls Register on every Registrar in the path between g and parent (top-to-bottom, i.e. game first, component last).
func (*Game) PathUnregister ¶
PathUnregister calls Unregister on every Registrar in the path between g and parent (bottom-to-top, i.e. component first, game last).
func (*Game) Prepare ¶
Prepare prepares a component and all subcomponents recursively. Note that this method does not implement Prepper itself.
func (*Game) Query ¶
Query recursively searches for components having both a given ancestor and implementing a given behaviour (see Behaviors in interface.go). visitPre is called before descendants are visited, while visitPost is called after descendants are visited. nil visitPre/visitPost are ignored.
It is up to the visitPre and visitPost callbacks to handle components that do not themselves implement the behaviour - more specifically, every ancestor (up to the given one) of each component with the behaviour will be visited. Visiting components in the tree that *don't* implement the behaviour is important when behaviours of the parent need to influence the behaviours of the children (e.g. a component can be a Hider and hiding all descendants, but not necessarily be a Drawer itself).
Query only visits components that are registered.
Note that every component is an ancestor of itself.
Query returns the first error returned from either visitor callback, except Skip when it is returned from a recursive call. Returning Skip from visitPre will cause visitPost and the descendants of the component to be skipped (see the implementation of Update for an example of how to use this).
func (*Game) REPL ¶
REPL runs a read-evaluate-print-loop. Commands are taken from src and output is written to dst. assets is needed for commands like reload.
func (*Game) Register ¶
Register registers a component into the component database (as the child of a given parent). Passing a nil component or parent is an error. Registering multiple components with the same ID is also an error. Registering a component will recursively register all children found via Scan.
func (*Game) ReversePath ¶
ReversePath returns the same slice as Path, but reversed. (ReversePath is faster than Path).
func (*Game) Unregister ¶
Unregister removes the component from the component database. Passing a nil component has no effect. Unregistering a component will recursively unregister child components found via Scan.
type Identifier ¶
type Identifier interface {
Ident() string
}
Identifier components have a sense of self. This makes it easier for components to find and interact with one another. Returning the empty string is treated as having no identifier.
type ImageRef ¶
type ImageRef struct { Path string // contains filtered or unexported fields }
ImageRef loads images from the AssetFS into *ebiten.Image form. It is your responsibility to import _ "image/..." for whatever format the files are in, and to load it (either return it as a subcomponent from Scan so that Game will Load it, or call Load yourself).
func (*ImageRef) Image ¶
func (r *ImageRef) Image() *ebiten.Image
Image returns the image, or nil if not loaded. Multiple distinct ImageRefs can use the same path efficiently.
type LoadingSwitch ¶
type LoadingSwitch struct {
During, After interface {
Disabler
Hider
}
// contains filtered or unexported fields
}
LoadingSwitch switches between two subcomponents. While After is being loaded asynchronously, During is shown. Once loading is complete, During is hidden and After is shown.
func (*LoadingSwitch) Load ¶
func (s *LoadingSwitch) Load(assets fs.FS) error
Load stores a copy of assets to pass to s.After.Load later.
func (*LoadingSwitch) Prepare ¶
func (s *LoadingSwitch) Prepare(game *Game) error
Prepare loads, registers, and prepares.After in a separate goroutine. Once ready, LoadingSwitch hides s.During and shows s.After.
func (*LoadingSwitch) Scan ¶
func (s *LoadingSwitch) Scan(visit VisitFunc) error
Scan only scans s.During. Only s.During is loaded automatically - s.After is loaded asynchronously from Prepare below.
type Parallax ¶
type Parallax struct { CameraID string Factor float64 // how much to translate in response to the camera Child any // contains filtered or unexported fields }
Parallax is a container that translates based on the position of a camera, intended to produce a "parallax" like effect.
type PerfDisplay ¶
type PerfDisplay struct {
Hides
}
PerfDisplay debugprints CurrentTPS and CurrentFPS in the top left.
func (PerfDisplay) Draw ¶
func (p PerfDisplay) Draw(screen *ebiten.Image, _ *ebiten.DrawImageOptions)
Draw uses DebugPrint to print the TPS and FPS in the top-left.
func (PerfDisplay) String ¶
func (PerfDisplay) String() string
type Prepper ¶
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 Prism ¶
type Prism struct { Cell int // contains filtered or unexported fields }
Prism represents a single prism in a PrismMap.
func (*Prism) BoundingBox ¶
BoundingBox returns a bounding box for the prism.
func (*Prism) Draw ¶
func (p *Prism) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions)
Draw draws the prism.
func (*Prism) DrawBefore ¶
DrawBefore reports if the prism should be drawn before x.
type PrismMap ¶
type PrismMap struct { ID Disables Hides Ersatz bool Map map[geom.Int3]*Prism // pos -> prism DrawOffset image.Point // offset applies to whole map PosToWorld geom.IntMatrix3x4 // p.pos -> world voxelspace PrismSize geom.Int3 // in world voxelspace units PrismTop []image.Point // polygon vertices anticlockwise, Y means Z Sheet Sheet // contains filtered or unexported fields }
PrismMap is a generalised 3D tilemap/wallmap/voxelmap etc.
func (*PrismMap) CollidesWith ¶
CollidesWith checks if the box collides with any prism.
type Registrar ¶
Registrar components can register and unregister other components (usually into internal data structures). Registrars are expected to automatically register/unregister subcomponents of components (usually recursively).
type Scanner ¶
Scanner components can be scanned. It is called when the game tree is walked (such as when the game component database is constructed) and various times afterward (such as during Update). Scan should visit each immediate subcomponent, aborting early if an error is returned from the visitor.
type SceneRef ¶
SceneRef loads a gzipped, gob-encoded Scene from the asset FS. After Load, Scene is usable. This is mostly useful for scenes that refer to other scenes, e.g.
sc := &Scene{ Components: []any{ &SceneRef{Path: "assets/foo.gob.gz"} // inflated at Load time }, }
type Sheet ¶
type Sheet struct { AnimDefs map[string]*AnimDef CellSize image.Point Src ImageRef // contains filtered or unexported fields }
Sheet handles images that consist of a grid of equally sized regions (cells) and can produce subimages for the cell at an index. This is useful for various applications such as sprite animation and tile maps. Additionally each sheet carries a collection of animations that use the sheet.
func (*Sheet) NewAnim ¶
NewAnim returns a new Anim for the given key, or nil if not found in AnimDefs.
type Sprite ¶
type Sprite struct { Actor Actor DrawOffset image.Point Hides Sheet Sheet // contains filtered or unexported fields }
Sprite combines an Actor with the ability to Draw from a single spritesheet.
func (*Sprite) BoundingBox ¶
BoundingBox forwards the call to Actor.
func (*Sprite) Draw ¶
func (s *Sprite) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions)
Draw draws the current cell to the screen.
func (*Sprite) SetAnim ¶
SetAnim sets the Anim to use for the sprite. If it is not the same as the one currently set, it resets the new anim.
type Tilemap ¶
type Tilemap struct { ID Disables Hides Map map[image.Point]Tile // tilespace coordinate -> tile Ersatz bool // disables collisions ("fake wall") Offset image.Point // world coordinates Sheet Sheet }
Tilemap renders a grid of rectangular tiles at equal Z position.
func (*Tilemap) CollidesWith ¶
CollidesWith implements Collider.
func (*Tilemap) Draw ¶
func (t *Tilemap) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions)
Draw draws the tilemap.
func (*Tilemap) TileBounds ¶
TileBounds returns a rectangle describing the tile boundary for the tile at the given world coordinate.
type Transformer ¶
type Transformer interface {
Transform() ebiten.DrawImageOptions
}
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.
type Updater ¶
type Updater interface {
Update() error
}
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).
type VisitFunc ¶
VisitFunc callbacks are either provided or called by various Game functions. For example, Query takes two VisitFuncs that are called for each result, and Scan is given a VisitFunc that should be called with each component. For recursive operations, return Skip for components that should be skipped.
type Wall ¶
type Wall struct { ID Ersatz bool // disables collisions ("fake wall") Offset image.Point // offset the whole wall Sheet Sheet UnitOffset image.Point // drawing offset UnitSize image.Point // tile size Units map[image.Point]*WallUnit }
Wall is a more flexible kind of tilemap. WallUnits can be added at the same level as other components and are responsible for their own drawing, so that Game can do draw ordering, e.g. hide the player character behind a wall. But Wall is still responsible for collisions.
func (*Wall) CollidesWith ¶
CollidesWith implements a tilerange collosion check, similar to Tilemap.
func (*Wall) Prepare ¶
Prepare makes sure all WallUnits know about Wall and where they are, for drawing.
type WallUnit ¶
type WallUnit struct { Disables Hides Tile Tile // chooses which cell in wall.Sheet to draw // contains filtered or unexported fields }
WallUnit is a unit in a wall. Unlike a tile in a tilemap, WallUnit is responsible for drawing itself.