DJ Quilter

Front-End Developer

RPG JS (Phase II): Avatars and Movement

So the next iteration of RPG JS took ages, but I think what I’ve done is fairly foundational; without this work, I ain’t got a game. So, what’s changed since last time? Loads!

The Avatar

The avatar should now look like a birds eye view of a person. Inspired by CSS3 experiments I’ve seen floating around, such as One Div and A Single Div, I used the :before and :after psuedo elements, box-shadow and animations. The box-shadows are animated when the move action is started via keypress.

What I have at the moment is very basic, but I will re-skin it at some point. The important thing for me was to get the animation looking right.

This was actually relatively easy to do (particularly when other people have had the good idea for you). It was actually the next part that caused me the most headaches.

Rotation

So I had an avatar that faced one direction, and I could move him left, right, up or down. But what about rotating him?

I started off by creating classes that set the direction that the avatar faced (via CSS transform: rotate), which were changed by Javascript when a rotation was needed. This was what caused me my main headache as, depending on which way you were facing and which way you wanted to face, you would sometimes get the avatar rotating in an unwanted direction. Basically taking the long way round.

I toyed for a while with some convoluted Javascript that changed the rotation classes in a hidden way so that you’d always get the rotation to happen in the direction that you wanted it. But, to cut a long story short, I couldn’t get it working and it looked really ugly.

So instead, the required rotation is applied dynamically to a constantly changing style attribute. A hash table stores the rotation required from and to each direction. Data-attributes store the direction so that the hash table can be referenced. It’s not much more pretty than those ‘hidden’ class changes, but it works a lot better.

Prevent Movements from Stacking

As everything came together, there was a bit of nonsense with movements ‘stacking up’. If you continued trying to move the avatar, additional movements would begin to clash with each other. The timings of the animations and transitions would often get themselves mixed up if you went a bit wild. There were two important things I did to fix this.

  • Firstly, I needed to add and remove event listeners as necessary. I needed a listener for both the rotation and directional movement, so I used a series of functions to step through the logical process of a ‘game move’.
  • I also added a flag to the movement function itself, which prevented the key logging from working whilst the avatar was moving.

Each movement currently takes 2-3 seconds, depending on whether a rotation is needed, which sometimes feels a bit slow. As such, I may change this in the future.

Setup Function

Finally, I fleshed out the ‘setup’ function which runs before that game starts. This wasn’t a particular goal of mine, but just seemed to happen logically as I was building everything else.

The values for the tile size dimensions and the map boundaries have now been moved here. This meant that I could remove ‘magic numbers‘ from elsewhere in the code and also set the tile size depending on the map that you’re on (now set within the JSON).

This Is What Took So Long

And for the Future

I haven’t quite decided what to start on next, but there’s a few things that I know I want/need to do:

  • Separate out Javascript files, so that they perform discrete tasks. This is probably a way off.
  • Unit testing – I’ve never done this before, but I’m told it’s what all of the cool kids are doing.
  • I need some other entities, by which I mean characters and landmarks, on the map. It’s going to be easy to put them there, but I need to work out how they interact.
  • Work out how to navigate from one game map to another.
  • Finish the move function/action. It’s going to need to play nicely with other actions, so I will need to write some other actions first!