In CLOS, instance remorphing considered useless in practice?
mail at mfiano.net
Wed Dec 9 08:49:38 UTC 2020
Hello there. I don't normally chime in on this list, but thought I could explain my usage of CHANGE-CLASS in a large Common Lisp project (~20k lines of code).
Said application is a game engine, as anyone familiar with my work would probably have guessed as much (I have several, this being the latest one I have developed over the past 2 years). CLOS, and most notably CHANGE-CLASS is an integral part of the entire system.
During a running game, there can exist multiple "entities" in the game world. They do nothing on their own however, until a "component" is attached to one. Entities and components are both represented as standard-object's. At any point in a game developer's code, they can create an entity, and either immediately or some other time later, attach a new component, or detach a previously attached component to/from an entity.
In actuality, there is no "has-a" relationship between entities and components. Upon attaching or detaching of a component from an entity, what effectively happens is the entity's class is changed by means of CHANGE-CLASS. It is done so in a way that it's class precedence list is topologically sorted according to an ordering the game developer defines. For example, they could specify that COMPONENT-FOO should be before or after COMPONENT-BAR.
At various points during the execution of each game frame, various hooks are called. For example, there are "on attach" and "on detach" hooks that are called when a component is attached or detached from an entity. There are also an "on render" hook that is fired if a particular component should be rendered to the screen, and many others.
However, since these hooks are defined by the programmer specializing on a component class, an invocation of any one of these hooks would only affect the most applicable object. And this is why we topologically sort the class precedence list as mentioned above; instead of the user-definable hooks using standard method combination, they actually all use PROGN method combination. This means any time a hook is fired for an entity, it will affect all of the components it has attached (with a no-op method for those the programmer does not define).
This whole system works beautifully for us, even though I probably didn't explain it very well. I personally use it for games with thousands of entities with various components each, that all have to be processed each frame, where 1 frame is 1/60 of a second. I am bottle-necked by CLOS somewhere around 2000 entities with a few components each for my personal game in progress, but I don't find this to be a problem for what I need currently.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the pro