Sunday, December 25, 2016

LibGdx Android Phone Resolution problem


I am using the LibGdx framework and have an issue.


Currently, I am creating a game in a resolution of 480 x 320 and using 'GL20' to remove the restriction of that dreaded 'power of two' error.


It works really well, but only in desktop and phones whose screen sizes are the same. But when I try it to a phone with a resolution of 320 x 240, I can only see a small part of the screen and the screen calculations that I made for touch events are now incorrect.



Is there any way to make it work the same as in the desktop version? Like for example, even on the 320x240 phone, the resolution of the game is still at 480x320.



Answer



This is a problem pretty much everyone faces when getting into LibGDX. What you need to remember as you code is this: pixels are bad. Down with pixels.


Because you're using a camera object to determine how/where to draw your sprites on screen, you can set your game's world to use any units you want, and scale to each screen just by constructing the camera appropriately.


If you were to use a tile map to build your levels, I'd say use those tiles as your unit. Doesn't matter how you draw your levels, though -- make up a unit of measurement and stick to it. My screen (in landscape view) is 20 units (tiles, metres, character-heights, whatever) high, with the width scaled so that the tiles are square (ppu is pixels per unit):


// Always a screen height of 20 units;
// width depends on screen aspect ratio.
float height = 20;
float ppu = Gdx.graphics.getHeight() / height;
float width = Gdx.graphics.getWidth() / ppu;


So say you run it on a Full HD screen (1920x1080). If height = 20, then ppu = (1080 / 20) = 54. So width = (1920 / 54) = 35.55555... Your sprites will be automatically scaled (up) to fit that screen size.


On the smaller of the resolutions you mentioned? ppu = (240 / 20) = 12, so width = (320 / 12) = 26.66666... Your sprites will be automatically scaled (down, this time) to fit that screen too.


Then construct your camera using those values:


OrthographicCamera cam = new OrthographicCamera(width, height);
cam.position.set(width / 2, height / 2, 0);
cam.update();

width / 2 and height / 2 being the centre of the screen. If you're using your camera's combined matrix as the SpriteBatch's projection matrix -- batch.setProjectionMatrix(cam.combined) -- then it'll take care of screen resolution for you. And that's it.


Well, almost. You now need to define your Sprites and any other objects in your shiny new world coordinates. If your Sprite was 32 pixels high on your test 480x320 phone, its new height is 2. Don't change the TextureRegions -- they're still in pixels, since they're to do with your image file, not your world. Not at all confusing, right?



Now, if you want to translate from touch coordinates to in-game coordinates, you need to do a two-step conversion as explained here. First from screen coords to camera coords, then from camera coords to world coords:


// Vector2 touchV comes from your InputAdapter.touchDown()
cam.unproject(touchV);
float x = cam.position.x - cam.viewportWidth + touchV.x;
float y = cam.position.y - cam.viewportHeight + touchV.y;

No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...