Hi all,
I was using a home made 2d engine for physics in my game using zay-es entity system, and I was experiencing almost not stuttering at all. Yesterday I decided to plug the excelent dyn4j physic engine and everything work perfectly : collisions, forces… it’s perfect.
I just have a system that do the following :
- call the world.updatev(MyAlwaysSameSecondPerTick)
- update the positioning component of my entities, reading body.getTransform().getTranslation()
But I encounter a jittering issue ! My bodies in motion seems to teleport back a few pixels at some random frame. The effect is irregular and get larger with speed.
Note that I have two threads : the jme thread with all the rendering, and a logic thread running at a fixed 50fps, running the logic and physics (and which seems to be never late, with an average 85% of idle time).
I don’t do any interpolation on the rendering side, and I know that the famous stuttering effect would become visible on very fast bodies or with lower fps. What’s strange is that this wasn’t noticable with my previous home made implementation. The jMonkey fps and logic thread idle time are the same than before.
Note that if I put all my logic systems into the jMonkey thread, everything become perfectly smooth.
Do you see what could have brought dyn4j to create this effect?
It may be the occasion to talk about game loop using entity system
Here is the system :
public class PhysicWorldProc extends BaseProcessor {
private final World world;
public PhysicWorldProc() {
world = new World(new AxisAlignedBounds(100, 100));
world.setGravity(new Vector2Adapter(Point2D.ORIGIN));
}
@Override
protected void registerSets() {
registerDefault(Physic.class, PlanarStance.class);
}
@Override
protected void onEntityAdded(Entity e) {
PlanarStance stance = e.get(PlanarStance.class);
Physic physic = e.get(Physic.class);
Body body = new Body();
body.getTransform().setTranslation(new Vector2Adapter(stance.getCoord()));
body.getTransform().setRotation(stance.getOrientation().getValue());
body.setLinearVelocity(new Vector2Adapter(physic.getVelocity()));
body.setAngularVelocity(physic.getAngularVelocity());
world.addBody(body);
Pool.bodies.put(e.getId(), body);
}
@Override
protected void onTickBegin() {
world.updatev(Pipeline.getSecondPerTick());
}
@Override
protected void onEntityEachTick(Entity e) {
PlanarStance stance = e.get(PlanarStance.class);
Body b = Pool.bodies.get(e.getId());
setComp(e, new PlanarStance(new Point2DAdapter(b.getTransform().getTranslation()), new Angle(b.getTransform().getRotation()), stance.elevation, stance.upVector));
}
@Override
protected void onEntityRemoved(Entity e) {
world.removeBody(Pool.bodies.get(e.getId()));
Pool.bodies.remove(e.getId());
}
}