[#PhaserFriday is a running series on the HTML5 game framework Phaser covering everything from basics of sprites to creating platformer games.]
Note: all examples in this post assume you have already loaded Phaser in a browser session or development environment.
Sprites and Group
In most game frameworks, there are two main components: something that defines one thing, and another that defines a grouping. One or many, basically. You are either dealing with a single instance, or want to deal with a set of things of some type.
In Phaser, these two main components are the objects Sprite and Group.
Sprite
Within general gaming design terms, a sprite is an on-screen entity. Depending on the framework, this can mean drawing something or defining how an image will be shown. In Phaser, it’s the former: a Sprite is defined by its position, its x and y, and some image (canvas) reference.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var game = new Phaser.Game( | |
200, //The width in pixels | |
200, //The height in pixels | |
Phaser.AUTO, //The render system | |
"phaser", //The element | |
{ | |
create: create, // The create function | |
update: update // The update function | |
} | |
); | |
function create() { | |
var sprite = game.add.sprite( | |
20, // The 'x' position | |
20, // The 'y' position | |
'sprite' // The image-cache name | |
); | |
} | |
function update() { | |
} |
In the above example, we are creating a Sprite using the standard game.add functionality, specifying a sprite with the game.add.sprite call, and passing it the three parameters of ’20’ (x), ’20’ (y), and ‘sprite’ (image cache-key).
Just like the parameters for creating a Phaser.Game object, Phaser maintains a listing of all the resources loaded. These are the cache keys. By referencing some image or canvas, in the example of the Sprite, we can also save ourselves some typing. We establish what we want its key and value to be early and then use its key after that.
However, if we want to load an image for the Sprite to use, we do that within the preload function of the Phaser.Game object. Once loaded, we then create the object within our create, and, although we are not using it in this example, would update some information in update.
Note: Many browsers have cross-origin rules in place to protect users from accidentally downloading or using recourses that may be harmful or contain malicious code.
One of these rules establishes something known as a ‘tainted canvas’ that applies to HTML 5 game frameworks like Phaser. What this means is that, after loading some image from a source outside of the current domain, for example, the canvas (the area where content is drawn) is now ‘tainted’ and cannot be used locally anymore.
In practice, this means that Phaser projects have to be tested on servers (and not use the file:// protocol) and cannot load resources like images from another domain.
In the above example, just like we did to create objects, we use the game.load functionality and call the specific function we wanted to use. To load an image, as we are doing, we use game.load.image and supply its cache-key and cache-value.
Group
Just like the name implies, a Group is some collection of things. And, as you might imagine from seeing the game.add.sprite usage, we create groups in a similar manner. However, unlike game.add.sprite, there are no parameters to pass or arguments to specify for Group in its most common usage.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var game = new Phaser.Game( | |
200, //The width in pixels | |
200, //The height in pixels | |
Phaser.AUTO, //The render system | |
"phaser", //The element | |
{ | |
preload: preload, // The preload function | |
create: create, // The create function | |
update: update // The update function | |
} | |
); | |
function preload() {} | |
function create() { | |
var group = game.add.group(); | |
} | |
function update() {} |
Like in the above example, Group is not very interesting by itself. It needs some entries to hold in order to have something happen. For Group, there are two different ways to do this.
- Group.create
- Group.add
If we want the group to create a Sprite by itself, we can tell a Group to create one simply by calling that combination: Group.create. It will create a Sprite given the arguments we supply and add it to itself.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var game = new Phaser.Game( | |
200, //The width in pixels | |
200, //The height in pixels | |
Phaser.AUTO, //The render system | |
"phaser", //The element | |
{ | |
preload: preload, // The preload function | |
create: create, // The create function | |
update: update // The update function | |
} | |
); | |
function preload() {} | |
function create() { | |
var group = game.add.group(); // Create the group | |
group.create( | |
20, // The x position | |
20, // The y position | |
'sprite' // The image cache-key | |
); | |
} | |
function update() {} |
If, on the other hand, we had some existing Sprite and wanted to add it to some group, we could do that by using the Group.add functionality. We simple have the Sprite be the argument to the function.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var game = new Phaser.Game( | |
200, //The width in pixels | |
200, //The height in pixels | |
Phaser.AUTO, //The render system | |
"phaser", //The element | |
{ | |
preload: preload, // The preload function | |
create: create, // The create function | |
update: update // The update function | |
} | |
); | |
function preload() {} | |
function create() { | |
var sprite = game.add.sprite( | |
20, // The x position | |
20, // The y position | |
'sprite' // The image cache-key | |
); | |
var group = game.add.group(); // Create the group | |
group.add(sprite); // Add 'sprite' to the group | |
} | |
function update() {} |
So, we can create a single Sprite or a Group. We can also add a Sprite to a Group, too. That’s cool and all, you might be thinking, but what does that give us? Why would we want to use a Group over a Sprite.
Well, a Group gives you some helpful multi-entry functionality like returning the number of ‘living’ or ‘killed’ objects within itself. Or, by setting the position of the group itself, how to move all the objects within it to the same place. In fact, by using the Group.set function, we can change some attribute on all of the entries collected in one function call!
We can also remove some object using a similar function call that we used for removing things from the game stage, too. To remove some object from a group, we simply use a reference to it as the argument to the Group.remove function.
(As might be obvious at this point, the game world’s ‘stage’ is actually a kind of group itself. In calling game.add or game.remove, we are calling specialized versions of the same functions all groups use to add to or remove from some objects.)