docs/02-overview.markdown @ a0fafd0adf19 v1.0.0
Fix stupid bug
| author | Steve Losh <steve@stevelosh.com> |
|---|---|
| date | Fri, 12 Aug 2016 02:42:49 +0000 |
| parents | d431e5cd0d3d |
| children | b4fab641f442 |
Overview ======== When you're making a video game you need a way to model things in the game world. In the past couple of decades Entity/Component systems have become popular: * <http://gameprogrammingpatterns.com/component.html> * <http://en.wikipedia.org/wiki/Entity_component_system> * <http://www.gamedev.net/page/resources/_/technical/game-programming/understanding-component-entity-systems-r3013> There are a couple of ECS libraries for Common Lisp already: * [cl-ecs](https://github.com/lispgames/cl-ecs) * [ecstasy](https://github.com/mfiano/ecstasy) Both of these favor composition over inheritance -- game objects (entities) *contain* various components, but they don't *inherit* from components. Beast takes the opposite approach, favoring (restricted) inheritance over composition. Components in Beast are called "aspects" to try to overload the word "component" a little bit less in this crazy world. Aspects are essentially [mixins](https://en.wikipedia.org/wiki/Mixin), with some sugar for defining them and running systems over them: :::lisp (define-aspect throwable accuracy damage) (define-aspect edible nutrition-value) (define-entity dart (throwable)) (define-entity cheese (edible)) (define-entity pie (throwable edible)) (define-system rot-food ((e edible)) (decf (edible/nutrition-value e)) (when (zerop (edible/nutrition-value e)) (destroy-entity e))) (defparameter *steel-dart* (create-entity 'dart :throwable/accuracy 0.9 :throwable/damage 10)) (defparameter *hunk-of-swiss* (create-entity 'cheese :edible/nutrition-value 50)) (defparameter *banana-cream-pie* (create-entity 'pie :throwable/accuracy 0.3 :throwable/damage 5 :edible/nutrition-value 30)) Beast tries to be just a very thin layer over CLOS, because CLOS is quite powerful. You can use `typep`, generic methods, before/after/around methods, and everything else CLOS gives you. Like every engineering decision this comes with are tradeoffs. You can't (easily) add or remove aspects to/from a particular entity at runtime like you can with cl-ecs. And there's no way to give an entity multiple "copies" of a single aspect. The author has found this approach to work well for his needs. You should take a look at both approaches and decide which is best for you. If you want to read more, check out the [Usage](../usage/) document.