1
\$\begingroup\$

I'm developing a game in Java for Android, using LibGDX. In my render(), between the batch.begin() and batch.end() I'm running through all the game objects and draw them.

Every game object is stored in a list, which that list is stored inside a hash map. I iterate through this hash map, getting every list and going through that list, like this:

    batch.begin();
    Iterator it = objectsMap.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry pair = (Map.Entry) it.next();
        Array list = (Array) pair.getValue();
        for (int i = 0; i < list.size; i++) {
            GameObject object = (GameObject) list.get(i);
            drawObject(object);
        }
    }
    batch.end();

My drawObject() code:

private void drawObject(GameObject object, float x, float y) {
    if (object == null) {
        return;
    }
    if (object.getVisibility()) {
        TextureAtlas.AtlasRegion currentFrame = object.getCurrentFrame();
        if (currentFrame != null) {
            float objectAlpha = object.getAlpha();
            Color color = batch.getColor();
            if (objectAlpha != 1) {
                color.a = object.getAlpha();
                batch.setColor(color);
            }
            batch.draw(currentFrame, x - object.getOriginX(), y - object.getOriginY(), object.getOriginX(), object.getOriginY(), currentFrame.getRegionWidth(), currentFrame.getRegionHeight(), object.scaleX, object.scaleY, object.getSpriteDirection());
            color.a = 1;
            batch.setColor(color);
        }
    }
}

A method called setRegion() sets the current animation frames of the object:

protected void setRegion(String name, float frameDuration) {
    currentFrame = atlas.findRegion(name, 0);
    if (currentFrame == null) {
        currentFrame = atlas.findRegion(name, -1);
    }
    width = currentFrame.getRegionWidth();
    height = currentFrame.getRegionHeight();
    animationStateTime = 0;
    animation = new Animation(frameDuration, atlas.findRegions(name),      Animation.PlayMode.LOOP);
}

And in the update() of the objects this is called:

            currentFrame = (TextureAtlas.AtlasRegion) animation.getKeyFrame(animationStateTime, isLooping);

The getCurrentFrame() method only returns currentFrame variable. The alpha is a field with a value between 0 and 1. (getAlpha() returns only the field)

My question is that considered a "heavy" activity? Can this be a significant impact on the FPS values? Because I'm running my game on old devices (like Galaxy S2) and the FPS can get pretty low values. I'm trying to find the cause to it.
I used to have a reference to every list but with the time I realized I'm going to have too much lists, so I decided to do it like this. Maybe you know a better way of holding references to all game objects?

Thanks!

\$\endgroup\$
  • \$\begingroup\$ How exactly do you draw things? Are you drawing tile based things? Are you drawing things that are off screen? Drawing things usually costs the most memory so you have to minimize the drawing and looping through as efficiently as possible. Sometimes this means you have to sacrifice memory over performance where you for example store a texture to get it directly instead of getting it from a list with a reference. \$\endgroup\$ – Madmenyo Jul 26 '15 at 9:20
  • \$\begingroup\$ I use atlases to draw all images of sprites. The only regular draw of a texture is of the background image. I edited my question with the method's code. \$\endgroup\$ – Gad Wissberg Jul 26 '15 at 9:26
  • \$\begingroup\$ Looking up atlasses each frame is not a good way. You are probably better off storing these in the objects. How do you get your X and Y? The method you post desires it but when you use the method you do not supply it. \$\endgroup\$ – Madmenyo Jul 26 '15 at 9:30
  • \$\begingroup\$ And are you drawing tilemaps? Tilemaps can be drawn extremely efficient. \$\endgroup\$ – Madmenyo Jul 26 '15 at 9:31
  • \$\begingroup\$ What is going on in getCurrentFrame() and getAlpha()? Really hard to say anything about it without the code itself. \$\endgroup\$ – Madmenyo Jul 26 '15 at 9:37
2
\$\begingroup\$

Basically, what a hashmap does is store the objects in a random location in your memory. Complexity is O(1) which means that it will always take the same amount of time to retrive an object from the hashmap. The amount of time depends on various factors. This might be quite fast for few objects, but as soon as you start drawing scene with hundreds of objects, I would consider a hashmap as very poorly performing (poor FPS as a result).
The reason for that is simple. Your memory has to go to get the object from a different location for every object. A more performant approach would be to store all objects right next to each other in memory (which in turn would be a very bad hashmap), so that you could go on where you left off in memory. Depending on the device and your application, this might as well be a major performance gain.
Also take a look at the Entity-Component-System, this article about data locality (which is the specific answer for this very question) and also all other articles on gameprogrammingpatterns.com. You might be able to improve other parts of your code as well :)

\$\endgroup\$
  • \$\begingroup\$ Thank you for the highlights, I will take a deep look in those docs! But I guess it's not supposed to affect it much because the objects are actually located inside the arrays, not inside the hash map. The hash map only holds references for the arrays. If I go back creating reference for every array without hash map, do you think it'll have a significant effect on performance? \$\endgroup\$ – Gad Wissberg Jul 23 '15 at 12:08
  • \$\begingroup\$ Ah, ok, I got you wrong, sry. Hashmaps certainly have an additional overhead. How big the impact on performance is, is hard to guess. You would have to benchmark the application with and without hashmaps to see the difference. \$\endgroup\$ – Marco Alka Jul 23 '15 at 13:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.