Handling different aspect ratios with camera?

Anything libgdx related goes here!

Handling different aspect ratios with camera?

Postby markww » Tue Sep 06, 2011 9:07 pm

Hi,

I'm moving along with box2d, I'm not sure how to set up my camera to handle different screen aspect ratios though. Right now I'm creating my camera as follows:

Code: Select all
Camera camera = new OrthographicCamera(32, 48);
camera.position.set(16, 24, 0);


I positioned the camera so that the world origin (0, 0) lines up with the bottom-left corner of my device screen. I just did that as a convenience for myself. Is that ok? The above camera would work great on a device screen with a 32:48 ratio, but on different aspect ratio devices, it seems the camera stretches to fill all available screen space. To test this, I added a single square body:

Code: Select all
Body box = createBox(BodyType.StaticBody, 1, 1, 0);
box.setTransform(16, 0, 0);


My 1x1 box appears as following on these two test devices:

wildfire
screen in pixels: 240 x 320
my box in pixels: 16 x 14

nexus-s
screen in pixels: 480 x 800
my box pixels: 31 x 34

I'm not sure if this is how most games cope with the different aspect ratios. I guess I have two options:

1) Let the camera stretch fill, which will modify my world aspect ratio (so squares might look rectangular, etc)
2) Let the camera stretch fill, but maintain aspect ratio. When it can not stretch any further, center in the device space.

What do most games do? I'm looking at the tutorial here (http://code.google.com/p/libgdx/wiki/Pr ... portCamera) as well, but using a camera like:

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


is transforming my scene in a way I don't understand (appears extremely zoomed in),

Thanks
markww
 
Posts: 23
Joined: Mon Sep 05, 2011 4:36 pm

Re: Handling different aspect ratios with camera?

Postby broken-e » Tue Sep 06, 2011 9:46 pm

If you want it to always be 32 wide and variable height based on aspect ratio, change your resize code to

Code: Select all
@Override
public void resize(int width, int height) {
    float aspectRatio = (float) height / (float) width; // swapped these
   camera = new OrthographicCamera(32f, 32f * aspectRatio);
}


Be aware that some screens like the QVGA are less than 1.5 ratio, so height would be less than 48f. What I do is program for 1.5 aspect ratio so i can assume i am guaranteed at least 48 units, and let those smaller screens squish a bit with:
if (aspectRatio < 1.5f)
aspectRatio = 1.5f;

or i guess you could use
float aspectRatio = Math.max(1.5f, (float) height / (float) width);
broken-e
 
Posts: 603
Joined: Sun Feb 06, 2011 7:20 am

Re: Handling different aspect ratios with camera?

Postby radioking » Tue Sep 06, 2011 10:05 pm

you could zoom out to compensate different visible area with

Code: Select all
camera.zoom
Please "give sth. back" to community and contribute your knowledge to our libgdx-users project community wiki:
http://code.google.com/p/libgdx-users/
Please see Mario's note on User Wiki 2.0: http://www.badlogicgames.com/wordpress/?p=2411
radioking
 
Posts: 284
Joined: Wed Aug 03, 2011 10:28 am

Re: Handling different aspect ratios with camera?

Postby Obli » Wed Sep 07, 2011 5:33 am

Code: Select all
/**
 * Sets the renderer viewport to display the specified world size when the
 * camera zoom is at 1.
 * @param metersX The word viewport width.
 * @param metersY The world viewport height.
 */
public void setWorldViewport(float metersX, float metersY) {
   screenSizeMeters.set(metersX, metersY);
   updateViewport();
}

/**
 * Changes the world viewport with a uniform pixels per meter ratio.
 */
public void setWorldViewportUniform() {
   float pxRatio = screenSizePixels.x / screenSizePixels.y;
   float mtRatio = screenSizeMeters.x / screenSizeMeters.y;

   if (pxRatio >= mtRatio) {
      screenSizeMeters.y = screenSizeMeters.x / pxRatio;
   } else {
      screenSizeMeters.x = screenSizeMeters.y * pxRatio;
   }

   updateViewport();
}

/**
 * Changes the world viewport with a uniform pixels per meter ratio.
 * Will try to fill the screen.
 */
public void setWorldViewportUniformToFill() {
   float pxRatio = screenSizePixels.x / screenSizePixels.y;
   float mtRatio = screenSizeMeters.x / screenSizeMeters.y;

   if (pxRatio >= mtRatio) {
      screenSizeMeters.x = screenSizeMeters.y * pxRatio;
   } else {
      screenSizeMeters.y = screenSizeMeters.x / pxRatio;
   }

   updateViewport();
}

private void updateViewport() {
   pixelsPerMeter.x = screenSizePixels.x / screenSizeMeters.x;
   pixelsPerMeter.y = screenSizePixels.y / screenSizeMeters.y;
   metersPerPixel.x = screenSizeMeters.x / screenSizePixels.x;
   metersPerPixel.y = screenSizeMeters.y / screenSizePixels.y;

   camera.viewportWidth = screenSizeMeters.x;
   camera.viewportHeight = screenSizeMeters.y;
   camera.update();
}


  • setWorldViewport: sets the desired world viewport (in meters, or "world units"), irrespective of the aspect ratio.
  • setWorldViewportUniform: makes the viewport uniform to the screen aspect ratio by shrinking the largest value.
  • setWorldViewportUniformToFill: makes the viewport uniform to the screen aspect ratio by growing the smallest value.

Typical use is to use setWorldViewport with a square viewport (or a dimension set to 0), and then call either uniformizer according to the side you need to align to.
This code is part of my base Renderer2D.java class. The screenSizePixels vector should be initialized at startup with the values given by Gdx.graphics.getWidth()/getHeight().
Obli
 
Posts: 616
Joined: Mon Jan 10, 2011 6:18 pm
Location: Bordeaux, France


Return to Libgdx

Who is online

Users browsing this forum: rggstech, Tekkerue, Yahoo [Bot] and 13 guests