I am drawing a series of Body objects on a Slick2D screen from a dyn4j World (World.getBodies()) and getting a very low frame rate, i.e. 6-10 FPS. Here is the part of the render loop in Slick2D that draws the dyn4j bodies:
for (int i = 0; i < space.getBodies().size(); i++) { // Iterate through World bodies
if (space.getBodies().get(i) instanceof lander.ShipFragmentPool.Fragment) {
lander.ShipFragmentPool.Fragment fragment = (lander.ShipFragmentPool.Fragment) space.getBodies().get(i);
float x = (float) (fragment.getWorldCenter().x * scale); // Extract fragementco-ordinates
float y = (float) (fragment.getWorldCenter().y * scale);
float tempX = x % bWIDTH;
if (tempX > bufferX // Only draw fragments that are on screen
&& tempX < bufferX + sWIDTH) {
float radius = (float) (fragment.getRadius() * scale); // Get radius
float diameter = (float) (radius * 2); // And diameter
float drawX = (tempX - bufferX) - radius; // Co-ordinates to draw on screen
float drawY = ((bHEIGHT - bufferY) - y) - radius;
g.setColor(Color.white);
g.drawOval(drawX, drawY, diameter, diameter);
}
}
}
I am guessing that the main issue that I am iterating over 36 bodies in the World object and having to test for object type in each case. The returned Body objects are of different types and so I have to test each body to see if it an instance of the type I want to render (ship fragments after an explosion). Is there a better (i.e. faster) way to construct this loop? Or is there another issue that I am missing?
Note:
- in the example above bufferY is fixed (the screen doesn't move when the explosion is happening)
- bWIDTH/bHEIGHT are the width and height of the background image, sWIDTH is the width of the screen
- I am iterating over a set of Body objects in dyn4J because I want to the individual explosion fragments to interact with the landscape, e.g. bounce, slide, etc.
- the Body objects have a single Fixture and this is a Circle
Thanks
Turns out it isn't the graphics drawing routine... it is the dyn4j iteration of the fragments during the
World.update()
method. Changing the fragment Fixtures to sensors (Fixture.setSensor(true)
) so they detect collisions, but don't respond to them, resolves the performance issues and I get about 130FPS if I run the game unchecked. Shame, given that it's only 36 objects. I didn't think that would be too many for dyn4j to handle... I suspect I am missing some setting somewhere to make this work effectively. :/ps. the
for (Object spaceBody : spaceBodies)
in my previous comment does work. Not sure what happened there, but a clean and build sorted it out.