# Keeping ratio the same across devices on fixed screen game

My game is an Android game using OpenGL ES 2.0 (But this question could apply to any platform).

I have read many questions on here regarding ratio management, and also read many tutorials outside of this site, but I'm still really confused as to how to manage this.

My game is a Fixed screen 2d platformer. By fixed screen, I mean the player sees the whole screen at once and the screen doesn't scroll. All action takes place on this one screen (kind of like Bubble Bobble). Therefore scrolling is not possible as we need to see the whole play area.

On my development device, I've written everything to look perfect, like so:

What I've currently done is when the game is run on other devices, I resize my GLViewport so that I maintain ratio like so:

Obviously, this has it's own problem - namely, it wastes screen real-estate. Now, I would accept this reluctantly, if I couldn't find a better solution, however, Google's documentation states that it's not allowed (of sorts) see: App uses the whole screen in both orientations and does not letterbox to account for orientation changes.

So, finally, I just stretched it out to fit the screen like so:

This takes the whole screen, but frankly looks a little naff as everything is stretched.

Am I out of options? I see some similar games on the Play Store (ie, fixed screen) and they seem to look identical on different screens (and nothing is stretched) and there doesn't appear to be any extra space, but I have absolutely no idea how they achieve this. Would love to hear from someone who has dealt with this problem themselves or has any ideas on how best to proceed.

• You could add a few more placeholder tiles to fill the black gaps of the second image. Take a look at Defender, on the following link. Notice how the game adds a decorative border on the top and bottom of the screen do account for different screen sizes. taigame.com/public/data/gamemobile/2135/defender4.png – glampert Jun 19 '14 at 19:23
• Hi @glampert, The thing is, when I have the black bars that's because the GLViewport has been re-sized and therefore, I can't draw outside of the viewport. (or can I? and if so, how?) Also, it would mean that the game will look slightly different on different screens, so main character will either be able to travel slightly further to the edge of the screen (onto the 'placeholder tiles' or I would have to stop him at the original tile & that would look at bit strange - hope you understand what I mean!! Any further suggestions / elaboration welcome. Cheers! – BungleBonce Jun 20 '14 at 2:03
• Here is a postmortem write-up a group did on how they fixed this issue blog.gemserk.com/2013/01/22/… – Jesse Laning Jun 20 '14 at 3:04
• Use glViewport with the screen resolution, draw the decoration, then glScissor to restrict drawing to the play area. – bogglez Jun 20 '14 at 3:46
• Thanks @boggles, could you give an example of using GLScissor. I've tried this but for some reason, it's displaying my game full-screen, then another copy of it within the smaller viewport (scissored area). – BungleBonce Jun 20 '14 at 14:27

You forgot to quote the important part of FN-U2 for your question (emphasis mine):

App uses the whole screen in both orientations and does not letterbox to account for orientation changes.

Minor letterboxing to compensate for small variations in screen geometry is acceptable.

What you're doing here is perfectly fine, since it indeed can be considered minor letterboxing.

Even Google does it as well (e.g. YouTube). You can't avoid this.

What they don't want to see (or you to avoid) is writing apps that would look like they're having a thick black border around the whole screen, e.g. to avoid upscaling.

If you're still unsure, try watching a YouTube video in portrait orientation. You'll notice that they'll fill the available screen space with the video description, suggestions, and comments, rather than leaving that area blank. In this case they don't want the area outside the video to be unused/blank.

• Thanks @Mario, of course, you're right. For some reason I was reading 'orientation changes' as 'ratio changes' - my app is locked to landscape so there is no orientation change. I'm also working on a way to fill in the black bars with something more aesthetically pleasing by using GLScissor - cheers! :-) – BungleBonce Jun 20 '14 at 18:22

So one way you could manage the border drawing scheme is by first rendering some sprites/image using the whole available screen to fill the "no man's land" area not used by the game.

Thinking in therms of OpenGL, you could:

// set to the actual screen size in pixels:
int physScreenWidth  = ...
int physScreenHeight = ...

// clear the screen:
glClear(GL_COLOR_BUFFER_BIT);

// set viewport and the projection matrix to the actual physical screen resolution:
glViewport(0, 0, physScreenWidth, physScreenHeight);

float aspect = (float)physScreenWidth / (float)physScreenHeight;

DrawBackgoundBorder();


So lets say the code above drew something like this:

Next you would proceed to draw the actual game on top of it. No need to blend or anything, since we are doing simple 2D. Also important NOT to clear the screen.

// set to fixed virtual size the game uses:
int virtualScreenWidth  = ...
int virtualScreenHeight = ...

// size in pixel of the previously drawn border.
int borderWidth  = ...
int borderHeight = ...

glViewport(borderWidth, borderHeight, virtualScreenWidth, virtualScreenHeight);

float aspect = (float)virtualScreenWidth / (float)virtualScreenHeight;
SetProjectionMatrix(aspect, virtualScreenWidth, virtualScreenHeight);

DrawRestOfTheGame();


To get as a result something like this:

You can also enable GL scissors to disable rendering outside the virtual game screen area if needed, but as long as you don't draw things on top of the border again, this should not be needed. glScissor works pretty much the same as glViewport, only difference is that you need to enable/disable the global scissors state.