Stability | experimental |
---|---|
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
This module is experimental, and its API might change between point releases. Use at your own risk.
The default relation between an entity and a component value is one to zero
or one. The entity may or may not have a value for the component, but if the
component value exists, it belongs to an entity. This module enables setting
multiple "child" component values rooted under the same "parent" entity,
providing a one to many relation: the parent entity has zero or more child
values of the component type. Concretely, these component values are of type
Child
c
, belong to their own separate entities, and are explicitly linked
to the parent entity.
Ad-hoc child relationships may be established without using this module by
including a parent Entity
in your component's type, but this is limiting in
regards to traversing the relationship. Systems concerned with the relationship
may only start from the child entities' component(s) and then fetch the parent
entity's component(s). By expressing the relationship using this module, you get
support for iteration over the parent-child relationship in whichever way is
more convenient for your systems, i.e. you can map over child entities using the
Child
component then fetch the child entity's parent component(s) as needed,
or you can map over the parent entities' ChildList
component then fetch the
child entities' component(s) as needed.
Some example use cases for this module:
- Parent entity has a position defined in world space and child entities have data relative to the parent's position e.g. hitboxes, sprite animations, etc.
- Parent entity is a leader and child entities are squad members e.g. a necromancer can summon skeletons
For an introduction to using this module, see the associated example.
Synopsis
- data Child c = Child !Entity !c
- newtype ChildValue c = ChildValue c
- newtype ChildList c = ChildList (NonEmpty Entity)
Component
The Child
component wraps the parent entity and the child entity's
underlying component value.
If you want a Foo
component in your game to be treated as a child
component, specify the component type as Child Foo
when declaring your
world:
newtype Hitbox = Hitbox AABB deriving Show instance Component Hitbox where type Storage Hitbox = Map Hitbox -- A type alias solely for TH quoting's sake. type ChildHitbox = Child Hitbox makeWorld "World" [''ChildHitbox]
If your system is iterating over the Child
component but does not need the
parent entity, use the ChildValue
pseudocomponent instead for better
performance.
Note that if you delete a parent entity (i.e. destroy
all of the parent entity's components), consider a
destroy
on the parent entity's children too. See
ChildList
for assistance on this. This is more from a memory
management point of view than one of safety: nothing via standard
usage of this library will break if a child "outlives" its
parent. However, both trying to directly get
some
component value of a child's non-existent parent or trying to
directly get
a parent's non-existent ChildList
will
result in runtime errors. Raw use of get
is inherently
dangerous and its risk is not specific to the behavior provided by
this module.
Pseudocomponents
newtype ChildValue c Source #
Accessor pseudocomponent that produces just the underlying component value
as opposed to Child
which also produces the parent entity.
For best performance, you should prefer ChildValue
over Child
if your
system is iterating over children and does not need the parent entities.
Instances
(MonadIO m, Component c, Has w m (Child c)) => Has w m (ChildValue c) Source # | |
Defined in Apecs.Experimental.Children | |
Component c => Component (ChildValue c) Source # | |
Defined in Apecs.Experimental.Children type Storage (ChildValue c) Source # | |
Show c => Show (ChildValue c) Source # | |
Defined in Apecs.Experimental.Children showsPrec :: Int -> ChildValue c -> ShowS # show :: ChildValue c -> String # showList :: [ChildValue c] -> ShowS # | |
Eq c => Eq (ChildValue c) Source # | |
Defined in Apecs.Experimental.Children (==) :: ChildValue c -> ChildValue c -> Bool # (/=) :: ChildValue c -> ChildValue c -> Bool # | |
type Storage (ChildValue c) Source # | |
Defined in Apecs.Experimental.Children |
Pseudocomponent that produces all child entities for a parent.
A useful property of this pseudocomponent is that it may be destroyed, which
does a cascading destroy
on all of the parent's children:
-- Remove all of player 1 entity's hitboxes: destroy player1 $ Proxy @(ChildList Hitbox)
The cascading destroy
behavior is provided for convenience,
but note that if you assigned additional components to the child entities,
those components will not be destroyed. In this case, you should destroy
all components on the children explicitly, e.g.:
ChildList children :: ChildList Hitbox <- get player1 for_ children $ \child -> do destroy child $ Proxy @ComponentsToDestroy