Search code examples
javalibgdx

LibGDX game lags when rendering


I have an array of obstacles (Array of Vector2 objects) which move from the right side of the screen to the left so in every call of render() function I decrement their x-positions by 400*deltaTime value and then I am drawing them using SpriteBatch. The problem is when they are moving left sometimes some obstacle lags so it looks like it moves to the right for a while or it stops and I don't know why. So they are moving left and some obstacle stops for a while then they are moving correctly again and then another obstacle lags for a while and this continues. In the same time there are approximatelly 4 obstacles on the screen and I recycle obstacles which aren't visible anymore. Can somebody explain me why this is happening? I noticed this "bug" in the libGDX example Thrust Copter too (which you can find in the book LibGDX Game Development Essentials - I wrote a topic for this problem too: LibGDX example game Thrust Copter lags). Thanks for any reply! :)

public class TapToJumpGame extends ApplicationAdapter {
    SpriteBatch batch;
    Texture obstacle;
    OrthographicCamera camera;
    Array<Vector2> obstacles;
    Array<Vector2> usedObstacles;
    double obsTime;
    Vector2 lastObstacle;

    @Override
    public void create () {
        batch = new SpriteBatch();
        usedObstacles = new Array<Vector2>();
        obstacle = new Texture("obstacle.png");
        camera = new OrthographicCamera();
        camera.setToOrtho(false, 800, 480);   
        resetGame();
    }

    private void addObstacle()
    {
        if(lastObstacle != null) if((810 - (lastObstacle.x + obstacle.getWidth())) < 200) return;
        Vector2 obs; 
        if(usedObstacles.size > 0) obs = usedObstacles.pop();
        else obs = new Vector2(); 
        obs.set(810, 10);
        obstacles.add(obs);
        lastObstacle = obs;
    }

    @Override
    public void render () {
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        updateScene();
        drawScene();
    }

    private void resetGame() {
        obstacles = new Array<Vector2>();
        obsTime = 1;
        lastObstacle = null;
    }

    private void drawScene() {
        camera.update();
        batch.setProjectionMatrix(camera.combined);
        batch.begin();
        for(Vector2 obs:obstacles)
        {
            batch.draw(obstacle, obs.x, obs.y);
        }
        batch.end();
    }

    private void updateScene() {

        float deltaTime = Gdx.graphics.getDeltaTime();

        obsTime -= deltaTime;
        if(obsTime < 0)
        {
            obsTime = MathUtils.random()*1+.5;
            addObstacle();
        }

        for(Vector2 obs:obstacles)
        {
            obs.x -= 400*deltaTime;
            if(obs.x + obstacle.getWidth() < -10) {
                usedObstacles.add(obs);
                obstacles.removeValue(obs, true);
            }
        }
    }
}

Solution

  • Looks like those lag spikes appear sometime when removing a object from an Array which is currently iterated through.

    Store what you want to remove somewhere and remove it after iteration like this:

    for (int i = 0; i < obstacles.size; i++) {
             Vector2 obs = obstacles.get(i);
             obs.x -= 400 * deltaTime;
             if (obs.x + obstacle.getWidth() < 250) {
                usedObstacles.add(obs);
                obstaclesToRemove.add(obs);
             }
          }
    
          for (int i = 0; i < obstaclesToRemove.size; i++) {
             obstacles.removeValue(obstaclesToRemove.get(i), true);
    
          }
          obstaclesToRemove.clear();