Moving a character around the map 2 – Movement and Orientation


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


If you have got the project up and running, you should be looking at a character moving around the screen when you click.

ZombieGamePlayerOnScreen

If you can not get the project to run, post a message at the bottom and we’ll sort it out.

PlayerCharacter

The PlayerCharacter is where we have our logic which deals with orientation and movement. We also draw our sprite here – it draws itself to a SpriteBatch when requested.

Movement and orientation is all done with vector logic, using Libgdx’s built-in Vector2 class.

When we set up the PlayerCharacter, we give him a random start position. The code to pick a random spot is quite straightforward for now – anywhere on the map which is classed as land.

Every time the PlayerCharacter’s update() method is called, the player will see whether a destination has been set, see if we are already at the destination, and if not – move towards it and point at it.

Movement

When we click in the PlayerInputSystem, we pass a tile to the PlayerCharacter to set as the destination. We also do this:

diff = destination.asVector().cpy();
diff.sub(pos);

diff is of type Vector2. diff is now a Vector2 representing the vector between the destination and the player’s current position.

Note: we’ve added a method to our Pair class, to convert it to a Vector2.

Next, we update(). First we check that we actually have a destination (if you haven’t clicked yet, it will be null!). Then we check that we aren’t already standing at the destination (or close to it). If either of these things are the case, we do nothing.

Assuming we want to update our position, we do this:

diff.setLength(PLAYER_SPEED);
pos.add(diff);

diff is still a vector pointing in the same direction as before, but with a fixed length (whatever you set PLAYER_SPEED as – try playing with it to see the effect). Our position is also a vector, so we add this ‘diff’ vector to our current position, and it gives us a new vector which is an addition of the two.

Vector addition
A visual representation of adding some vectors. Think of A, B and C as the results of 3 different clicks

Orientation

Ok, we have updated our position. Now for the orientation. All we do is work out the angle between two vectors (our position and destination):

private void updateOrientation() {
   float angle = (float) Math.toDegrees(Math.atan2(destination.x - pos.x, destination.y - pos.y));
   this.orientation = - angle + 90f;
}

Why did we add that +90f at the end? It is just to correct for the player image looking the wrong way. If you just updated the actual image to be pointing another 90 degrees round, you would get the same effect. I probably could have done that in the time in took me to write this explanation…

That’s it! You’ve updated the orientation and position variables. Now, when we are told to draw the player, we have all the information necessary.

public void draw(GameController game, SpriteBatch batch) {
   playerSprite.setCenter(pos.x, pos.y);
   playerSprite.setOrigin(1, 1);
   playerSprite.setRotation(orientation);
   playerSprite.draw(batch);
}

We’re walking on water!

Yes we are. This is the most basic implementation of movement I could put in for now; we don’t even check whether we can proceed without touching water. Once we’ve moved on to later tutorials, we’ll actually be doing path-finding each time we touch somewhere. We will abandon this approach – naively move in a straight line – and the player will walk around bodies of water!

If you fancy a challenge now, and to improve your understanding of how things tie together, why don’t you stop the player from being able to walk on water? It doesn’t require any path-finding.

We’re going to use path-finding instead. So is this logic useless to us?

No! A feature will we add in a few tutorials is to fire bullets at zombies. This logic will be used for that – sprites moving in a straight direction, able to move over land or water – perfect for bullets.

Conclusion

We’ve taken a look at vector logic for moving in straight directions, and orienting sprites to ‘look at’ what we want them to look at.

Next up:

  • Determining which tile we have just touched
  • Having a camera track the player


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 *