Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LibGDX How To Use Multiple Viewports/ Cameras?

In my LibGDX game that I am currently working on, I have ran into a problem regarding Viewports. I am trying to create two viewports- one that holds the whole screen, including the controls, and one that holds the visuals of the game in the middle of the first. This is what I mean.

I'm running into issues using these viewports, however. First of all, the tiled map and the player rendered inside of the FitViewport's apply are not seen (either not rendered or off of the visible screen space), but my Rayhandler's light is seen (and spread more than it's allocated 1:1 ratio). Proof.

private OrthographicCamera camera;    
Viewport v1;
Viewport v2;
//...
RayHandler devRay;
//...
TiledMap map;
OrthogonalTiledMapRenderer tmr;
Player player;

@Override
public void show() {    
    camera = new OrthographicCamera(VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
    camera.setToOrtho(false,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
    //...
    v1 = new ScreenViewport();
    v2 = new FitViewport(160, 160, camera);
    //...
    tmr = new OrthogonalTiledMapRenderer(map);
    tmr.setView(camera);
    RayHandler.useDiffuseLight(true);
    devRay = new RayHandler(world);
}
public void render(float delta) {

    Gdx.gl.glClearColor(1,1,1,1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    v1.apply();
    //Draw Controls

    v2.apply();
    //Draw Visuals  
    tmr.render(); //Tiled Map Renderer
    player.render();
    devRay.updateAndRender();
    //...
}   

I'm guessing that I entirely missed the point of the Viewport. I was wondering if there was any way to separate the playable area and the control area in my project so that, for example, I could move the FitViewport's camera without the game view taking up more than a 1:1 ratio. Thank you for your help!

like image 241
Darth Null Avatar asked Feb 28 '16 22:02

Darth Null


2 Answers

I faced with the same problem. There is an answer in the Official Documentation.

Multiple viewports When using multiple viewports that have different screen sizes (or you use other code that sets glViewport), you will need to apply the viewport before drawing so the glViewport is set for that viewport.

viewport1.apply();
// draw
viewport2.apply();
// draw

When using multiple Stages:

stage1.getViewport().apply();
stage1.draw();
stage2.getViewport().apply();
stage2.draw();
like image 198
Novdar Avatar answered Oct 18 '22 05:10

Novdar


What I usually do is having a single camera to render the world and just overlay the hud by drawing the stage last stage.draw(). Stage is excellent for this. Obviously this obscures some of the game world that should normally be visible without the hud so if you really want multiple "viewports" then you have to work with Viewports.

Viewports are easy to implement and handles everything for you if you pick the correct one. After you have setup the camera you can create a viewport like this:

    camera = new OrthographicCamera(1920 / 2, 1080);
    //1920, 1080 for sake of example. This could be anything and it is often
    // better to not think in pixels but in world units.

    viewport = new FitViewport(camera.viewportWidth, camera.viewportHeight, camera);
    viewport.setScreenBounds(0, 0, Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight());

This will create a viewport on the left half of the screen by using setScreenBounds(...). Since we are drawing the stuff on the camera by only half the screen we have to match the aspect ration, otherwise it would appear stretched.

For clarification since this is a bit confusing sometimes:

float worldWidth, worldHeight; // How much of the world to display
viewport = new FitViewport(worldWidth, worldHeight, camera);

int screenPosX, screenPosY, screenWidth, screenHeight; 
// The position of the viewport where 0, 0 is bottom left and 
// Gdx.graphcis.getWidth, Gdx.graphics.getHeight is top right
viewport.setScreenBounds(screenPosX, screenPosY, screenWidth, screenHeight);

You actually don't need to specify your camera width and height since that is being overridden anyway once you hit vp.apply() with that camera attached to the vp.

In the update() method, before you draw anything on that specific viewport you have to apply the viewports first viewport.apply().

like image 33
Madmenyo Avatar answered Oct 18 '22 06:10

Madmenyo