#LOWREZJAM: Dev Diary #4

demo4_guts

Dev Update

Well, I missed the first deadline. When I originally started this jam, it was 19 May. Everything had to be done by that date. But then, at some point I guess, Game Jolt became part of it and the deadline was extended to the whole month of May. So, at least in my mind anyway, I missed that original deadline. And I’m kinda bummed about that.

However, despite dealing with a number of distractions since my last post on this, I’m still mostly on track for getting everything done within in the next 24 hours. All I have left is to add in Gutsman himself and then do more testing. So far, I’ve got a few frames of him drawn, but I haven’t worked out how I want his AI to work yet. That’s probably what I’m going to add in last.

I’m also not really holding to 32×32 pixels rules anymore either. As I noted in my first post, up-scaling images in not easy cross-browser. Even with using a canvas-to-canvas scaling trick, it still didn’t look right to me. So, I’ve basically decided to just release this on my own site when I’m done and not bother with putting it up on Game Jolt as many others have done.

Art + Code

Since I’m finally done with the tile art, I’ve posted it to Open Game Art for people to use under a CC BY 3.0 license. If you want a 8×8 pixel tileset that look like, but is notably dissimilar from, those in the Gutsman stage of Mega Man, you can use those. (Or, do like I do, and use them for inspiration to draw your own.)

This post, I’m also sharing the code that drives the AI behind the Picket Men. Unlike previous posts, though, I’m also sharing the code that drives it from within the game state’s update loop too.

GameState.prototype.create = function() {
...
this.picketGroup = this.game.add.group();
this.picketGroup.add(new PicketMan(this.game, 116, 9, 'picketMan'));
this.picketGroup.add(new PicketMan(this.game, 128, 7, 'picketMan'));
this.picketGroup.add(new PicketMan(this.game, 139, 7, 'picketMan'));
...
};
GameState.prototype.update = function() {
...
this.game.physics.arcade.collide(this.player, this.picketGroup,
function(player) {
player.damage(1);
player.blink();
});
this.picketGroup.forEach(function(enemy) {
if (this.game.physics.arcade.collide(enemy.bulletGroup, this.player,
function(player, bullet) {
bullet.kill();
player.damage(1);
player.blink();
})) {
}
if (enemy.triggerBox.contains(this.player.x, this.player.y)) {
enemy.frame = 0;
enemy.shoot();
} else {
enemy.frame = 1;
}
}, this);
...
};
view raw GameState.js hosted with ❤ by GitHub
function PicketMan(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 5 bullets using the 'pickaxe' cache key
this.bulletGroup.createMultiple(5, 'pickaxe');
// 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 = 4200;
// The time of the next shot
this.nextFire = 0;
// The velocity of each created or revived bullet
this.bulletSpeed = 550;
// The initial firing angle
this.firingAngle = 245;
// The 'triggerBox'
// If another sprite is within this rectangle, shoot at them
this.triggerBox = new Phaser.Rectangle(
x - (this.width * 2),
y - (this.height),
this.width * 2.5,
this.height * 1.5);
// The 'explosionGroup' for spawning explosions
this.explosionGroup = new ExplosionGroup(this.game);
// Set that this sprite is 'alive'
this.alive = true;
}
PicketMan.prototype = Object.create(Phaser.Sprite.prototype);
PicketMan.prototype.constructor = PicketMan;
PicketMan.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 1 bullets 'dead'
if (this.game.time.now > this.nextFire && this.bulletGroup.countDead() > 1)
{
// Update the timer
this.nextFire = this.game.time.now + this.fireRate;
// 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 'anchor' to center (0.5 * width, 0.5 * height)
bullet.anchor.setTo(0.5, 0.5);
// 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);
//Unlike other projectiles, this trajectory
// needs to be curved. To do that, apply
// a high gravity to pull it down as it moves.
bullet.body.gravity.y = 895;
// Reset the lifespan so that it is kill()'ed after a
// certain amount of time
bullet.lifespan = 1600;
}
}
};
PicketMan.prototype.update = function() {
// Since the hammers need to spin,
// iterate through the bulletGroup each update
// and add to each sprite's angle
this.bulletGroup.forEach(function(pickaxe) {
pickaxe.angle += 15;
});
};
PicketMan.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 PicketMan.js hosted with ❤ by GitHub

 

Here is also the code that drives the Bigeye and its update code as well.

function Bigeye(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);
// The 'triggerBox'
// If another sprite is within this rectangle, jump at them
this.triggerBox = new Phaser.Rectangle(
x - (this.width * 5),
y - (this.height * 5),
this.width * 5.5,
this.height * 5.5);
// The 'explosionGroup' for spawning explosions
this.explosionGroup = new ExplosionGroup(this.game);
// Set that this sprite is 'alive'
this.alive = true;
// Set the gravity
this.body.gravity.y = 825;
// Set health
this.health = 12;
// The jumping rate (in milliseconds)
this.jumpingRate = 1400;
// Time of next jump
this.nextJump = 0;
// Always moving left
this.body.velocity.x = -12;
}
Bigeye.prototype = Object.create(Phaser.Sprite.prototype);
Bigeye.prototype.constructor = Bigeye;
Bigeye.prototype.jump = function() {
// Every (jumping rate), move up (negative velocity)
if (this.game.time.now > this.nextJump) {
this.nextJump = this.game.time.now + this.jumpingRate;
this.body.velocity.y = -350;
}
};
Bigeye.prototype.update = function() {
// If this is !alive (dead), don't update anything
if (this.alive) {
// Adjust the triggerBox coordinates
this.triggerBox.x = this.x - (this.width * 5);
this.triggerBox.y = this.y - (this.height * 5);
this.triggerBox.width = this.width * 5.5;
this.triggerBox.height = this.height * 5.5;
}
};
Bigeye.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 Bigeye.js hosted with ❤ by GitHub
GameState.prototype.create = function() {
...
this.bigeye = new Bigeye(this.game, 167, 64, 'bigeye');
this.game.add.existing(this.bigeye);
...
};
GameState.prototype.update = function() {
...
this.game.physics.arcade.collide(this.bigeye, this.layer);
this.game.physics.arcade.collide(this.player, this.bigeye,
function(player) {
player.damage(1);
player.blink();
});
...
if (this.bigeye.triggerBox.contains(this.player.x, this.player.y)) {
this.bigeye.jump();
}
...
};
view raw GameState.js hosted with ❤ by GitHub