22
\$\begingroup\$

How do I make my libGDX game resolution/density independent? Is there a way to specify image sizes as "absolute" regardless of the underlying density?

I'm making a very simple kids game; just a bunch of sprites displayed on-screen, and some text for menus (options menu primarily). What I want to know is: how do I make my sprites/fonts resolution independent? (I have wrapped them in my own classes to make things easier.)

Since it's a simple kids game, I don't need to worry about the "playable area" of the game; I want to use as much of the screen space as possible.

What I'm doing right now, which seems super incorrect, is to simply create images suitable for large resolutions, and then scale down (or rarely, up) to fit the screen size. This seems to work okay (in the desktop version), even with linear mapping on my textures, but the smaller resolutions look ugly.

Also, this seems to fly in the face of Android's "device independent pixels" (DPs). Or maybe I'm missing something and libGDX already takes care of this somehow?

What's the best way to tackle this? I found this link; is this a good way of solving the problem?: http://www.dandeliongamestudio.com/2011/09/12/android-fragmentation-density-independent-pixel-dip/

It mentions how to control the images, but it doesn't mention how to specify font/image sizes regardless of density.

\$\endgroup\$
2
  • \$\begingroup\$ Possibly related? gamedev.stackexchange.com/questions/34/… \$\endgroup\$
    – thedaian
    Feb 28, 2012 at 3:54
  • \$\begingroup\$ @thedaian not quite. That's about resolution; I'm more concerned about the interplay between density and resolution. \$\endgroup\$
    – ashes999
    Feb 28, 2012 at 15:11

4 Answers 4

12
\$\begingroup\$

Since you can read the device density and render fonts during runtime in libgdx, I use this solution to achieve a density independent font size:

float densityIndependentSize = origFontSize * Gdx.graphics.getDensity();
int fontSize = Math.round(densityIndependentSize );
BitmapFont font = generator.generateFont(fontSize );
\$\endgroup\$
1
  • \$\begingroup\$ My discussion is about images as well as fonts. +1 for dynamic font rendering though (I do this already). \$\endgroup\$
    – ashes999
    Oct 18, 2013 at 21:28
10
\$\begingroup\$

To achieve this in libgdx, you can use the "orthographicCamera" there you asign the size that you wat to use, and in every resolution you may see all your images scaled to that size (i use the 800X480 because its the larger screen in Android) and it works good :)

public class GameStage extends Stage 
{ 
     public GameStage(float width, float height, boolean stretch) 
     { 
          this.camera = new OrthographicCamera(800, 480);
          this.camera.position.set(800/2, 480/2, 0f); 
     } 
}
\$\endgroup\$
4
  • \$\begingroup\$ Can I get a code sample, please? \$\endgroup\$
    – ashes999
    Feb 29, 2012 at 1:12
  • \$\begingroup\$ Thats the code, and you create a class that implements the Screen interface, in the constructor you build your stage, and in the render method, you put stage.draw(). If you dont want to use Stages, you may declare a variable in the Screen implemented class of type Camera, and do the same thing as in Stage, but in the render method you apply an update to the camera. \$\endgroup\$
    – Rudy_TM
    Feb 29, 2012 at 15:33
  • \$\begingroup\$ This actually works pretty well. \$\endgroup\$
    – you786
    Sep 26, 2013 at 17:35
  • \$\begingroup\$ A more extensive code sample would be helpful \$\endgroup\$
    – xjcl
    Sep 2, 2020 at 21:50
4
\$\begingroup\$

I believe Android's "device independent pixels" are just a measuring stick for classifying devices, and aren't actually available as renderable pixels. So you're not missing out on any magical DPI-solving infrastructure. As far as I understand the state of the art here, you have discovered all the options. There are two basic approaches for dealing with different devices:

  1. Scale pre-existing images to match the actual device DPI.
  2. Choose from a variety of pre-scaled images at run-time based on the DPI.

Of course, you can do some mix of the two (picking a roughly accurate image and then scaling it), or use different approaches for different elements of your UI (e.g., pre-existing images for fonts/text, and dynamic scaling for gameplay sprites).

What your specific game is trying to do can really make a difference in which approach makes more sense. For example, if you've got an on-screen menu you'll want to make sure the buttons are some reasonable multiple of a finger-tip size (so the button is always easy to hit, but isn't larger than necessary on big devices like tablets). Alternatively, if you're trying to build a puzzle game where you want to make sure the entire puzzle is visible at once, you'll need to scale the elements to fit on the screen (for example, with a tic-tac-toe game perhaps you'd like each element to use roughly 1/3 of the screen).

I think for things like fonts that have a lot of fine detail you'll want to have a variety of pre-rendered images with text, and then pick the best-matching. So buttons might change their relative shape/size from one device to another, but will generally always look nice.

Check out Mario Zerchner's Beginning Android Games for some discussion of the problems and some solutions. Note that Mario is the author of libGDX, so the book's approach mirrors the libGDX one (note they're not one-to-one, the book covers writing a library similar to libGDX, but not libGDX itself).

\$\endgroup\$
3
  • \$\begingroup\$ Even if I select from pre-made image collections based on DPI, I don't see how I can guarantee that "this sprite MUST display as 64x64." \$\endgroup\$
    – ashes999
    Feb 29, 2012 at 17:35
  • 1
    \$\begingroup\$ I was assuming you set your OpenGL camera to match the physical display, so 1 OpenGL pixel maps to 1 display pixel. At that point a 64x64 image will show up as 64x64 on the screen. As Rudy_TM points out, you can mess with the camera mapping to get whole-screen scaling. \$\endgroup\$
    – P.T.
    Feb 29, 2012 at 18:14
  • \$\begingroup\$ Okay, this looks like the "secret sauce" I was after. I'll check and let you know, thanks. \$\endgroup\$
    – ashes999
    Feb 29, 2012 at 18:26
1
\$\begingroup\$

One way to do it is to define minimum aspect ratio and a maximum aspect ratio for your game. These will be the ratios that you want to support. Then you need to use a Viewport that is now provided in libGdx. The viewport will scale your world according to the settings you provide.

There are several types of viewports and you need to select the one that is most appropriate for your game.

You can use ExtendViewport for example and fix either your height or width and calculate the other. Then you need to make sure that all graphics can be seen in your minimum aspect ratio. The extend viewport will scale your graphics to the correct aspect ratio without distorting the graphics. However the ExtendViewport works by adding additional space to your world so you should also provide graphics for backgrounds for example that cover your whole extend of covered aspect ratios, when the world is smaller than your maximum aspect ratio the extra part of the graphics won't be shown.

\$\endgroup\$

You must log in to answer this question.

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