Slick2 / dyn4j render loop performance when iterating number of bodies

381 Views Asked by At

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:

  1. in the example above bufferY is fixed (the screen doesn't move when the explosion is happening)
  2. bWIDTH/bHEIGHT are the width and height of the background image, sWIDTH is the width of the screen
  3. 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.
  4. the Body objects have a single Fixture and this is a Circle

Thanks

1

There are 1 best solutions below

0
On BEST ANSWER

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.