Moving a character around the map 4 – Camera, Viewport

Code for this tutorial is on this git branch:

git clone -b First_signs_of_movement

Have a look here for help setting it up


A viewport is Libgdx’s way of managing your camera’s width and height. Although we will not be resizing our viewport during the game, it means that you do not need to worry about different sizes of screens.

We are using a specific Libgdx viewport – the StretchViewport.

import com.badlogic.gdx.utils.viewport.StretchViewport;

From the documentation:

A ScalingViewport that uses Scaling.stretch so it does not keep the aspect ratio, the world is scaled to take the whole screen

When you run the game on your computer, you can resize the window and see how everything updates to the correct size. This is the viewport managing the camera/graphics for you.

large small

You can see from these two (by the size of the title text) that one is zoomed and one is not, but the viewport has dealt with the resizing fine.

ZombieGame extends MyGame

When we launch the game, the ZombieGame class creates our viewport:

protected void initViewport() {
   // Total view width
   float viewWidth =32;
   float viewHeight = Math.round(;

   // World width, in squares. Always 100 wide.
   worldWidth = 32 * 3;
   worldHeight = (int) Math.floor(viewHeight);
   setViewport(new StretchViewport(viewWidth,viewHeight));

initViewport() is an abstract method, so you have no choice but to implement it.

Our first two lines are to set the width and height of our viewport.

float viewWidth =32;
float viewHeight = Math.round(;

The extra logic there is to maintain the ratio we want.

The next two lines are to set the size of the actual world that the player walks around in.

worldWidth = 32 * 3;
worldHeight = (int) Math.floor(viewHeight);

That *3 means that the world is going to be three times larger than the size of the viewport. If you want to prove that to yourself – set the worldWidth to just be 32, and you will see that it is the same size as the viewport.

Try fiddling with these variables and see the effects it creates. The wider your view, the further out you are zoomed.

Finally, all that’s left to do is create and set the viewport so the game knows about it.

setViewport(new StretchViewport(viewWidth,viewHeight));

What about the camera?

The StretchViewport creates its own instance of a camera – an OrthographicCamera.

An OrthographicCamera is one which projects 3D images into 2D. This image from Wikipedia should hopefully show you what is meant by that:

By Yuri Raysper - Has drawn from the bookThis vector image was created with Inkscape., Public Domain,
By Yuri Raysper – Has drawn from the book This vector image was created with Inkscape., Public Domain,

So it is good for 2D games – in the case of 3D games (outside the scope of this tutorial series), it would not be used.

All we want this camera to do is follow the player, to always be looking down on him. Therefore, we need a reference to this camera and then to update it every time the player moves.


When we create our PlayerInputSystem, we create a reference to the camera:

public PlayerInputSystem(MainScreen screen) {
		this.screen = screen;
		camera = (OrthographicCamera) ZombieGame.getViewport().getCamera();

Now, we can update it when we want.

Why do we keep our reference in the PlayerInputSystem? This is so we can directly access the camera when pressing buttons. For example:

public boolean keyDown(int keycode) {
   if (keycode == Keys.R) {
   else if (keycode == Keys.Q) {
   float moveAmount = 1.0f;
   if (keycode == Keys.UP) {
      camera.position.y += moveAmount;
   } else if (keycode == Keys.DOWN) {
      camera.position.y -= moveAmount;
   } else if (keycode == Keys.LEFT) {
      camera.position.x -= moveAmount;
   } else if (keycode == Keys.RIGHT) {
      camera.position.x += moveAmount;
   } else if (keycode == Keys.Z) {
      camera.zoom += moveAmount;
   } else if (keycode == Keys.X) {
      camera.zoom -= moveAmount;
   return false;

You may recognise this as code we were playing with in the first round of tutorials. This is why we have the camera here – however, you may choose to move it. It slightly irritates me having the camera here, as the PlayerInputSystem class should deal with input and nothing else. It may move in a future tutorial.

Aside: You may have also noticed that this code doesn’t work any more. I can’t zoom! I can’t navigate left and right! Is it broken? Actually, every time the game updates now, it centres the camera above the player. So this code runs, but you never see the effects of it. To get it working again, comment out everything in the updateCamera() method. Though this will, of course, stop the camera from centering over the player.

UpdateCamera() is where the action happens:

public void updateCamera() {
   if (camera == null || camera.position == null || getPlayer() == null) {

   camera.position.x = getPlayer().getX();
   camera.position.y = getPlayer().getY();


We have a bit of code safety first, just to make sure we aren’t going to null-pointer before we’ve set up all our objects.

Then we simply set the camera’s location to be that of the player. We don’t need to worry about translating this into the correct on-screen co-ordinate, because the viewport deals with that for us.


That is pretty much it for now! The final thing I wanted to highlight was the viewport’s project/unproject functionality, which makes converting from screen co-ordinates to map co-ordinates very easy. I already wrote about this in the previous tutorial – go back to it if you missed it – but I wanted to highlight that this is another positive for the viewport.

If you like these tutorials, or want to see a game that was written in much the same way, please download Dinowar from the Google Play Store. It costs nothing and is ad-free.

Leave a Reply

Your email address will not be published. Required fields are marked *