1

I have been trying to solve this for 3 weeks now. I got myself started with viewports with libgdx wiki about it, and browsing through many questions in this forum about viewports, virtual viewports and the likes, and found the best solution for my game is to have 2 viewports: 1 Fitviewport for my Game rendering (not using stage) , and another Screenviewport for my UI (using Stage). The UI is drawn perfectly although i have a specific problem with that which i believe involves DPI cause the controls get rendered very small on a Samsung S4 and they are barely usable, but I'll make a separate question about that. My problem is with the Game rendering and the FitViewport on libgdx. I'm setting the game camera and its viewport this way on the PlayScreen constructor which implements Screen :

gameCamera = new OrthographicCamera();
gameCamera.setToOrtho(false);
gameViewport = new FitViewport(800, 480,gameCamera);

Then on the render method I apply it this way:

input(Gdx.graphics.getDeltaTime());

update(Gdx.graphics.getDeltaTime());

Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

gameCamera.update();
uiCamera.update();
MyGame.batch.setProjectionMatrix(gameCamera.combined);
gameViewport.apply();
MyGame.batch.begin();   
//DRAW CODE AFTER THIS
MyGame.batch.end();

//apply stage ScreenViewport and draw:
game.stage.getViewport().apply();
game.stage.draw();

Then in resize method i only have these 2 lines:

game.stage.getViewport().update(width,height,true);
gameViewport.update(width,height);
gameCamera.position.set(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2,0);

The drawing methods are based on Gdx.graphics.getHeight() and Gdx.graphics.getWidth() coordinates. My game world is a top down shooter that uses Gdx.graphics.getWidth() and getHeight() to spawn creatures and limit the player's movement.

Again the problem i have is the following: -The FitViewport doesnt seem to be working properly. When i try it on my device, the viewport fits, creates gutter lines but I cant see the player drawn in relation to the Gdx.graphics coordinates. - When i do a test drive on desktop with weird resolutions, i can see the bullets being drawn outside the viewport into the gutter lines. I dont know why this happens.

I believe my problem could be that i should create my world in relation to other coordinates which are not Gdx.graphics dimensions, but I cant seem to figure out a possible solution to this. But what i trully dont understand is why can i see bullets in the gutter lines.

rufoDev
  • 33
  • 9

1 Answers1

0

I see a lot of people struggling with this and I must admit I have struggled with it a bit too early on. But once you understand the basics it's really easy to implement.

Let's take FitViewport, when you initialize this new FitViewport(float worldWidth, float worldHeight, camera) you are specifying world coordinates. This means the viewport will draw that given portion of the world no matter what.

  • If your world is bigger it won't draw all
  • If your viewport is outside the screen bounds you won't see all
  • If your viewport aspect is not equal to these world aspects it's drawing it will stretch.

We have not set screen bounds yet so let's do that:

vp.setScreenBounds(Gdx.graphics.getWidth() / 2, 0, Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight());

Here it is asking screenWidth and screenHeight which represesent screen coordinates. Since everyone uses a different screen we get it from the graphics itself. You can have one guess where it draws the viewport ;).

Anyway this viewport new FitViewport(1920 / 2, 1080) will always render 960 X 1080 of my world on the right half of the screen.

If my world is .9f x 1.6f large then I could init the vp like this new FitViewport(.9f, 1.6f, camera).

PS: Don't forget to apply the VP in render() before you start drawing.

