Moving a character around the map 3 – Input Processing


Code for this tutorial is on this git branch:

git clone -b First_signs_of_movement https://dglencross@bitbucket.org/dglencross/zombiegametutorial.git

Have a look here for help setting it up


Next we turn to the PlayerInputSystem, our class which implements Libgdx’s InputProcessor.

When we touch the screen, we want the following to happen:

  • Detect the co-ordinates of the screen that we touched/clicked
  • Convert these to map co-ordinates
  • Work out which tile we have touched based on these map co-ordinates
  • Implement some basic logic to stop you touching off-map

ZombieGamePlayerOnScreen

Most of this logic is built-in to Libgdx. When you touch/click the screen, the method touchDown() is called. Let’s take a look at our implementation:

@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {

   if (!screen.gameController.isRunning()) {
      return false;
   }

   currentTouch.x = screenX;
   currentTouch.y = screenY;
   
   convertScreenToWorldCoordinates(currentTouch);

   int x = (int) currentTouch.x;
   int y = (int) currentTouch.y;

   Pair selectedTile = screen.gameController.getWorld().getMap()[x][y];
   /*
    *
    * Pretty much all commands are done here...
    *
    */

   getPlayer().setDestination(selectedTile);

   return false;

}

First up, we check if the game is running. If not, we do nothing. What does this mean? Basically we just want to make sure input is not processed before we’re ready for it. We try to access elements of our map – what if we haven’t created it yet? This is just a precaution for that.

Next, we create a vector and pass it off to be converted:

convertScreenToWorldCoordinates(currentTouch);

Let’s take a look at that method:

private Vector3 convertScreenToWorldCoordinates(Vector3 touch) {
   ZombieGame.getViewport().unproject(touch);
   
   if (touch.x < 0 ){
      touch.x = 0;
   } else if (touch.x > screen.gameController.getWorld().getWidth()) {
      touch.x = screen.gameController.getWorld().getWidth();
   }

   if (touch.y < 0) {
      touch.y = 0;
   } else if (touch.y > screen.gameController.getWorld().getHeight()) {
      touch.y = screen.gameController.getWorld().getHeight();
   }

   return touch;
}

The core part of this is just the unproject() method call. This is built into Libgdx and according to the documentation: “Transforms the specified screen coordinate to world coordinates.”

Next, we make sure the co-ordinates not off-map. You may have noticed that you cannot make the player character walk off the map. In fact, you can never set its destination to be off-map. This is where we make sure of that.

Now we return to touchDown():

int x = (int) currentTouch.x;
int y = (int) currentTouch.y;

Pair selectedTile = screen.gameController.getWorld().getMap()[x][y];

We convert to ints so that we can directly access the tiles of the map, and we ask for the tile (Pair) corresponding to those co-ordinates.


Aside: you might want to round these floats first before casting them to ints. I didn’t bother – but keep in mind that casting from float to int isn’t quite the same as rounding – it doesn’t round to the nearest number, it just discards everything after the decimal point. If your game requires this precision, use Math.round() first.


Now we’ve got a Pair to work with. In Dinowar, we next have a bunch of logic depending on which Pair you’ve clicked. Did you select your a tile belonging to your own base? Did you select a tile belonging to an opponent’s base? Did you touch water? Depending on all these, different logic is applied.

Move dinosaurs around based on which tile was touched
Move dinosaurs around based on which tile was touched

For us now, all we want to do is tell the player where to go:

/*
 *
 * Pretty much all commands are done here...
 *
 */

getPlayer().setDestination(selectedTile);

In later tutorials, we’ll flesh out the logic here. What if you touch a zombie? Maybe we should fire a bullet in that situation, rather than walk towards it.

Now you’ve got an idea of how we’re selecting where to move around the map. Next up, we’ll take a look at the camera and viewport, to make sure that we always track the player’s movement.



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 *