Talking about Drop Wizard game, Game development, HTML5, Javascript and Phaser.
Welcome to the third part of the creation of Drop Wizard game. A small recap:
* Create an HTML5 game like “Drop Wizard” with Phaser – player movement showed you how to create a level with its platforms and make the player move around it.
* Create an HTML5 game like “Drop Wizard” with Phaser – player fire, by extending sprite class was focused on player capability of firing bullets, by extending Phaser’s Sprite class.
Now it’s time to add enemies to the game, and such enemies must be able to patrol the platform they are placed on. Enemies too will be created as an extension to Sprite class, so the only difficult thing will be making them move on their platform without falling down.
Have a look at the result:
You can change the direction your Wizard – actually your red square – is moving by clicking on the stage, but above all watch the enemies as they patrol their platforms.
How can we make enemies patrol the platforms using Arcade physics? Have a look at the source code, with highlighted lines to let you see what changed since previous step:
window.onload = function() { var game = new Phaser.Game(480,320,Phaser.CANVAS,"",{preload:onPreload, create:onCreate, update:onUpdate}); var playerSpeed = 150; var bulletXSpeed = 3; var enemySpeed = 70; var player; var platformGroup; var onPlatform = false; var readyToFire = false; function onPreload() { game.load.image("platform180","platform180.png"); game.load.image("platform120","platform120.png"); game.load.image("player","player.png"); game.load.image("ground","ground.png"); game.load.image("bullet","bullet.png"); game.load.image("enemy","enemy.png"); } function onCreate() { platformgroup = game.add.group(); game.physics.startSystem(Phaser.Physics.ARCADE); player = game.add.sprite(240, 0, "player"); player.anchor.setTo(0.5); game.physics.enable(player, Phaser.Physics.ARCADE); var enemy = new Enemy(game, 100, 124, 1, enemySpeed); game.add.existing(enemy); enemy = new Enemy(game, 380, 124,-1, enemySpeed); game.add.existing(enemy); enemy = new Enemy(game, 100, 204, 1, enemySpeed); game.add.existing(enemy) enemy = new Enemy(game, 380, 204,-1, enemySpeed); game.add.existing(enemy) game.physics.arcade.gravity.y = playerSpeed; addPlatform(240,60,"platform180"); addPlatform(340,140,"platform120"); addPlatform(140,140,"platform120"); addPlatform(420,220,"platform120"); addPlatform(60,220,"platform120"); addPlatform(100,316,"ground"); addPlatform(380,316,"ground"); game.input.onDown.add(changeDir, this); } function addPlatform(posX,posY,asset){ platform = game.add.sprite(posX,posY,asset) platform.anchor.setTo(0.5); game.physics.enable(platform, Phaser.Physics.ARCADE); platform.body.allowGravity = false; platform.body.immovable = true; platformgroup.add(platform); } function onUpdate() { player.body.velocity.y = Math.abs(playerSpeed); player.body.velocity.x = 0; onPlatform = false; game.physics.arcade.collide(player, platformgroup, movePlayer); if(!onPlatform){ readyToFire = true; } if(player.y>320){ player.y = 0 } if(player.x<12){ player.x=12; playerSpeed*=-1 } if(player.x>468){ player.x=468; playerSpeed*=-1 } } function movePlayer(){ player.body.velocity.x = playerSpeed; onPlatform = true; if(readyToFire){ var bullet = new Bullet(game, player.x, player.y, playerSpeed, bulletXSpeed); game.add.existing(bullet); readyToFire = false; } } function changeDir(){ playerSpeed *= -1; } Enemy = function (game, x, y, direction, speed) { Phaser.Sprite.call(this, game, x, y, "enemy"); this.anchor.setTo(0.5); game.physics.enable(this, Phaser.Physics.ARCADE); this.xSpeed = direction*speed; }; Enemy.prototype = Object.create(Phaser.Sprite.prototype); Enemy.prototype.constructor = Enemy; Enemy.prototype.update = function() { game.physics.arcade.collide(this, platformgroup, moveEnemy); this.body.velocity.x = this.xSpeed; }; function moveEnemy(enemy,platform){ if(enemy.xSpeed>0 && enemy.x>platform.x+platform.width/2 || enemy.xSpeed<0 && enemy.x<platform.x-platform.width/2){ enemy.xSpeed*=-1; } } Bullet = function (game, x, y, direction, speed) { Phaser.Sprite.call(this, game, x, y, "bullet"); game.physics.enable(this, Phaser.Physics.ARCADE); this.xSpeed = direction*speed; }; Bullet.prototype = Object.create(Phaser.Sprite.prototype); Bullet.prototype.constructor = Bullet; Bullet.prototype.update = function() { this.body.velocity.y = 0; this.body.velocity.x = this.xSpeed; if(this.x<0 || this.x>480){ this.destroy(); } }; }
You should be already able to extend Sprite class to create new enemies, so I am only focusing on patrol routine.
Line 102: this function is automatically called at each update, for every Enemy instance in the game.
Line 103: if the current enemy collides with something in platformGroup
group – which contains all platforms – then moveEnemy
function is called.
Line 104: finally enemy velocity is updated according to xSpeed property. The key to make the enemy change direction can be found in this property. Let’s see how we can change it.
Line 107: this function is called when an enemy hits a platform, which should always happen when the enemy is already on the platform, but it’s useful to place the code here in case you want to create the enemy in an empty space, so it can land on a platform, then move.
Line 108: here is the key of the script: thanks to enemy
and platform
arguments passed at line 107, we can know which enemy and which platform we are talking about, and check if the enemy is getting close to platform edge, according to its position, its direction and platform position.
Line 109: in this case, we just invert enemy speed.
And this is how we added patrolling enemies in a few lines. Next time, we’ll complete the level by making both enemies and Wizard killable, meanwhile you can download the source code.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.