Madmenyo
  • 8,389
  • 7
  • 52
  • 99
  • ok i understand, but im reading this :void com.badlogic.gdx.utils.viewport.Viewport.setScreenBounds(int screenX, int screenY, int screenWidth, int screenHeight) . and what you gave as arguements doesnt seem to match the function's description. shouldnt i pass: (0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight()) ? – rufoDev Mar 02 '16 at 20:23
  • If you want to use the viewport full screen, yes. My example puts it in the right half. – Madmenyo Mar 02 '16 at 21:09
  • alright. I have tried both gameViewport.setScreenBounds(0,0,Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); and gameViewport.setScreenBounds(Gdx.graphics.getWidth() / 2, 0, Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight()); after the gameViewport = new FitViewport(800, 480,gameCamera); inside the constructor method of the PlayScreen , and it hasnt changed the behavior at all. Maybe I'm missing something else? BTW I do use gameViewport.apply() before batch.begin() inside render() function – rufoDev Mar 02 '16 at 21:18
  • Is your world 800x480 and your camera in the middle of it? – Madmenyo Mar 02 '16 at 21:29
  • My world is a top down shooter that uses Gdx.graphics.getWidth() and getHeight() to spawn creatures and limit the player's movement. The camera is centered in the resize method : gameCamera.position.set(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2,0); . In the question theres a typo it sais cameCamera instead of gameCamera but thats just here. Maybe i was unclear about the problem. The problem is that the player appears in a location that you cant see, when it s supposed to appear inside the Gdx.graphics.getWidth() and Height() dimensions when i test it on the desktop. – rufoDev Mar 02 '16 at 21:34
  • "Is your game world 800x480 and your camera in the middle of it?". I am quoting myself because if it is not then obviously it draws not everything. Like I say in my answer, if your game world is bigger it won't fit. – Madmenyo Mar 02 '16 at 21:35
  • Also when i try this on desktop i can see bullets being drawn outside the viewport even though the background is fit to the viewport. – rufoDev Mar 02 '16 at 21:38
  • You can see it draw stuff outside, yet you scale your viewport to the screen bounds? – Madmenyo Mar 02 '16 at 21:39
  • you 're right. my game world is not 800x480. I should define my game dimensions instead of making it act according to Gdx.graphics dimensions. Then again i cannot accept your answer as correct since I cant understand yet why bullets are drawn outside of the viewport inside the gutter lines. – rufoDev Mar 02 '16 at 21:39
  • Please supply a screenshot. Nothing is being drawn visibly outside the viewport (by using that viewport). Either you mistake it's bounding lines or it's being draw from somewhere else. – Madmenyo Mar 02 '16 at 21:45
  • It's really easy, `vp = new FitViewport(1000, 1000, camera);` and `vp.setScreenBounds(200, 200, 400, 400);` shows me a `1000x1000 (WORLD UNITS)` gameworld from the camera point of view on a `400x400 (PIXEL)` view port starting at `200x200 (PIXEL)` from bottom left screen. There is nothing more to it. – Madmenyo Mar 02 '16 at 21:50
  • ok im beggining to understand. now im using gameViewport = new FitViewport(600,300,gameCamera); gameViewport.setScreenBounds(200,100,400,200); and it doesnt render stuff outside the viewport anymore. but i keep having the problem that my player is drawn outside of the screen on my android device, and when using diff resolutions on desktop i can see him in the screen just fine. i need the player to be drawn in relation to what you see on screen. like say, 50 pixels to the 0 coordinates of the screen. Im doing it this way: position = new Vector2(50,Gdx.graphics.getHeight() / 2 - 25); – rufoDev Mar 02 '16 at 22:01
  • Don't think of your world (player, objects, enemies) as pixels. 1 pixel can mean 1mm in a ant farm simulator or 10 light years when traveling trough space. The position of your player relative to the screen has to do with the camera. If you want him in the bottom left you update your camera accordingly. `camera.position.set(player.position.x, player.position.y, 0)` sets the camera center at those coordinates. Now offset according to your world units so it is positioned right. – Madmenyo Mar 02 '16 at 22:16
  • The problem on android is likely in the resize() method. You made a typo `cameCamera` and your not updating it. Resize is exactly the same but it supplies you width and height so you don't need to get it from `Gdx.graphics`. – Madmenyo Mar 02 '16 at 22:22
  • ok this all has been working perfectly! i just have one last quesiton: how do i know how many world units is my character? Im using this units setup: gameViewport = new FitViewport(600,300,gameCamera); gameViewport.setScreenBounds(200,100,400,200); I will already put your answer as correct. Thank you so so much btw man, you saved me days of stress. – rufoDev Mar 02 '16 at 22:28
  • Only you know but if it's a human it's probably around 1,80m. You decide what your world is and if it should be in inches, meters or lightyears. The viewport or camera decides how much pixels to draw so everything scales properly. – Madmenyo Mar 02 '16 at 22:30
  • edited the "cameCamera" typo since i did that manually. it was never like that in the code. just so the solutions (which were several at once) are clear, and none of them was the "cameCamera" typo. Again thanks so much. Not only you helped me fixed the game, but you made me learn a lot of stuff in the process. – rufoDev Mar 02 '16 at 22:53
  • Your welcome, it's hard when you see everything as pixels. The things is that everything is relative. You could make your character `1`, `0.02f` or `150` high and as long as you stay true to these measurements when creating your world, and zoom the camera properly, nobody will notice. – Madmenyo Mar 02 '16 at 22:58