I’ve been working on this steering behavior library for a while, and recently I’ve made substantial progress however I’m starting to feel more and more uneasy about my design as I start making example games/simulations using the library.
I have these 3 different concepts: SpatialEntity, SteerSubject, & Target (my Vector class implements Target).
Issues arise when I want to use one in place of another, since they’re so similar (all have a position, 2 have a radius, one has velocity, direction & acceleration). For example I have a TargetClosest which given a SteerSubject will return the closest SpatialEntity. I have steering behaviors which take targets like this and determine whether to stay away from, steer to, steer around, hide from, etc. It returns a SpatialEntity (which SteerSubject implements BTW) because I didn’t want to say all spatial entities (which can be added to spatial databases) have a velocity, acceleration, etc…
My options as I currently see it:
- Add a super interface to everything, it has: position, spatialGroups, spatialCollisionGroups, isStatic, isInert, direction, velocity, maximum velocity, acceleration, maximum acceleration. The defaults are 0 (or vectors at the origin), except position is required. This would mean 13 methods would be implemented, but in some cases (like Vector) it would only return one useful value. I think this is useful however, since maybe I want the unit to guard a Vector opposed to another unit, or the future position of a unit.
- Add a lightweight component system, so that the super interface has getFloat|Vector where SpatialProperty is an enum and each implementation would instead have a switch statement on the enum which would be fairly fast.
- Add an interface for each concept, like Spatial{isStatic,isInert,spatialGroups,spatialCollisionGroups}, HasPosition{position}, HasVelocity{velocity, maximum velocity}, and HasAcceleration{acceleration,maximum acceleration}. This will result in some very verbose code in the library, I will have generics like <T extends HasPosition & HasVelocity> and I don’t know whether that explicitness is a nice thing or not.
Another dilemma I’m working on is whether instead of having a radius, I can have a shape (which I have shapes implemented already: Segment, Plane, Bounds, Sphere). I liked radius initially because that keeps things super simple and fast. But I don’t know whether someone would maybe wan’t something else. Decisions…
If anyone could shed any light on this… I’ve had this exact same problem many times and I’ve always just picked one but I’ve always had bits of regret and I was hoping maybe someone can talk me into using one method or another so I don’t have to make these decisions.