ben berizovsky
ben berizovsky

Reputation: 761

Libgdx have two different views drawn with own coordinate systems?

Take a look at this screenshoot:

enter image description here

I want to split my UI to two parts, controls and game draw area, but I don't want the controls to overlap the draw area, I want the 0,0 of the game draw area, start above the controls area.

Is that possible to do with Libgdx?

Upvotes: 2

Views: 1115

Answers (2)

haxpor
haxpor

Reputation: 2601

As you said you want each view to have its own coordinate system thus splitting the screen technique as answered by Julian will do the trick, but it's not all to properly use it.

To make it fully works, you should have 2 separate OrthographicCamera one for game draw view, and another for control view. I suggest also to create 2 Viewport mapping to each camera as well. In my experience, when working in multiple camera situation, always create associate Viewport for it. Better for changes that could introduce in the future (i.e. adapt to any screen resolution), debugging purpose like checking touching, position etc.

So combine splitting technique with camera/viewport management, you will have robust system to work for each area independently.

Code

I provided the following code as it's used and working in my game, but changed variable names to fit your need. It's in Kotlin, but should be relatively easy to see it as Java. You initialize things first for game area stuff.

// create a camera
gameAreaCamera = OrthographicCamera()
gameAreaCamera.setToOrtho(false, GAME_WIDTH, GAMEVIEW_HEIGHT)
gameAreaCamera.update()

// create a viewport associated with camera
gameAreaViewport = ExtendViewport(GAME_WIDTH, GAMEVIEW_HEIGHT, gameAreaCamera)

Next, for control area stuff.

// create a camera
controlAreaCamera = OrthographicCamera()
controlAreaCamera.setToOrtho(false, GAME_WIDTH, CONTROLVIEW_HEIGHT)
controlAreaCamera.update()

// create a viewport associated with camera
controlAreaViewport = ExtendViewport(GAME_WIDTH, CONTROLVIEW_HEIGHT, controlAreaCamera)

PS: Notice width and height of each view. It's set to occupy area as per your intention.

Now you should have something like this in render() method.

override fun render() {
    // clear screen
    Gdx.gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
    Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT)

    // draw game area
    drawGameArea()
    // draw control area
    drawControlArea()
}

For your drawGameArea() assume that sb is your SpriteBatch that you maintain it in the current class,

private fun drawGameArea() {
    // the following twos to let system know we will operate against game area's camera
    // set the projection matrix
    sb.projectionMatrix = gameAreaCamera.combined
    // set gl viewport
    Gdx.gl.glViewport(0,0,GAME_WIDTH, GAMEVIEW_HEIGHT)

    // draw your stuff here...
    sb.begin()
    ...
    sb.end()
}

That would goes in the same way for drawControlArea()

private fun drawControlArea() {
    // the following twos to let system know we will operate against control area's camera
    // set the projection matrix
    sb.projectionMatrix = controlAreaCamera.combined
    // set gl viewport
    Gdx.gl.glViewport(0,GAMEVIEW_HEIGHT,GAME_WIDTH, CONTROLVIEW_HEIGHT)

    // draw your stuff here...
    sb.begin()
    ...
    sb.end()
}

Note Gdx.gl.glViewport() we supply it with target rectangle area to draw things on. Viewports are not directly used, but it's more to tell the system which kind of screen resizing strategy to fit your game's graphic into screen, and for better debugging purpose. You can read more here.

Two frequently used options you will use most is ExtendViewport and FitViewport. If you want the game to be appeared and cover entire area of the screen without affect aspect-ratio with no black-bars (black on left-side or right-side), ExtendViewport is likely to be what you want, or if you want the similar effect but with black-bars thus game screen will be the same for every player (thus provide no advantage over player with wide-screen) then FitViewport is your choice.

Checking Hit On UI

I guess you will need this, so I should include it too. Whenever you need to check whether such UI element is clicked (or tapped) by user, then you can have the following in its corresponding update() method to check whether touching position is within bound of such object's bounding area or not.

The following code safely and work very well with ExtendViewport, but it also should work the same with other Viewport as the code doesn't require any specific information from ExtendViewport. So it's generic.

fun update(dt: Float, cam: Camera: viewport: Viewport) {
    // convert screen coordinate to world coordinate
    val location = Vector3(Gdx.input.getX(), Gdx.input.getY(), 0f)
    cam.unproject(location, viewport.screenX.toFloat(), viewport.screenY.toFloat(), viewport.screenWidth.toFloat(), viewport.screenHeight.toFloat())

    if ((Gdx.input.isTouched() && 
    boundingRect.contains(location.x, location.y)) {
        // do something here...
    }
}

Upvotes: 4

Julian Hilbers
Julian Hilbers

Reputation: 127

You can use two cameras and position them as shown in your image. I think this post could give you a hint: Split-Screen in LibGDX

Upvotes: 1

Related Questions