DJ Quilter

Front-End Developer

RPG JS (Phase III): Prototypes, Decorators and Non-Player Objects

Last time I did a post on this project I had a list of things that I wanted to do next. I’ve done none of them. Well, that’s a lie. I’ve partially done some of them. So that’s something!

Prototypes and Decorators

The main thing that I wanted to do was get some other ‘entities’ on the page, so I attacked this, with the fairly loose initial idea that I’d make use of Javascript Prototypes. But things did not go to plan.

I initially thought about creating a long chain of Prototypes for each entity (human, tree, chicken). I had a feeling that this would get overly complicated though, so I started thinking about having each Object having multiple Prototypes. I quickly discovered however, that Javascript doesn’t allow multiple inheritance in this way, that is, Objects can’t have multiple Prototypes. This bummed me out a bit, but after a little bit of research, I found a workaround.

Having recently read Addy Osmani’s Learning Javascript Design Patterns, I instead was looking to use the Decorator pattern, which I felt would be a good fit. As I created new entities, I would be able to add the required properties and methods, and then mix-and-match them as I needed to when creating new entities. This was essentially my idea for multiple Prototypes, but I didn’t need to use Prototypes!

Multiple Inheritance

Being that I couldn’t use Prototype, all I needed to do was add properties and methods to Objects by creating functions (or Decorators) to return the necessary values. This was obviously most simple for properties:

var entities = {
  human: function() {
    this.feet = characteristics.bipedal();
  }
};

var characteristics = {
  bipedal: function() {
    return 2;
  }
};

var fred = new entities.human();

console.log(fred.feet); // Returns 2

But it wasn’t that much more difficult for methods:

var entities = {
  human: function() {
    this.speak = actions.speak;
  }
};

var actions = {
  speak: function(words) {
    alert(words);
  }
};

var fred = new entities.human();

fred.speak('Hello!'); // Alerts 'Hello!'

I did have a problem though, when I wanted to add both properties and methods. For example, my movement method (which runs all the players movement in the game) requires a method and properties that live outside of that method. Feasibly an inventory method would also contain an array and a number of functions.

Working on the movement method, the solution I came up with was to make mobility a characteristic (similar to the bipedal property above), but to make that mobility an Object that would contain everything that I needed for the method, as well as the method itself, which would be the beating heart of the Object.

var entities = {
  human: function(avatar) {
    this.mobile = characteristics.mobile(avatar);
  }
};

characteristics = {
    mobile: function(avatar) {
        mobile = {
            avatar: avatar,
            move: actions.move
        }
        return mobile;
    },
};

var fred = new entities.human();

console.log(fred.avatar); // Returns reference to a DOM element
fred.move(this.avatar, event); // Moves Fred as per the event (in this case, a keypress)

Perfect! I am now required to pass in a parameter for the DOM element that represents our entity, which is the only major change, and isn’t a big deal.

The idea was to get some other actions written, but that should be easy now that I know how to structure them. (First in line for being written is the inventory action which I mentioned earlier.)

So, what changed?

If you’ve been paying attention, you’ll have noticed three Objects being created to hold everything:

Entities
Will contain any Constructor. Currently contains one for humans, chickens, trees and rocks.
Characteristics
Was originally going to just contain properties, but our multiple inheritance issues showed that it will need to contain Objects which reference our actions/methods. Essentially these are all Decorators for our entities.
Actions
All of the methods. Although some of these will probably be Decorators for our Entities, others will just be methods for Characteristics (or Decorators for our Decorators).

I can see these three getting massive. But that’s a problem for another day. One thing I did do was separate these Objects into a different file (away from main.js), which sort of covers off the ‘separate out Javascript code’ which was one of my action points last time.

Creating NPCs and Other Non-Player Objects

I could finish there right? I mean, that’s a lot of work. But no, on a whim, I decided to try and add a new entity to the game map. It actually ended up being pretty simple.

I took a copy of the function that’s used to create the player avatar and passed it another Object which I created in the setting.js. The idea was to pass in all of the entity’s positional information rather than just having it hard-coded (as the player currently is). The little grey circle below is the ‘drone’ which I created in this way.

I’m pretty happy with that. The only issue I have is that there are two functions now which do the same thing (for creating the player and also the non-player characters). It’ll be pretty simple to combine them.

And for the Future

  • Combine our player/NPC creation functions. I expect there will be some difficulty making entities that aren’t drones/copies of the player.
  • Separate out Javascript files some more. I feel like this is going to be an ongoing thing.
  • Unit testing – sounds cool, right?
  • I’ve got one other entity on the map. I could do with some more though, and ones that are prettier than my grey drone.
  • Work out how to navigate from one game map to another. Realistically, this is not going to happen for a while.
  • Add some more actions! I’ve got my eye on an inventory for our player.
  • Get a menu sorted. If the player is going to interact with other things in the game, I reckon we’ll need a menu.