Shift
Shift

Reputation: 181

Displaying FPS in LibGDX game

So, im making a game, and i need to display fps in it. It is how it looks like

You can think that it is okay, but if i try to fly away, text stays there. It is not moving.

    public void render(SpriteBatch batch) {
        batch.begin();
        Draw.draw();
        MainScreen.player.draw();
        TextManager.displayMessage("FPS: "+ Gdx.graphics.getFramesPerSecond(), true, false, false, false);
        PlayerControl.update();
        CamControl.update();
        UI.drawCurrentBlock();
        batch.end();
    }

This is a code that displays fps.

I need it moving with my screen.

UPD: idea with making static camera didn't work. It just literally doesn't moves. If i try to sync text with camera coordinates, it moves, but it is 'shaking'.

Are there another methods to display it literally in screen, or make it's sync with camera normal?

Upvotes: 7

Views: 3690

Answers (1)

bornander
bornander

Reputation: 1148

This is often solved with dual cameras, one camera is your game camera that observes the game world, the other is a stationary camera that is the view of the HUD.

The HUD camera never moves and is configured so that the width and height is suitable for whatever graphics it is supposed to display, this can be but does not have to be the pixel-dimensions of the window.

The position of the camera can be whatever suits your needs, but if you set the postion to viewportWidth / 2.0, viewportHeight / 2.0 you'll get a viewport for the HUD where (0, 0) is the lower left corner of the screen:

For example:

hudCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
hudCamera.position.set(hudCamera.viewportWidth / 2.0f, hudCamera.viewportHeight / 2.0f, 1.0f);

In the render method this can then be used to draw text:

hudCamera.update();
spriteBatch.setProjectionMatrix(hudCamera.combined);
spriteBatch.begin();
font.draw(spriteBatch, "Upper left, FPS=" + Gdx.graphics.getFramesPerSecond(), 0, hudCamera.viewportHeight);
font.draw(spriteBatch, "Lower left", 0, font.getLineHeight());
spriteBatch.end();

In the example below the red circle is the player, and the yellow grid is the game world. The player moves in the game world with the game camera both following it and sometimes being stationary, during both of these operations the HUD text is stationary as that is rendered using the HUD camera which does not move. The full source code for the example is included after the image, it uses the default bitmap font from the libGDX github (Font PNG file and FONT .fnt file)

HUD camera example

package somepackage;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Vector2;

public class HudExampleGame extends Game {

    private OrthographicCamera gameCamera;
    private OrthographicCamera hudCamera;
    private ShapeRenderer shapeRenderer;

    private Vector2 playerPosition = new Vector2();
    private boolean cameraFollowsPlayer = true;

    private SpriteBatch spriteBatch;
    private BitmapFont font;

    @Override
    public void create() {
        float aspectRatio = (float) Gdx.graphics.getHeight() / (float) Gdx.graphics.getWidth();
        float viewableWorldWidth = 32.0f;
        gameCamera = new OrthographicCamera(viewableWorldWidth, viewableWorldWidth * aspectRatio);
        gameCamera.position.set(playerPosition.x, playerPosition.y, 1.0f);

        hudCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        hudCamera.position.set(hudCamera.viewportWidth / 2.0f, hudCamera.viewportHeight / 2.0f, 1.0f);

        shapeRenderer = new ShapeRenderer();
        spriteBatch = new SpriteBatch();

        font = new BitmapFont(Gdx.files.internal("default.fnt"));
    }

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

        // Use the game camera to render the game world
        gameCamera.update();

        shapeRenderer.setProjectionMatrix(gameCamera.combined);
        shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
        shapeRenderer.setColor(Color.YELLOW);

        for (int x = -32; x <= 32; ++x)
            shapeRenderer.line(x, -32, x, 32);

        for (int y = -32; y <= 32; ++y)
            shapeRenderer.line(-32, y, 32, y);

        shapeRenderer.setColor(Color.RED);
        shapeRenderer.circle(playerPosition.x, playerPosition.y, 1.0f, 24);

        Vector2 movement = new Vector2();
        if (Gdx.input.isKeyPressed(Input.Keys.LEFT))
            movement.x -= 1;
        if (Gdx.input.isKeyPressed(Input.Keys.RIGHT))
            movement.x += 1;
        if (Gdx.input.isKeyPressed(Input.Keys.UP))
            movement.y += 1;
        if (Gdx.input.isKeyPressed(Input.Keys.DOWN))
            movement.y -= 1;
        if (Gdx.input.isKeyJustPressed(Input.Keys.SPACE))
            cameraFollowsPlayer = !cameraFollowsPlayer;

        playerPosition.add(movement.scl(Gdx.graphics.getDeltaTime() * 8.0f));
        if (cameraFollowsPlayer)
            gameCamera.position.set(playerPosition.x, playerPosition.y, 1.0f);

        shapeRenderer.end();

        // Use the HUD camera to render the text
        hudCamera.update();
        spriteBatch.setProjectionMatrix(hudCamera.combined);
        spriteBatch.begin();
        font.draw(spriteBatch, "Upper left, FPS=" + Gdx.graphics.getFramesPerSecond(), 0, hudCamera.viewportHeight);
        font.draw(spriteBatch, "Lower left", 0, font.getLineHeight());
        spriteBatch.end();
    }
}

Upvotes: 11

Related Questions