#LOWREZJAM: Dev Diary #3

Guts_demo2

The above GIF represents the latest build of what I’ve decided to call Guts. Since my last post a few days ago, I’ve created and positioned the Mets and Bladers, and as the red half-transparent red boxes in the later area show, am still testing the triggering areas for spawning Bladers in the vertical part of the level. I’m just about ready to add in the Picket Men and Big Eye.

Just like in my earlier posts, I’m also going to share the code I’m using to re-create classic Mega Man enemies. This time, it’s for the Mets and Bladers.

Here is the code for the “Met” (Tool):

function Tool(game, x, y, cacheKey) {
// Call the Phaser.Sprite constructor
Phaser.Sprite.call(this, game, x, y, cacheKey);
// Enable physics
this.game.physics.enable(this);
// Set the (physics) body to be immovable
this.body.immovable = true;
// Center the anchor
this.anchor.setTo(0.5, 0.5);
// Create a group for the bullets
this.bulletGroup = this.game.add.group();
// Enable all create items to have (physics) bodies
this.bulletGroup.enableBody = true;
// Set the type of physics bodies to be ARCADE
this.bulletGroup.physicsBodyType = Phaser.Physics.ARCADE;
// Create 13 bullets using the 'enemyBullet' cache key
this.bulletGroup.createMultiple(13, 'enemyBullet');
// Check if bullets collide with world bounds
this.bulletGroup.setAll('checkWorldBounds', true);
// If they do collide with world bounds, they are killed
this.bulletGroup.setAll('outOfBoundsKill', true);
// Bullets only 'live' for 1600ms
this.bulletGroup.setAll('lifespan', 1600);
// Set the firing rate (how long between shooting)
this.fireRate = 1800;
// The time of the next shot
this.nextFire = 0;
// The velocity of each created or revived bullet
this.bulletSpeed = 150;
// The initial firing angle
this.firingAngle = 135;
// The 'triggerBox'
// If another sprite is within this rectangle, shoot at them
this.triggerBox = new Phaser.Rectangle(
x - (this.width * 3),
y - (this.height * 3),
this.width * 3.5,
this.height * 3.5);
// The 'explosionGroup' for spawning explosions
this.explosionGroup = new ExplosionGroup(this.game);
// Set that this sprite is 'alive'
this.alive = true;
}
Tool.prototype = Object.create(Phaser.Sprite.prototype);
Tool.prototype.constructor = Tool;
Tool.prototype.shoot = function() {
// Is this sprite alive?
if (this.alive) {
// It is alive, so check if enough time has past since the last
// shot and that there are at least 3 bullets 'dead'
if (this.game.time.now > this.nextFire && this.bulletGroup.countDead() > 3)
{
// Update the timer
this.nextFire = this.game.time.now + this.fireRate;
// Run for three loops
for (var i = 0; i < 3; i += 1) {
// Get the first 'dead' sprite
var bullet = this.bulletGroup.getFirstDead();
// Reset its position to the same as this sprite's position
// making some adjustments for where the bullets should
// come from for this sprite.
bullet.reset(this.body.x + (this.width / 2), this.body.y + (this.height / 2) - 18);
// Set the firing angle
bullet.angle = this.firingAngle;
// Set the firing trajectory as based on
// the angle and set velocity (linear diagonal motion)
this.game.physics.arcade.velocityFromAngle(bullet.angle,
this.bulletSpeed,
bullet.body.velocity);
// Update the firing angle by 45 degrees
this.firingAngle += 45;
}
// Reset the firing angle to 135 degrees
this.firingAngle = 135;
}
}
};
Tool.prototype.kill = function() {
// Create an explosion at this position
this.explosionGroup.explode(this.x, this.y);
// kill() this sprite by calling Phaser.Sprite's
// own kill function and passing 'this'
Phaser.Sprite.prototype.kill.call(this);
};
view raw Tool.js hosted with ❤ by GitHub

 

And here is the code for the Bladers:

function Blader(game, x, y, cacheKey) {
// Call the Phaser.Sprite constructor
Phaser.Sprite.call(this, game, x, y, cacheKey);
// Enable physics
this.game.physics.enable(this);
// Set the (physics) body to be immovable
this.immovable = true;
// Set the initial target coordinates
this.target = new Phaser.Point(0, 0);
// Set the 'fly' animation
this.animations.add('fly', [0, 1], 5, true);
// Set the velocity to chase another sprite
this.speed = 90;
// The 'explosionGroup' for spawning explosions
this.explosionGroup = new ExplosionGroup(this.game);
// Set that this sprite is 'alive'
this.alive = true;
// Set the distance at which a Blader should
// destory() itself.
this.killDistance = this.width * 24;
}
Blader.prototype = Object.create(Phaser.Sprite.prototype);
Blader.prototype.constructor = Blader;
/*
* This is called from the main game loop like the following:
* this.bladerGroup.callAll('updateTarget', null, this.player.x, this.player.y);
*
* It updates the 'target' position for all Bladers in the group
*
*/
Blader.prototype.updateTarget = function(x, y) {
this.target.x = x;
this.target.y = y;
};
Blader.prototype.update = function() {
// If the 'target.x' is still 0, don't do anything
if (this.target.x !== 0) {
// At some point, the 'target' has been updated, so
// we need to move toward the target at the 'speed'
this.game.physics.arcade.moveToXY(this,
this.target.x, this.target.y, this.speed);
// Since we are moving, play the 'fly' animation
this.play('fly');
// If the target is greater than 24 * width OR 24 * height away,
// go ahead and destory yourself. (If they are that
// far away, a Blader cannot ever catch up.)
if ((this.target.x - this.x) > this.killDistance ||
(this.target.y - this.y) > this.killDistance) {
Phaser.Sprite.prototype.destroy.call(this);
}
}
};
Blader.prototype.kill = function() {
// Create an explosion at this position
this.explosionGroup.explode(this.x, this.y);
// kill() this sprite by calling Phaser.Sprite's
// own kill function and passing 'this'
Phaser.Sprite.prototype.kill.call(this);
};
view raw Blader.js hosted with ❤ by GitHub

 

As a bonus, here is the code for the explosion groups these both use too:

function ExplosionGroup(game) {
// Call the Phaser.Group constructor
Phaser.Group.call(this, game);
// Have the game add this group
this.game.add.existing(this);
}
ExplosionGroup.prototype = Object.create(Phaser.Group.prototype);
ExplosionGroup.prototype.constructor = ExplosionGroup;
ExplosionGroup.prototype.explode = function(x, y) {
// Get the first 'dead' member of the group
var explosion = this.getFirstDead();
// If 'explosion' is null, there weren't any 'dead' memebers
if (explosion === null) {
// Create a sprite using the 'explosion' cache key
explosion = this.game.add.sprite(0, 0, 'explosion');
// Center its anchor
explosion.anchor.setTo(0.5, 0.5);
// Create an animation based on the 'explosion' cache key
// and label it 'boom' for later playing.
// (We also need to save a reference to the create animation.)
var animation = explosion.animations.add('boom', [0, 1, 2, 3], 50, false);
// Tell the animation to kill() itself when done
animation.killOnComplete = true;
// All the sprite + animation to the group
this.add(explosion);
}
// If there was a 'dead' member in the group, revive it.
// Otherwise, 'revive' the new member.
explosion.revive();
// Reset its position to those passed into this function
explosion.reset(x, y);
// Pick a random angle for the sprite (and thus animation)
explosion.angle = this.game.rnd.integerInRange(0, 360);
// Play the 'boom' animation.
// (When it is done, it will kill the animation.)
explosion.animations.play('boom');
};