I am developing a JME3.2 project with usage of Physics.
I have implemented some architecture, and have questions if I should restructure the application:
I still did not implement Save/Load functionality
I still did not implement HUD Display and menu
Through a control or AppState - probably a control.
Looks pretty ok but it really depends on how it works for you. If adding features is like pulling teeth you might want to reconsider your design. The only thing Iâd suggest is that you might want to look into an ECS like @pspeedâs Zay-Es.
Now that Iâm reading this⌠I probably should split my CollisionAppstate into several controls, because it looks like an eldritch abomination of EntityId and class castingâŚ
Truthfully, any architecture based on treating Spatials as game objects is going to collapse under its own weight eventually. For the right sized game, you might finish it before that happens, though.
public class MyCollisionControl extends AbstractControl {
private EntityData ed;
private EntitySet entities;
private ModelState modelState;
private Dyn4jMEAppState dyn4jMEAppState;
public MyCollisionControl (ModelState modelState, Dyn4jMEAppState dyn4j) {
this.ed = FightAppState2.ed;
entities = ed.getEntities(MyCollidable.class);
this.modelState = modelState;
this.dyn4jMEAppState = dyn4j;
}
@Override
protected void controlUpdate(float tpf) {
entities.applyChanges();
for (Entity e : entities) {
Spatial coll= modelState.getSpatial(e.getId());
// retrieve the physics bodies, then check collision
if (dyn4jMEAppState.getPhysicsSpace(0).checkCollisionNP(body1,body2)) {
//hit! This destroy the spatial we're controlling...
//entities.release();
}
}
}
}
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {
}
}
Please note what is NOT coded but always present on @pspeed examples :
entities.release();
entities = null;
Ather a collision the entity is removed, so does the Spatial and therefore the MyCollisionControl is gone. But if I call entities.release() within the loop, and then add a new MyCollisionControl to another spatial it doesnât collide at all.
I donât know⌠this is already in a very strange direction to me.
Generally speaking, itâs very strange to marry an ES to controls. Itâs unclear to me why the control even needs to know about physics at all in an ES.
Normally, physics would be a system that manages the physical entities. The spatials are just dumb followers of whatever the entity says (which is likely fed by the physics system but maybe not⌠it doesnât care).
In your case, you seem to have a control that is somehow managing ALL collidable entities. Do you then have this control on every collidable spatial, ie: some huge N:N combinatorial mess?
Itâs very strange to manage collisions this way instead of centrally as part of a global system. You end up doing at least twice the work if not more.
Weâre kind of derailing OPâs thread but letâs bring it back to some âES theoryâ just in case OP finds that approach interesting.
One of the ideas behind an entity system is to think of your game in the sense of bulk operations. Itâs one way to look at system decomposition that might be helpful but it is certainly not the only way and certainly not the only benefit. (Think of a system in terms of bulk operations also nicely separates code concerns, etc., too⌠itâs just a âgood thing.â)
Leave the ES structures aside for a momentâŚ
So imagine if you have a million game objects that you want to perform simple physics on. Acceleration, velocity, etcâŚ
Think of one giant memory coherent array of all acceleration vectors and velocity vectors. You loop over all one million and increase velocity by accleration * timeStep. There is literally no faster way to do that.
Next you do a similar loop over all velocity and positions, add velocity * timeStep to position.
This is the type of operation you want to think of in a data-centric design. It leads to some interesting things.
itâs the fastest way. Provably so. And if you were writing native level highly optimized code, you avoid cache misses, memory can be streamed, all kinds of goodness we Java developers donât care about but itâs interesting to think about anyway.
decoupling. In this silly example, the velocity update and the position update are completely independent. You could swap out the implementation and nothing cares. You could decide that you donât want acceleration at all and things will just be straight velocity. The position update loop doesnât care about that.
threading. There is no reason these two things couldnât be run in parallel, really. If you donât care about per-frame integrity then you really really donât care. And if you were simulating a world with a million objects at once, Iâm going to guess you probably arenât going to care about frame-step-level integrity. But certainly in examples that DONâT involve physics, there are hundreds of cases where per-frame game-wide consistency is unimportant.
Unfortunately, collisions donât allow us a nice loop like that since on some level you have to compare objects to other objects⌠however, almost always the physics engine you are using will have some kind of internal optimizations for you. Likely, you can either list out all of the contacts or at least iterate over the colliding bodies.
From there you could produce contacts or other synthesized results that follow on stages use. (Iâm a fan of contact entities but now weâre starting to get back into ES-specific terms).
The bottom line is that this sort of data-centric decomposition is almost always a good thing. For the three reasons above and more.
My ES modelstate invoke the factory which in turn invoke the add(Spatial) I posted; so to answer your question I think it should be managed by an ES (or at least that is my goal).
I had to go through the same thing with a project I was working on earlier (just getting back into coding after a bit of a break). It was a little hard to wrap my noodle around how to make it work but man o man⌠Once itâs setup⌠Itâs soooooo much easier to control things via physics.