HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Performance optimization on Box2D with libgdx

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
box2dwithoptimizationlibgdxperformance

Problem

A few days ago I decided that I wanted to get involved with libgdx. So far I'm blown away by how simple it is to get something on the screen to work with.

I'm trying to make a very simple tech demo where stars fall from the sky that can get collected by a player controlled cloud. Stars that get not collected will be left on the bottom on the screen.

The purpose of this tech demo is to test the performance on various devices so that I can get a feel of what I can do with libgdx (Box2D) and what I can not do.

So far this is working fine but I quickly run into performance issues on my galaxyS5. After I have like 500 stars at the screen the FPS starts to drop.

I would kindly ask you libgdx experts to point out critical flaws in my code that are bad for performance.

The project consists of the following four classes:

Game.java

```
package game;

import java.util.ArrayList;
import java.util.Random;

import game.entities.Collectable1;
import game.entities.EntityConstants;
import game.utilities.Utility;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.FPSLogger;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.Contact;
import com.badlogic.gdx.physics.box2d.ContactImpulse;
import com.badlogic.gdx.physics.box2d.ContactListener;
import com.badlogic.gdx.physics.box2d.EdgeShape;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badl

Solution

Unfortunately, I don't know libgdx, and cannot answer about your performance problem,
but some issues with this code jump into the eye.

Public fields

public class MyGame extends ApplicationAdapter implements InputProcessor {
    SpriteBatch batch;
    Sprite spritePlayer;
    Texture img;


Public fields or fields with default visibility are a bad practice.
Make these (and all others in all your classes) private and add getters and setters as necessary.

Inefficient if statements

@Override
public boolean keyUp(int keycode) {

    if (keycode == Input.Keys.RIGHT)
        body.applyForceToCenter(10f, 0f, true);
    if (keycode == Input.Keys.LEFT)
        body.applyForceToCenter(-10f, 0f, true);

    if (keycode == Input.Keys.UP)
        body.applyForceToCenter(0f, 10f, true);
    if (keycode == Input.Keys.DOWN)
        body.applyForceToCenter(0f, -10f, true);


The if statements above are inefficient,
because the conditions are mutually exclusive (only one of them can be true),
but all of them will be evaluated always.
You could remove the inefficiency by using else if,
but it will be more compact and readable to rewrite with a switch instead:

switch (keycode) {
    case Input.Keys.RIGHT:
        body.applyForceToCenter(10f, 0f, true);
        break;
    case Input.Keys.LEFT:
        body.applyForceToCenter(-10f, 0f, true);
        break;


This will eliminate some unnecessary evaluations, improving the performance of handling key presses, though this will not be noticeable at all.

Code duplication

While this is quite alright, it has some duplicate code:

int randomInt;
    if (random.nextInt(2) == 1) {
        randomInt = random.nextInt(GAME_WIDTH / 2);
    } else {
        randomInt = -random.nextInt(GAME_WIDTH / 2);
    }


It's better to not repeat yourself:

int randomHalfWidth = random.nextInt(GAME_WIDTH / 2);
    int randomInt = random.nextInt(2) == 1 ? randomHalfWidth : -randomHalfWidth;

Code Snippets

public class MyGame extends ApplicationAdapter implements InputProcessor {
    SpriteBatch batch;
    Sprite spritePlayer;
    Texture img;
@Override
public boolean keyUp(int keycode) {

    if (keycode == Input.Keys.RIGHT)
        body.applyForceToCenter(10f, 0f, true);
    if (keycode == Input.Keys.LEFT)
        body.applyForceToCenter(-10f, 0f, true);

    if (keycode == Input.Keys.UP)
        body.applyForceToCenter(0f, 10f, true);
    if (keycode == Input.Keys.DOWN)
        body.applyForceToCenter(0f, -10f, true);
switch (keycode) {
    case Input.Keys.RIGHT:
        body.applyForceToCenter(10f, 0f, true);
        break;
    case Input.Keys.LEFT:
        body.applyForceToCenter(-10f, 0f, true);
        break;
int randomInt;
    if (random.nextInt(2) == 1) {
        randomInt = random.nextInt(GAME_WIDTH / 2);
    } else {
        randomInt = -random.nextInt(GAME_WIDTH / 2);
    }
int randomHalfWidth = random.nextInt(GAME_WIDTH / 2);
    int randomInt = random.nextInt(2) == 1 ? randomHalfWidth : -randomHalfWidth;

Context

StackExchange Code Review Q#77687, answer score: 3

Revisions (0)

No revisions yet.