The Sprite onKilled event in phaser
When making a Phaser ce powered javaScript game project there are of course sprites, and when working with sprites there are useful events. In this post the focus will be on the sprite.events.onKilled event in phaser ce. This is a signal that will fire when the sprite.kill method is called, which is very different from sprite.destroy. The kill method is what I would call if I want to set certain values to what would be appropriate if the sprite has been killed, but I do not want to actually destroy the sprite completely. So in this post I will be coving some use case examples for this method.
1 - Start here
In this post I am writing about the onKilled event that is fired when a sprite is killed with the sprite.killed method in phaser ce. There is also the onDestroy event that is fired when a sprite is completely removed from the game world, and cache completely. In most projects I like to have a pool of sprite objects that I reuse, rather than the alternative which would be a mechanic where there is no set maximum of enemies that can be in the world. In any case it is good to be ware of both of these events, as well as the many other events that are fired by game objects in phaser ce.
1.1 - This is a phaser ce 2.x post
In this post I am using Phaser ce 2.11.0, not the newer phaser 3.x major release of phaser.
2 - A full example using sprite.events.onKilled
For this posts full working example I made a simple little project that involves a pool of sprites that spawn from the upper left corner of the screen, and then move across the screen, wrapping around within the screen when going out of bounds. When a sprite is clicked it looses hp, and will be killed when hp reaches zero. At which point the sprite.events.onKilled event will fire, in this example I have some logic that determines how many points the player should get when killing the enemy.
2.1 - My enemies.js file
So in this example I have an enemies.js file that contains many methods that help with the creating of a group of enemies, that is then used in my main.js file where I create an instance of Phaser.Game, and add some states to it. In this file I make a javaScript object literal, and append a few methods to it including a method that makes use of sprite.events.onKilled.
2.1.1 - Staring off the Enemy module, and Enemy.setup
For this module I went with just the Object literal module pattern, which works fine for this example as it is okay that everything is public. I then start off with a setup method that I will call in a boot state when making the phaser game instance later.
|
|
When I do call the setup method it will create an append a data object to the game instance when I call it with Function.call. Just appending a data object to the Phaser.Game instance is a common way to set some game wide variables.
2.1.2 - The Enemy.onKill handler
Here is the handler that I will use with the sprite.events.onKill method.
|
|
So in this example each time an enemy is killed a points value will be figured out, and appended to the score property of my game.data object.
2.1.3 - The Enemy.onInputDown handler
So another useful event is the sprite.events.onInputDown event. I this example I will want one of these attached for each sprite as well, so that when one is clicked by the player something happens in this case it looses a single hp point.
|
|
2.1.4 - Generate Sprite Data objects
So this method will create a new data object for a sprite. The sprite.data object is an official phaser ce way of setting some values and methods for a sprite that are specific to the nature of the game itself that I am making. The sprite.data object is not used my phaser itself internally, so it is safe to do whatever seems right with it.
|
|
In this example I will just be setting some delta values, and a hit point value.
2.1.5 - Make a sprite sheet with canvas
So this is just a simple demo rather than a real serious game that consists of many lines of code. Never the less I am using sprites, and I will want a way to skin these sprites, even if they are just solid colored boxes. So for many of my examples for these posts I like to use a canvas solution for making a sprite sheet.
|
|
2.1.6 - Create a pool of enemies
So because this is an example of sprite.events.onKilled, I will be working with a pool of sprites. This is because of the differences between the sprite.kill, and the sprite.destroy methods. The sprite.kill method will set a bunch of properties of a sprite to a status that is that considered dead. The sprite can then later be reused by using a method like group.getFirstDead, or sprite.revive. This is very different from the sprite.destroy method that will completely remove the sprite from phaser all together.
|
|
So I am calling sprite.kill right after making the sprite to start it off in a dead state. I then have another method Enemy.spawn that will revive these at a set rate.
2.1.7 - The spawn method
So here is my spawn method that will be called every second or so in the main state that will run this example.
|
|
Here I am using the group.getFirstDead method to get and revive the first dead sprite in the pool or group of sprites. In the event that they are all alive this method will return null, so i test if it is not before setting a new sprite.data object to it with the genSpriteData helper I made earlier.
2.1.8 - An update method for the enemies
So when I make a module like this I often have an update method as well that will be called each time there is a frame tick in the main game state when making my state objects of the instance of Phaser.Game
|
|
For this method I am using group.forEach to loop over all sprites an stepping there position with the current deltas in the sprite.data object.
2.2 - The Phaser.Game instance, and states
So now to tie everything to together with a Phaser.Game instance an a few state objects. For this example I just have a boot state, and a demo state, I guess I could just have everything in a single state, but I like to start off with this even for simple examples like this one. In a real game there will end up being a lot of state objects, this helps to break things down, making them more fine grain. Fine grain code is often easier to read, and debug.
2.2.1 - The Phaser.Game instance, and boot state
So like always I create a new instance of Phaser.game, setting a mobile friendly resolution of 32- by 240. I just about always set the renderer to Phaser.AUTO, and often have a div in my html with an id attribute of ‘gamearea’.
|
|
In my boot state I set up the game.data object with the Enemy.setup method, create the sprite sheet with Enemy.mkSheet, and set up the sprite pool with Enemy.createEnemyPool. Once way or another I need to share the instance of Phaser.Game with these methods, by passing them as an argument, or using Function.call to set the value of the this keyword.
2.2.2 - The demo state
I start the game by starting the boot state, that will set some things up, and then start the actual demo state. In the demo state I start a loop that will call Enemy.spawn every second to spawn a new enemy, and create a text display object to display the current player score.
|
|
In the update method of the demo state I call my Enemy.update method, and update the score to the latest value in the game.data object created with Enemy.setup
3 - Conclusion
All of this results in an example where sprites in a pool a revived at a rate of one per second, the player can then click on one to damage it, and again to kill it. Once the sprite is killed the onKilled event that I attached to it fires, and in the body of this method I update the players score.