4
\$\begingroup\$

I'm trying to scale down my fonts as my game objects are also small.

I'd like to scale them down the same way as my sprites. However, if I scale them below .05, the font disappears!

My attempt at small, smooth text above an orange grid:

oversized text

The code:

private void initTestObjects() {
        textures = new TextureAtlas(Gdx.files.internal("data/atlas.atlas"));//i am not using atlas params(for now -.-, I cut from texture..)

        //text texture and bitmapfont
        texturesText = new Texture(Gdx.files.internal("data/fonts_0.png"), true);
        texturesText.setFilter(Texture.TextureFilter.MipMapLinearNearest, Texture.TextureFilter.Linear);
        bitmapFonts = new BitmapFont(Gdx.files.internal("data/fonts.fnt"), new TextureRegion(texturesText), false);
        bitmapFonts.setScale(.1f);

        //grid texture and sprite
        TextureAtlas.AtlasRegion grid = textures.findRegion("grid");
        gridSprite = new Sprite(grid);
        gridSprite.setSize(SIZE, SIZE);//4x4
        gridSprite.setOrigin(gridSprite.getWidth() / 2, gridSprite.getHeight() / 2);
        gridSprite.setPosition(0 - gridSprite.getOriginX(), 0 - gridSprite.getOriginY());

        //players' textures
        o = textures.findRegion("o");
        x = textures.findRegion("x");

        line = textures.findRegion("line");
    }

What am I doing wrong?

\$\endgroup\$
1
  • \$\begingroup\$ what is the camera width/height set as? \$\endgroup\$
    – wes
    Apr 21, 2014 at 16:33

2 Answers 2

2
\$\begingroup\$

I see you use gridSprite.setSize(SIZE, SIZE);//4x4. That means that your sprite uses 4x4 units of your camera's viewportWidth and viewportHeight for drawing. And that means, that your world is scaled. If you were using viewportWidth and viewportHeight set to screen resolution in pixels, then text will be all right. But when the world is scaled, viewportWidth and viewportHeight are set in world units, for example 15x10. And for that reason you see very big text - it just remains the same, while the world is scaled. There’s no need for the sprite’s dimensions and position to be given in pixels. We could set the width and height of the sprite to 4×2 and it would still map to for example 855×480 pixel region in the texture atlas. BitmapFont doesn't do that magic for us. If you still want to draw text in your world coordinate space, one way is to change the projection matrix for the time, text is drawn:

batch.begin();
// here goes actual drawing of your game world
Matrix4 originalMatrix = batch.getProjectionMatrix().cpy(); // cpy() needed to properly set afterwards because calling set() seems to modify kept matrix, not replaces it
batch.setProjectionMatrix(originalMatrix.cpy().scale(getUnitsInPixel(), getUnitsInPixel(), 1));
bitmapFonts.draw(batch, "YO", 0, 1);
batch.setProjectionMatrix(originalMatrix); //revert projection

getUnitsInPixel() returns, for example, 1/240f when the height of the screen is 480 in pixels and you've set viewportHeight to 2 units. 2/480 equals 1/240

It is explained in libgdx book in step by step "Canyon Bunny" game creation. Here is one of the implementations I found, which looks like it is based on book: https://github.com/Gizmmo/CanyonBunny/blob/master/core/src/com/packtpub/libgdx/canyonbunny/WorldController.java There sprite is set to have 1x1 units in game space. It is done like you did - with sprite.setSize(1, 1); And here is mentioned how sprite makes magic for us: http://www.badlogicgames.com/wordpress/?p=1403 "Note that there’s no need for the sprite’s dimensions and position to be given in pixels". And after checking things out, I've found that:

1. SpriteBatch draw(...x, y...) methods deals with pixels.

All except one method:

spriteBatch.draw(texture, 0, 0, 1, 1, 0, 0,
                texture.getWidth(), texture.getHeight(), false, false); // that method draws texture taking (0, 0, texture.getWidth(), texture.getHeight()) to camera viewport at (0, 0, 1, 1) in unit space. So, if your viewport is 2 units tall, then you'll see texture taking half of all visible space in height.

2. Suppose, we have viewport in 2 units tall:

@Override
public void resize(int width, int height) {
    float aspectRatio = (float) width / (float) height;
    camera = new OrthographicCamera(2f * aspectRatio, 2f);
    camera.update();
}

Then if you've drawn some fullscreen textures before:

spriteBatch.draw(texture, 0, 0)

Then, you'll see now only 2 pixels of it! But if you drawn with sprites, all you need is just sprite.setSize(newCorrectWidthInUnits, newCorrectHeightInUnits) and after:

sprite.draw(batch);

You'll see the same picture on screen. Thats in short, how this works, as I understand. And of course there is a stage with it's own batch drawing logic inside.

\$\endgroup\$
3
\$\begingroup\$

It looks like you are using a scale camera for your game objects (the grid). That's fine. However fonts in libgdx are scaled in pixel dimensions and not your game world units. The best course of action here is to maintain two sperate cameras to render your game: world, and ui.

The world camera will be in your world units as you have it now. The ui camera will be in pixel units scaled to the game window. Use the project and unproject methods on the camera classes to position your ui elements correctly. Render the world using the world camera then do a ui pass over that with the ui camera.

\$\endgroup\$
1
  • \$\begingroup\$ Hey Matt Sams, So if you have 2 cams, How would you "put text on the top of the enemy head, and the enemy is moving, the text is follow after the enemy, not the UI / Screen",( keep the ratio, the original points X&Y of the main screen game) ? \$\endgroup\$
    – adam
    Jun 16, 2017 at 20:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .