Building Aukera Part 4: Actors and their Features
I said in Part 3 that there’s nothing special about Actors. They’re any
object that’s registered with the game as such, and if an actor happens to have
a method in place for a certain pseudo-event then it will be called at the
appropriate times. So really, to make an actor one just adds a method to an
existing object, and then passes it to game.addActor
. One could just write an
actor ad-hoc and add it to the game. Could it be any simpler?
Actually, it could.
The Actor Constructor
It’s not considered part of the core engine, but I think it’d be silly not to
use it. The Actor component adds a constructor at auk.Actor
. The
actors created by this constructor are a great place to start for any actor the
game may need: For starters, there’s properties for the position and image, and
an update loop that draws the actor in the right place. Now, if this were a
classical language I’d tell you to create a new class extending Actor and go
from there, but javascript is capable of some much more interesting solutions.
Here’s a quick sample of how it looks though, which I’ll add to as we go along.
The game’s addActor
method returns the actor it’s given, so assuming we’ve got
one of those already, right away things look pretty clean:
var player = game.addActor(new auk.Actor(0,0,0, 'images/actor.png'));
The Update Steps
I mentioned that these actors have update loops already, what I didn’t mentioned
is that the update loop is designed to be expanded on. Each of these actors has
an array at actor.updateSteps
that contains all the functions that need to be
run when the actor is update. The functions are called using the .call()
method, so they actually run as methods of the actors. All that has to be done
to add functionality is a call to actor.updateSteps.push(). I don’t recommend
using this feature as a permanant fixture in you code, since the add()
method
I’m about to show you is much nicer, but it can be very useful for testing new
functionality without writing new components and the like. Here’s how you could
make the actor from the previous example move across the screen:
var player = game.addActor(new auk.Actor(0,0,0, 'images/actor.png'));
player.updateSteps.push(function () {
// Remember, these functions are called as methods of the
// Actor, so `this` points to the actor itself
this.x += 0.01;
});
And that’s it! The actor will now walk across the room at 0.01 grid units per frame. But what if we want something more powerful than just more functions called on update?
Actor features
Actor features are lumps of functionality components can provide for actors in
the game. Features don’t assume the actors they’re being added to a built from
the actor constructor, but they may assume certain other features (like the
updateSteps
array) are present. All features have an addTo()
method that
accepts an actor (and sometimes settings), and then messes with it. Some
features, like the one available from keybinding objects, just add
some properties that other features can use. More powerful features (like
auk.Physics.motor
from the Physics component) add multiple
properties and add to the updateSteps
array.
"Okay, so what? you’re saying, you just said this doesn’t depend on the actor
constructor, so what is it doing here? Well, the actor constructor has a
convenience method that really plays nice with features. actor.add()
takes a
feature and an options object, and calls the features addTo()
method with
itself and the options object as arguments. When feature.addTo()
returns, the
add()
method returns itself for easy chaining. What this means is that with
the right components installed, creating an actor that walks around using the
WASD keys and jumps with space is as simple as:
player = game.addActor(
new auk.Actor(5,5,6, 'images/actor.png')
.add(new auk.Keybinding({
87 : 'up',
68 : 'right',
83 : 'down',
65 : 'left',
32 : 'jump'
}))
.add(auk.Physics.jump, {power: 35})
.add(auk.Physics.motor, {speed: 6})
);
I’ll talk more about physics and keybindings in some other posts.