Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am designing my (Android/OpenGL ES 2.0) app on one device and want it to run all all other devices while keeping the screen ratio of the development device (so the image doesn't stretch / squash), by altering the GLViewport ratio of the current device to match the development device, thus having either pillarboxing or letterboxing.

The only values I know for sure, are the physical screen ratio of the development device (in landscape) and the current device (regardless of orientation).

Please refer to my other question (which was regarding centering the viewport once I'd set it's size here: Centering GLViewport position within physical screen ) - on further study I see that my maths is somewhat incorrect (maybe too simplistic?) and the viewport doesn't seem to be getting sized correctly on all targets.

Is there a 'formula' for doing what I'm trying to do?

I get my ratio by doing the following:

float ratio = width / height;

Then I simply want to set my viewport like so:

GLES20.glViewport(0+offsetX, 0-offsetY, widthToUse, heightToUse);

The offsetX and Y values I think I'm OK with as per my previous Q. It's the 'widthToUse' and 'HeightToUse' that I can't seem to work out properly.

You can see from my other question, that I'm working out the 'widthToUse' value my multiplying the current device's height by the [development devices] ratio. However, this doesn't work on all devices as the resulting figure could actually be larger (wider) than the physical screen.

Here are some examples of what I'm trying to achieve, for illustration (ratio's much exaggerated here)

In the pics, the black outter-box is the physical screen of the devices and the blue square is the viewport.

enter image description here

Side note: I realise that my game will most likely be locked to a particular orientation (the one I'm currently developing will, eventually be locked to landscape mode) so I probably don't need to handle orientation changes, however, I would like to know, if possible, how to display at a particular ratio in either orientation in case this is required in the future. So in other words, I may develop an app for landscape, but 'allow' it to run in portrait (albeit with large letterboxing).

Also I know there are similar questions on here, but I've read them over and over and they either don't apply to my situation (or way of doing things), or I'm otherwise not able to get my answer from them.

share|improve this question
add comment

2 Answers

up vote 2 down vote accepted

Pretty simple, there are two candidate solutions, one where the full width is used and one where the full height is used, you must always pick the smaller of those:

widthToUse = Math.min(screenWidth, screenHeight * ratio)
heightToUse = Math.min(screenHeight, screenWidth / ratio)
offsetX = (screenWidth - widthToUse) / 2
offsetY = (screenHeight - heightToUse) / 2
share|improve this answer
    
Thanks for this @eBusiness, I can't believe how simple it was! –  user22241 May 3 '13 at 0:29
    
You can see it in a GLSurfaceView implementation here; it's essentially the same computation, but not as concise: code.google.com/p/android-breakout/source/browse/src/com/… –  fadden May 3 '13 at 20:13
add comment

I'm using code similar to the following:

public static final float NOMINAL_WIDTH = 1700;
public static final float NOMINAL_HEIGHT = 1000;
public static final float NOMINAL_ASPECT_RATIO = NOMINAL_WIDTH/NOMINAL_HEIGHT;

float aspectRatio = width / height;
if (aspectRatio < NOMINAL_ASPECT_RATIO) {
    viewportHeight = height;
    viewportWidth = width/height*NOMINAL_HEIGHT;
} else { // aspectRatio >= NOMINAL_ASPECT_RATIO
    viewportHeight = height/width*NOMINAL_WIDTH;
    viewportWidth = width;
}
share|improve this answer
    
You probably meant to write viewportWidth = height*NOMINAL_ASPECT_RATIO and viewportHeight = width/NOMINAL_ASPECT_RATIO. –  eBusiness May 2 '13 at 20:22
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.