How to deal with various proportions in libGDX?

I have implemented some screens using libGDX, which will obviously use the Screen class provided by the libGDX framework. However, the implementation of these screens only works with predefined screen sizes. For example, if the sprite was intended for a screen size of 640 x 480 (aspect ratio 4: 3), it will not work as expected on other screen sizes, since sprites correspond to the screen size and do not scale to the screen size at all. Moreover, if simple scaling were provided by libGDX, the problem I ran into would still be there because it would change the aspect ratio of the game screen.

After researching the Internet, I came across a blog / forum that discussed the same issue. I implemented it, and so far it is working fine. But I want to confirm whether this is the best option to achieve this or whether there are better alternatives. Below is the code showing how I deal with this legitimate issue.

FORUM LINK: http://www.java-gaming.org/index.php?topic=25685.new

 public class SplashScreen implements Screen { // Aspect Ratio maintenance private static final int VIRTUAL_WIDTH = 640; private static final int VIRTUAL_HEIGHT = 480; private static final float ASPECT_RATIO = (float) VIRTUAL_WIDTH / (float) VIRTUAL_HEIGHT; private Camera camera; private Rectangle viewport; // ------end------ MainGame TempMainGame; public Texture splashScreen; public TextureRegion splashScreenRegion; public SpriteBatch splashScreenSprite; public SplashScreen(MainGame maingame) { TempMainGame = maingame; } @Override public void dispose() { splashScreenSprite.dispose(); splashScreen.dispose(); } @Override public void render(float arg0) { //----Aspect Ratio maintenance // update camera camera.update(); camera.apply(Gdx.gl10); // set viewport Gdx.gl.glViewport((int) viewport.x, (int) viewport.y, (int) viewport.width, (int) viewport.height); // clear previous frame Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); // DRAW EVERYTHING //--maintenance end-- splashScreenSprite.begin(); splashScreenSprite.disableBlending(); splashScreenSprite.draw(splashScreenRegion, 0, 0); splashScreenSprite.end(); } @Override public void resize(int width, int height) { //--Aspect Ratio Maintenance-- // calculate new viewport float aspectRatio = (float)width/(float)height; float scale = 1f; Vector2 crop = new Vector2(0f, 0f); if(aspectRatio > ASPECT_RATIO) { scale = (float) height / (float) VIRTUAL_HEIGHT; crop.x = (width - VIRTUAL_WIDTH * scale) / 2f; } else if(aspectRatio < ASPECT_RATIO) { scale = (float) width / (float) VIRTUAL_WIDTH; crop.y = (height - VIRTUAL_HEIGHT * scale) / 2f; } else { scale = (float) width / (float) VIRTUAL_WIDTH; } float w = (float) VIRTUAL_WIDTH * scale; float h = (float) VIRTUAL_HEIGHT * scale; viewport = new Rectangle(crop.x, crop.y, w, h); //Maintenance ends here-- } @Override public void show() { camera = new OrthographicCamera(VIRTUAL_WIDTH, VIRTUAL_HEIGHT); //Aspect Ratio Maintenance splashScreen = new Texture(Gdx.files.internal("images/splashScreen.png")); splashScreenRegion = new TextureRegion(splashScreen, 0, 0, 640, 480); splashScreenSprite = new SpriteBatch(); if(Assets.load()) { this.dispose(); TempMainGame.setScreen(TempMainGame.mainmenu); } } } 

UPDATE: Recently I found out that libGDX has its own proportions maintenance functions that I would like to discuss here. While searching for aspect ratio questions on the Internet, I came across several forums / developers who had this problem: "How do I keep aspect ratio on different screen sizes?" One of the solutions that really worked for me was posted above.

Later, when I continued implementing the touchDown() methods for the screen, I found that due to scaling when resizing, the coordinates on which I implemented touchDown() would change by a large amount. After working with some code to translate coordinates in accordance with the change in screen size, I reduced this value to a large extent, but I could not maintain them with exact points. For example, if I implemented touchDown() on a texture, changing the screen size would change the touchListener in the texture area by a few pixels left or right, depending on the size, and this was clearly undesirable.

Later I learned that the stage class has its own functionality that supports aspect ratio ( boolean stretch = false ). Now that I have implemented my screen using a scene class, aspect ratio supports it. However, when changing the size or different sizes of the screen, the black area that is generated always appears on the right side of the screen; that is, the screen is not centered, which makes it pretty ugly if the black area is substantially large.

Can any member of the community help me solve this problem?

+75
android opengl-es aspect-ratio libgdx
Feb 08 2018-12-18T00:
source share
7 answers

How to do it now:

Since this is one of the most famous issues in libgdx, I will give it a little update :

LibGDX v1.0 introduced Viewport to solve this problem. It's a lot easier to use, and a scaling strategy plugs in, which means that one line can change the behavior, and you can play with it and see which one suits your game.

Everything you need to know about this can be found here .

+49
Apr 18 '14 at 6:31
source share

EDIT: developing libGDX. The best answer now is this user. Be sure to check out the link to the Viewport documentation. .

Since SteveBlack posted a link to the problem that was reported in the scene class, I went there to find out that the problem (actually this is not my problem) was resolved in the last night hours.

After studying here and there on the Internet on the problem that I had, I could not find a solution, so I decided to contact the person who reported the error directly. After that, he answered me on the libgdx forums, and I owe him for helping me. Here's the link

This was the only line of code, and all you have to do is:

In the resize () parameter:

 stage.setViewport(640, 480, false); stage.getCamera().position.set(640/2, 480/2, 0); 

Where 640 X 480 is the resolution of your TextureRegion that describes the estimated aspect ratio. If your TextureRegion size was 320 X 240, then both arguments must be changed to a new resolution to do the trick.

Profile link of the original person who really resolved my problem

+24
Feb 24 2018-12-12T00:
source share

Black bars on the left / right or top / bottom look better than just distorting the whole scene to fit the screen. If you aim for an aspect ratio that is in the middle of the possible ranges (maybe 4: 3, probably low, 16: 9, probably high), then the bars should stay small for most devices. It also allows you to use most of the screen even on large screens, and you already have this guy's code, so it's pretty easy. It would be even better if it were just an option built into libgdx.

But, I think the best approach is to use the full screen. I have not done this yet, but this will be the approach that I will take for my next project. The idea is that if someone has a wider screen, then they should see more around. Chris Prouette talks about how to do this in one of his conversations (the link to what you say is actually pretty good), the idea is to scale in height, and then set your viewport wide enough to fit the screen. OpenGL should take care of displaying the rest. The way he does it is here .

For libgdx, maybe there is an easy way to do this with scene2d by moving the camera around the scene, but I never worked with scene2d. In any case, running the application as your own resizable window is a much easier way to test multiple screen sizes than creating a bunch of AVDs.

+7
Feb 09 '12 at 18:01
source share

See the last part of the View section in white papers: https://code.google.com/p/libgdx/wiki/scene2d#Viewport

+5
May 18 '13 at 3:15
source share

The ResolutionFileResolver class allows you to resolve file names with better resolution. I believe that it will work with other proportions if you created sprites for these proportions. There is an example using AssetManagerTest .

+3
Feb 15 '12 at 18:54
source share

I use this method from http://blog.acamara.es/2012/02/05/keep-screen-aspect-ratio-with-different-resolutions-using-libgdx/

I made this function, which returns a point on the screen, touching, reduced to the desired position of the game.

 public Vector2 getScaledPos(float x, float y) { float yR = viewport.height / (y - viewport.y); y = CAMERA_HEIGHT / yR; float xR = viewport.width / (x - viewport.x); x = CAMERA_WIDTH / xR; return new Vector2(x, CAMERA_HEIGHT - y); } 

Use this when landing / up / dragging and you can check for touch in your game.

0
Mar 16 '14 at 19:15
source share

This code works for me with the latest update: * OrthographicCamera is a cam, it does not crop, just changes the viewport, so the width is still "many times larger than the actual window / device

 public void resize(int width, int height) { int newW = width, newH = height; if (cam.viewportWidth > width) { float scale = (float) cam.viewportWidth / (float) width; newW *= scale; newH *= scale; } // true here to flip the Y-axis cam.setToOrtho(true, newW, newH); } 
0
Aug 11 '14 at
source share



All Articles