A component/entity system
nimble install entoody
this is a rewrite of my entity system (fowltek/entitty)
Entity is an aggregate of components. Their combined data and behaviors.
Components are data and/or behavior. We use an object type (similar to a struct) to store data, and define messages to implement behavior.
Message is a function that operates on an entity. There are two kinds of messages, unicast and multicast. Unicast messages are fulfilled by at most ONE component, while multicast messages may be
Only unicast messages may return a value. For multicast messages, another mechanism would have to be added to make sense of all the return values. That sounds like YOU work to me, lul. I recommend you pass along a seq where results can be collected, then you can make sense of them later: ```nimrod proc debugInfo (results: var seq[string]) {.multicast.} ## Collect information on an entities components proc debugInfo* (entity:PEntity): string = ## Collect component information as a var res: seq[string] = @[] entity.debugInfo(res) # call the message result = res.join(", ") # collect the results
defMsg(Position, debugInfo) do (res: var seq[string]): res.add "Position: "& $entity[Position].TPoint2d defMsg(Orientation, debugInfo) do (res: var seq[string]): res.add "Orientation: $# degrees" % $entity[Orientation].radians.radToDeg.formatFloat(ffDecimal, 2) ```
Yes. Can see sample. ```nimrod import entoody, basic2d
entity: PEntity
is inserted in the functionproc getPosition* : TPoint2d {.unicast.} proc setPosition* (pos: TPoint2d) {.unicast.}
type Position* = distinct TPoint2d
defMsg(Position, getPosition) do -> TPoint2d: # you can use the subscript operator to access an entity's components entity[Position].TPoint2d defMsg(Position, setPosition) do (pos: TPoint2d): entity[Position] = pos.Position
type Orientation* = object radians*: float
discard componentID(Orientation)
when isMainModule: # You should be done defining static components before you can instantiate an entity var dom = newDomain() var ent = dom.newEntity(Position, Orientation) assert ent.hasComponent(Position) ent.setPosition point2d(100,100) let pos = ent.getPosition assert pos.distance(point2d(100,100)) < 1.0 ```
MSG message_name
, this way when you
implement a message with def_msg you get an error if the arguments mismatch.allocate
, initialize
, destroy
msgImpl
will be renamed to defMsg
, msgImpl now does not allow for unicast weight, but you can still read it to find out what the defMsg() macro doesfindMessage(ci:PComponentInfo, messageName:semistatic[string]): TMaybe[pointer]
for getting the raw function for a message (if the component responds to it). The return value is really TMaybe[MSG message_name
]