TLDR: if I have entities like Ship
and Bullet
and components like Positionable
and Drawable
, should I create interfaces for each component and inject them into my entities using DI, or should I be doing something else?
(In this case, Ship
would extend IPositionable
and have an instance of a PositionableComponent
which is injected by DI. Any calls to ship.getX
or ship.setX
would be implemented as myPositionable.getX
or myPositionable.setX
.)
I just moved away from MVC towards something more component-architecture-like. I have no concept of messages yet (it's rough prototype code), objects just get internal properties and values of other classes for now.
That issue aside, it seems like this is turning into an aspect-oriented-programming challenge. I've noticed that all entities with, for example, a position
component will have similar properties (get/set X/Y/Z, rotation, velocity).
Is it a common practice, and/or good idea, to push these behind an interface and use dependency injection to inject a generic class (eg. PositionComponent) which already has all the boiler-plate code?
(I'm sure the answer will affect the model I use for message/passing)
Edit: The DI model I'm proposing is as follows.
- Create entity classes like
Ship
andBullet
- Create interfaces to represent these components. Eg. I can expect a
PositionableComponent.getX
method. - Create component classes like
PositionableComponent
,DrawableComponent
which implement my interface - Entities like
Ship
will have components likePositionableComponent
. They will implement the methods by internally keeping an instance of apositionalbleComponent
and redirecting all interface calls to the component. - My DI framework will (presumably automatically) wire up components by interface, eg.
Ship._positionableComponent = new PositionableComponent()
. This is how NInject works, which is the only framework I've ever used (and I'm working in Haxe now).
This will allow me to work on a higher level (ships contain components), and reduce boilerplate code (component implementations), but introduces duplicate code (redirecting to the internal component). Since I'm working in Haxe, I may be able to avoid writing that boilerplate by hand.
However, the advantage is that I can override component behaviours. If undeadMonster.IsAlive()
should return true when its HP is above -100 (instead of 0), I can easily code this, and the change becomes very visible from the code level.
But I'm not sure if I'm solving this correctly.
No comments:
Post a Comment