Skip to content

Instantly share code, notes, and snippets.

@exelotl
Created August 26, 2019 22:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save exelotl/09c7fb07ae08d97aa9738d63b960bacc to your computer and use it in GitHub Desktop.
Save exelotl/09c7fb07ae08d97aa9738d63b960bacc to your computer and use it in GitHub Desktop.
# Each Actor object has a pointer an 'implementation' object (i.e. a vtable) containing methods such as create, update, draw, etc.
# The methods are free to do whatever they want with the 'data' in the actor, depending on what kind of actor it is (by casting the data to some relevant object type)
# Actor[T] is used to provide some safety and convenience when dealing with an Actor of a known kind (though T is not used anywhere in the type definition).
# Why am I doing this?
# Well this game is for an embedded platform (GBA) and I need a 'mixed bag' of objects of different kinds.
# I'd like to stay clear of malloc, allocating everything statically is hugely beneficial to me.
# Nim methods in their current state don't quite cut it for me (dispatch trees + too many hidden fields from RootObj)
const ActorDataSize = 64
type
Actor*[T] = ptr ActorObj
ActorObj* = object
impl*: ptr ActorImpl ## vtable pointer
dataBytes: array[ActorDataSize, byte] ## pointer to any kind of data
ActorMethod* = proc (actor:pointer) {.nimcall.}
ActorImpl* = object
create*: ActorMethod
destroy*: ActorMethod
update*: ActorMethod
draw*: ActorMethod
template data*[T](actor:Actor[T]): ptr T =
## Retrieve the data from an actor of a known kind
cast[ptr T](addr actor.dataBytes)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment