This week’s effort was spent on basic battle mechanics (amongst many, many other things). I learned how to use Phaser to kill things and figured out targeting, attacking, and basic speech bubbles. This post concentrates on attacking and killing sprites.

I’ve reorganized my classes to inherit from a base Character class. This class understands how to attack after moving towards a target (using agreed-upon animation names like attackright and attackdown). The attack() method itself uses the built-in Phaser.Sprite.damage() method.

Here’s our attack() method so far. It’s obviously not finished yet (as you can see by the 1-point damage), but this is a good foundation:

Character.prototype.attack = function(target) {
    if (!this.alive) {
        return;
    }

    var angle = Phaser.Point.angle(this, target);

    if (angle <= 1*Math.PI/4 && angle > -1*Math.PI/4) {
        this.animations.play('attackleft', 15, false);
    } else if (angle <= 3*Math.PI/4 && angle > 1*Math.PI/4) {
        this.animations.play('attackup', 15, false);
    } else if (angle >= 3*Math.PI/4 || angle < -3*Math.PI/4) {
        this.animations.play('attackright', 15, false);
    } else {
        this.animations.play('attackdown', 15, false);
    }

    this.game.time.events.add(Phaser.Timer.HALF, function() {
        if (target.health) {
            target.damage(1);
        }
    });
};

Our method finds the angle between the character and the target and plays the appropriate animation. It then waits half a second before issuing damage so that it looks like the damage is issued in the middle of the attack rather than right at the start. This method still needs many improvements (like range checks, variable damage, etc) but it’s a good starting point.

As you can see, our attack uses the damage() method, which is a very convenient way to issue damage to a Phaser Sprite.

The biggest issue with the built-in damage() method is that it calls kill() automatically. The kill method will, as advertised, immediately kill a sprite and stop rendering it. Unfortunately, you typically have stuff you want to do when a character dies. You may want to run a death animation. You might want to keep the sprite on-screen so that you can collect items from it.

What this really means is that we need to override the built-in kill() method and make it do what we want. First, let’s take a look at Phaser’s default kill(), which you can find in Sprite.js.

Phaser.Sprite.prototype.kill = function() {

    this.alive = false;
    this.exists = false;
    this.visible = false;

    if (this.events)
    {
        this.events.onKilled$dispatch(this);
    }

    return this;
};

It’s a pretty simple method — it sets alive, exists and visible to false, and then it dispatches the onKilled event.

Our version of this method should kill the character, but keep it visible and active (for item retrieval and for the littered-corpses-everywhere) feel. But we mustn’t forget to dispatch the onKilled event (which I certainly would have over-looked), so I’m glad I looked up the original method!

Here’s our version so far:

Character.prototype.kill = function() {

    this.alive = false;
    this.body.velocity.setTo(0,0);
    this.animations.stop();
    this.animations.play('die');
    this.events.onAnimationComplete.addOnce(function() {
        this.exists = true;
        this.visible = true;
        this.inputEnabled = false;
        if (this.input) {
            this.input.useHandCursor = false;
        }
        this.events.destroy();
    }, this);

    if (this.events) {
        this.events.onKilled$dispatch(this);
    }

    return this;
};

Since we’re still early in development, our methods are still procedural, small, and straightforward. We stop all movement, stop all animations, play the death animation, and then add a one-time event to the end of the death animation to disable input and all event handlers on the sprite (eventually we’ll add a click handler to rummage through the dead sprite’s inventory).

Check out this week’s snapshot below! Attack and kill enemies by clicking on them – but be careful, 20 hits and you’re dead, too!