Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The following Phaser coding references are provided in this GitBook:
There are many other Phaser references, examples, and tutorials available online. Here's some you may find particularly useful:
Phaser CE API documentation (provides details for every Phaser CE command)
Phaser CE code examples on Phaser.io (Phaser 2 = Phaser CE)
Phaser community tutorials on Phaser.io (older examples prior to 2018 use Phaser 2, but newer examples use Phaser 3)
Phaser game examples by Emanuele Feronato (her older examples prior to 2018 use Phaser 2, but newer examples use Phaser 3)
PHASER 3 VS. PHASER CE: Phaser 3 is the newest version of Phaser (first released in February 2018), which is maintained and updated by the folks at Photon Storm. Phaser CE is an open-source version of the previous Phaser 2, which is maintained and updated by the Phaser developer community.
While the API methods for Phaser 3 are similar to Phaser CE, code written for one will not work in the other without modification. All of the code examples in this project guidebook are based on Phaser CE. Eventually, this guidebook will be revised to use Phaser 3, which does offer improvements. However, in the meantime, be sure to use Phaser CE for this project.
The game display is the HTML <canvas>
element that Phaser adds to the webpage to display your game. Phaser also refers to this as the Stage.
The game display shows the player's view into your game world. The game world can be the same size as the game display (e.g., a single-screen game like Space Invaders) — or the game world can extend beyond the game display (e.g., a scrolling game like Crossy Road). For extended game worlds, the position of the game camera determines what is shown in the game display.
Set Size of Game Display
Change Background Color of Game Display
Change Background to Random Color
You set the width and height of your game display when you first create your Phaser.Game object, which is typically done at the beginning of your JavaScript game code — before the preload()
function.
In the code above, the game display will be 800 pixels in width by 600 pixels in height. You can change these numbers for your game. However, you'll want the game display to fit within the available width and height of the player's browser window. For beginning game developers, just choose a width and height that fits your own screen.
REMINDER: Remember that 'my-game'
represents the id name of your game container <div>
in your HTML. If your CSS sets a width or height for #my-game
, then be sure to update those values to match the size of the game display in your JavaScript.
While we won't cover details here, Phaser has a Scale Manager that can be used to scale your game display to fit the size and orientation (landscape vs. portrait) of the player's device, so your game is playable on a range of device sizes. This is a feature for advanced game developers.
By default, Phaser uses black as the background color for your game display. However, you can change this to any color using a CSS hex string.
In the code above, '#ffffff'
represents white — replace this with your own CSS hex string.
In most cases, you would add this command in your create()
function (probably towards the beginning — just to make it easy to find it). For example, if you only need to change the background color once, then do this in the create()
function.
However, you can also use this command in your update()
function or in a custom function. For example, you might do this if you wanted to change the background color based on certain conditions or events in the gameplay.
You can also let Phaser choose a random color for the game display background:
You can add text to your game to display feedback or information as part of your game's user interface. Phaser handles text as a display object with properties and methods that allow you to modify the text in various ways.
Add Text (and Set Style)
Add Text Shadow
Change Anchor for Text Position
Change Text Position
Rotate Text to Angle
Make Text Stay Fixed to Camera View
Hide Text (and Unhide)
Change Text Content
Clear Out Text Content
Add Line Breaks in Text Content
Change Text Style
Properties and Methods for Text
If you have static text (i.e., won't change during game) that just needs to be positioned and have basic style properties set, you can add the text object directly (without assigning it to a variable):
The command to add text would be placed in your create()
function (probably towards the end, so that it will be displayed in front of other objects).
350, 20
represent the x
and y
coordinates where the text will be positioned (based on the text's anchor, which is its top-left corner by default). Change these values to the position you need.
'Health'
represents the text string to display as the text. Replace this with your text.
OPTIONAL: You can style the text by providing a comma-separated list of style properties and values inside curly braces { }
(i.e., a JSON object).
However, if the text will be dynamic (i.e., will change during the game) or needs to be modified beyond basic style properties (such as adding a text shadow, hiding the text, etc.), then you need to declare a variable and assign the text object to the variable:
scoreText
represents a variable name. Change this to the name of your variable.
If you only need to change the text properties within the create()
function, you can assign the text object to a local variable.
Otherwise, if you need to change the text in the update()
function or a custom function, then assign the text object to a global variable.
The default style for text will be Arial 20pt bold in black — but you can modify any of these default properties.
The Phaser API documentation for Text lists all the style properties that can be set for text. Here's a list of the most common style properties that you might use:
font
sets the font-family. By default, it will use 'Arial'
. The font must be already be installed on the user's computer, so stick with a web-safe font family. If you're interested in using a special font, here's an example of how to load a webfont from Google in Phaser.
fontSize
sets the size of the font. By default, it will use '20pt'
(20pt is approximately 27px). For more accurate layout, you may want to use px (pixels) to set the size, such as: '30px'
fontWeight
sets the weight of the font, such as 'normal'
or 'bold'
. By default, it will use 'bold'
.
fill
sets the color of the text. By default, it will use 'black'
. Set the value (as a string) using either a HTML color name or a CSS hex code.
If you've assigned the text object to a variable, you can add a shadow behind the text:
The first value is the horizontal offset (in pixels) of the shadow. Positive values shift the shadow to the right, while negative values shift it to the left. Use a value of 0
for no horizontal offset. (A small value between 0-5 usually works well for offset.)
The second value is the vertical offset (in pixels) of the shadow. Positive values shift the shadow down, while negative values shift it up. Use a value of 0
for no vertical offset. (A small value between 0-5 usually works well for offset.)
The third value is the color of the shadow. The color can listed either as a CSS hex string or as a RGBA string. Colors that often work well for shadows are either '#000000'
(black) or 'rgba(0, 0, 0, 0.7)'
(slightly transparent black) — but it depends on the color of the text and the color of the background.
The fourth value is the blur (in pixels) of the shadow. Use a value of 0
for a sharp shadow. Use a value up to about 10
for a softer shadow. (A small value between 0-5 usually works well for blur.)
The x
and y
coordinates of a display object (text, image, sprite, etc.) represent the position of the object's anchor.
By default, an object's anchor is its top-left corner. However, you can change the anchor for an object (e.g., to make the object's center become its anchor for positioning).
For example, to change the anchor of a text object named messageText
:
The first number represents the horizontal position of the anchor, as a number between 0-1 (0 = left edge, 0.5 = horizontal center, 1 = right edge).
The second number represents the vertical position of the anchor, as a number between 0-1 (0 = top edge, 0.5 = vertical center, 1 = bottom edge).
For most text, it will be fine to leave the anchor as the top-left corner (the default).
However, for some text, it may make more sense to set its anchor to its center (0.5, 0.5)
— or possibly to its top-middle (0.5, 0)
or bottom-middle (0.5, 1)
.
If you need to change the position of the text, just change its x
and/or y
coordinates.
For example, you could change the position of a text object named messageText
:
You can rotate text (around its anchor point) by changing the value of its angle
property.
For example, you could rotate a text object named gameTitle
:
-10
represents the angle in degrees. Change this to any value from -180 to 180. Negative values rotate the image counterclockwise. Positive values rotate the image clockwise.
Phaser also has a property called rotation
that can be used to get or set the angle of rotation of an text. The only difference is that the rotation
property uses radians for its units, instead of degrees (2π radians = 360°).
You can make an image stay fixed within the game camera view, so the image won't move when the game world scrolls.
Phaser display objects (such as images, text, sprites, etc.) have a property called fixedToCamera
. By default, this property is set to false
— changing this value to true
will make the object stay fixed to the camera view.
For example, you can make a text object named scoreText
stay fixed to the camera view:
If you've assigned the text object to a variable, you can hide (or unhide) the text by changing its visible
property.
For example, to hide the text:
To show the text again, just unhide it:
You can change the content of the text that is displayed by assigning a new text string to its text
property:
You can concatenate (combine) text strings and/or variable values using the +
sign. JavaScript will treat the result as one continuous text string.
For example, if your game has a numerical variable named score
, you could display a text label plus the value of score
:
Notice that a blank space was included in the text string (inside the quotes). Otherwise, there would be no space between the word "Score" and the number when the text is displayed.
You can clear out the text content (make it blank) by simply assigning an empty string to the text
property:
If necessary, you can add line breaks to split up your text into multiple lines.
To add a line break, insert: \n
For example, the following text will be split into 3 lines:
The text would be displayed as:
Game Over You Lost Try Again
If you do use multi-line text, you may want to change the text so each line will be center-aligned:
The options for align
are 'left'
, 'center'
, or 'right'
. By default, the alignment will use 'left'
. This can also be set as one of the style properties when you add the text object.
If you've assigned the text object to a variable, you can later modify any of its style properties. Here's a few examples:
You can create a group of sprites. You can have different groups for different types of sprites. The members of a particular group should be related in some way, such as a group containing enemies, a group containing platforms, etc. The members of a group typically have many similarities — but they can also have differences.
The main advantage of using a group is that is makes it easier to perform checks or actions on each member of the group.
Another advantage is that your code can recycle "dead" members of a group (which helps save memory and make your game run faster).
Add New Group
Create New Member in Group
Set Property for Specific Member of Group
Set Property for All Members of Group
Create Multiple Members Using For Loop
Position Members at Regular Intervals
Position Members at Random Locations
Position Members at Specific Locations
Call Function for Each Member of Group
Call Function for Each Alive (or Dead) Member of Group
Count Members of Group
Get Specific Member of Group
Recycle Dead Members of Group
Freeze or Hide Group (and Undo)
Kill All Members of Group
Created Nested Group Containing Other Groups
Sort Members of Group for Pseudo Depth Effect
You can add a new group to your game by assigning it to a variable. Use a global variable if you will need to refer to the group or its members in your update()
function or in a custom function.
For example, to add a group to a global variable named platformGroup
:
This command would be placed in your create()
function.
Once a group has been added, you can then create a new member in the group, and add the member to the game world at a specific position.
Adding new members to a group is typically done in the game's create()
function. However, it can also be done in the update()
function if you need to add new members as the game proceeds.
For example, to create a new member in a group named platformGroup
:
200, 500
represent the x
and y
coordinates where the member will be positioned in the game world (based on the member's anchor, which is its top-left corner by default). Change these values to the position you need.
'platform-100'
is the asset key of the image or spritesheet to use for this member. Change this to the asset you want to use.
If you need to create more members in the group, just repeat the command, and change the x, y
position and/or asset key for each new member:
The members of a group are sprites, so each member of a group can have its sprite properties set, can have physics properties enabled and set, and can have animations added.
If you need to change the value of a property for a specific member of the group (but not the other members), first create the new member by assigning it to a local variable. Then change the property for that specific member by referring to its variable name.
bottomPlatform
represents a local variable name for the new member. Change this to a variable name that makes sense to you.
The second line of code in the example changes a property (the scale
property) only for this specific member of the group. Change this to list the property and value that you want to set. If necessary, you can modify multiple properties for this specific member of the group.
You can use the setAll()
method to change the value of a property for all members of a group. Inside the parentheses, you first list the name of the property (in quotes) and then list the value that you want to set for the property.
For example, this command will set a property for all members of a group named platformGroup
:
true
represents the value for the property. Some properties use true
or false
for their value. Some properties use a number for their value. Some properties use a string (text) for their value (if so, list the string within quotes). List the value you want to use for your property.
You can use a for
loop to create multiple new members in a group. If you do this, you have several options for positioning the new members:
position the members at regular intervals (such as: every 200 pixels, etc.)
position the members at random locations
position the members at specific locations using JSON data array
In order to position the new members at regular intervals in the game world, you need to create a calculation that will space the members horizontally (in the x
direction) and/or vertically (in the y
direction). Typically, these calculations use the i
variable that the for
loop uses to count iterations.
For example, this code would create 10 new members in the coinGroup
located at regular intervals in the game world:
The for
loop shown above will create 10 new members in the group.
var i = 0
creates a local variable named i
that starts at zero and will be used as the "counter" for the number of times to iterate (repeat) the loop.
i < 10
sets a condition to decide when the loop should stop iterating (repeating). In this case, the number 10
controls the number of members that will be created. Change this to the number that you need to create.
i++
changes the local variable at the end of each iteration by increasing its value by one (i++
is shorthand for i = i + 1
).
The x
position of each new member will be calculated using i * 200 + 100
.
200
represents how far apart (in pixels) the members will be positioned.
100
represents the position of the first member.
As the value of
The first new member (when i = 0
) will have an x
position of 100 (0 200 + 100 = 100). The next member (when i = 1
) will have an x
position of 300 (1 200 + 100 = 300). The next member (when i = 2
) will have an x
position of 500 (2 * 200 + 100 = 500) - and so on.
The y
position of each new member will simply be set as 0
(top of game world). Presumably, each coin
will have a gravity value set that will make it fall down.
Modify the code to use your own calculations (and/or numbers) for the x
and y
positions.
You can also just position each new member at a random location.
For example, this code would create 10 new members in the coinGroup
at random locations in the game world:
You can also create a JSON data array that contains specific x
and y
positions for the new members to be created. Then you would use a for
loop to iterate through the JSON data array to create the new members, and add them into the game world at their specific positions.
For example, here is a JSON data array that list positions that will be used to create new members in a group:
Square brackets [ ]
are used to contain the items in an array. Within the array, the JSON data for each item is listed inside curly braces { }
using name-value pairs: the name of a variable followed by its value. A colon is used to separate the variable name and its value. If you were using variables that have strings (text) for their values, then list the values within quotes.
Within the JSON data for an item, a comma is used to separate different name-value pairs (so you can list multiple variables for each item). As you can see, the JSON data list an x
and y
variable for each coin.
Commas are also used to separate the different items within the array (i.e., the comma that appears after the right-hand curly brace). Notice that you don't include a comma after the last item in the array.
Each item in an array is identified using an index number, which is based on the order in which the items are listed. The first item in an array is always numbered as index 0
. Since there are 10 items listed in the coinData
array, they are numbered in order as 0-9. For example, coinData[1]
actually refers to the 2nd item in the array, which is the data: { x:150, y:0 }
The variable values for an item in an array can be referenced by using the item's array index number followed by a period and then the variable name. For example, coinData[1].x
is 150
and coinData[1].y
is 0
.
Now you're going to loop through this array to use the JSON data to create the new members in coinGroup
.
This for
loop will iterate through the entire coinData
array, using i
to represent the index number of the current item: i
will start at 0
and increase by one after each loop (i++
) until it reaches the end of the array (which is represented by coinData.length
).
Inside the for
loop a local variable named coin
is created as a new member in the coinGroup
using the x
and y
values stored in coinData[i]
. You can add optional code to set other properties for each member (e.g., set its anchor, add animations, etc.).
You can use the forEach()
method to call a function for each member of a group. Inside the function, you can list whatever commands you need to perform for each member. The forEach()
method will iterate through each member of the group, performing the commands you listed.
For example, this would call an inline function for each member of a group named enemyGroup
:
enemy
represents a local variable name that will be used within the function to refer to a member of the group. Change this to a variable name that makes sense for the group.
Within the curly braces { }
, list one or more commands to be performed for the member. In this example, the code sets the anchor for the member, adds an animation to the member, and starts playing the member's animation. Change these to whatever commands you need.
The forEach()
method can be used in your create()
method to set properties of each member before the game starts.
You can also use the forEach()
method in your update()
function (or in a custom function) to perform commands on each member during gameplay.
You can use the forEachAlive()
or forEachDead()
methods to call a function only for the "alive" (or "dead") members of the group. Inside the function, you can list whatever commands you need to perform for each alive (or dead) member.
For example, this would call an inline function only for each "alive" member of a group named enemyGroup
:
For example, this would call an inline function only for each "dead" member of a group named enemyGroup
:
These methods would typically be used during gameplay in your update()
function (or in a custom function).
If your game needs to know how many members are in a specific group, there are several options available to get a count.
For example, if the name of your group were enemyGroup
:
enemyGroup.total
would be the total number of members in the group, including both "alive" and "dead" members
enemyGroup.countLiving()
will return the number of "alive" members in the group
enemyGroup.countDead()
will return the number of "dead" members in the group
If your game needs to get a specific member of a group (in order to do something with that member), there are several methods available to select a member.
For example, if the name of your group were enemyGroup
:
enemyGroup.getFirstAlive()
will return the first "alive" member of the group that it finds.
enemyGroup.getFirstDead()
will return the first "dead" member of the group that it finds.
enemyGroup.getRandomExists()
will return a random existing member of the group.
enemyGroup.getClosestTo(player)
will return the member of the group that is closest in distance to the player
sprite. Change player
to whichever sprite or display object that you want.
enemyGroup.getFurthestFrom(player)
return the member of the group that is farthest in distance from the player
sprite. Change player
to whichever sprite or display object that you want.
In order to use of the methods above, you will want to create a local variable to store the result (the member) returned by the function. Then you will be able to add commands to do something with that specific member.
For example, the following code will get a random member of the enemyGroup
, assign the member to a local variable named enemy
, and the make that enemy
move towards the player
:
You can recycle "dead" members of a group by adding them back to the game (making them "alive" again). By recycling dead members (instead of constantly creating new members), your game will use less memory and run faster.
For example, your game might be designed to add back members of an enemy group that have been removed using the kill()
method. Since the members are sprites, you can add a "dead" member back into the game using the revive()
or reset()
method.
To do this, you would need to find the first dead member of the group, and assign this member to a local variable. Then you can revive or reset the member and change any of its properties (position, velocity, etc.).
For example, add this code to your update()
function to immediately recycle a dead member of a group named enemyGroup
:
This code tries to find the first dead member of the group, and assigns this member to a local variable called enemy
(change to a name that makes sense for your group).
If a dead member was found, then it will run the code inside the if
statement — this is where you would either revive or reset the member to make it alive again. You can add other code to change the member's properties or perform other actions.
If there weren't any dead members (i.e., every member of the group is already alive), then the local variable will be assigned a value of null
and the code inside the if
statement will not be performed.
If you want to add a brief random interval before recycling a dead member of the group, use this slightly modified code:
This modified code will only check for a dead member to recycle if it generates a random number below a certain value (0.01
in this case). Increasing this value will make it more likely that recycling will occur during any specific game loop — the intervals between recycling will still be random, but recycling will occur more frequently on average. (Decreasing the value has the opposite effect.)
If you game needs to freeze or hide all members of a group at once, you can use change the exists
property or the visible
property.
NOTE: The way that the exists
property affects a group is different from how it works for an individual sprite.
You can change a group's exists
property prevent its member sprites from being affected by any physics interactions. However, the member sprites will still be visible in the game. Basically, it will cause the member sprites to become "frozen" at their current position and become non-interactive.
For example, to "freeze" a group named enemyGroup
:
To unfreeze the group (and make it interactive again):
You can change a group's visible
property to make all of its member sprites invisible. However, the member sprites will still be involved in certain physics interactions (moving, falling, colliding, etc.) because the sprites still exist (they're just invisible).
For certain games, invisible sprites could be interesting (e.g., creating invisible enemies that the player must avoid, etc.).
For example, to make a group named enemyGroup
invisible:
To show the group again:
You can also change both properties at the same time.
For example, to freeze and hide a group named enemyGroup
:
To unfreeze and show the group again:
If your game needs to kill all members of a group at once, there is a method specifically to do this:
If necessary, you can create a group that contains other groups (as well as individual sprites) nested within it. There may be certain situations where using a nested group is helpful.
You can simply use the add()
method to add another group (or a sprite) into a group.
For example:
Some 2D games attempt to create a "pseudo-3D" visual effect by using side-view sprites combined with top-down movement (meaning sprites can move up, down, left, and right — and have no gravity applied) plus depth sorting (based on y
position).
Sprites that are towards the top of the game display (lower y
values) are supposed to be farther back while sprites that are towards the bottom (higher y
values) are supposed to be closer. The game sorts the visual layering of the sprites based on their y
positions to make "closer" sprites appear in front of "farther" sprites.
To be clear, using this "depth" effect will not make your game look like a true 3D game. However, the sprites will have a psuedo-depth effect relative to each other, which can add a slight bit of a "third dimension" to your game.
For example, to do a depth sort for the members of a group named 'treeGroup`:
If the members of the group do not move, then you could just perform the sort one time by placing it in the create()
function.
However, if you the members of the group are moving and changing their y
positions, then you would want to perform the sort every game loop by placing it at the end of your update()
function. For example, you might need to do this for a group of enemies.
If you want apply a depth sort to the player's sprite plus other sprites and groups, then you should create a nested group that contains all the sprites and groups that should be sorted by depth.
For example, add a new group named depthGroup
in your create()
function, and then add the other sprites and groups into the depthGroup
:
Then at the end of your update()
function (after any sprites or group members may have changed position during a game loop), do a depth sort on the depthGroup
:
You can add one or more background images to your game, and if your game world is larger than the game display, you can also make your game world scroll automatically to follow the player. This can be done without using a tilesprite — you can just position whatever image(s) you want throughout your game world, and make the game camera follow the player.
A is used to create a single background image that looks like it is scrolling as the player moves. A tilesprite can be used for a single-screen game or for an extended game world.
However, not just any image will work as a tilesprite. There are two main criteria: pattern and size.
In order to create a smooth scrolling effect, the tilesprite image must have a pattern that matches seamlessly across opposite edges — which could be its horizontal edges (left and right), its vertical edges (top and bottom), or both — depending on which direction(s) your game world is supposed to scroll.
In the image above, notice that the pattern of the sky and clouds along the left edge matches perfectly with the right edge. If you were to place multiple copies of this image side-by-side, the pattern would repeat seamlessly, so this image would be perfect for a horizontally scrolling game.
The other criteria for a tilesprite background image is that it should be the exact size of your game display. If necessary, use an image editor to resize your tilesprite image to match the width and height of your game display. (Alternatively, you could change the size of your game display to match the size of the image.)
Load Image for Tilesprite
Add Tilesprite
Make Tilesprite Stay Fixed to Camera View
Scroll Tilesprite When Player Moves
Create Parallax Effect to Simulate Depth
Just like other images, the image file for your tilesprite must be loaded into the game's memory before you can add it to your game world.
The command to load an asset is always placed in your preload()
function.
'sky'
represents an asset key — a key is sort of like a variable name. You decide what string to use for the key, as long as each image asset has a unique key.
'assets/images/sky-clouds.jpg'
represents the folder path and filename of the image to load. Change this to match your specific folder path and filename.
Once the image asset has been loaded into memory, you can add the tilesprite to your game world.
You will need to declare a global variable for the tilesprite and assign the tilesprite to the variable in your create()
function.
For example, to add a tilesprite to the variable named skyTile
:
0, 0
represent the x
and y
position for the top-left corner of the tilesprite image. This is normally where you want to position tilesprite images.
800, 600
represent the width and height of the tilesprite image. Be sure the size of your tilesprite matches the size of your game display. Change these numbers to match your tilesprite and game display.
'sky'
is the asset key for the tilesprite image.
Remember that the code to add background images, such as tilesprites, should be listed in your create()
function before the code to add other sprites, images, text, etc.
You can also layer multiple images to create a more complex background. This only works if the layer(s) in front have some transparent areas, so you can see part of the other layer(s) behind.
For example, imagine the background of your game will consist of these three tilesprites:
skyTile
will be the farthest back tilesprite layer — an image showing sky and clouds
mountainTile
will be the middle tilesprite layer — an image showing a mountain ridge but with a transparent sky (so you can see part of the skyTile
behind it)
cityTile
will be the closest tilesprite layer — an image showing a silhouette of city buildings but with a transparent sky (so you can see part of the mountainTile
and skyTile
behind it)
Add the tilesprites in the order of their "depth" from back to front:
If your game world is larger than your game display, then you must make the tilesprite stay fixed to the game camera's view.
For example, to make a tilesprite named skyTile
stay fixed to the camera view:
If you have layered multiple tilesprite images to create your background, then be sure to fix each of them to the camera.
In order to create a realistic scrolling effect, the tilesprite should scroll in the opposite direction that the player is moving. For example, if the player's sprite is moving to the right, then the tilesprite should scroll to the left.
You can scroll the tilesprite by changing its tilePosition.x
and/or tilePosition.y
values — depending on whether the tilesprite should scroll horizontally, vertically, or both:
Change the tilesprite's tilePosition.x
to simulate horizontal scrolling:
If the player is moving to the right, make the tilesprite scroll left by decreasing its tilePosition.x
.
If the player is moving to the left, make the tilesprite scroll right by increasing its tilePosition.x
.
Change the tilesprite's tilePosition.y
to simulate vertical scrolling:
If the player is moving down, make the tilesprite scroll up by decreasing its tilePosition.y
.
If the player is moving up, make the tilesprite scroll down by increasing its tilePosition.y
.
The code to scroll the tilesprite should be included in your update()
function (after any player movement has occurred).
If the tilesprite scrolling in your game seems too fast or too slow (relative to the player's movement), adjust the value used to scroll the tilesprite:
If the scrolling seems too fast, use a smaller value.
If the scrolling seems too slow, use a larger value.
There are several options for how to scroll the tilesprite, depending on how your game is set up:
If you have a single-screen game that moves the player by directly changing the player's position (x
and/or y
coordinates), use Option 1 below.
If you have a single-screen game that moves the player by changing its velocity or acceleration, use Option 2 below.
If you have an extended game world with a game camera set to follow the player, use Option 3 below.
If you have a single-screen game (game world is same size as game display) that moves the player's sprite by directly increasing or decreasing its x
or y
coordinates, then move the tilesprite at the same time (but in the opposite direction).
For example, this code checks the arrowKey
inputs used to move the player
sprite and horizontally scrolls a tilesprite named skyTile
:
The example above scrolls the tilesprite by the same amount that the player's position is moved. As necessary, adjust the scrolling value to a number that feels right for your game.
If your game needs to scroll the tilesprite vertically, use similar code to change the y
positions of the player and tilesprite.
NOTE: +=
is the addition assignment operator. It is a shortcut for adding a value to a variable's current value.
player.x += 5
is the same as player.x = player.x + 5
-=
is the subtraction assignment operator. It is a shortcut for subtracting a value from a variable's current value.
player.x -= 5
is the same as player.x = player.x - 5
If you have a single-screen game (game world is same size as game display) that moves the player's sprite by changing its velocity (or acceleration), then move the tilesprite in the opposite direction by subtracting the player's velocity (reduced by a scaling factor).
For example, to horizontally scroll a tilesprite named skyTile
:
Dividing the player velocity by 50
represents a scaling factor, so the scrolling is not too fast. As necessary, adjust this scaling factor to a number that feels right for your game.
If your game needs to scroll the tilesprite vertically, use a similar command:
If your game has an extended game world (larger than the game display) with a game camera set to follow the player, then you can scroll the tilesprite relative to the game camera's position.
For example, to horizontally scroll a tilesprite named skyTile
:
Multiplying the camera position by -0.2
represents a scaling factor, so the scrolling is not too fast. Using a negative value makes the tilesprite scroll in the opposite direction of the camera movement. As necessary, adjust this scaling factor to a number that feels right for your game.
If your game needs to scroll the tilesprite vertically, use a similar command:
In the real world, we experience a visual phenomenon called parallax — as we move, objects in the distance seem to shift more slowly compared to objects that are closer to us. This is one of the ways that our vision system detects depth and distance.
You can simulate parallax in your game by creating a background consisting of multiple tilesprite layers and then scrolling these tilesprites at different rates based on their depth — the farthest back tilesprite layer should scroll the slowest, while the tilesprite layers that are closer should scroll faster.
In your create()
function, create a layered background by adding multiple tilesprites in the order of their "depth" from back to front. Two or three tilesprite layers will be sufficient for a parallax effect.
For an extended game world, be sure to make each tilesprite stay fixed to the camera.
For example, imagine the background of your game consists of these three tilesprites:
skyTile
is the farthest back tilesprite layer — an image showing sky and clouds
mountainTile
is the middle tilesprite layer — an image showing a mountain ridge but with a transparent sky (so you can see part of the skyTile
behind it)
cityTile
is the closest tilesprite layer — an image showing a silhouette of city buildings but with a transparent sky (so you can see part of the mountainTile
and skyTile
behind it)
Create the parallax effect by scrolling the tilesprites at different rates (by using different scaling factors) based on their relative depth.
The furthest back tilesprite layer should scroll the slowest, while the other tilesprite layers should scroll faster as they get closer to the front.
Scroll the tilesprites using one of the three options shown below.
As necessary, adjust the scrolling rates to numbers that feel right for your game.
As necessary, adjust the scaling factors to numbers that feel right for your game.
As necessary, adjust the scaling factors to numbers that feel right for your game.
You can add sound effects and music to your game. Sounds can be looped, faded, paused, etc.
You can only use the following formats for Phaser audio files:
.wav
.mp3
.ogg
If you find or create sound files that you want to use in your Phaser game, check the file extension to see what format the audio is saved in. If necessary, you may need to (typically .wav
or .mp3
).
RECOMMENDED: Avoid using audio with large file sizes, as it will slow down your game. Most of your audio files should probably be less than 100 KB. Music files will typically be much larger (several MB).
Load Audio
Add Audio
Set Audio to Loop
Play Audio (and Stop)
Pause Audio (and Resume)
Change Volume of Audio
Make Audio Fade
Each audio file (also referred to as an asset) must be loaded into the game's memory before you can add it to your game world.
The command to load an asset is always placed in your preload()
function.
'coin-sound'
represents an asset key — a key is sort of like a variable name. You decide what string to use for the key, as long as each audio asset has a unique key.
'assets/sounds/coin.wav'
represents the folder path and filename of the audio to load. Change this to match your specific folder path and filename.
Once an audio asset has been loaded into memory, you can add the audio to your game so it will be ready to play.
Declare a global variable for the sound, and add the sprite by assigning it to the variable. The command to add audio is placed in the create()
function.
'coin-sound'
represents the asset key of the audio to use. Replace this with your asset key.
0.3
represents the volume to use when playing this sound, which can be a value between 0 to 1 (with 1 being the file's maximum volume). Adjust this value to the volume you want.
Be aware that the sound won't actually play until you use a command telling it to start playing.
TIP: The volume to set for each sound depends on how loud the recording of the sound is — and on how loud you want it to be relative to the other sounds in the game. As you keep adding new sounds to your game, you may need to adjust their volumes relative to one another.
By default, when a sound is played, it will play once and then stop. However, you can set a sound to play over and over again in a continuous loop. You'll still be able to stop the sound if and when needed.
Looping can be useful for background music or for certain sound effects.
You would set a sound to loop by including a command in your create()
function, after adding the audio to the game.
For example, to set a sound named spinSound
to loop:
Once audio has been added to the game, it is ready to play.
For example, to play a sound named spinSound
:
Typically, commands to play sounds are placed in the update()
function or in custom functions.
However, you can also play a sound by including a command in the create()
function. This would be useful for background sounds (music, etc.) that you want playing at the start of the game.
By default, when a sound is played, it will play once and then stop.
However, if you have a long audio track (such as background music, etc.) or you have set a sound to loop, you can stop the audio whenever you need to.
For example, to stop playing a sound named spinSound
:
If you have stopped a sound, then it will start from the beginning of the audio track when you play it again.
You can also pause audio and then resume playing it.
For example, to pause a sound named gameMusic
:
Then to resume playing the sound from its pause point:
If necessary, you can change the volume of a sound during gameplay.
For example, to change the volume of a sound named gameMusic
:
0.2
represents the volume which can be a value between 0 to 1 (with 1 being the file's maximum volume).
You can play a sound and make it fade by changing its volume over a specific duration. This might be useful for background music or for certain sound effects.
Phaser has three methods that can be used for fading audio:
fadeIn()
— the sound starts playing from a volume of 0 and increases to a volume of 1 over a duration you specify
fadeOut()
— the sound starts playing from a volume of 1 and decreases to a volume of 0 over a duration you specify
fadeTo()
— the sound starts playing from its currently set volume and changes to a new volume you specify over a duration you specify
For example, to play a sound named gameMusic
and make it fade in (from volume of 0 to volume of 1):
2000
represents the duration in milliseconds for the fade (1000 ms = 1 second). Change this value to whatever duration you want.
For example, to play a sound named gameMusic
and make it fade out (from volume of 1 to volume of 0):
2000
represents the duration in milliseconds for the fade (1000 ms = 1 second). Change this value to whatever duration you want.
For example, to play a sound named gameMusic
and make it fade from its currently set volume to a new volume:
2000
represents the duration in milliseconds for the fade (1000 ms = 1 second). Change this value to whatever duration you want.
0.2
represents the new volume to fade to, which can be a value between 0 to 1 (with 1 being the file's maximum volume).
The game world contains all of your game objects. Your game world can extend beyond the , and the can follow the player's sprite as it moves through your game world.
Set Size of Game World
Positions of Objects in Game World
Change Anchor for Object's Position
Get Current Position of Object
Change Position of Object
Layering of Objects in Game World
Change Order of Object's Layer
Get Center Position of Game World
Get Random Position in Game World
Get Boundaries of Game World
Make Sprite Wrap Around World
By default, Phaser will set your game world to be the same size as your game display. However, you can set the boundaries of your game world to be larger than your game display.
This Phaser command should be placed near the beginning of your create()
function.
The first two numbers 0, 0
represent (in order) the x
and y
coordinates of the top-left corner of your game world. Typically, you'll use 0, 0
for your top-left corner.
The next two numbers 3000, 600
represent (in order) the width and height (in pixels) of your game world. Change these to any values that you want (as long as they are equal to or greater than the size of your game display).
Side-Scrolling Game: Make the width of the game world larger than the width of the game display. Keep the height of the game world the same as the height of the game display.
Vertically-Scrolling Game: Keep the width of the game world the same as the width of the game display. Make the height of the game world larger than the height of the game display.
Top-Down Scrolling Game: Make both the width and height of the game world larger than the width and height of the game display.
Every display object (images, sprites, text, etc.) in the game world has a position defined by its x
and y
coordinates: x, y
The x
and y
coordinates represent pixel positions, relative to the top-left corner of the game world (which is 0, 0
).
The x
coordinates start at 0
(left boundary) and increase as you move from left to right.
The y
coordinates start at 0
(top boundary) and increase as you move from top to bottom.
For example, an object placed at coordinates 250, 100
will be positioned 250 pixels to the right and 100 pixels down, relative to the top-left corner.
The x
and y
coordinates of a display object (image, sprite, text, etc.) represent the position of the object's anchor.
By default, an object's anchor is its top-left corner. However, you can change the anchor for an object (e.g., to make the object's center become its anchor for positioning).
For example, to change the anchor of a sprite named player
:
The first number represents the horizontal position of the anchor, as a number between 0-1 (0 = left edge, 0.5 = horizontal center, 1 = right edge).
The second number represents the vertical position of the anchor, as a number between 0-1 (0 = top edge, 0.5 = vertical center, 1 = bottom edge).
For some objects, it will make sense to leave the anchor as the object's top-left corner (the default).
For other objects (especially sprites), it will make more sense to set an object's anchor to its center (0.5, 0.5)
.
For certain objects, it might even make sense to set the object's anchor to its top-middle (0.5, 0)
or its bottom-middle (0.5, 1)
.
The current x
and y
coordinates of an object's position (based on its anchor) are stored as properties of the object.
For example, to get the current position of a sprite named player
:
player.x
represents its current x
coordinate
player.y
represents its current y
coordinate
You can also set or modify the x
and/or y
coordinates of an object to change its position in the game world.
For example, you could change the position of a sprite named enemy
by assigning it specific x
and y
coordinates:
As another example, you could move a sprite named player
relative to its current position:
In the example above, the player
sprite would be moved 5 pixels to the right and 5 pixels up from its current position.
Increasing the x
coordinate moves an object to the right, while decreasing x
moves the object to the left.
Increasing the y
coordinate moves an object down, while decreasing y
moves the object up.
IMPORTANT: The order in which game objects are added in the create()
function determines the stacking of these layers in the game world.
So if you have an image that is supposed to be a background for your game, that image should be added first in the create()
function, so it will be the farthest back layer. Each new display object (image, sprite, text, etc.) that is added in the code will appear in front of the previous layers.
For example, if you added the player's sprite first and then added the background image, the player's sprite would be hidden behind the background. To fix this, change the order of the code, so the background image is added first and then the player's sprite is added.
TIP: You can use the layering of the game objects to help create a sense of depth within your otherwise flat 2D game world. For example, if your game takes place in a forest, you could add images of trees in the background, then add the player's sprite, and then add more trees in the foreground. As the player's sprite moves through the game world, it will pass in front of the background trees but behind the foreground trees — giving the illusion of depth within your virtual forest.
Your Phaser game maintains a display list of the stacking order of every object in your game world. If necessary, you can modify the relative order of an object's layer within this list.
For example, the following could be used to modify the stacking order of a sprite named enemy
:
enemy.moveDown();
would move this sprite farther back by one layer
enemy.moveUp();
would move this sprite closer to the front by one layer
enemy.sendToBack();
would make this sprite the farthest back layer
enemy.bringToTop();
would make this sprite the closest layer
game.world.centerX
is the center x
coordinate
game.world.centerY
is the center y
coordinate
game.world.randomX
is a random x
coordinate (will be different every time you use it)
game.world.randomY
is a random y
coordinate (will be different every time you use it)
game.world.left
is the left x
boundary (typically equals 0
)
game.world.right
is the right x
boundary (typically equals width of game world)
game.world.top
is the top y
boundary (typically equals 0
)
game.world.bottom
is the bottom y
boundary (typically equals height of game world)
You can make a sprite (or a member of a sprite group) wrap around to the opposite side of world if it moves outside of the game world boundaries.
For example, if the sprite moves out of the world across the right boundary, the sprite will reappear at the left boundary of the world (and vice versa). The same is true for the top and bottom boundaries.
This feature is typically used for single-screen games. For example, in Asteroids, the asteroids and the player's ship wrap around the world. However, this feature can be used for any size of game world.
To make an individual sprite wrap around the world:
The code example above must be placed in the update()
function (otherwise, it will not work).
player
represents the sprite's variable name. Change this to the name of your sprite.
32
represents the amount of padding (in pixels) to allow before wrapping the sprite. In this case, the sprite can move 32 pixels outside of the world before the sprite will be wrapped around to the other side. Change this to any value you want (including 0 for no padding).
The advantage of using padding is that it can prevent the sprite from appearing to be visually split — i.e., part of the sprite shown on one side of the world and the rest of the sprite shown on the opposite side of the world.
To prevent this visual split, use a padding value that is at least half the width or height of the sprite (whichever is greater).
To make each member of a sprite group wrap around the world:
Again, the code example above must be placed in the update()
function (otherwise, it will not work).
asteroidGroup
represents the group's variable name. Change this to the name of your sprite group.
asteroid
is a local variable used in the function to represent an individual member of the group. Change this to any local variable name that makes sense.
20
represents the amount of padding to allow before wrapping the sprite. Change this to any value you need.
If you only want the sprite to wrap around the world horizontally between left and right (but not between top and bottom):
If you only want the sprite to wrap around the world vertically between top and bottom (but not between left and right):
You can add images to help create your game world (backgrounds, etc.) or as part of your game's user interface (icons, etc.). Phaser handles each image as a display object with properties and methods that allow you to modify the image in various ways.
Load Image
Add Image
Change Anchor for Image Position
Change Image Position
Make Image Stay Fixed to Camera View
Hide Image (and Unhide)
Rotate Image to Angle
Scale Image (or Flip Image)
Crop Image Using Rectangle
Tint Image Using Color
Each image file (also referred to as an asset) must be loaded into the game's memory before you can add it to your game world.
The command to load an asset is always placed in your preload()
function.
'logo'
represents an asset key — a key is sort of like a variable name. You decide what string to use for the key, as long as each image asset has a unique key.
'assets/images/game-logo.png'
represents the folder path and filename of the image to load. Change this to match your specific folder path and filename.
Once an image asset has been loaded into memory, you can add the image to your game world.
If you have an image that simply needs to placed at a specific position and won't be modified in any way, you can add the image directly (without assigning it to a variable):
The command to add an image is typically placed in the create()
function:
0, 0
represent the x
and y
coordinates where the image will be positioned in the game world (based on the image's anchor, which is its top-left corner by default). Change these values to the position you need.
'background'
represents the asset key of the image to use. Replace this with your asset key.
However, if you will need to modify the image (change image property, rotate image, etc.), then you need to declare a variable and assign the image to the variable:
gameTitle
represents a variable name. Change this to the name of your variable.
If you only need to modify the image within the create()
function, you can assign the text object to a local variable.
Otherwise, if you need to modify the image in the update()
function or a custom function, then assign the image to a global variable.
The x
and y
coordinates of a display object (text, image, sprite, etc.) represent the position of the object's anchor.
By default, an object's anchor is its top-left corner. However, you can change the anchor for an object (e.g., to make the object's center become its anchor for positioning).
For example, to change the anchor of a image named gameTitle
:
The first number represents the horizontal position of the anchor, as a number between 0-1 (0 = left edge, 0.5 = horizontal center, 1 = right edge).
The second number represents the vertical position of the anchor, as a number between 0-1 (0 = top edge, 0.5 = vertical center, 1 = bottom edge).
For most images, it will be fine to leave the anchor as the top-left corner (the default).
However, for some images, it may make more sense to set its anchor to its center (0.5, 0.5)
— or possibly to its top-middle (0.5, 0)
or bottom-middle (0.5, 1)
.
If you need to change the position of an image, just change its x
and/or y
coordinates.
For example, you could change the position of a image named gameTitle
:
You can make an image stay fixed within the game camera view, so the image won't move when the game world scrolls.
Phaser display objects (such as images, text, sprites, etc.) have a property called fixedToCamera
. By default, this property is set to false
— changing this value to true
will make the object stay fixed to the camera view.
For example, you can make an image named gameTitle
stay fixed to the camera view:
You can hide (or unhide) an image by changing its visible
property.
For example, to hide an image named gameOverPic
:
To show the image, just unhide it:
You can rotate an image (around its anchor point) by changing the value of its angle
property.
For example, you could rotate an image named gameTitle
:
-10
represents the angle in degrees. Change this to any value from -180 to 180. Negative values rotate the image counterclockwise. Positive values rotate the image clockwise.
Phaser also has a property called rotation
that can be used to get or set the angle of rotation of an image. The only difference is that the rotation
property uses radians for its units, instead of degrees (2π radians = 360°).
You can make an image larger or smaller by changing its scale
property. You can also use this property to flip the image (forming a mirror image).
For example, you could scale an image named gameTitle
:
The first number represents the horizontal scale, which affects the image's width. Change this to the value you need for scaling.
The second number represents the vertical scale, which affects the image's height. Change this to the value you need for scaling.
Each direction (horizontal or vertical) can be scaled using the same value (which keeps the same image proportions) — or can be scaled using different values (which changes the proportions).
A scale value less than 1 will make the image smaller in that direction. For example, a value of 0.5 would make the image half of its original size.
A scale value of exactly 1 will keep the image its original size in that direction.
A scale value greater than 1 will make the image larger in that direction. For example, a value of 2 would make the image twice its original size.
Using a negative scale value will flip the image in that direction (forming mirror image). For example, a value of -1 will keep the image its original size but flip it.
You can apply a rectangular crop to an image. Any portion of the image outside the crop rectangle will be hidden from view. The crop is a reversible visual effect — you can change the crop or removed it if desired.
The first line of code creates a rectangle and assigns it to a variable named livesCrop
. Change the variable name for your rectangle.
0, 0
represent the x and y coordinates of the top-left corner of the crop rectangle (relative to the top-left corner of the image that it will crop). Change these values based on where you need to position your crop rectangle on the image.
75, 25
represent the width and height (in pixels) of the crop rectangle. Change these values based on how much of the image you need to show.
The second line of code applies the crop rectangle to an image named livesBar
. Change the names to match the your image and crop rectangle.
If needed, you can change the size and/or position of your crop rectangle and then update to show the new cropped image.
If you need to change the size of the crop rectangle, change the width and/or height of the rectangle.
If you need to change the position of the top-left corner of the crop rectangle, change the x
and/or y
position of the rectangle. (NOTE: This changes what part of the original image is shown, but the cropped image will still be positioned at the same location in the game world.)
Once you've changed the value(s) for your crop rectangle, update the crop.
Unfortunately, there isn't a built-in method to directly "uncrop" an image once it has been cropped. Instead, the solution is to make the crop rectangle the same size as the original image and then apply this full-sized crop (which will show the entire image).
You can tint an image using a specific color. For example, if you have a background of a light blue sky ("daytime"), you could tint it a reddish color to represent sunrise or sunset — or tint it a dark color to represent nighttime.
For example, to tint an image named sky
:
The tint color is added as a semi-transparent layer on top of the image, so the tint color will visually mix with the colors in the image.
For example, adding a yellow tint on top of a blue image will actually make the image look green (yellow + blue = green).
So you may need to try different tint colors to achieve your desired result (and it may not be possible to get the exact result you want, depending on the original colors of the image).
To remove the tint color and restore the image to its original appearance, change the tint color to 0xffffff
(white represents no tint):
The members will be created as , so be sure to load the image or spritesheet asset for the members in the preload()
function. Each member of a group can use the same asset, or you can use different assets for different members in a group.
'body.immovable'
represents the name of the property to change. The name should be listed within quotes. Group members are sprites, so list the name of the specific you want to change.
This code creates a local variable named coinData
which is an array containing for the members of a group.
If you want to check for dead members to recycle based on a timed interval (such as every 10 seconds), then to your game to do this.
Here's an . In the example, as you move the player (using the arrow keys) through the trees, the player's "depth" relative to specific trees will change.
Every display object (images, sprites, text, etc.) is added to the game world as a layer (using the property). These object layers are stacked on top of each other, meaning they can overlap (and hide) other objects behind them.
0xff66cc
is a code for the color. Change this to your own color by listing 0x
followed by a .
You can use Arcade Physics to add a particle emitter that can release particles for visual effects. Particle emitters can be used for one-time effects (such as explosions, etc.) or continuous effects (such as rain, snow, etc.).
The "particle emitter" is really just a group of "particles" ready to be emitted (similar to how a Phaser weapon is just a group of bullet objects). The particles can be emitted from a single point or from an extended area.
By default, particles are emitted in random directions with slightly different speeds and rotations. As the particles fan out, they are pulled downward by gravity until they are removed after two seconds. However, you can customize the emitter to change how the particles are emitted (speed, rotation, gravity, lifespan, etc.).
Load Image or Spritesheet for Particles
Add Emitter
Add Particles to Emitter
Set Particle Emitter Properties
Change Emitter Position
Set Emitter Size
Make Emitter Stay Fixed to Camera
Set Particle Speed
Set Particle Rotation
Set Particle Gravity
Set Particle Lifespan
Set Particle Transparency (Fade In or Out)
Set Particle Scale (Change Size)
Emit Single Particle
Emit One-Time Burst of Particles
Emit Continuous Flow of Particles
Make Particles Collide
The particles for a particle emitter can use an image or a spritesheet (e.g., for animated particles).
The image or spritesheet file for your particles must be loaded into the game's memory before you can add the particle emitter to your game.
The command to load an asset is always placed in your preload()
function.
'particle'
represents an asset key — a key is sort of like a variable name. You decide what string to use for the key, as long as each image asset has a unique key.
'assets/images/asteroid-piece.png'
represents the folder path and filename of the image to load. Change this to match your specific folder path and filename.
Once the asset for the particles has been loaded into memory, you can add the particle emitter to your game.
You will need to declare a global variable for the particle emitter and assign the particle emitter to the variable in your create()
function.
For example, to add a particle emitter to a variable named asteroidEmitter
:
0, 0
represent the center x
and y
position where the particles will be emitted from. For one-time effects (such as explosions, etc.), you will typically change the position later during gameplay. For continuous effects (such as rain, etc.), you might already know the specific position to use. Later, you can also change the size of the emitter to release particles from an extended area (useful for effects like rain, etc.). If necessary, change this position for your game.
50
represents the number of particles for this particle emitter. Particles are automatically recycled as they are emitted and removed, so this represents the maximum number that could be on-screen in the game at any one time. Change this number to what you need.
Even if the emitter is only intended for one-time bursts of particles, you may need to create enough particles for multiple bursts being on-screen at the same time, depending on on how frequently the bursts may occur.
As another example, to add a rainEmitter
that will be positioned at the top-center of the game display (and have 400 "rain" particles):
NOTE: There is no visual indication that a particle emitter has been added to the game — until you instruct it to release particles.
Once the particle emitter has been added, you need to actually add the particles to the emitter by using the image or spritesheet asset for the particles.
For example, to add the particles to the asteroidEmitter
emitter:
'particle'
is the asset key for the particles. Change this to match your asset key name.
NOTE: There is no visual indication that the particles have been added to the emitter — until you instruct it to release particles.
This sub-section describes the most common particle emitter properties that you might change in your game.
These particle emitter properties are typically set in your create()
function after adding the particle emitter. However, sometimes certain properties are adjusted during gameplay (such as position, etc.).
You can change the emitter position during gameplay by setting new values for the emitter's x
and y
coordinates. This can be done in the update()
function or in a custom function.
Changing the position of an emitter is typically done when the emitter is used for one-time bursts of particles (e.g., creating a particle explosion when an object is destroyed, etc.).
For example, to set the emitter to a specific position using numbers:
You can also set the emitter position by referencing the position of another object, such as a sprite.
For example, an emitter named asteroidEmitter
is used to create a one-time burst of asteroid particles whenever a specific asteroid
is destroyed. The emitter is set to the asteroid's position before removing the asteroid and creating the particle explosion:
By default, a particle emitter will emit particles from a single point defined by its x
and y
coordinates.
However, you can set the size of the emitter to emit particles from an extended area. For example, you could emit "rain" particles from across the entire width of the game display.
To set the size of the emitter, just specify values for its width and height (in pixels).
For example, to set rainEmitter
to the width of the game display (but a height of just 1 pixel):
If you have an extended game world, you can make the particle emitter stay fixed to the camera view. This is typically done for emitters that produce continuous weather effects (rain, snow, etc.).
First, set the emitter's fixedToCamera
property to true
. Next, set the center x
position of the emitter using the cameraOffset.x
property.
NOTE: For some reason, the original emitter.x
center position gets set to 0
when emitter.fixedToCamera
is set to true
. Setting cameraOffset.x
seems to be the only way to shift the emitter position. If needed, you can also set a value for cameraOffset.y
.
For example, to set rainEmitter
to be fixed to the camera and centered horizontally within the game display (assume that its y
value was set to 0
when the emitter was added):
By default, particles are emitted outward at random speeds (though relatively slow) and random directions. If needed, you can specify a range of speeds for the x
direction and/or y
direction. Each particle will receive a random speed within your specified range.
This can be used not only to change how fast or slow the particles move — but also which direction they move (e.g., you could make "rain" particles only move downward, etc.)
To set a range of speeds for the x
direction (horizontal), provide values for the minimum and maximum values (in pixels per second):
min
and max
can be any values you want. Negative values for the x
speed make particles move to the left, and positive values make particles move to the right.
To set a range of speeds for the y
direction (vertical), provide values for the the minimum and maximum values (in pixels per second): :
min
and max
can be any values you want. Negative values for the y
speed make particles move upwards, and positive values make particles move downwards.
For example, here are particle speed ranges for a rainEmitter
:
The x
speed range has been set to allow the rain particles to move left (negative) or right (positive) but only at a very slow speed (5 or less).
The y
speed range has been set to only allow the rain particles to move down (positive values) but at fairly fast speed (between 300-500 pixels per second).
By default, particles are emitted with a slow random rotation speed (angular velocity). If needed, you can specify a range for the angular velocity that controls the rotation. Each particle will receive a random rotation speed within your specified range. You can also turn off the rotation if desired.
To set a range of speeds for the rotation (angular velocity), provide values for the the minimum and maximum values (in degrees per second):
min
and max
can be any values you want. Negative values for rotation make particles rotate counter-clockwise, and positive values make particles rotate clockwise.
For certain particle emitters, you may not want the particles to rotate. For example, you may want "rain" particles to simply fall down without rotating.
To prevent particles from rotating, set the rotation range to zero:
By default, particles have a small amount of gravity in the vertical direction that pulls them downward. If desired, you can change the gravity values for the x
and/or y
directions. You can also turn off the particle's gravity.
This can be used make the particles respond more realistically to your game's simulated environment — but it also could be used as another way (besides particle speed range) to direct particles (e.g., by pulling them in a specific direction).
For certain games (e.g., game using top-down perspective, game set in outer space, etc.), you might not want the particles to be affected by gravity.
By default, the emitter's gravity.x
value is set to 0
(no gravity).
To set a different gravity value for the x
direction (horizontal), provide a value (in pixels per second squared):
50
represents the gravity value (in pixels per second squared). Change this to the value you need for your particle effect. Negative values for gravity.x
pull particles to the left, and positive values pull particles to the right.
By default, the emitter's gravity.x
value is set to 100
.
To set a different gravity value for the y
direction (vertical), provide a value (in pixels per second squared):
200
represents the gravity value (in pixels per second squared). Change this to the value you need for your particle effect. Negative values for gravity.y
pull particles upwards, and positive values pull particles downwards.
To turn off the gravity effect for particles, just set both gravity values to zero:
By default, each particle will be automatically removed 2 seconds after being emitted. However, you can change the particle lifespan.
NOTE: You will typically set the particle lifespan when using the explode()
or flow()
methods to emit particles. So you don't necessarily need to directly set the lifespan
property unless necessary for other reasons.
To set the particle lifespan:
1000
represents the lifespan (in milliseconds) of each particle (1000 ms = 1 second). Change this to the duration you want.
If desired, you can change the transparency of a particle by changing its alpha value. You can make a particle semi-transparent by lowering its alpha value. You can also change the alpha value of each particle over time to make the particles fade in or fade out.
For example, "smoke" particles for an explosion would look more realistic if they were semi-transparent and faded out over time.
By default, particles have an alpha value of 1 (no transparency applied).
However, you can set your own range for the particle transparency by setting the minimum and maximum alpha values for the particles. Each particle will receive a random alpha value within your specified range.
For example, to set the alpha range for a smokeEmitter
:
Change the values to whatever you need:
An alpha value of 0 is completely transparent.
Alpha values between 0-1 are semi-transparent. Lower numbers are more transparent.
An alpha value of 1 has no transparency applied.
If desired, you can make each particle fade in or out over a specified amount of time.
To do this, you specify the starting and ending alpha values, as well as the amount of time over which the change in transparency should occur.
startAlpha
represents the starting alpha value for each particle. Use whatever number you want.
endAlpha
represents the ending alpha value for each particle. Use whatever number you want, but it should be different from the starting value. Use a larger value to make the particles become less transparent (fade in), or use a smaller value to make the particles more transparent (fade out).
duration
represents the amount of time (in milliseconds) over which each particle will fade (1000 ms = 1 second). Change this to the duration you want.
A "fade in" will typically change the alpha from 0 to 1. It could start or end at other values, as long as the ending value is higher.
A "fade out" will typically change the alpha from 1 to 0. It could start or end at other values, as long as the ending value is lower.
For example, to make "rain" particles fade in over time
For example, to make "smoke" particles fade out over time:
For example, to make "smoke" particles fade in and then fade out:
By default, all the particles will be displayed at actual size (the size of your particle's image or spritesheet frame). If desired, you can set a range to scale the particles, so they vary in size. Alternatively, you can make the particles change in size over a specified duration.
You can set a range for the particle sizes by setting the minimum and maximum scales for the particles. Each particle will receive a random scale within your specified range.
For example, to set the scale range for the asteroidEmitter
:
Change the values to whatever you need:
A scale value less than 1 will make the particle smaller. For example, a value of 0.5 would make the particle half of its original size.
A scale value of exactly 1 will keep the particle its original size.
A scale value greater than 1 will make the particle larger. For example, a value of 2 would make the particle twice its original size.
If desired, you can make each particle change in size over a specified amount of time.
To do this, you specify the starting and ending scale values for the x
direction and the y
direction. (To avoid distorting your particle images, use the same values for both x
and y
.) Then specify the amount of time over which the change in size should occur.
startX
represents the starting scale value in the x
direction (horizontal). Use whatever number you want.
endX
represents the ending scale value in the x
direction (horizontal). Use whatever number you want, but it should be different from the starting value. Use a larger value to make the particles grow larger, or use a smaller value to make the particles get smaller.
startY
represents the starting scale value in the y
direction (vertical). It is recommended to use the same value as you did for startX
.
endY
represents the ending scale value in the y
direction (vertical). It is recommended to use the same value as you did for endX
.
duration
represents the amount of time (in milliseconds) over which each particle will change in size (1000 ms = 1 second). Change this to the duration you want.
For example, to make "rain" particles grow in size over time
For example, to make "asteroid" particles shrink in size over time:
For example, to make "smoke" particles grow larger and then shrink:
If needed, you can emit a single particle from the emitter:
The explode()
method is used to emit a one-time burst of particles from the emitter. You can either emit all the particles or a certain quantity. This is commonly used to create an explosion effect.
The explode()
method is typically placed in the update()
function or in a custom function to start the particle burst when needed.
For example, to emit a one-time burst of particles from an emitter named asteroidEmitter
:
1000
represents the lifespan (in milliseconds) of each particle (1000 ms = 1 second). Change this to the duration you want.
5
represents the number of particles to emit. Change this to the quantity you want. (If you want to emit all the particles, then just leave out this number).
The flow()
method is used to emit a continuous flow of particles from the emitter at specified time intervals.
You can make the flow emit one particle at a time — or multiple particles each time. You can allow the flow to run forever — or have it stop after a certain number of particles have been released. You can also stop the flow manually if needed.
For particle emitters being used for weather effects (such as rain, etc.), the flow()
method is typically placed in the create()
method, so that the particle flow will be running at the start of the game.
However, you can also use the flow()
method in your update()
function or in a custom function to start or stop the particle flow when needed.
To continuously emit one particle at specified intervals:
1500
represents the lifespan (in milliseconds) of each particle (1000 ms = 1 second). Change this to the duration you want.
25
represents the time interval (in milliseconds) between each release of a particle (1000 ms = 1 second). Change this to the interval you want.
To continuously emit multiple particles at specified intervals:
1500
represents the lifespan (in milliseconds) of each particle (1000 ms = 1 second). Change this to the duration you want.
25
represents the time interval (in milliseconds) between each release of a particle (1000 ms = 1 second). Change this to the interval you want.
5
represents the quantity of particles to release at each interval. Change this to the quantity you want.
To have the emitter stop flowing after a certain number of particles have been released:
1500
represents the lifespan (in milliseconds) of each particle (1000 ms = 1 second). Change this to the duration you want.
25
represents the time interval (in milliseconds) between each release of a particle (1000 ms = 1 second). Change this to the interval you want.
5
represents the quantity of particles to release at each interval. Change this to the quantity you want.
2000
represents the total number of particles to release before stopping. Change this to the total you want.
You can also manually stop the flow from an emitter by using:
This makes the emitter release one last particle and then turn off automatically. If necessary, you can always turn the emitter back on again using a different flow()
command.
By default, particles do not collide with each other or with other sprites. However, if you want, you can make them collide. The particle emitter acts like a group of sprites, so just use the variable name for the particle emitter in collide()
methods to make the individual particles collide with each other and/or with other sprites (or groups).
See the Physics and Collisions reference section for more details on the collide()
method.
You can use any keys on the keyboard as inputs for player actions. You can also use mouse or touch input for your game. Phaser even has support for gamepads.
Phaser treats touch input as a pointer — i.e., similar to a mouse (the position of the touch is treated like the position of a mouse cursor, a tap is treated like a mouse click, a double-tap is treated like a double-click, etc.).
Phaser does not have built-in properties or methods to directly detect touch gestures such as: swipe left, swipe right, pinch to zoom, rotate, etc. However, Phaser allows you to have up to 10 "pointer" inputs (i.e., for up to ten fingers), and Phaser Pointer objects do have certain properties and methods that can be used to indirectly detect certain touch gestures (such as: swipe direction, etc.).
NOTE: This reference section focuses on keyboard and mouse input — and will not cover details for gamepads or complex touch input (beyond position or taps).
Add Arrow Keys as Inputs
Add Specific Key as Input
Check If Key Currently Pressed (or Not)
Check If Key Just Pressed (or Just Released)
Check Multiple Properties for Same Key
Check If Multiple Keys Pressed at Same Time
Get Duration of Key Press
Get Current Position of Pointer (Mouse or Touch)
Check If Pointer Is Down (Click or Tap)
Check Left and Right Mouse Buttons Separately
Check for Double Click (or Double Tap)
Check Duration Pointer Was Held Down
In addition, the Physics and Collisions section has coding references for physics methods that involve the Pointer (mouse or touch):
Move Sprite Towards Pointer
Find Distance from Sprite to Pointer
Find Angle from Sprite to Pointer
Since it is common for games to use the arrow keys for input, Phaser has a command to add all four arrow keys as inputs (rather than having to add them individually).
Phaser refers to the arrow keys as cursor keys (since many computer programs use the arrow keys to move the cursor).
Add this command in your create()
function to add the arrow keys as inputs assigned to a global variable named arrowKey
:
This command will make all 4 arrow keys (left, right, up, down) into inputs assigned to the arrowKey
variable. The individual keys are identified using the properties left
, right
, up
, and down
as follows:
arrowKey.left
arrowKey.right
arrowKey.up
arrowKey.down
Even though this command will add all 4 arrow keys as potential inputs, your game doesn't necessarily have to actually use all of them. Your game might only check 2 or 3 of the arrow keys for actual input.
You can add an individual key as input by referencing its Phaser key code.
For example, add this command in your create()
function to add the spacebar key as an input assigned to a global variable named fireKey
:
SPACEBAR
represents a specific Phaser key code. Change this key code to match the specific key you need.
Phaser key codes are listed in UPPERCASE:
For letter keys, the keycode is simply the letter (such as: A, B, C, etc.).
For number keys, the keycode is the name of the number (such as: ONE, TWO, THREE, etc.).
For arrow keys (if you wanted to add one or more individually), the keycode is the name of its direction (such as: LEFT, RIGHT, UP, DOWN)
For other keys, the keycode is a name or description (such as: SPACEBAR, ENTER, SHIFT, TAB, CONTROL, etc.).
Here is a complete list of all the available Phaser key codes.
Phaser has several properties for detecting input on keys. JavaScript if-else conditional statements are used to check these input properties to see whether they are true
or false
.
Keys have two properties that can be used to detect whether or not a specific key is currently being pressed by the player:
isDown
will be true
if the key is currently pressed down — this property will remain true as long as the player continues to hold the key down
isUp
will be true
if the key is currently up (i.e., not being pressed) — this property will remain true as long as the player doesn't press the key
At any given moment, a key is either being pressed or it's not. So one of these two properties has to be true
(and the other property has to be false
). For example, if the key is being pressed, isDown
is true
(which means that isUp
has to be false
).
TIP: The isDown
property is the most commonly-used way to detect input on a key.
For example, here's code that checks for input on global variables named arrowKey
and spacebar
:
This code would be placed in the update()
function (or in a custom function that is called by the update()
function every game loop).
Notice that an if-else statement is used to check input on both the right and left arrow keys. This is done because these particular keys are supposed to be mutually exclusive — the game can't move the player both left and right at the exact same time, so else
is used to help detect three possible conditions: 1. the player is pressing the right arrow key 2. else the player is pressing the left arrow key 3. else the player is not pressing either of them
In the event that the player is actually pressing the right and left arrow keys at the same time (which will probably happen at some point during gameplay), the game will act as if the player were only pressing the right arrow key. This is because the if-else statement first checks for input on the right arrow key (and will skip checking the other conditions once a true
condition is detected).
Notice that a separate if
statement is used to check input on the spacebar. By checking this key with its own if
statement, the game allows the player to press the spacebar at the same time as one of the arrow keys.
Also notice that we didn't include an else
statement for the spacebar — though you could if you needed to for your game.
If you have other keys to check, you would add more if
statements to separately check the input on each key.
If different keys are supposed to be mutually exclusive (i.e., do opposite things) in your game, then you would combine their input checks into the same if-else statement.
In some games, you may want to detect exactly when the player first presses a specific key — or when the player first releases the key that was being pressed.
Remember that your core gameplay occurs in your update()
function, which loops many times per second. Phaser can detect the exact game loop during which a key was first pressed (or first released) by the player.
Keys have two properties that can be used to detect whether the key was just pressed or just released in the current game loop:
justDown
will be true
if the key was just pressed down during the current game loop (so you can detect exactly when the key is pressed down) — this property is only true during the specific game loop when the key is first pressed down — after that loop, it becomes false, even if the player keeps pressing the key
justUp
will be true
if the key was just released during the current game loop (so you can detect exactly when the key is released) — this property is only true during the specific game loop when the key is first released — after that loop, it becomes false, even if the player still isn't pressing the key
For example, here is code to check input on a global variable named spacebar
:
This code would be placed in the update()
function (or in a custom function that is called by the update()
function every game loop).
What would be the difference between checking spacebar.isDown
versus spacebar.justDown
?
For example, let's say that the spacebar is used by the player to fire a weapon:
If your game checks for spacebar.isDown
, the player can simply hold down the spacebar to keep firing the weapon continuously (limited only by the weapon's fire rate).
If your game checks for spacebar.justDown
, the weapon will only fire one time if the player holds down the spacebar. In order to fire the weapon again, the player will have to release the spacebar and press it again.
Either input option is perfectly fine — it simply depends on what kind of input style you want your game to use.
You can also check multiple properties for the same key as part of an if-else statement to do different things based on whether the key was just pressed — versus the key is still being pressed — versus the key was just released — versus the key is still up:
This code would be placed in the update()
function (or in a custom function that is called by the update()
function every game loop).
You don't necessarily have to check all 4 properties for the same key. However, if you are checking multiple properties (2 or more) for the same key, then list them in the order shown above (otherwise, your game logic may not work as you expect) — just remove the property check that you don't need.
If necessary for your game, you can also check whether the player is pressing multiple keys at the same time. For example, maybe your game requires a special combination of keys to be pressed for certain actions to occur.
An if statement can check for multiple keys being pressed together simply by combining multiple conditions using the &&
logical operator (which represents AND).
For example, imagine your game has a power boost feature that allows the player to run at a faster speed when the boostKey
is pressed at the same time as an arrowKey
. The code for checking the player input related to movement might look like this:
This code would be placed in the update()
function (or in a custom function that is called by the update()
function every game loop).
Once a key has been released, you can use the duration
property to get the amount of time (in milliseconds) that the key was held down before being released.
This might be useful for a game where the force or magnitude of a player's action depends on how long a key was held down.
If your game needs to check a key's duration
property, then you would only want to do this after you first detect that the key was just released.
For example, add this code in your update()
function (or in a custom function that is called by the update()
function every game loop):
Inside the if
statement, the value of spacebar.duration
will be the amount of time (in milliseconds) that the spacebar
key was held down before being released. (Reminder: 1000 ms = 1 second)
You can get the current position of the pointer (mouse or touch) using:
game.input.activePointer.x
game.input.activePointer.y
Use these positions to do something in your update()
function or in a custom function.
You can check for a mouse click or touch event (tap) using the isDown
property (similar to checking for a key being pressed):
For example, add this code in your update()
function (or in a custom function that is called by the update()
function every game loop):
If your game will only use the left button of the mouse, then just use the code in the previous section to check if the pointer is down.
However, if your game will use both the left and right buttons on the mouse for different actions, then you can check them separately:
This code would be placed in the update()
function (or in a custom function that is called by the update()
function every game loop).
You can check for a double-click (mouse) or double-tap (touch) by adding an onTap
signal that will call a custom function whenever a tap (or click) occurs. The custom function will be able to detect whether it was a double tap or single tap.
First, add this command to your create()
function:
Whenever a tap (or click) occurs during the game, a custom function named checkTap
will be run. (If desired, you can change the name of the custom function.)
Next, add the custom function after your update()
function:
You can check the duration that the pointer (mouse or touch) was held down by adding an onUp
signal that will call a custom function whenever the pointer is released. The custom function will be able to use the duration
property to get the amount of time (in milliseconds) that the pointer was held down before being released.
This might be useful for a game where the force or magnitude of a player's action depends on how long the pointer was held down.
First, add this command to your create()
function:
Whenever the pointer is released up, a custom function named checkDuration
will be run. (If desired, you can change the name of the custom function.)
Next, add the custom function after your update()
function:
Inside the custom function, the value of pointer.duration
will be the amount of time (in milliseconds) that the pointer was held down (clicked or tapped) before being released. (Reminder: 1000 ms = 1 second)
You can use Phaser code to develop enemy behaviors that will give the enemies "artificial intelligence", so they respond appropriately to certain conditions or events during gameplay. Many games actually use very simple rules to create enemy behaviors that seem "intelligent" to the player.
A very simple (but still useful) model of behavior is: STIMULUS → RESPONSE
You should decide on a set of a few simple rules that will guide how your enemies should behave. As necessary, restate each rule as a more specific "stimulus-response" statement (which will act like pseudocode). What are the specific conditions (stimulus) that will lead to a specific enemy behavior (response)? The final step is try to translate this into actual code. Hint: Phaser Arcade Physics has properties and methods that are useful when coding enemy behaviors.
Here's an example of how to translate a general rule for enemy behavior into "stimulus-response" pseudocode and then into Phaser code:
Rule for Enemy Behavior
If the player gets close enough to an enemy, the enemy will follow the player.
Restated as "Stimulus-Response" Pseudocode
If the enemy and the player are within a certain distance of each other AND the enemy is moving away from the player (or the enemy is not currently moving), make the enemy move towards the player.
Translated into Possible Phaser Code
This reference section will supply some examples of common enemy behaviors used in games. However, you may be able to develop other behaviors using your own code (or by finding other code examples elsewhere online).
Make Enemies Bounce Off Obstacles, Each Other, or the Player
Make Enemies Patrol Back and Forth on Platforms
Make Enemies Patrol Back and Forth using Step Counter
Make Enemies Move Towards Player
Make Enemies Fire Weapon at Player
You can make enemies bounce off obstacles, each other, and/or the player. To do this, you need to set the bounce
property for the enemies, and then check for collisions (or overlap) between the enemies and the other sprites.
For example, if the enemies move horizontally (left or right), then set their body.bounce.x
property to a value of 1
when adding each enemy in your create()
function:
Using a value of 1
will ensure the enemy will not lose any velocity when it collides with an object and reverses direction. (If you want the enemy to slow down after each collision, then use a value less than 1.)
In your create()
function, be sure to set each member of the obstacle group to "immovable":
In your update()
function, add a collide()
method between the enemy group and the obstacle group:
In your update()
function, add a collide()
method between the members of the enemy group:
In your update()
function, add an overlap()
method between the player and the enemy group to run a custom function (called touchEnemy
in this example):
Then add the custom function after your update()
function. Inside the custom function, reverse the enemy's direction by multiplying its velocity by -1
.
You could add other code inside the custom function, such as damaging the player's health, etc.
You can make a group of enemies patrol back and forth on platforms. If an enemy is about to move off the edge of a platform, then the enemy should reverse its direction. When the enemy reaches the opposite platform edge, the enemy will reverse again — patrolling back and forth on the platform without falling off.
In order to accomplish this, you need to have your collide()
method between the enemies and platforms run a custom function (which will check whether or not each enemy needs to reverse its direction).
In your update()
function, your collide()
method might look like this:
Then you'll need to add the custom function patrolPlatform()
after your update()
function.
The custom function will check the enemy's current direction of movement (right vs. left) and also check whether the enemy has started to move over the edge of the platform (by comparing the edge positions of the enemy and platform). If the enemy is moving off the edge of the platform, the enemy's direction will be reversed (by multiplying its velocity by -1).
You can make a group of enemies patrol back and forth (whether they are on a platform or not) simply by counting the number of "steps" they take and reversing each enemy when they reach a certain number (the step limit).
Before your preload()
function, declare a global variable named stepLimit
, and assign it a value representing the number of "steps" that each enemy can take before reversing direction. Each step actually represents one game loop (as a general rule of thumb, about 50-60 game loops occur in every 1 second of game time).
When adding each enemy in your create()
function, give the enemy a starting velocity. You can either give each enemy the same velocity or give each enemy a random velocity within a specified range.
For example, this command would give each enemy a random horizontal velocity between 125 and 175 and also randomly select either a positive velocity (moving to right) or negative velocity (moving to left):
When adding each enemy, you also need to give them a new property which we'll call currentStep
. This is not a built-in Phaser property. However, you can add new properties to an existing JavaScript object (including a Phaser object) just by assigning a value to the property. If the object doesn't already have a property with this name, then JavaScript will automatically add the property to the object.
Rather than starting each enemy at a step count of zero, let's make each enemy's starting stepCount
somewhere between 0 and the stepLimit
:
Giving each enemy a random starting point for its stepCount
will help prevent the enemies from all reversing direction at the exact same moment in the game. (If you do want the enemies to move in unison with each other, instead just set them to the same stepCount
at the start.)
Then in your update()
function, you need to increase each enemy's stepCount
with each game loop (i.e., each time the update()
function runs). If an enemy reaches the stepLimit
, then reverse the enemy's direction by multiplying its velocity by -1
and reset its step counter:
You can make the enemies in your game move towards the player by detecting where the player is located relative to an enemy and then changing the direction of the enemy's movement, so the enemy will move towards the player.
Provided below are examples for a side-view game and for a top-down game.
Let's assume you have a side-view game with platforms where the enemies can move either left or right.
Let's also assume that an enemy will only change direction to move towards the player if the player is within a certain distance AND the player and enemy are possibly on the same platform (i.e., their "bottom" positions are the same).
For each enemy, you would first need to check whether its bottom position matches the player AND the player is within a specified distance. If that's true, then next you need to detect whether the player is currently located to the left or the right of the enemy (by comparing their x
positions) AND whether the enemy is moving away from the player (by checking whether its velocity is positive or negative, which tells you direction). Then when necessary, you'd change the enemy's direction to move towards the player.
Here is example code that could be included in your update()
function:
You could revise the code above however you need for your game. For example:
You could change the distance from 400 pixels to something else.
You could add other code to change the enemy animation, make the enemy fire a weapon, etc.
If you don't want to worry about the player and enemy being on the same platform (or your game doesn't have platforms), you could remove the condition that compares the bottom
positions.
If you don't want to worry about a minimum distance between the player and enemy, you could remove the condition that checks the distanceBetween()
— or you could even remove the entire outer if
statement.
If your enemies are stationary and should only start to move when the player gets close, then remove the condition that checks whether the enemy.body.velocity.x
is greater than or less than zero. (Then be sure to directly set the enemy velocity instead of multiplying it by -1.)
If your game allows enemies to move up and down, then compare the y
positions of the player and enemy, in order to decide whether the enemy should move up or down.
etc.
Let's assume you have a top-down game where the player and enemy can rotate and move in any direction (i.e., at any angle).
Let's also assume that an enemy will only change direction to move towards the player if the player is within a certain distance.
For each enemy, you would first need to check whether the player is within a specified distance. If that's true, then next you can rotate the enemy to face towards the player (but that's optional, depending on your game). Then you'd move the enemy towards the player.
Here is example code that could be included in your update()
function:
You could revise the code above however you need for your game. For example:
You could change the distance from 400 pixels to something else.
You could change the enemy velocity from 150 pixels/second to something else.
You could add other code to make the enemy fire a weapon, etc.
The enemies in a group can share a single enemy weapon, rather than needing to create a separate weapon for each enemy.
In your create()
function, add a weapon for the enemies to share, set any necessary weapon properties (such as: fireRate
, bulletSpeed
, etc.), and add a function to play a sound effect when the weapon fires:
In your update()
function, you need to select a specific enemy to use the weapon, move the weapon to that enemy's position, adjust the weapon's fire angle (if necessary), and then fire the weapon:
The code shown above is "generic" code. See below for more details on how to select an enemy, set the fire angle, etc.
You need to decide on a rule for which enemy will fire the weapon: a random enemy, the closest enemy, all enemies within a certain distance, etc. Once the specific enemy has been selected, you give the weapon to that enemy using the trackSprite()
method.
To select a random enemy from the group, and give it the weapon:
To select the closest enemy to the player, and give it the weapon:
To select an enemy within a certain distance of the player, and give it the weapon:
NOTE: If you use the forEachAlive()
function to select nearby enemies to fire the weapon, be aware that the enemy weapon's fireRate
(as well as the number of bullets in the enemy's weapon) will limit how many frequently the weapon is actually fired. The result is that even though multiple enemies might be close to the player, typically just one enemy at a time will fire the weapon (and that same enemy tends to keep firing until it is no longer close to the player).
For certain games, the enemies always fire in the same direction. For example, in Space Invaders, the aliens always fire straight down. If this is how your game works, then you can set the enemy weapon fire angle in the create()
function — and you won't need to change it during gameplay.
However, in other games, the enemies need to adjust the enemy weapon fire angle during gameplay, in order to fire at the player.
Let's assume you have a side-view game where the enemies can fire the weapon either left or right in the direction of the player. You would need to determine whether the player is currently located to the left or the right of the enemy. You could do this simply by comparing their x
positions. Then you would set the enemy weapon fire angle to the point in the direction of the player.
To make the enemy weapon fire to the left:
To make the enemy weapon fire to the right:
If needed, you can set the enemy weapon to other angles (e.g., to fire up or down, to fire at a non-perpendicular angle, etc.)
If the enemy has been rotated to face towards the player, then make the enemy weapon fire in the same direction of the enemy's angle:
Otherwise if your game does not rotate the enemy to face the player, then get the angle between the enemy and player, and make the enemy weapon fire at this angle:
If you wanted to add small margin of error to the angle (so the enemy doesn't always have perfect aim), add this extra line of code after setting the "perfect" angle (but before firing the weapon):
5
represents the maximum amount of error (in degrees). In this case, it would add a random error between -5 to +5 degrees (including the possibility of 0 degrees — i.e., no error). Change this number to the maximum amount of error you want.
You can use Arcade Physics to add a weapon to your game that fires bullets. The weapon is not represented visually by an actual weapon (such as a gun, etc.). The "weapon" is really just a group of "bullets" ready to be fired.
The "bullets" can be any visual object you want — bullets, laser beams, arrows, fireballs, snowballs, hearts, etc. It simply depends on the image or spritesheet that you use for the bullets.
When you fire a weapon, a bullet appears at the weapon's position and travels outward at an angle and speed determined by the weapon's properties (which you can set). When the bullet hits another object, you can perform specific actions (such as damaging or killing the object, etc.).
RECOMMENDATION: If you only think of a "weapon" as a literal weapon with bullets (such as a gun), you'll be overlooking interesting ways to use a Phaser weapon in your game. Think more broadly about objects that can be thrown, shot, or directed at a target.
In the game Angry Birds, the "bullets" are birds that you aim and shoot using a slingshot.
In a basketball game, the basketball is a "bullet" that is shot towards the goal. You can add gravity and rotation to make your basketball "bullet" act realistically.
Load Image or Spritesheet for Bullets
Add Weapon
Set Weapon Properties
Auto Fire
Fire Angle
Fire Rate
Fire Limit
Bullet Speed
Bullet Kill Type (Remove Bullet)
Bullet Kill Distance
Bullet Kill Lifespan
Bullet Gravity
Bullet Rotate to Match Direction
Make Weapon Track Sprite
Fire Weapon
Call Function When Weapon Fired Successfully
Check for Bullets Hitting Objects
Change Collision Area of Bullets
Display Visual Weapon
Properties and Methods for Arcade Physics Weapon
The bullets for a weapon can use an image or a spritesheet (e.g., for animated bullets).
The image or spritesheet file for your weapon's bullets must be loaded into the game's memory before you can add the weapon to your game.
The command to load an asset is always placed in your preload()
function.
'laser'
represents an asset key — a key is sort of like a variable name. You decide what string to use for the key, as long as each image asset has a unique key.
'assets/images/laser.png'
represents the folder path and filename of the image to load. Change this to match your specific folder path and filename.
Once the asset for the bullets has been loaded into memory, you can add the weapon to your game.
You will need to declare a global variable for the weapon and assign the weapon to the variable in your create()
function. Typically you will want to add the weapon before adding the sprite or group that will use the weapon (so that the weapon bullets will appear from behind the sprite using the weapon).
For example, to add a weapon to the variable named laser
:
5
represents the number of bullets to create for this weapon. Bullets are automatically recycled as they are fired and removed, so this represents the maximum number that could be on-screen in the game at any one time. Change this number to what you need.
'laser'
is the asset key for the bullets. Change this to match your asset key name.
NOTE: There is no visual indication that a weapon has been added to the game. When the weapon is fired, a bullet will appear and begin to travel — but otherwise, there is no actual "weapon" displayed.
This sub-section describes the most common weapon properties that you might use in your game.
These weapon properties are typically set in your create()
function after adding the weapon. However, sometimes certain properties are adjusted during gameplay (such as fire angle, etc.).
If you want a weapon to automatically fire itself (limited only by its fireRate
and fireLimit
), then set its autofire
property to true
.
For example, to set the laser
weapon to autofire:
If you don't set a weapon to autofire, then be sure to add an input that the player can use to manually fire the weapon.
You can use the fireAngle
property to set the angle (in degrees) at which bullets will be fired.
For example, to set the fire angle for the laser
weapon:
Change the angle to any value from -180 to 180. Negative values rotate the fire angle counterclockwise. Positive values rotate the fire angle clockwise.
Here are some commonly used values for the fire angle:
0
represents pointing right
-90
represents pointing up
180
represents pointing left
90
represents pointing down
If the sprite using the weapon will rotate during gameplay, you use the trackSprite()
method to automatically rotate the weapon's fire angle to match the sprite's rotation.
You can use the fireRate
property to set a limit on how frequently the weapon can be fired. The rate represents the minimum amount of time (in milliseconds) between fires.
For example, to set a fire rate for the laser
weapon:
In this example, the laser
can only be fired once every 250 milliseconds, even if the player is pressing the "fire key" faster than that.
You can use the fireLimit
property to set a limit on the total number of bullets that can be fired during the game. Once the limit is reached, the weapon won't fire any more (unless you reset it).
By default, a weapon has no fire limit (i.e., has unlimited bullets), unless you specifically change it.
For example, to set a fire limit for the laser
weapon:
The shots
property keeps track of how many total bullets have been fired from the weapon. When the value of shots
reaches the fireLimit
, the weapon cannot be fired anymore.
For example, this code would calculate the number of shots remaining by subtracting the number of shots fired from the fire limit:
Once the fire limit has been reached, you have to reset the shots
counter back to zero to allow the weapon to be fired again. Once reset, the fire limit is still in effect (so the weapon will eventually "run out" of bullets again).
You can add a function that will be called whenever a weapon's fire limit has been reached. The most common use for this is to reset the bullet count after subtracting from the player's inventory of saved bullets ("ammo packs").
For example, this code will check to see if the player has any more bullets in inventory to "load" into the weapon. If so, it will reset the weapon to fire again.
You can use the bulletSpeed
property to set the speed at which the bullets travel (in pixels per second).
For example, to set the bullet speed for the laser
weapon:
You can set the bulletKillType
property to automatically remove bullets under certain conditions. Here are the most commonly-used values for this property:
Phaser.Weapon.KILL_WORLD_BOUNDS
is the default value unless you change it. It automatically removes a bullet if it leaves the game world boundaries.
Phaser.Weapon.KILL_CAMERA_BOUNDS
automatically removes a bullet if it leaves the game camera boundaries.
Phaser.Weapon.KILL_DISTANCE
automatically removes a bullet after it has traveled a certain distance, which is determined by the bulletDistance
property.
Phaser.Weapon.KILL_LIFESPAN
automatically removes a bullet after it has traveled for a certain amount of time, which is determined by the bulletLifespan
property.
For example, to automatically remove the laser
weapon bullets if they leave the game camera:
NOTE: In addition to setting the bulletKillType
property, you will still need to manually remove bullets (using the kill()
method) when they hit other objects.
If you set the bulletKillType
property to Phaser.Weapon.KILL_DISTANCE
, then you need to set a distance (in pixels) for the bulletKillDistance
property.
For example, to automatically remove the laser
weapon bullets after they have traveled 500 pixels:
If you set the bulletKillType
property to Phaser.Weapon.KILL_LIFESPAN
, then you need to set an amount of time (in milliseconds) for the bulletLifespan
property (1000 ms = 1 second).
For example, to automatically remove the laser
weapon bullets after they have traveled for 2 seconds:
You can set the bulletGravity
property to make the bullets respond to gravity.
By default, weapon bullets will not be affected by gravity and will travel in a straight line (based on its fire angle).
You can set the bullets' gravity value for the horizontal direction (x
) and/or the vertical direction (y
). The value represents the acceleration due to gravity measured in pixels per second squared. By default, a bullet's gravity is set to zero in each direction, unless you specifically change it.
bulletGravity.x
— change this value to add gravity in the horizontal direction. Positive values will pull the bullet to the right, and negative values will pull the bullet to the left.
bulletGravity.y
— change this value to add gravity in the vertical direction. Positive values will pull the bullet downwards, and negative values will pull the bullet upwards.
Adding a bulletGravity.y
works well for "bullets" that are shot or thrown up into the air at an angle, such as arrows, a basketball, etc.
For example, to make the bullets from a bowArrow
weapon fall downward:
You can use the bulletRotateVelocity
property to make the bullets rotate to match the direction of their travel. This can create the effect of a bullet "pointing" to the path it is following (such as: an arrow being fired from a bow, etc.). This works best when you have set a bulletGravity
value.
For example, to make the bullets from a bowArrow
weapon rotate to align with the direction of their travel:
You can make the position of the weapon automatically track the position of the sprite using the weapon.
For example, to make a weapon named laser
track the position of the player
sprite:
player
represents the name of the sprite that the weapon will track. Change this to match your sprite.
0, 0
represents an x-y offset from the sprite's anchor position. Using 0, 0
means the weapon will fire from the player sprite's anchor. Change these numbers as necessary to position the firing point of the weapon.
true
means that the weapon's fire angle should track the sprite's rotation. If the sprite will rotate in the game, you should list this as true
. Otherwise, list false
and adjust the fire angle using your own code.
Include this command in your create()
function after adding the weapon and the sprite to be tracked. Phaser will automatically update the weapon's position during gameplay.
For a group of enemies, it is common to create a single enemy weapon that they all can share. Then during gameplay, specific members of the group are selected to use the weapon. A specific enemy is selected from the group, and then the enemy weapon is moved to that enemy's position and fired. Then the process can be repeated.
If you want to change which sprite the weapon is tracking, then you can use the trackSprite()
method in your update()
function (or in a custom function called by the update()
function).
For example, this code could be included in your update()
function to continuously select the closest enemy to the player and make that enemy fire a weapon:
The fire()
method is used to fire a bullet from the weapon. The bullet speed, direction (fire angle), fire rate, etc. depend on the values set for the weapon's properties.
For example, to fire a weapon named laser
:
You may need to adjust the direction that a bullet will be fired by changing the fire angle based on the direction that the sprite using the weapon is moving (or was last moving).
For example, this code would move the player
right or left and also change the fire angle of the laser
weapon to match the player's direction:
As another example, this code will detect the current horizontal direction that the enemy
is moving and adjust its fire angle to match its direction before firing its weapon:
You can add a function that will be called whenever a weapon's bullet is successfully fired. The most common use for this is to play a sound effect representing the weapon firing.
For example, this will play laserSound
whenever the laser
weapon is fired:
This code would be placed in your create()
function after the code that adds the weapon.
The reason for using the onFire
signal to play the weapon sound effect is that the firing of the weapon is limited by its fireRate
(and potentially also by a fireLimit
).
If your code played the sound whenever the player pressed the "fire key", the sound would play even if a bullet was not</> actually fired (because the weapon was being limited by its fireRate
or fireLimit
). Using the onFire
signal to play the sound will keep the sound effect synced with the actual weapon firing.
You can use the Arcade Physics overlap()
method to detect when a weapon's bullet hits another object. (You can also use the collide()
method if you prefer.)
For the purposes of the overlap()
method, the weapon bullets are treated as a group referred to as weapon.bullets
(replace weapon
with the specific variable name of your weapon).
For example, to detect when one of the player's bullets hits a members of the enemyGroup
:
enemyGroup
represents the sprite or group to check for being hit by the bullets. Change this to match the name of your sprite or group.
laser.bullets
refers to the weapon's bullets. Change laser
to match the name of your weapon.
enemyHit
is the name of a custom function to run when an overlap is detected. List the function name without parentheses. You will have to create this custom function in your game. Change this to any unique function name that makes sense for your game.
null, this
are additional parameters that you need to list.
Next, you will need to create the custom function by adding it after your update()
function:
enemyHit
is the name of the custom function. Change this to match the name you listed in your collide()
command.
enemy, bullet
are the parameter variables that will be passed into the function by your collide()
command. These represent the two specific sprites that were involved in the collision. Change these to names that make sense for your collision.
The parameters are received in the same order as the original groups are listed in your overlap()
command, so the order of the names matters (in order to make your code perform the actions you intend).
The parameter names that you use will be different from the original group names. However, it will be much easier to understand what's happening in the custom function if the names are similar to the original group names.
Inside the custom function, whatever you do to the parameter variables will affect the original sprites they represent.
In this example function, enemy
represents the specific member of the enemyGroup
that was hit, and bullet
represents the specific bullet that hit the enemy
. So if the commands enemy.kill()
and bullet.kill()
were used inside the custom function, it would remove those specific members from the game world.
For example, the complete code for the enemyHit()
function might look like this:
By default, the physics body collision area for a weapon's bullet is treated as a rectangle the same width and height of the image or spritesheet frames used for the bullet.
Sometimes the image or spritesheet for a bullet includes transparent areas around the outer edges. These transparent areas are counted as part of the bullet's collision area, so it can make collisions look or feel unnatural.
If necessary, you can change the size and position of the rectangle used to detect collisions of the bullet's physics body. (This won't change the visual appearance of the bullet.)
For example, to change the collision rectangle for the bullets of a weapon named laser
:
24, 12
represent the width and height (in pixels) of the collision rectangle. Change these numbers to match the size you want to use for your bullet.
6, 6
represent the horizontal offset and vertical offset (in pixels) of the collision rectangle's top-left corner, relative to the top-left corner of the bullet. Change these numbers to position the collision rectangle where you need it to be.
There is no visual indication that a weapon has been added to the game. When the weapon is fired, a bullet will appear — but otherwise, there is no actual "weapon" displayed.
If you want to have a visual weapon displayed, then either include the weapon as part of the image or spritesheet used for the character carrying the weapon (e.g., include a weapon in the frames of the player's spritesheet) — or create a separate sprite for the weapon itself (using its own image or spritesheet).
If you do create a separate sprite for the weapon, then you would probably want to constantly update its position to match the position of the character that is carrying the weapon.
Using a separate sprite for the weapon would allow you to place the weapon in the game world for the player to find and collect — and to allow the player to change weapons (by either changing to a different sprite or by changing to a different sprite frame).
For example, let's assume that you've created a Phaser weapon named laser
which contains the bullets group. Separately, you've created a sprite named laserGun
that displays a visual weapon.
In your update()
function, you could add this code to make the laserGun
sprite follow the player
sprite's position:
If necessary, you could add (or subtract) numbers from the player.x
or player.y
positions to fine-tune the pixel position of the laserGun
relative to the player
.
Then you could set the Phaser weapon named laser
(containing the bullets) to track this sprite:
If you needed to switch the orientation of the laserGun
sprite (e.g., to point left instead of right), then you could either switch to a different sprite frame — or just flip the sprite horizontally by scaling its width to negative one:
The weapon's bullets would still be fired from laser
:
Phaser has built-in methods to generate different types of random numbers (and to select things at random). Using these methods is easier than writing your own code to generate specific types of random numbers based on the JavaScript Math.random()
function.
Random numbers are commonly used in video games to introduce variation that makes the game less predictable. Random numbers are also used to make decisions based on probabilities of certain events happening. Applying random numbers in the right ways can increase the challenge in the game and make repeated playing more enjoyable.
For example, some games place certain resources or obstacles in random or varied locations. Many games use random numbers to create variation in how enemies behave.
Your game doesn't have to use random numbers to be enjoyable, but you should try to think about ways that variation or randomness could improve the gameplay experience.
Get Random Position in Game World
Get Random Member of Group
Get Random Whole Number Within Range
Get Random Decimal Number Within Range
Get Random Angle in Degrees
Get Random Number Between 0 and 1
Get Random Number Between -1 and 1
Get Random Sign (Positive or Negative)
Properties and Methods for Random Data Generator
You can get a random x
position and/or random y
position within your game world boundaries. For example, this could be used to place resources, obstacles, or enemies within your game.
For example, to add a zombie
to a random position within the game world:
You can get a random existing member of a group of sprites. For example, this could be used to add unpredictability to enemy behavior.
For example, to select a random member of zombieGroup
to move towards the player
:
You can get a random integer (whole number) within a range by specifying the minimum and maximum numbers for the range. (The minimum and maximum values will be included as part of the possible range to randomly select from.)
For example, to give each enemy a random velocity between 125 and 175 pixels per second:
You can get a random real number (decimal number) within a range by specifying the minimum and maximum numbers for the range. (The minimum and maximum values will be included as part of the possible range to randomly select from.)
For example, to give each asteroid
a different size by scaling it to a decimal value between 0.5 and 2:
You can get a random angle between -180 degrees and 180 degrees.
As a reference for angle direction, here are a few examples:
0
represents pointing to the right
-90
represents pointing up
-180
and 180
both represent pointing to the left
90
represents pointing down
For example, in a top-down game, this could be used to give each enemy in a group a random angle for its movement.
You can get a random decimal number between 0 and 1 (which is like getting a random fraction, proportion, or chance).
This is equivalent to using the regular JavaScript random function:
For example, you could use this to make decisions in the game by calculating the chances of something happening. Imagine that your game is designed so that an enemy's bullet has a 25% chance of damaging the player by 10 points — but will otherwise cause only 5 points of damage.
You can get a random decimal number between -1 and 1.
For example, imagine that you want to introduce a small margin of error in the fire angle of the enemy weapon (so the enemy is not a perfect shot every time it aims and fires at the player). Let's say you wanted to add a small random margin of error between -5 and 5 degrees to the enemy's aim.
You can get a random sign (positive or negative). It returns a result of either -1 or 1. Think of it like a coin flip: heads or tails.
For example, in a side-view game, this could be used to give each enemy in a group a random direction for its horizontal velocity: about half of the enemies will randomly get a positive velocity (moving to right), and the rest will get a negative velocity (moving to left).
This section explains how to add other miscellaneous game features, such as a start screen, a game over screen, etc.
IMPORTANT: You should add your core game mechanics before worrying about adding any of these miscellaneous features.
Add Start Screen for Game
Add Input Signal to Pause Game (and Resume)
Add Game Over Screen
Add Input Signal to Restart Game
You can add a simple "start screen" to your game. Since your game is a single-state game, this "start screen" will simply display an image and/or text (such as the game title and maybe some information). The "start screen" will be hidden once the game is started (by the player pressing a specific key, etc.).
NOTE: If you create a Phaser game that has multiple states, you would create a separate game state just for the start of the game. Creating a multi-state game is not recommended if you're new to creating games.
You need to decide what to display at the start of the game as your "start screen":
You could display an image that will cover all (or some) of the game screen.
You could display an image of the game's title (or you could just display the title as text).
You could display some text information (such as the game's premise, some basic instructions, etc.).
You could display a combination of the above — or anything else you might want.
As necessary, find or create any image(s) that you need. If you want your "start screen" to completely cover and hide the game (until the game is actually started), then create an image that is the same width and height as your game camera view.
In this example, the "start screen" will simply display an image of the game's title and some text explaining how to start the game. The rest of the game world will be visible behind the "start screen." (Again, if you want to hide the game world at the start, create an image that will completely cover the the game camera view.)
Before your preload()
function, declare global variables for any images or text objects that will be displayed as part of your "start screen". Use any unique variable names that make sense for your game.
In the example code above, gameTitle
will be the variable for an image of the game's title, and gameStartText
will be the variable for some text explaining how the player can start the game.
If you are using any images in your "start screen", be sure to load the images in your preload()
function.
Towards the end of your create()
function (after adding all the other sprites, images, and text for your game world), add the image(s) and/or text that you want to display as your "start screen".
As necessary, change the positions to place the images and/or text where you need.
You need to decide how to prevent the normal gameplay from starting (until the game's start signal has occurred):
You could pause the game.
You could hide the player's character.
You could prevent the game's inputs from performing normal gameplay actions.
You could use a combination of the above — or another method that makes sense.
The simplest approach is to just pause the game until the player has started the game. This will "freeze" everything in the game world.
However, for certain games, you could hide the player's character until the game's start signal occurs. However, the other sprites in the game world (such as enemies, etc.) can still move around before the game's start signal has occurred. For example, in Practice 2, the Asteroids 2084 game simply hides the player's spaceship until the game is started (which occurs when the player presses the spacebar).
To pause the game, add this command in your create()
function (after the code that adds your "start screen" and the signal that will start the game):
If you aren't pausing the game, then you could hide the player's sprite until the game's start signal has occurred.
To hide the player's sprite, add this command in your create()
function (after the code that adds the player
sprite and sets its properties):
You might also need to modify some of the code in your update()
function that checks for player input, so the input will only work if player.exists
is true
. Otherwise, those inputs might perform actions that should only occur once the game has officially started.
For example, if the code in your update()
function to check the fireKey
input looked like this:
Then you might need to modify that code to include the condition that player.exists
is true
, like this:
You need to add a one-time signal that will be used to start the game:
You could start the game when the player clicks the mouse button.
You could start the game when the player presses a specific key.
You could start the game when the player clicks on a specific image or sprite.
You could set a timer to automatically start the game after a certain amount of time.
You could use another signal that makes sense for your game.
When the signal occurs, a custom function will be called that will hide the "start screen" and allow the normal gameplay to begin.
Below are several options for signals. Each option adds a signal that will call a custom function named startGame
(which you'll add to your game code in Step 4). You would add the signal in your create()
function (after adding the images and text for your "start screen").
You can designate a separate input key that will only be used to start the game — or you can use an existing input key that is normally used during gameplay for another action (e.g., to fire a weapon, to make the player jump, etc.).
In either case, before your preload()
function, be sure to declare a global variable for the input key that will be used to start the game, such as:
To add a separate input key that will only be used to start the game:
To re-use an existing input key normally used for another gameplay action (such as firing a weapon, etc.), the code is identical except the input key's variable name is its "normal" name:
You can add a signal to start the game when a specific image or sprite is clicked using the mouse (or tapped using a finger).
Before your preload()
function, be sure to declare a global variable for the image or sprite that will be used to start the game, such as:
In your preload()
function, be sure to load the image (or spritesheet).
In your create()
function, add the image (or sprite), and enable it to act as an input:
To start the game automatically when a timer ends, set the timer for the amount of time that you want your "start screen" to be displayed:
After your update()
function, you'll need to add the custom function named startGame
that will be called by the game's start signal. This custom function will hide the "start screen" and allow the normal gameplay to begin.
Inside the custom function, you will hide each image or text object displayed in your "start screen" by setting its visible
property to false
. Be sure to do this for each image or text object that should be hidden once the game is started.
The custom function will also allow the game to start by either unpausing the game or by unhiding the player sprite (depending on which option you used in Step 2).
If you paused the game in your create()
function:
If you hid the player
sprite in your create()
function:
You can pause a Phaser game by setting the game's paused
property to true
. Setting the property back to false
will resume the game.
When the game is paused, the update()
function is paused, which causes everything in your game world to be frozen in place. However, you can still detect input and run custom functions, which allows you to designate a key to resume the game again.
NOTE: If your game displays a timer using game.time.totalElapsedSeconds()
, be aware that pausing the game does not pause the game's internal clock — so even though your timer display will stop updating while the game is paused, the game time will keep elapsing in the background. Once you resume the game, the timer display will jump ahead to reflect the amount of time that elapsed while the game was paused. To avoid this issue, you'll need to figure out how to modify your timer.
Let's add a key that can be used to pause the game (and also resume the game). Each time the key is pressed, we'll toggle game.paused
between true
or false
.
Select a key that will be used as an input to pause (and resume) the game. This example will use the P
key (for "pause"). We'll add a signal that will call a custom function whenever this key is pressed down.
This example will also display text on the screen to indicate when the game is paused. However, adding this text is optional.
Before your preload()
function, declare global variables for the input key and the text (if you're using the text):
In your create()
function (towards the end), add this code:
If desired, you can leave out pauseText
— or change its properties (such as what the text displays, its position, its fill color, etc.).
Notice that whenever pauseKey
is pressed down, Phaser will run a custom function named togglePause
, which you'll need to add to your game code.
After your update()
function, add the custom function togglePause()
:
If you're not using pauseText
in your game, then remove those lines of code from the custom function.
You can add a simple "game over screen" to your game. Since your game is a single-state game, this "game over screen" will simply display text (but could also display images or other elements). The "game over screen" will be hidden at the start of the game and will only be displayed when the game detects specific conditions that indicate it is over.
In general, a game can end in two possible ways — either the player "wins" (e.g., the player completes the challenge, the player reaches the end of a level, etc.) or the player "loses" (e.g., the player's character dies, the player runs out of available time, etc.).
However, in certain games, there isn't really a way to "win" the game — instead, your game performance is measured in some way (such as: score points, achievements, progress, etc.). For example, every player will eventually "lose" Space Invaders by running out of lives; however, your Space Invaders gameplay is measured by how high your score is at the end of the game.
NOTE: If you create a Phaser game that has multiple states, you could create a separate game state just for the end of the game (or a level). Creating a multi-state game is not recommended if you're new to creating games.
You need to decide what to display at the end of the game as your "game over screen" — if necessary, you may need to display different things if the player "wins" versus "loses" the game:
You could display one or more images (e.g., the game's logo, different images for "win" versus "lose", etc.).
You could display text (e.g., a message such as "You Win" or "Try Again", instructions for how to play again, etc.).
You could display a combination of the above — or anything else you might want.
As necessary, find or create any image(s) that you want to use in your screen(s).
In this example, the "game over screen" will simply display a different image based on whether the player won or lost, as well as some text indicating whether the player won or lost.
Before your preload()
function, declare global variables for any images or text objects that will be displayed as part of your "game over screen". Use any unique variable names that make sense for your game.
In the example code above, gameWinImage
and gameLoseImage
will be the variables for the different images that will be displayed based on how the game ended, and gameOverText
will be the variable for the text indicating whether the player won or lost the game.
If you are using any images in your "game over screen", be sure to load the images in your preload()
function.
Towards the end of your create()
function (after adding all the other sprites, images, and text for your game world), add the image(s) and/or text that you want to display as your "game over screen".
As necessary, change the positions to place the images and/or text where you need.
The "game over screen" needs to be hidden when the game starts.
In your create()
function (immediately after adding the elements for your "game over screen"), hide each element in your "game over screen" by setting its visible
property to false
:
You need to detect the specific conditions that cause the game to be over. If your game can end in multiple ways (such as "winning" or "losing"), then you'll need to detect each of these possible conditions.
For example, a side-scrolling game could be designed to be "won" if the player reaches the end of the level — or "lost" if the player runs out of lives (or time).
When a condition occurs that causes the game to end, you will call a custom function named gameOver()
to display the "game over screen".
Some common examples of "lose" conditions and "win" conditions will be provided here. You can mix and match these with each other — and with your own conditions — based on what's needed for your game design.
If your game could end with the player either "winning" or "losing" the game, then it will help to have a variable to track the game's final result.
Before your preload()
function, declare a global variable to represent whether or not the player has won the game. Assign an initial value of false
to the variable (because the game hasn't been won yet at the start).
Later, if the player does win the game, the variable will be changed to true
.
In some games, the player has only one life: if the player's character dies, the game is over.
In this example code, when the player is killed, the game will call a custom function named gameOver()
:
The example code above would be placed in the create()
function after the code that adds the player
sprite.
In some games, the player can have multiple lives: when the player's character dies, the game continues if the player has any lives remaining — otherwise, the game is over.
In this example code, when the player is killed, the game will check to see if the player has any lives remaining. If so, the player is reset back into the game world with full health. Otherwise (when the player is out of lives), a custom function named gameOver()
is called:
The example code above would be placed in the create()
function after the code that adds the player
sprite.
In some games, there is a limited amount of time for the player to complete the game's level.
You can create a countdown timer for your game that displays the amount of time remaining (based on a time limit that you specify).
In this example code, if time limit is not over, it displays the time remaining. Otherwise (when the time runs out), a custom function named gameOver()
is called:
The example code above would be placed in the update()
function. Be sure to add the other code necessary to create the countdown timer.
In some games, the player wins by reaching the end of the level. A simple way to detect this is to compare the position of the player against a specific position (x
and/or y
) in the game world.
For example, this code will detect when the player
sprite has reached an x
position of 4950 pixels (which might represent the "end" of a game level that is 5000 pixels in width):
The example code above would be placed in the update()
function.
In some games, the player wins by reaching a specific object in the game world (e.g., a treasure, an exit door, another character, etc.). A simple way to detect this is to check for overlap between the player
sprite and the object's sprite.
For example, in your update()
function, check for the overlap of the player and the target object (the lostCat
sprite in this example):
Then after your update()
function, add the custom function called by the overlap method:
In some games, the player wins by defeating a specific enemy, such as a boss enemy.
In this example code, when the bossEnemy
is killed, the game will call a custom function named gameOver()
:
The example code above would be placed in the create()
function after the code that adds the bossEnemy
sprite.
In some games, the player wins by defeating all the enemies in a group.
In this example code, when there are no more living members left in the enemyGroup
, the game will call a custom function named gameOver()
:
The example code above would be placed in the update()
function.
In some games, the player wins by collecting all the objects in a group (such as a group of coins, etc.).
In this example code, when there are no more living members left in the coinGroup
, the game will call a custom function named gameOver()
:
The example code above would be placed in the update()
function.
After your update()
function, you'll need to add the custom function named gameOver()
that will be called when a "game over" condition is detected. The custom function will show the "game over screen" (and might need to cause the normal gameplay to end).
Inside the custom function, you will show each image or text object displayed in your "game over screen" by setting its visible
property to true
. Be sure to do this for each image or text object that should be shown once the game ends. You can also add other code to change the text, play a sound, etc.
NOTE: You may want (or need) to add other code to prevent the normal gameplay from continuing once the game is supposed to be over. Here are two simple options (but there are other possible options):
Pause the gameplay by using: game.paused = true;
Remove the player by using: player.exists = false;
You can add an input signal to allow the player to restart the game (i.e., start a new game) when the current game is over. Often this is used in combination with displaying a "game over screen".
A Phaser game can be restarted by using:
The instructions below will show how to embed the "restart" command within a custom function that is called by a signal within your game.
In your gameOver()
function, you would add a one-time signal that will restart the game:
You could restart the game when the player clicks the mouse button.
You could restart the game when the player presses a specific key.
You could restart the game when the player clicks on a specific image or sprite.
You could set a timer to automatically restart the game after a certain amount of time.
You could use another signal (or combination of signals) that makes sense for your game (e.g., restart when specific enemy defeated, etc.).
When the signal occurs, a custom function will be called that will restart the game.
Below are several options for signals. Each option adds a signal that will call a custom function named restartGame
(which you'll add to your game code in Step 2).
In your gameOver()
function, add the signal to restart the game:
You can designate a separate input key that will only be used to start the game — or you can use an existing input key that is normally used during gameplay for another action (e.g., to fire a weapon, to make the player jump, etc.).
In either case, before your preload()
function, be sure to declare a global variable for the input key that will be used to start the game, such as:
To add a separate input key that will only be used to start or restart the game, first add the input key in your create()
function:
Then add the signal in your gameOver()
function:
To re-use an existing input key normally used for another gameplay action (such as firing a weapon, etc.), first, add the input key in your create()
function:
Then add the signal in your gameOver()
function:
To add a dedicated key that can restart the game at any point during gameplay, use a separate input key that's not used for any other purpose, change the signal from addOnce()
(one-time signal) to add()
(repeatable signal), and add the signal in your create()
function (instead of in the gameOver()
function):
You can add a signal to restart the game when a specific image or sprite is clicked using the mouse (or tapped using a finger).
Before your preload()
function, be sure to declare a global variable for the image or sprite that will be used to start the game, such as:
In your preload()
function, be sure to load the image (or spritesheet).
In your create()
function, add the image (or sprite, enable it to act as an input, and hide the image (until the game is over):
In your gameOver()
function, show the image, and add the signal to it:
To restart the game automatically after a timer delay, set a timer for the amount of time that you want your "game over screen" to be displayed.
In your gameOver()
function, add the timer:
After your update()
function, you'll need to add the custom function named restartGame
that will be called by the signal you added. This custom function will use the game.state.restart()
method to restart the current game.
Restarting the game skips the preload()
function (because all the game assets should already be loaded into memory from the previous game). Instead, it first clears out the current game world. Then it runs the create()
function again one-time (to rebuild a fresh game world). After that, the update()
function begins to runs in a continuous loop for the new gameplay.
IMPORTANT: If you have any custom game variables (e.g., to store the player's score, etc.), those variables will keep the same values they had at the end of the previous game. For some variables, that's perfectly fine. However, for other variables (such as the player's current score, etc.), you may need to reset the values of those variables for the new game before restarting the game. If desired, you can also change the values of certain variables (such as updating the game's high score, increasing the enemy count for the next game, etc.).
Inside the custom function, change or reset the values of certain game variables (as necessary) for the start of a new game. Then restart the game:
You can add certain types of animation effects using a tween. A tween changes a game object's property from one value to another value over a specified amount of time. Phaser figures out all the "in between" values to make the change occur smoothly over the time duration. Tweens can be used for objects such as text, images, sprites, etc.
For example, a tween could be as simple as making the game's title fade in (or fade out). However, a tween can also be more complex. You can use a tween to change multiple properties of an object at the same time, such as moving a sprite while also making it smaller and making it fade out. You can also chain multiple tweens together (for the same object or multiple objects) to have them play in sequence.
Here's an example of a tween animation effect that changes the values of the y
and angle
properties for a set of sprites (each sprite is an image of a letter). The tweens use delays to start playing in a staggered fashion from left to right.
Object Properties Used in Tweens
Add Tween to Change Object Property
To Tween (Current Value → Different Value)
From Tween (Different Value → Current Value)
Deciding Which Type of Tween to Use
Easing Patterns for Tween Effects
Examples of Tweens
Tween Alpha (Make Object Fade In or Fade Out)
Tween Angle (Make Object Rotate)
Tween Scale (Make Object Larger or Smaller)
Tween Position (Move Object Horizontally or Vertically)
Tween Multiple Properties of Same Object at Same Time
Chain Tweens Together in Sequence
Control Playing of Tween (Start, Pause, Resume, Stop)
Detect When Tween Completed
Properties and Methods for Tween Classes and Methods for Phaser Easing Patterns
The most commonly-used object properties used in tweens include:
alpha
(make object fade in or fade out using transparency)
angle
(make object rotate)
scale
(make object larger or smaller)
x
position (make object move left or right)
y
position (make object move up or down)
However, any object property can used in tweens, as long as the property can have a range of numeric values.
You can add a tween in your create()
function, update()
function, or in a custom function. Tweens can be set to start automatically or can be started manually (which requires assigning them to a variable).
There are two types of tweens:
To Tween — changes property from its current value to a new value
From Tween — changes property from a specified value to its current value
In order to apply a tween to a game object (such as: text, image, sprite, etc.), the object must be assigned to a variable (so you can reference the object's variable name in the tween).
If you want to automatically play the tween, you can add the tween directly (without assigning the tween to a variable).
However, if you want to manually control the playing of the tween (start, pause, etc.), you must add the tween by assigning it to a variable.
A "to" tween changes an object's property (or set of properties) from its current value to a different value over a designated amount of time.
Here is the generic format for a "to" tween:
target
represents the variable name of the object whose property will be changed.
{ property: value }
represents the name of the object's property and its new value.
Any property that can have a range of numeric values can be tweened.
The value can be absolute (i.e., a specific number such as 300
) or relative (i.e., a change such as '+300'
or '-300'
). Relative values need to be listed inside quotes.
If needed, you can change multiple properties by separating property-value pairs with a comma: { property: value, property: value }
duration
represents the amount of time (in milliseconds) over which the property's value should change from its current value to the new value. If no value is listed, it will default to 0
(no delay).
easing
represents the name of a mathematical pattern that determines how the property's value will be changed over time. If no value is listed, it will default to linear easing (steady change).
autostart
determines whether the tween will automatically start. List true
to automatically start the tween, or list false
to manually start the tween. Tweens that will be manually started must be assigned to a variable. If no value is listed, it will default to false
(manual start).
delay
represents the delay (in milliseconds) before the tween will start. If no value is listed, it will default to 0
(no delay).
repeat
represents the number of times that the tween should repeat itself. List the number of times to repeat, or list -1
to make tween repeat itself continuously. If no value is listed, the default is 0
(play tween once but don't repeat).
yoyo
determines whether the tween will reverse itself. List true
to make the tween play and then reverse itself (play backwards — returning to the starting value). If no value is listed, the default is false
(play tween once but don't reverse).
Only the target
name and the property: value
pair are required parameters. The other parameters are optional and will use their defaults if omitted.
However, it is recommended to list values for duration
, easing
, autostart
, and delay
. This will make it easier for you to fine-tune the tween animation effect.
A "from" tween changes an object's property (or set of properties) from a different value to its current value over designated amount of time.
Here is the generic format for a "from" tween:
The parameters are the same as a "to" tween (see above for descriptions).
How do you decide whether to use a "to" tween versus a "from" tween?
The short answer: It may not matter. You can most likely use either type of tween to achieve the same effect.
The longer answer: It depends. It might be slightly easier to use one versus the other. Just use whichever one makes more sense to you (or for your game).
Possible reasons to use a "to" tween:
You want the current value of the object's property to be different when the tween effect is completed. (The tween will start from the current value and change to a different value.)
You have a specific ending value in mind for the property.
Possible reasons to use a "from" tween:
You want the current value of the object's property to be the same when the tween effect is completed. (The tween will start from a different value and change to the current value.)
You have a specific starting value in mind for the property.
Again, in most cases, you could probably use either type of tween. Your code will just be slightly different.
Phaser has different "easing patterns" that determine how the values of the property are mathematically changed from its starting value to its ending value.
The default easing pattern is to change the value in a linear pattern (i.e., steady change over time). In many cases, a linear pattern will work just fine for a tween effect.
However, in other cases, you may want to use a different easing pattern to achieve a more realistic (or interesting) animation effect for the tween. For example, a cubic pattern is often used for changes that naturally speed up or slow down.
Here are some of the more commonly-used Phaser easing patterns (not a complete list):
Phaser.Easing.Default
— the same as Phaser.Easing.Linear.None
Phaser.Easing.Linear.None
— value changes at steady rate
Phaser.Easing.Cubic.In
— value changes slowly at first and then speeds up
Phaser.Easing.Cubic.Out
— value changes rapidly at first and then slows down
Phaser.Easing.Cubic.InOut
— value changes slowly at first, then speeds up, and then slows down again
Some of the other classes of Phaser easing patterns include: back easing, bounce easing, circular easing, elastic easing, sinusoidal easing, etc.
VISUAL REFERENCE: Here are graphs that visually represent the different Phaser Easing patterns.
The black line in each graph shows how the property's value will change over time during the tween. (Time progresses from left to right across the graph.)
The red lines represent the starting and ending values for the property. (The bottom red line represents the starting value. The top red line represents the ending value. The graph shows the value increasing over time, but the pattern still applies if the value is decreasing over time — just imagine flipping the graph vertically.)
PowerX easing patterns are no longer included in Phaser.
Exponential easing patterns are not shown, but they would look similar to the quintic easing patterns.
For example, to fade in the gameTitle
from a value of 0
(transparent) to its current value (which is 1
unless you previously set it to something else):
As another example, to fade out the gameTitle
from its current value (assume 1
) to a new value of 0
(completely transparent):
For example, to make the gameTitle
rotate from a value of 360
degrees to its current value (which is 0
unless you previously set it to something else):
This will rotate the gameTitle
360 degrees counter-clockwise. To make it rotate clockwise, use -360
as the "from" value.
Scale is a property that has multiple components:
scale.x
(horizontal scale)
scale.y
(vertical scale)
Because this property has multiple components, you must use object.scale
as the target and { x: value, y: value }
for the property-value pairs.
This also means that you cannot combine scale and another property into the same tween. However, if you want to tween an object's scale and another property at the same time, just create separate tweens that play at the same time.
For example, to scale gameTitle
from a value of 4
to its current value (which is 1
unless you previously set it to something else):
To scale gameTitle
while also making it fade in at the same time, just add separate tweens (one directly after the other):
As another example, to scale the gameTitle
from its current value to a new value of 0
(i.e., make it shrink until it disappears):
An object's position is determined its x
and y
properties. You can move an object by tweening its x
and/or y
positions.
NOTE: Since x
and y
are actually two separate properties (rather than components of the same property), you can change both x
and y
positions with the same tween, if needed.
NOTE: If the object is a sprite that has gravity (gravity.x
or gravity.y
), its gravity will also affect the sprite as you move it with a tween.
For example, to move the gameTitle
to position 300, 20
:
If desired, you can use negative values for position in order to move an object off-screen (or move the object from off-screen to on-screen).
For example, to move the gameTitle
vertically from a position off-screen (y: -100
) down to its current y
position:
Remember that values can be absolute (i.e., a specific number such as 300
) or relative (i.e., a change such as '+300'
or '-300'
). Relative values need to be listed inside quotes.
For example, to move the bossEnemy
horizontally from its current position to a new position 300 pixels to the right:
To move the bossEnemy
horizontally to the left use a negative relative value (such as: '-300'
).
To make the bossEnemy
repeatedly move horizontally to the left by 300 pixels and back again to its original position, set the tween to repeat continuously and to reverse itself in a yoyo:
You can tween multiple properties of the same object at the same time by adding multiple tweens and/or listing multiple property-value pairs in the same tween.
For example, these two tweens for gameTitle
are added back to back and thus will start at the same time:
Together, these two tweens will make the gameTitle
become larger (scale from 0 to 1), fade in (from 0 to 1), rotate clockwise (from -360 to 0), and move down (from 150 pixels above its current y
position). All four of these effects will start at the same time and occur over the same duration of time.
If you assign a tween to a variable and set the tween's autostart parameter to false
, then you can control the playing of the tween. You will be able to start, pause, resume, and/or stop the tween whenever you want. You'll also be able to replay (reuse) a tween if needed.
First, add the tween by assigning it to a variable. Use any unique variable name that make sense for your game.
Then when needed in your game, you can use any of the methods to start, pause, resume, and/or stop the tween.
NOTE: If the tween is being added in one function (such as the create()
function) but will be controlled in a different function (such as the update()
function or a custom function), then the tween should be assigned to a global variable. (Otherwise, if the tween is added and controlled within the same function, a local variable can be used.)
You can chain multiple tweens together, so they play in a sequence — when the first tween ends, the next tween will start, etc.
One of the tweens will represent the start of the chain. The other tweens will represent additional "links" in the chain.
First, add the individual tweens by assigning them to variables. Use any unique variable names that make sense for your game.
Then use the chain()
method to "link" the tweens in order (which represents the order in which they will play).
NOTE: If the chain is being created in one function (such as the create()
function) but will be started in a different function (such as the update()
function or a custom function), then the first tween in the chain should be assigned to a global variable (but the other tweens in the chain can just use local variables if the tweens and chain are created within one function).
NOTE: If you want multiple tweens to play at the same time (in parallel instead of in sequence), then do not chain them together (just add them one after another).
You can add an onComplete
signal to call a custom function when a particular tween has completed.
First, add the tween by assigning it to a global variable. Use any unique variable name that make sense for your game. Then add an onComplete
signal to specify the name of the custom function to call. Use any unique function name that make sense for your game.
Finally, add the custom function after your update()
function. Be sure to use the same name that you listed in the onComplete
signal.
The game camera controls the player's view into the game world. By default, the game camera is set to the same size as your game display.
You can change the camera's position within the game world, or you can set the camera to automatically follow a specific sprite (such as the player's character). You can also set certain objects (images, text, etc.) to stay "fixed" within the camera view, as part of the game's user interface.
Make Camera Follow Specific Sprite
Focus Camera on Specific Object or Location
Make Object Stay Fixed to Camera View
Make Camera Shake
Make Camera Flash
Make Camera Fade
Properties and Methods for Game Camera
If your game world is larger than your game display, you can set the game camera to automatically follow a specific sprite (typically the player's character) as it moves through the game world.
In the code above, player
represents the name of the sprite to follow. If necessary, change this to match the variable name of your sprite.
You would typically add this command in your create()
function after adding the sprite to the game.
You also have the option of selecting a follow style with a specific type of "deadzone" — an invisible rectangular area in the middle of the game display where the camera won't move (until and unless the sprite moves outside the rectangle).
Phaser.Camera.FOLLOW_LOCKON
is the default style used if you don't select a style. It has no deadzone and will closely track the movement of the sprite.
Phaser.Camera.FOLLOW_PLATFORMER
is a style that has a tall, narrow deadzone.
Phaser.Camera.FOLLOW_TOPDOWN
is a style that has a square deadzone.
Phaser.Camera.FOLLOW_TOPDOWN_TIGHT
is a style that has a small square deadzone.
To use a different style, modify the command so it lists the follow style after the sprite's name:
You can turn off the following of a sprite using this command:
This would be helpful if you want the camera to follow a different sprite or to focus on a specific object or location.
You can make the camera move to focus on a specific display object (image, sprite, etc.) or location in the game world. This is a one-time camera movement (not a continuous following behavior). This might be helpful as visual feedback to draw the player's attention to an object or event, etc.
To focus the camera on the current location of a specific display object, use this command:
In the code above, explosion
represents the name of the display object (sprite, etc.) to focus on. Change this to match the variable name of your object.
To focus the camera on a specific location using x
and y
coordinates, use this command:
In the code above, 600
is the x
coordinate, and 300
is the y
coordinate. Changes these to match your desired coordinates.
You can make specific objects (images, text, etc.) stay fixed within the camera view, so the objects won't move when the game world scrolls. For example, a game's user interface elements (score, health bar, etc.) typically stay "fixed" to the camera view.
Phaser display objects (such as images, text, sprites, etc.) have a property called fixedToCamera
. By default, this property is set to false
— changing this value to true
will make the object stay fixed within the camera view.
In order to change this property, the display object needs to be assigned to a variable name. For example, if the player's score were displayed using a text object named scoreText
, you would use this command:
Change scoreText
to the variable name of your display object. Add the command in your create()
function after adding the display object. (The x, y
position where the object is added will be the position where it will stay fixed, relative to the top-left corner of the game camera.)
As a visual effect, you can make the game camera shake back and forth briefly (and then return to normal). This can be helpful as visual feedback for a collision, explosion, etc.
0.02
represents the intensity of the shaking (as a percentage of the camera size). Change this value as needed, but you'll probably want to use a low number (less than 0.1).
250
represents the duration of the shaking in milliseconds (1000 ms = 1 second). Change this value to whatever duration you need.
You also have the option of selecting which direction the camera should shake:
Phaser.Camera.SHAKE_BOTH
is the default direction used if you don't select a direction. It will shake the camera both horizontally and vertically.
Phaser.Camera.SHAKE_HORIZONTAL
will only shake the camera from left to right.
Phaser.Camera.SHAKE_VERTICAL
will only shake the camera up and down.
To use a specific direction, modify the command so it also lists true
plus the shake direction:
As a visual effect, you can make the game camera briefly flash a specific color (and then fade back to normal). This can be helpful as visual feedback for a reward, punishment, etc.
0x00ff00
is a code for the color (green in this example). Change this to your own color by listing 0x
followed by a CSS hex color code. For example, white would be 0xffffff
, red would be 0xff0000
, etc.
500
represents the duration of the flash in milliseconds (1000 ms = 1 second). Change this value to whatever duration you need.
As a visual effect, you can make the game camera fade to a specific color (black, red, white, etc.). It is basically the opposite of a camera flash (except the game camera will remain that color until you reset it). This can be helpful as visual feedback to indicate a character dying, reaching the end of a level, etc.
0x000000
is a code for the color (black in this example). Change this to your own color by listing 0x
followed by a CSS hex color code. For example, white would be 0xffffff
, red would be 0xff0000
, etc.
500
represents the duration of the fade in milliseconds (1000 ms = 1 second). Change this value to whatever duration you need.
At the end of the camera fade, the game display will remain that color (black, red, white, etc.) until you reset it back to normal using this command:
You can add simulated physics interactions to your game. Objects in the game can move and accelerate. Objects can be affected by gravity and friction. Objects can collide and bounce off each other — and can respond differently based on their relative masses.
The cool thing about simulated physics is that you can make your game world behave however you want. You could change gravity so objects will "fall up" instead of falling down. You could selectively apply gravity only to certain objects — or eliminate gravity entirely.
You can set your game physics to simulate different kinds of actions in different kinds of environments, such as jumping into the air, sliding on ice, swimming in water, flying through space, etc.
NOTE: Phaser has several physics systems to choose from. However, this reference section will focus only on the Arcade Physics system, which is a good choice for many games.
Arcade Physics has lots of useful physics properties and methods, plus support for weapons (e.g., shooting or throwing objects such as bullets, lasers, arrows, fireballs, snowballs, etc.). Arcade Physics is more simplistic than the other physics systems, but it runs much faster as a result.
Start Physics System
Enable Physics on Sprite or Group of Sprites
Set Physics Body Properties for Sprite
Gravity
Collide With World Boundaries
Velocity
Maximum Velocity
Acceleration
Drag
Bounce
Mass
Immovable
Friction
Angular Velocity
Maximum Angular Velocity
Angular Acceleration
Angular Drag
Check for Collide or Overlap of Sprites and Groups
Change Collision Area of Sprite
Find Group Member that is Closest or Farthest to Sprite
Get Distance from Sprite to Object, Location, or Pointer
Move or Accelerate Sprite Towards Object, Location, or Pointer
Get Angle Between Sprite and Object, Location, or Pointer
Move or Accelerate Sprite in Direction of Angle
Create Platforms that Move Back-and-Forth
In addition, see the Weapon section for coding references explaining Arcade Physics weapons.
In order to use any physics properties and methods in your game, you first need to start the physics system.
To start the Arcade Physics system, add this command at the beginning of your create()
function:
Physics properties and methods can only be applied to sprites or groups of sprites. However, you must first specifically "enable" physics on each sprite or group that you want to involve in physics interactions.
When you enable physics on a sprite (or a group of sprites), it creates a "physics body" for the sprite (or for each sprite in the group). You can then get or set the sprite's physics body properties and also check for collisions between the physics bodies of different sprites.
For example, to enable physics on an individual sprite named player
:
Add this command in your create()
function after adding the sprite (and before setting any of its physics body properties).
You will need to enable physics on every sprite that you want to involve in physics interactions.
For example, to enable physics on a group of sprites named platformGroup
:
Add this command in your create()
function after adding the group (and before setting any physics body properties for members of the group).
You will need to enable physics for every group that you want to involve in physics interactions.
When you enable physics on a sprite or a group of sprites, it creates a "physics body" for the sprite. This sub-section describes the most common physics body properties that you might use in your game.
You can use gravity to pull a sprite in a certain direction (make it fall down, etc.), and make the sprite collide with the world boundaries (to simulate colliding with a solid surface).
You can use velocity or acceleration to move a sprite, and set a drag that slows it down.
You can set the bounce and mass of a sprite to change how it is affected by collisions with other sprites.
You can make a sprite immovable to prevent collisions from changing its position or speed. If the "immovable" sprite is moving (e.g., moving platform), you can set a friction value that affects other sprites riding on top of it.
You can use angular velocity or angular acceleration to rotate a sprite, and set an angular drag that slows it down.
We're used to Earth's gravity pulling objects down towards the surface. Earth's gravity affects all objects and causes them to fall at the same rate.
However, in your game world, you have custom control over each sprite's gravity. You can set a sprite's gravity to make it fall up — or to make the sprite get pulled sideways by gravity — or do both. Gravity only affects the sprites you want, and you can set different gravity values for different sprites.
For certain games (e.g., game using top-down perspective, game set in outer space, etc.), you might not want your sprites to be affected by gravity (i.e., you'd just leave the sprite's gravity at its default value of zero).
You can set a sprite's gravity value for the horizontal direction (x
) and/or the vertical direction (y
). The value represents the acceleration due to gravity measured in pixels per second squared. By default, a sprite's gravity is set to zero in each direction, unless you specifically change it.
body.gravity.x
— change this value to add gravity on the sprite in the horizontal direction. Positive values will pull the sprite to the right, and negative values will pull the sprite to the left.
body.gravity.y
— change this value to add gravity on the sprite in the vertical direction. Positive values will pull the sprite downwards, and negative values will pull the sprite upwards.
If you want to add a "normal" Earth-type gravity to a sprite, then set a positive value for its body.gravity.y
property.
For example, to make the player
sprite fall downward:
You can force a sprite to stay within the game world by making it collide with the world boundaries. Otherwise, it might leave the game world if it is moving (due to its velocity or gravity). By default, a sprite will not collide with the world boundaries, unless you specifically tell it to do so.
For example, to force a sprite named player
to collide with the game world boundaries:
player.body.collideWorldBounds = true;
Velocity represents the speed and direction of a sprite:
A positive velocity means the sprite is moving in a particular direction.
A negative velocity means the sprite is moving in the opposite direction.
A velocity of zero means the sprite is not moving.
Thus, if you set a sprite's velocity to any non-zero value (positive or negative), it will cause the sprite to move.
The velocity is a number representing the sprite's speed in pixels per second. This property is set separately for the x
and y
directions:
body.velocity.x
— change this value to move the sprite in the horizontal direction. Positive values will move the sprite to the right, and negative values will move the sprite to the left. Larger numbers (whether positive or negative) move the sprite faster.
body.velocity.y
— change this value to move the sprite in the vertical direction. Positive values will move the sprite down, and negative values will move the sprite up. Larger numbers (whether positive or negative) move the sprite faster.
For example, to make the player
sprite move to the left:
-200
represents the speed in pixels per second. The negative value represents moving to the left. Change this value as needed.
NOTE: Once a sprite is given a non-zero velocity, it will keep moving at that speed and direction unless something else causes the velocity to change.
For example, if you were creating a side-scrolling endless runner game, you could set a positive value for player.body.velocity.x
in the create()
function to make the player move to the right at a constant speed. Then your update()
function might only give the player the option to move up and down by changing the player.body.velocity.y
value.
You can also get (i.e., read) the values to check the speed and/or direction of a sprite.
For example, to determine if the player
sprite is moving to the left or right (or not moving at all):
You can set a maximum velocity for a sprite to set a limit on how fast it can move. This is typically done in the create()
function.
The maximum velocity is set as a number representing the maximum speed in pixels per second. This property is set separately for the x
and y
directions:
body.maxVelocity.x
body.maxVelocity.y
For example:
It is common to use the same value for both directions, so you can also set both directions at the same time. For example, to set a maximum velocity for a sprite named player
:
500, 500
represent the values for the x
and y
directions (in that order). If you only list one number, then it will use that same value for both directions. Change these numbers as needed.
Acceleration is the rate of change in a sprite's velocity:
A positive acceleration means the sprite is speeding up.
A negative acceleration means the sprite is slowing down.
An acceleration of zero means the sprite is maintaining the same speed.
Acceleration is a number representing the sprite's change in speed in pixels per second. This property is set separately for the x
and y
directions:
body.acceleration.x
— change this value to change the sprite's velocity in the horizontal direction. Positive values will speed up the sprite, and negative values will slow down the sprite. Larger numbers (whether positive or negative) change the speed more quickly.
body.acceleration.y
— change this value to change the sprite's velocity in the vertical direction. Positive values will speed up the sprite, and negative values will slow down the sprite. Larger numbers (whether positive or negative) change the speed more quickly.
For example, to accelerate a sprite named player
in the horizontal direction:
In the example above, if the player.body.velocity.x
were initially zero (not moving), then after 1 second its velocity would be 100 pixels per second, after 2 seconds it would be 200, after 3 seconds it would be 300, etc.
NOTE: If you keep applying an acceleration, it will continue to change the sprite's velocity:
Example 1: A sprite initially has a velocity of zero (not moving). Applying a positive acceleration will increase the sprite's velocity (causing it to start moving). Continuing to apply a positive acceleration will continue to increase the sprite's velocity (making it move faster over time).
Example 2: A sprite initially has a positive velocity (moving). Applying a negative acceleration will decrease the sprite's velocity (making it slow down). Continuing to apply a negative acceleration will continue to decrease the sprite's velocity (making it slow down further) until it reaches zero (stops moving) and then becomes negative (moving again but now in the opposite direction).
Drag represents a negative acceleration that slows down the sprite when it is moving. Drag is a type of friction also referred to as air resistance (or fluid resistance if moving in a liquid).
Drag only affects the sprite when it is moving. If the sprite is not moving (velocity is zero), then drag will not affect it.
Drag is a number representing the sprite's reduction in speed in pixels per second squared. This property is set separately for the x
and y
directions. By default, a sprite's drag is set to zero in each direction unless you specifically change it.
body.drag.x
— reduces the sprite's velocity in the horizontal direction when the sprite is moving
body.drag.y
— reduces the sprite's velocity in the vertical direction when the sprite is moving
For example, to set the horizontal drag of the player
sprite:
It is common to use the same value for both directions, so you can also set both directions at the same time. For example:
25, 25
represent the values for the x
and y
directions (in that order). If you only list one number, then it will use that same value for both directions. Change these numbers as needed.
The effects of drag are most noticeable if your game changes the sprite's speed by using acceleration (instead of by setting a specific velocity value).
You can set the bounce
property for a sprite's physics body, which affects its rebound velocity after colliding with another physics body (i.e., another sprite).
The bounce
property typically uses a value between 0-1. A value of 0 results in no bounce after a collision. A value of 1 results in a perfectly elastic bounce, where the sprite bounces backward from a collision without losing any velocity. A value of 0.5 results in the sprite bouncing backwards with only 50% of its original velocity.
However, you can also set the bounce
to a value greater than 1, which will actually cause the sprite to gain velocity whenever it bounces. A value of 1.25 would result in the sprite bouncing backwards with 125% of its original velocity. This could be an interesting feature for certain games.
You can set a sprite's bounce value for the horizontal direction (x
) and/or the vertical direction (y
). By default, a sprite's bounce is set to zero in each direction unless you specifically change it.
body.bounce.x
— change this value to add a bounce to the sprite in the horizontal direction. You would typically use a value between 0-1 (but can use a higher value if desired).
body.bounce.y
— change this value to add a bounce to the sprite in the vertical direction. You would typically use a value between 0-1 (but can use a higher value if desired).
For example, to give the player
sprite a small bounce effect in the vertical direction:
You can also set both directions at the same time. For example, to make a sprite named pinball
have perfectly elastic bounces (without losing any velocity):
1, 1
represent the values for the x
and y
directions (in that order). If you only list one number, then it will use that same value for both directions.
You can set the mass of a sprite (basically the "weight" of the sprite). The mass will affect how the velocity of the sprite changes after a collision because Phaser physics systems conserve momentum during collisions (just like real-life physics).
Momentum is calculated as an object's mass multipled by its velocity. When objects collide, they transfer kinetic energy, which can cause one object to slow down while the other object speeds up. These changes in speed are affected by the masses of the objects and their velocities before the collision.
The conservation of momentum means that the total momentum of objects before a collision is equal to the total momentum of the objects after the collision.
Every sprite's mass is set to 1 by default, unless you change it. The value for mass is relative: use a value less than 1 to make a sprite less massive, or use a value greater than 1 to make a sprite more massive.
If you want to add more realistic collisions between objects, then set different values for their masses.
For example, to set the mass of a sprite named player
:
This would make the player
sprite have 2 times the mass of other sprites (if they still have the default mass of 1).
A sprite that is set as "immovable" will not be affected by collisions (meaning its position and velocity will not be changed if something else collides with it).
Platforms, walls, and similar types of objects are typically set to be immovable. If you didn't set these to immovable, then they would move if something collided with them, such as the player jumping onto a platform or the player running into a wall. (Though, collapsible platforms and movable walls might be an interesting feature for certain games.)
For example, to make a sprite named platform
immovable:
platform.body.immovable = true;
NOTE: Despite the name "immovable" — you can make a immovable sprite actually move by setting its velocity, acceleration, or gravity. For example, this would allow you to create moving platforms that the player could jump on and ride.
The best way to understand "immovable" is this:
An immovable sprite can move itself, but it cannot be moved by other sprites that collide with it.
In Arcade Physics, the friction property is only applicable to "immovable" sprites. Friction affects other sprites that are riding on top of a moving "immovable" sprite (such as a moving platform, etc.).
Friction is set as a value between 0-1 where 0 represents no friction and 1 represents maximum friction. Friction is set separately for the x
and y
directions. By default, an immovable sprite's friction is set to 1 for the x
direction and 0 for the y
direction, unless you specifically change them.
body.friction.x
(defaults to 1)
body.friction.y
(defaults to 0)
To change the horizontal friction for a sprite named platform
:
Imagine the player sprite jumps on top of a horizontally-moving platform (set to be "immovable"):
If the platform's body.friction.x
is set to 1, the player will stick to the platform and can ride it. As the platform moves, the player will be carried along at the same speed.
If the platforms's body.friction.x
is set to 0, the player can land on the platform but won't stick to it — the platform will slide along beneath the player (without carrying the player along) — in order to stay on the platform, the player will eventually have move itself.
If the platforms's body.friction.x
is set to 0.5, the player can land on the platform, but it will be less sticky. As the platform moves, it will slide a bit underneath the player, only moving the player at half the platform's speed (and eventually the player will slide off unless the player moves itself).
The best way to understand friction in Arcade Physics is to try different values in your game to see the effect when another sprite (such as the player) lands on a moving "immovable" object.
Angular velocity represents the rotational speed and direction of a sprite:
A positive angular velocity means the sprite is rotating clockwise.
A negative angular velocity means the sprite is rotating counter-clockwise.
An angular velocity of zero means the sprite is not rotating.
Thus, if you set a sprite's angular velocity to any non-zero value (positive or negative), it will cause the sprite to rotate.
The angular velocity is a number representing the sprite's rotational speed in degrees per second.
body.angularVelocity
— change this value to rotate the sprite. Positive values will rotate the sprite clockwise, and negative values will rotate the sprite counter-clockwise. Larger numbers (whether positive or negative) rotate the sprite faster.
For example, to make the player
sprite rotate counter-clockwise:
-200
represents the rotational speed in pixels per second. The negative value represents counter-clockwise rotation. Change this value as needed.
You can set a maximum angular velocity for a sprite to set a limit on how fast it can rotate. This is typically done in the create()
function.
The maximum angular velocity is set as a number representing the maximum speed in degrees per second.
For example, to set a limit on the rotational speed of the player
sprite:
Angular acceleration is the rate of change in a sprite's velocity:
A positive angular acceleration means the sprite's rotation is speeding up.
A negative angular acceleration means the sprite's rotation is slowing down.
An angular acceleration of zero means the sprite's rotation is maintaining the same speed.
Acceleration is a number representing the sprite's change in rotational speed in pixels per second.
body.angularAcceleration
in degrees per second squared
For example, to accelerate the rotation of the player
:
In the example above, if the player.body.angularVelocity
were initially zero (not rotating), then after 1 second its angular velocity would be 100 pixels per second, after 2 seconds it would be 200, after 3 seconds it would be 300, etc.
NOTE: If you keep applying angular acceleration, it will continue to change the sprite's angular velocity:
Example 1: A sprite initially has a angular velocity of zero (not rotating). Applying a positive angular acceleration will increase the sprite's angular velocity and cause it to start rotating clockwise. Continuing to apply a positive acceleration will continue to increase the sprite's angular velocity (making it rotate faster over time).
Example 2: A sprite initially has a positive angular velocity (rotating clockwise). Applying a negative acceleration will decrease the sprite's angular velocity (making its rotation slow down). Continuing to apply a negative acceleration will continue to decrease the sprite's angular velocity (making it slow down further) until it reaches zero (stops rotating) and then becomes negative (rotating again but now in the counter-clockwise direction).
Angular drag represents a negative acceleration that slows down the player when it is rotating. Angular drag is a type of friction also referred to as air resistance (or fluid resistance if rotating in a liquid).
Angular drag only affects the sprite when it is rotating. If the sprite is not rotating (angular velocity is zero), then drag will not affect it.
Drag is a number representing the sprite's reduction in rotational speed in degrees per second squared. By default, a sprite's angular drag is set to zero, unless you specifically change it.
For example, to set the angular drag for the player
sprite:
The effects of drag are most noticeable if your game changes the sprite's speed by using angular acceleration (instead of by setting a specific angular velocity value).
Phaser's Arcade Physics system has two methods to detect when sprites "touch" each other:
collide()
checks to see if two sprites are touching and keeps them separated (so they don't overlap, as if they were "solid") — if one or both of the objects is moving, they can transfer momentum between each other (e.g., one sprite might speed up while the other slows down, etc.)
overlap()
simply checks to see if two sprites are touching (but the objects can overlap and move past each other as separate layers)
The two sprites being checked for collide()
or overlap()
can be individual sprites and/or groups of sprites, such as:
Sprite vs. Sprite
Sprite vs. Group
Group vs. Group
For groups, each member of the group is checked individually. You can even check a group against itself. For example, you could check to see if any members of the same group are colliding with each other.
The collide()
and overlap()
commands must be placed in your update()
function, so your game will constantly check them during gameplay.
Different sprites can overlap and will move past other as separate layers unless you use a collide()
statement to keep them separated.
For example, to make the player
sprite collide with the enemyGroup
:
player, enemyGroup
are the names of the two sprites to check for collisions. You can check: sprite vs. sprite, sprite vs. group, group vs. group. Change these to match the names of your sprites or groups.
If two moving sprites collide with each other, they can transfer momentum between each other (depending on the mass
and velocity
of each sprite), which can change how fast they are moving. Also, they might "pile up" unless you give one or both of them a value for their physics body bounce
property.
If one of the sprites or groups has been set to immovable
, then its position or velocity will not be affected when another sprite collides with it. Sprites or groups representing platforms, walls, etc. are typically set to immovable
and then made to collide with the other sprites or groups.
For example, to make the player
sprite, coinGroup
, and enemyGroup
all collide with the platformGroup
:
To make members of the same group collide with each other, you can just list the group once:
This command tells the Arcade Physics system to check for collisions between any two members of enemyGroup
. This will keep the members separated and prevent them from moving past each other.
However, if you do make members of the same group collide with each other, they might "pile up" unless you give each of them a value for their physics body bounce
property.
Often, you'll want your game to perform certain actions whenever two specific sprites collide with each other.
For example, if the player
sprite collides with a member of the coinGroup
, you might want to perform several actions, such as: remove the specific member of the coinGroup
, play a sound effect, change the player's score, etc.
You can modify the collide()
command to list the name of a specific custom function that should run whenever a collision occurs between the two sprites. You will have to create the custom function in your game code.
The specific sprites involved in the collision will be passed into the custom function as parameters (variables), so you can perform actions involving them (such as: damage one of the sprites, etc).
For example, to call a custom function when the player
sprite collides with any member of enemyGroup
:
player, coinGroup
are the names of the two sprites to check for collisions. You can check: sprite vs. sprite, sprite vs. group, group vs. group. Change these to match the names of your sprites or groups.
collectCoin
is the name of the custom function to run. List the function name without parentheses. You will have to create this custom function in your game. Change this to any unique function name that makes sense for your game.
null, this
are additional parameters that you need to list.
Next, you will need to create the custom function by adding it after your update()
function:
collectCoin
is the name of the custom function. Change this to match the name you listed in your collide()
command.
player, coin
are the parameter variables that will be passed into the function by your collide()
command. These represent the two specific sprites involved in the collision. Change these to names that make sense for your collision.
The parameters are received in the same order as the original sprites or groups are listed in your collide()
command, so the order of the names matters (in order to make your code perform the actions you intend).
The parameter names that you use can be different from the original sprite or group names. However, it will be much easier to understand what's happening in the custom function if the names are either identical or similar to the original sprite or group names. (If the parameter represents a member of a group, then use a name similar to the group — but not the actual group name, which might be confusing.)
Inside the custom function, whatever you do to the parameter variables will affect the original sprites they represent.
In this example function, player
represents the player
sprite involved in the collision, and coin
represents the specific member of the coinGroup
that was involved in the collision. So if the command coin.kill()
were used inside the custom function, it would remove that specific member of the coinGroup
from the game world.
For example, the complete code for the collectCoin()
function might look like this:
Sometimes, you want your game to perform certain actions whenever two specific sprites touch each other — but you don't want to separate them by making them collide. This is when you would instead using the overlap()
method.
For example, if the player
sprite overlaps with a member of the checkpointGroup
, you might want to perform several actions, such as: play a sound effect, change the player's score, etc.
In the overlap()
command, you list the name of a specific custom function that should run whenever an overlap occurs between the two sprites. You will have to create the custom function in your game code.
The specific sprites involved in the overlap will be passed into the custom function as parameters (variables), so you can perform actions involving them (such as: damage one of the sprites, etc).
For example, to call a custom function when the player
sprite overlaps with any member of checkpointGroup
:
player, checkpointGroup
are the names of the two sprites to check for overlap. You can check: sprite vs. sprite, sprite vs. group, group vs. group. Change these to match the names of your sprites or groups.
updateCheckpoint
is the name of the custom function to run. List the function name without parentheses. You will have to create this custom function in your game. Change this to any unique function name that makes sense for your game.
null, this
are additional parameters that you need to list.
Next, you will need to create the custom function by adding it after your update()
function:
updateCheckpoint
is the name of the custom function. Change this to match the name you listed in your collide()
command.
player, checkpoint
are the parameter variables that will be passed into the function by your overlap()
command. These represent the two specific sprites that are overlapping. Change these to names that make sense for your overlap.
The parameters are received in the same order as the original sprites or groups are listed in your overlap()
command, so the order of the names matters (in order to make your code perform the actions you intend).
The parameter names that you use can be different from the original sprite or group names. However, it will be much easier to understand what's happening in the custom function if the names are either identical or similar to the original sprite or group names. (If the parameter represents a member of a group, then use a name similar to the group — but not the actual group name, which might be confusing.)
Inside the custom function, whatever you do to the parameter variables will affect the original sprites they represent.
In this example function, player
represents the player
sprite involved in the collision, and checkpoint
represents the specific member of the checkpointGroup
that was involved in the collision. So if the command checkpoint.kill()
were used inside the custom function, it would remove that specific member of the checkpointGroup
from the game world.
For example, the complete code for the updateCheckpoint()
function might look like this:
By default, the physics body collision area for a sprite is treated as a rectangle the same width and height of the image or spritesheet frames used for that sprite.
Sometimes the image or spritesheet for a sprite includes transparent areas around the outer edges. These transparent areas are counted as part of the sprite's collision area, so it can make collisions look or feel unnatural.
For example, here is an enlarged view of a spritesheet frame used for the player
sprite in Practice 3.
The gray-and-white checkerboard pattern represents transparent areas in the frame image. (The checkerboard pattern would not be visible in the game.)
The original spritesheet frame is 32 pixels in width and 48 pixels in height (including the transparent areas). By default, this will be the size of the collision area for this sprite.
However, using this default collision rectangle can result in collisions that look unnatural. For example, during gameplay, the sprite can look like it has completely stepped off the edge of a platform — yet it won't fall off because the sprite's transparent corner is still on top of the platform.
Instead, this sprite would behave more naturally in collisions if its collision area more closely matched its visual appearance, as shown below:
A pink rectangle has been added to show the size and position of a new collision rectangle that would work better for this sprite. (The rectangle would not be visible in the game.) This new collision rectangle is 20 pixels in width and 40 pixels in height. It is offset from the sprite's top-left corner by 8 pixels horizontally and 8 pixels vertically, so that it will be better positioned to match the sprite's visual body.
This new collision rectangle would ignore most (but not all) of the transparent area. Even this new collision rectangle is not perfect, as some of the sprite's head extends outside of the rectangle. However, overall, this rectangle is a much better match to the visual size of the body.
If necessary, you can change the size and position of the rectangle used to detect collisions of the sprite's physics body. (This won't change the visual appearance of the sprite.)
For example, to change the collision size for the player
sprite:
20, 40
represent the width and height (in pixels) of the collision rectangle. Change these numbers to match the size you want to use for your sprite.
8, 8
represent the horizontal offset and vertical offset (in pixels) of the collision rectangle's top-left corner, relative to the top-left corner of the sprite. Change these numbers to position the collision rectangle where you need it to be.
You can even change the sprite's collision area to have the shape of a circle, instead of a rectangle. In certain situations, this may make more sense than using a rectangular collision area.
For example, here is a spritesheet frame used for the asteroid sprites in Practice 2.
The spritesheet frame is 40 pixels in width and 40 pixels in height (including the transparent areas represented by the checkerboard pattern). By default, this would be the size of the collision area for this sprite.
A pink circle has been added to show the size and position of a new collision area that would work better for this sprite. (The circle would not be visible in the game.) This new collision circle is 30 pixels in diameter (15 pixels in radius). It is offset from the sprite's top-left corner by 5 pixels horizontally and 5 pixels vertically, so that it will be better positioned to match the sprite's visual body.
For example, to change the collision size for a asteroid
sprite:
15
represents the radius (in pixels) of the collision circle. Change this number to match the size you want to use for your sprite.
5, 5
represent the horizontal offset and vertical offset of the collision circle, relative to the top-left corner of the sprite. Change these numbers to position the collision circle where you need it to be.
WARNING: In some games, changing a sprite's collision area to be a circle can result in unusual bounce
effects if it collides with a sprite that has a rectangular collision area. Even if the sprite visually looks like a circle, sometimes the best way to get natural-looking collisions is to use a rectangular collision area for the sprite.
Arcade Physics has methods to find the specific member in a group that is closest or farthest to a target sprite (such as the player
sprite).
The closest()
and farthest()
methods return the specific member as an object, so you must assign the result (i.e., the specific member) to a local variable, in order to do something with the result.
For example, you could find the closest enemy to the player and then make that enemy fire a weapon at the player. The code might look like this:
Arcade Physics has methods to find the distance (in pixels) from a sprite to another object (another sprite, an image, etc.), a specific x, y
location, or the pointer's cursor location.
These distance methods return the distance as a number, so you must assign the result to a local variable, in order to do something with the result.
For example, you could find the distance between the player and a boss enemy, and then make the boss enemy fire a weapon at the player if the distance is below a certain value. The code might look like this:
Arcade Physics has methods to move or accelerate a sprite towards another object (another sprite, an image, etc.), a specific x, y
location, or the pointer's cursor location.
In the methods, you specify a value for the speed or acceleration to use when moving the sprite:
Positive values will move the sprite forwards.
Negative values will move the sprite backwards.
NOTE: These methods will move or accelerate the sprite in a direct line towards the destination. If you want the sprite to only move horizontally and/or vertically, then you may want to move the sprite using your own code, rather than these methods.
For example, you could find the closest enemy to the player and then move that enemy towards the player at a speed of 150 pixels per second. The code might look like this:
For example, your game could use the mouse to move the player. Whenever the mouse button is clicked, you could accelerate the player towards the mouse pointer location. The code might look like this:
Arcade Physics has methods to find the angle (in radians) from a sprite to another object (another sprite, an image, etc.), a specific x, y
location, or the pointer's cursor location.
These methods return the angle as a number, so you must assign the result to a local variable, in order to do something with the result.
Most people are familiar with using degrees to measure an angle. Radians are just another unit that can used to measure an angle (2π radians = 360°).
If needed, Phaser has a method to convert radians to degrees:
angleRad
represents an angle measured in radians
For example, the fire angle of a weapon uses degrees (not radians), so you could get the angle between a sprite and a "target" location, convert the angle from radians to degrees, and then set the weapon's fire angle (so the weapon is lined up with the "target").
As a reminder, sprites have a property called rotation
that can be used to rotate a sprite to a specific angle (in radians).
angleRad
represents an angle measured in radians
For example, once you get the angle between a sprite and a "target" location, you could rotate the sprite to that angle (so the sprite is lined up with the "target").
For example, you could get the angle between an enemy and the player, and rotate the enemy to that angle, so the enemy is pointed towards the player. The code might look like this:
For example, your game could use the mouse to shoot the player's weapon. Whenever the mouse button is clicked, you could get the angle between the player and the mouse pointer location. Then you could set the player's weapon to that angle (by converting radians to degrees) and fire the weapon. The code might look like this:
Arcade Physics has methods to move or accelerate a sprite in the direction of a specific angle. These methods are most commonly used to move a sprite in the direction of its current angle or rotation.
In the methods, you specify a value for the speed or acceleration to use when moving the sprite in the direction of the angle:
Positive values will move the sprite forward.
Negative values will move the sprite backwards.
As a reminder, Phaser has two properties for a sprite's angle of rotation:
sprite.angle
can be used to get or set the angle of rotation of the sprite, measured in degrees
sprite.rotation
can be used to get or set the angle of rotation of the sprite, measured in radians (2π radians = 360°)
Both properties do the same thing — they just use different units of measurement.
A common value used for angleDeg
is the sprite's current angle: sprite.angle
For example, you could use the arrow keys to rotate the player and to move the player forward or backwards in the direction of its current angle. The code might look like this:
A common value used for angleRad
is the sprite's current rotation: sprite.rotation
For example, for each member of an enemy group, you could rotate the enemy towards the player and then move the enemy forward towards the player. The code might look like this:
A common value used for angleRad
is the sprite's current rotation: sprite.rotation
For example, you could get the angle between an enemy and the player, and then accelerate the enemy forward at that angle (towards the player) — but without rotating the enemy's body.
You can create platforms that will move back-and-forth in a repeating pattern — either side-to-side or up-and-down. The player's sprite (and other sprites) can ride on top of these moving platforms.
You can make a platform move simply by setting a non-zero value for its body.velocity.x
(horizontal motion) or body.velocity.y
(vertical motion).
The instructions below will show you how to add moving platforms into your "regular" platform group, which will also contain your non-moving platforms.
In your create()
function, create a JSON array listing data for the moving platforms.
The example JSON array below lists data for 4 moving platforms:
Modify the JSON data for your platforms. Within the array, each platform's data is listed inside curly braces { }
using name-value pairs. You can list data for however many moving platforms you want.
For each platform, the following data should be listed:
x
represents the initial x-position of the top-left corner of the platform. List the value you want.
y
represents the initial y-position of the top-left corner of the platform. List the value you want.
asset
represents the name of the image asset key to use for the platform. Different platforms can use different assets, in order to look different and/or have different sizes. List the name of the asset you want to use. Be sure to list the asset name inside quotes.
direction
represents whether the platform should move horizontally (left-and-right) or vertically (up-and-down). List either 'horz'
or 'vert'
based on the motion you want.
distance
represents how far the platform should move (in pixels) before reversing its motion. Change this to the value you want.
speed
represents the speed (in pixels per second) at which the platform should move. Change this to the value you want. You can list either a positive value or a negative value, depending on which direction you want the plaftform to be initially moving:
For horizontally-moving platforms, a positive speed will make the platform initially move to the right, and a negative speed will make the platform initially move to the left. In either case, the platform will reverse direction once it has moved its specified distance.
For vertically-moving platforms, a positive speed will make the platform initially move downwards, and a negative speed will make the platform initially move upwards. In either case, the platform will reverse direction once it has moved its specified distance.
In your create()
function, create the moving platforms within your "regular" platform group using a for
loop and the JSON data.
Insert this for
loop after the commands that add your platformGroup
and enable physics on the group members. You can insert the for
loop before or after your code that adds non-moving platforms into the group.
If necessary, change platformGroup
to the name of your platform group (only need to change this in the first line of code inside the for
loop).
After adding all the platforms (moving and non-moving), be sure to set the body.immovable
property to true
for all members of your platform group.
In your update()
function, you need to check each moving platform in your platform group to see if it has moved its specified distance. If so, its direction will be reversed by multiplying its velocity by -1.
If necessary, change platformGroup
to the name of your platform group (only need to change this in the first line of code).
This code can be inserted anywhere in your update()
function, but it might make sense to place it towards the end after your collide()
statements and player input actions.
You can keep track of the elapsed time (or remaining time) in your game. You can also add timers to make certain events occur after a designated amount of time has elapsed.
Event timers work by calling a custom function (that you create) once the designated amount of time has elapsed. Your custom function contains whatever actions you want to perform for the event.
For example, your game might have power-ups that give the player a boost in speed for a certain amount of time. Once the player collects a power-up, your game could start a timer so the speed boost will be stopped by a custom function after 10 seconds.
Useful Constants for Setting Timers
Add Timer for Single Event
Add Timer for Repeated Event
Add Timer for Looping Event
Get Elapsed Game Time
Calculate Elapsed Time Between Events
Create Count Up Timer (Elapsed Game Time)
Create Countdown Timer (Game Time Remaining)
Start Timer After Specific Key Pressed
Timers are set in milliseconds (1000 ms = 1 second). You can list a specific number (e.g., 5000
would be 5 seconds) or a calculated number (e.g., 1000 * 5
would also be 5 seconds).
Phaser has two constants that are helpful when setting a timer:
Phaser.Timer.SECOND
represents the number of milliseconds in one second (1000 ms = 1 second).
Phaser.Timer.MINUTE
represents the number of milliseconds in one minute (60000 ms = 1 minute).
For example, imagine that you need to set a timer for 2 minutes. Any of these could be used to represent the number of milliseconds in 2 minutes:
120000
1000 * 60 * 2
Phaser.Timer.SECOND * 120
Phaser.Timer.MINUTE * 2
Even though any of those could be used, the last option is probably the easiest to understand when reading the code (and the least likely for you to make a mistake when typing the code).
You can set a timer for a single event. When the designated amount of time has elapsed, a custom function will be called to perform whatever actions you decide.
The generic code for setting a single event timer is:
time
is the amount of time (in milliseconds) that should elapse before calling the event function. Change this to any time that you need.
timerEvent
is the name of the custom function to run when the timer is completed. List the function name without parentheses. You will have to create this custom function in your game. Change this to any unique function name that makes sense for your game.
If you want the timer to start when the game starts, then set the timer in your create()
function.
If you want to start the timer at some other point during the game, then set the timer in your update()
function or in a custom function.
For example, to set a 10 second timer:
Then be sure to add your custom function after the update()
function:
You can set a timer for a repeated event. When the designated amount of time has elapsed, a custom function will be called to perform whatever actions you decide. Then a new timer will be started — this will repeat however many times you specify.
The generic code for setting a repeated event timer is:
time
represents the amount of time (in milliseconds) that should elapse before calling the event function. Change this to any time that you need.
quantity
represents the number of times that the timer should repeat itself.
timerEvent
is the name of the custom function to run when the timer is completed. List the function name without parentheses. You will have to create this custom function in your game. Change this to any unique function name that makes sense for your game.
If you want the timer to start when the game starts, then set the timer in your create()
function.
If you want to start the timer at some other point during the game, then set the timer in your update()
function or in a custom function.
For example, to set a 10 second timer that will repeat itself 5 times:
Then be sure to add your custom function after the update()
function:
You can set a timer for a looping event. When the designated amount of time has elapsed, a custom function will be called to perform whatever actions you decide. Then a new timer will be started — this will keep repeating in an endless loop throughout the game.
The generic code for setting a looping event timer is:
time
represents the amount of time (in milliseconds) that should elapse before calling the event function. Change this to any time that you need.
timerEvent
is the name of the custom function to run when the timer is completed. List the function name without parentheses. You will have to create this custom function in your game. Change this to any unique function name that makes sense for your game.
If you want the timer to start when the game starts, then set the timer in your create()
function.
If you want to start the timer at some other point during the game, then set the timer in your update()
function or in a custom function.
For example, to set a 30 second timer that will keep repeating in a loop:
Then be sure to add your custom function after the update()
function:
Phaser keeps track of how much total time has elapsed (in seconds) since the game started. You can get this value and assign it to a variable to do something with the result.
The total elapsed time will be a decimal number representing exactly how many seconds have elapsed since the game started.
If you want to get the exact time that a particular event occurred, you would use this:
If you want to get the elasped time rounded down to the nearest whole second, you would use this:
You can use global variables to store the exact time that two different events occurred in the game, and then subtract the times to calculate how much time passed between them.
For example, get the time that the first event occurred and store it in a global variable:
Then get the time that the second event occurred and store it in another variable. Subtract the two times to get the amount of time that elapsed between the two events:
As a more specific example, imagine that your game rewards the player for how fast they progress from one checkpoint to the next. Your game could have an overlap()
method to detect when the player reaches a checkpoint (assume that each checkpoint is a member of a group of sprites). When an overlap occurs, a custom function is called that gets the exact time the event occurred and awards a score point bonus based on how much time elapsed since the previous checkpoint.
For example, some of the code might look like this:
You can create a "count up" timer to display the elapsed time since the game started.
Create a global variable named timeText
that will be used to display the count up timer.
In your create()
function, add a text object by assigning it to timeText
. If you have an extended game world, be sure to make the text stay fixed to the camera view.
Next you'll add a custom function that get the current elapsed time (rounded down the nearest second) and then convert that into minutes and seconds to display on-screen as text.
After your update()
function, add this custom function:
update()
Now you just need to call the custom function in your update()
function, so it will update the count up timer every game loop.
Just include this as the first line of code inside your update()
function:
You can create a countdown timer to display the amount of time remaining in the game (based on a specified time limit). The timer starts counting down when the game starts.
You could display the countdown timer as text or as a timer bar. Both options will be provided below.
Before your preload()
function, declare a global variable named timeLimit
for your countdown timer, and assign it a value representing the number of seconds for the countdown timer (e.g., 120
would represent a 2 minute countdown timer). Declare a global variable named timeOver
that will be used to detect when the countdown timer has reached zero. Also declare a global variable named timeText
that will be used to display the time remaining.
In your create()
function, add a text object by assigning it to timeText
. If you have an extended game world, be sure to make the text stay fixed to the camera view.
Next you'll add a custom function that get the current elapsed time (rounded down the nearest second) and then convert that into minutes and seconds to display on-screen as text.
After your update()
function, add this custom function:
update()
Now you just need to call the custom function in your update()
function, so it will update the count up timer every game loop until the time runs out.
Just include this at the beginning of your update()
function:
Create an image of a solid rectangle (whatever color you want) that will be used as the timer bar (to represent time remaining). This example will use a green rectangle that is 200px in width and 20px in height:
Create an image of an identical-sized solid rectangle (of a different color) that will be used as a background bar (to represent elapsed time). This example will use a red rectangle that also is 200px in width and 20px in height:
Before your preload()
function, declare a global variable named timeLimit
for your countdown timer, and assign it a value representing the number of seconds for the countdown timer (e.g., 120
would represent a 2 minute countdown timer). Declare a global variable named timeOver
that will be used to detect when the countdown timer has reached zero. Finally, declare a global variable named timeBar
for the timer bar:
In your preload()
function, load the two rectangle images:
The background bar (red) and the timer bar (green) will be added to the game at the same position. However, the background bar will be added first, so it will be stacked behind the timer bar.
In your create()
function, add the background bar by assigning it to a local variable. Then add the timer bar at the same position by assigning it to its global variable.
You should also add a text label to the left of the bars by assigning it to a local variable.
If your game world is larger than your game display, then be sure to make the images and text label fixed to the camera.
As the amount of time remaining decreases, the width of the timer bar is supposed to shrink proportionately. When the timer bar shrinks, it will reveal some of the background bar behind it.
We can make the timer bar shrink by changing its scale
property. The correct value for the scale can be calculated by dividing the time remaining by the time limit.
After your update()
function, add this custom function:
update()
Now you just need to call the custom function in your update()
function, so it will update the count up timer every game loop until the time runs out.
Just include this at the beginning of your update()
function:
You can also make your timer wait to start until a specific key is pressed. The player won't be able to perform any other actions until the "start" key has been pressed.
In this example, we'll use the spacebar as the "start" key. Once the game is "started," this same key can be used instead for other normal game actions. For example, some games use the spacebar for actions such as jumping or firing a weapon.
This example will work with a countdown timer or a countup timer - but you'll need to use a slightly modified function for your timer that adjusts for the actual "start time" when the player first pressed the spacebar key.
Before your preload()
function, declare a global variable named started
, and assign it a value of false
(later when the spacebar key is first pressed, you'll change this variable to a value of true
).
Declare another global variable named startTime
, and assign it an initial value of zero (later this variable will be used to store the time when the spacebar key is first pressed).
Finally, declare a global variable named spacebar
that will be used to represent the spacebar key.
Within your create()
function, make the spacebar
variable represent user input using the spacebar key.
Again, if you also want to use the spacebar for other player actions (such as jumping, firing weapon, etc.) after the game is "started," you'll be able to do so.
Within your update()
function, you'll add some if
statements that will check whether the variable named started
has a value of true
or false
. These will be added after your game.physics.arcade.collide()
functions (which are usually listed at the beginning of the update()
function).
If started
has a value of true
, then the game will updated the time left in the countdown timer and check for any player input to perform normal game actions (such as moving, jumping, firing weapon, etc.).
However, if started
has a value of false
, then the game will only check to see if the spacebar was pressed. The game will NOT update the countdown timer (meaning it will act like it is "paused"), and the game won't allow the player to perform any other actions. The game is simply waiting for the player to press the spacebar.
Once the spacebar is pressed, the game will change the value of started
to true
, and store the current game time in the startTime
variable (so the timer can adjust itself based on the start time).
Finally, you'll have to modify your timer function to adjust for the start time (when the player first pressed the spacebar).
The custom function for your timer should be placed after the update()
function.
Here's a modified countdown timer function for displaying a shrinking time bar:
If you are using a countup timer, your modified timer function would instead look like this:
You can add a special type of image object called a sprite to your game world. Sprites are used for characters and other game objects that need to move and interact with each other.
Sprites are basically image objects that have additional properties allowing for animations, simulated physics interactions (moving, falling, colliding, etc.), and simulated life (gaining health, losing health, being killed, etc.).
A sprite can be created from a regular image, but an animated sprite will need to use a special type of image called a spritesheet, which is a set of identical-sized smaller images (called frames) that have been combined into one large image (which usually has a transparent background).
Example spritesheet image consisting of 9 frames
At any given moment during gameplay, a sprite only displays one possible frame from its spritesheet. By rapidly changing which frame is displayed, the game can animate the sprite to create the illusion that it is moving or changing.
Load Spritesheet
Add Sprite
Change Anchor for Sprite Position
Get Current Position of Sprite
Change Position of Sprite
Rotate Sprite to Angle
Add Animations to Sprite
Play Animations
Display Specific Sprite Frame
Hide Sprite (and Unhide)
Remove Sprite (Kill)
Set Sprite Lifespan
Set Sprite Health
Damage or Heal Sprite
Set Maximum Health for Sprite
Recycle Dead Sprite (Revive or Reset)
Run Function When Sprite Killed
Create Health Bar
Create Lives Counter
Each spritesheet image file (also referred to as an asset) must be loaded into the game's memory before you can add it to your game world.
The command to load an asset is always placed in your preload()
function.
'dude'
represents an asset key — a key is sort of like a variable name. You decide what string to use for the key, as long as each spritesheet asset has a unique key.
'assets/images/dude.png'
represents the folder path and filename of the spritesheet image to load. Change this to match your specific folder path and filename.
32, 48
represent the width and height (in pixels) of each frame within the spritesheet. Phaser will use these measurements to divide the spritesheet into a set of individual frames. Change these values to match your frame size.
If you're not sure of the size of each frame in a spritesheet, you can easily calculate it from the size of the entire spritesheet.
Spritesheets have their identical-sized frames combined into a grid (with a certain number of columns and rows).
Determine the width and height (in pixels) of the spritesheet image. One way to do this is to open the spritesheet in an image editor (such as Pixlr Editor, etc.).
Count the number of frames (columns) contained in the top row across the spritesheet's width. Divide the width of the spritesheet by the number of columns. The result should be a whole number and represents the width of each frame.
Count the number of frames (rows) contained in the left column down the spritesheet's height. Divide the height of the spritesheet by the number of rows. The result should be a whole number and represents the height of each frame.
Once a sprite's asset (either a "regular" image or a spritesheet) has been loaded into memory, you can add the sprite to your game world.
Declare a global variable for the sprite, and add the sprite by assigning it to the variable. The command to add a sprite is typically placed in the create()
function.
player
represents a variable name. Change this to the name of your variable.
100, 500
represent the x
and y
coordinates where the sprite will be positioned in the game world (based on the sprite's anchor, which is its top-left corner by default). Change these values to the position you need.
'dude'
represents the asset key of the spritesheet (or image) to use. Replace this with your asset key.
The x
and y
coordinates of a display object (text, image, sprite, etc.) represent the position of the object's anchor.
By default, an object's anchor is its top-left corner. However, you can change the anchor for an object (e.g., to make the object's center become its anchor for positioning).
The command to change the anchor is typically placed in the create()
function (after adding the sprite).
For example, to change the anchor of a sprite named player
:
The first number represents the horizontal position of the anchor, as a number between 0-1 (0 = left edge, 0.5 = horizontal center, 1 = right edge).
The second number represents the vertical position of the anchor, as a number between 0-1 (0 = top edge, 0.5 = vertical center, 1 = bottom edge).
For most sprites, it will make the most sense to set its anchor to its center (0.5, 0.5)
.
However, for some sprites, it might make more sense to set its anchor to its top-middle (0.5, 0)
or bottom-middle (0.5, 1)
— or possibly just leave the anchor as the top-left corner (the default).
The current x
and y
coordinates of an sprite's position (based on its anchor) are stored as properties of the sprite.
For example, to get the current position of a sprite named player
:
player.x
represents its current x
coordinate
player.y
represents its current y
coordinate
If you need to change the position of a sprite, just change its x
and/or y
coordinates.
For example, you could change the position of a sprite named player
:
As another example, you can also move a sprite relative to its current position:
In the example above, the player
sprite would be moved 5 pixels to the right and 5 pixels up from its current position.
Increasing the x
coordinate moves an object to the right, while decreasing x
moves the object to the left.
Increasing the y
coordinate moves an object down, while decreasing y
moves the object up.
It will typically be more common that a sprite's position is changed automatically by its simulated physics properties — e.g., its velocity will cause the sprite to move, its gravity will cause the sprite to fall, etc.
You can rotate an image (around its anchor point) by changing the value of its angle
property.
For example, you could rotate a sprite named player
:
-90
represents the angle in degrees. Change this to any value from -180 to 180. Negative values rotate the image counterclockwise. Positive values rotate the image clockwise.
Phaser also has a property called rotation
that can be used to get or set the angle of rotation of a sprite. The only difference is that the rotation
property uses radians for its units, instead of degrees (2π radians = 360°).
A spritesheet typically contains one or more sequences of frames that represent animations.
For example, in the spritesheet shown below, the first four frames represent an animation sequence for "running to the left", the fifth frame represents "standing still", and the last four frames represent an animation sequence for "running to the right."
Sprite frames are referenced by an index number, with the first frame numbered as 0, the second frame numbered as 1, the third frame numbered as 2, etc.
You can add an animation sequence to a sprite by specifying which particular frames should be played during the animation.
The command to add an animation is typically placed in the create()
function (after adding the sprite).
For example, to add an animation to a sprite named player
(using the spritesheet shown above):
'left'
represents an animation key — a key is sort of like a variable name. You decide what string to use for the key, as long as each animation has a unique key.
[0, 1, 2, 3]
is an array listing the index numbers of the specific spritesheet frames to use for the animation. The frames will be played in the order listed in the array. Change the array to list whichever frame numbers you need (in the order you need them to play).
10
represents the frame rate for the animation, in frames per second. Depending on your animation, you can change this number to make it play faster or slower.
true
indicates that this animation should play repeatedly in a loop. If you don't want an animation to loop, then list false
.
This just adds the animation into memory, so it's ready to use. The animation won't actually play until you use a command telling it to start playing.
If your sprite has multiple animations, use additional commands to add the other animation(s):
Animations won't play until you tell them to do so.
For example, to play an animation that was added to a sprite named player
:
'right'
represents the animation key to play. Change this to your animation key.
To switch the sprite to play a different animation, simply change the animation key:
To stop a sprite's animation:
When the animation stops, the sprite will display a random frame from the most recent animation (whichever frame was being displayed at the exact moment the animation stopped).
In some cases, you may want to the sprite to display a specific frame when no animation is being played.
To make a sprite display a specific frame (e.g., when no animation is being played), simply change the frame
property of the sprite.
4
represents the index number of the frame to display. Remember that frames are numbered starting with 0 (so 4 is actually the 5th frame of the spritesheet). Change this value to the frame index number you want.
There are two properties that can be used to hide a sprite:
visible
property
exists
property
You can change a sprite's visible
property to make the sprite invisible. However, the sprite will still be involved in physics interactions (moving, falling, colliding, etc.) because the sprite still exists (it's just invisible).
For certain games, invisible sprites could be interesting (e.g., creating invisible enemies that the player must avoid, etc.).
For example, to make a sprite named enemy
invisible:
To make the sprite visible again:
You can change a sprite's exists
property to make the sprite invisible and also prevent it from being affected by any physics interactions. When you want, you can easily make the sprite exist again.
For example, to make a sprite named powerUp
not exist:
To make the sprite exist again:
You can remove a sprite from the game use the kill()
method. This sets the sprite's visible
, exists
, and alive
properties to false
.
For example, to remove a sprite named coin
:
Killing a sprite removes it from the game, but not from the game's memory. This allows you to recycle "dead" sprites by adding them back into the game using the revive()
or reset()
method. For example, this would allow you to give the player's character additional lives — or to replenish resources or enemies that get removed during the course of the gameplay.
If desired, you can give a sprite a limited lifespan in the game, which will automatically remove (kill) the sprite after it has existed for a certain amount of time.
For example, to set a lifespan for a sprite named powerUp
:
5000
represents duration of the lifespan in milliseconds (1000 ms = 1 second). The lifespan begins as soon as the sprite has been added to the game. When the lifespan expires, the sprite will be automatically removed (killed).
If desired, you can give a sprite a certain amount of health. Your game can have various ways for the sprite to gain health (collecting resource, etc.) or lose health (being attacked, etc.). If the sprite's health reaches zero, the sprite will be automatically removed (killed).
This health property is typically used for sprites representing characters (player, enemies, allies, etc.) — but it can be used for any sprite you want (obstacles that must be destroyed, etc.).
For example, to set the health for a sprite named player
:
100
represents amount of health. Change this to any value that makes sense for your game.
You should set a sprite's initial health value in the create()
function after adding the sprite. If needed, you can also set a new value in the update()
function or custom functions if certain conditions or events occur.
You can increase or decrease a sprite's health using the heal()
or damage()
method. You would most likely use these methods in the update()
function or custom functions if certain conditions or events occur in the game.
For example, to decrease the health for a sprite named player
:
10
represents amount to decrease the sprite's health. Change this to any value that makes sense for your game.
For example, to increase the health for a sprite named player
:
10
represents amount to increase the sprite's health. Change this to any value that makes sense for your game.
You can also set the maximum health for a sprite (so it cannot be healed beyond this value).
For example, to set the maximum health for a sprite named player
:
100
represents the maximum health value possible for the sprite. Change this to any value that makes sense for your game.
You would typically set a sprite's maximum health value in the create()
function after adding the sprite and setting its initial health value. If needed, you can also set a new value for the maximum health in the update()
function or custom functions if certain conditions or events occur.
You can recycle "dead" sprites by adding them back into the game using the revive()
or reset()
method. For example, this would allow you to give the player's character additional lives — or to replenish resources or enemies that get removed during the course of the gameplay.
If you have a group of sprites, there is a method to getFirstDead()
sprite in the group. For more information on this method, see Groups of Objects.
REVIVE: The revive()
method adds the dead sprite back into the game at the same position where it was killed (though you add commands to change the sprite's position). The sprite will also have the same values for its physics motion (velocity, acceleration, etc.) that it had when it was killed (though you can add commands to change these values).
RESET: The reset()
method adds the dead sprite back into the game at a specific position you indicate. It also resets the sprite's physics motion (velocity, acceleration, etc.) to zero.
You can use revive()
and reset()
for sprites that are supposed to have health (player, etc.) or for sprites that don't have health (resource, etc.).
For example, to revive a dead sprite named powerUp
that isn't supposed to have health:
For example, to revive a dead sprite named player
that should have health:
50
represents the amount of health to give the sprite when adding it back to the game. Change this to any value that makes sense for your game.
For example, to reset a dead sprite named powerUp
that isn't supposed to have health:
400, 200
represent the x
and y
coordinates where the sprite will be added back into the game world (based on the sprite's anchor, which is its top-left corner by default). Change these values to the position you need.
For example, to revive a dead sprite named player
that should have health:
The first two numbers 100, 500
represent the x
and y
coordinates where the sprite will be added back into the game world (based on the sprite's anchor, which is its top-left corner by default). Change these values to the position you need.
The last number 50
represents the amount of health to give the sprite when adding it back to the game. Change this to any value that makes sense for your game.
You can add an onKilled
event to a sprite to run a function whenever that sprite is killed (either because the kill()
method was used on the sprite or because the sprite's health
reached zero).
The onKilled
event should be added in your create()
function (after adding the sprite).
For example, to add an onKilled
event for the player
sprite:
An onKilled
event is commonly added to the player sprite to end the game — or to add the player back into the game (e.g., back to the start or at a checkpoint) depending on how many "lives" the game allows (endless or limited).
For example, this code checks to see if the player has any lives remaining. If so, the player is reset back into the game at the last checkpoint position with full health. If the player is out of lives, then it runs a custom function called gameOver()
:
Some games display a health bar to represent how much health the player's character has remaining compared to the maximum possible. The health bar shrinks or expands as the player's health changes.
You can create your own custom health bar by following these steps:
Create an image of a solid rectangle (whatever color you want) that will be used as the health bar (to represent health remaining). This example will use a green rectangle that is 200px in width and 20px in height:
Create an image of an identical-sized solid rectangle (of a different color) that will be used as a background bar (to represent missing health). This example will use a red rectangle that also is 200px in width and 20px in height:
Before your preload()
function, declare a global variable for the health bar:
In your preload()
function, load the two rectangle images:
In your create()
function, set the values for the initial health and the maximum health for your player's sprite (after adding the sprite):
The background bar (red) and the health bar (green) will be added to the game at the same position. However, the background bar will be added first, so it will be stacked behind the health bar.
In your create()
function, add the background bar by assigning it to a local variable. Then add the health bar at the same position by assigning it to its global variable.
You should also add a text label to the left of the bars by assigning it to a local variable.
If your game world is larger than your game display, then be sure to make the images and text label fixed to the camera.
When the player's health changes, the width of the health bar is supposed to shrink or expand proportionately. If the health bar shrinks, it will reveal some of the background bar behind it. If the health bar expands, it will cover more of the background bar.
We can make the health bar shrink or expand by changing its scale
property. The correct value for the scale can be calculated by dividing the player's health by its maximum health value.
For example, if the player's health is currently 25 and its maximum health value is 100, the current scale for the health bar should be 0.25 (25/100 = 0.25), which would look like this:
Anytime the player's health changes (sprite is damaged, healed, revived, or reset), you need to change the scale for the width of the health bar:
This command sets a scale value for the width and height of the health bar:
player.health / player.maxHealth
is the calculated scale for the width
1
is the scale for the height (1 = 100% height)
HINT: If desired, you could use these steps to create a scalable bar to represent other elements of your game (such as: timer bar, progress bar, etc.).
Some games display a counter to represent how many lives the player has remaining. This counter could simply be shown as a number. However, in some games, the lives counter is shown as a row of icons representing the individual lives remaining. As the number of lives changes, the number of icons displayed changes.
Games that utilize an icon-based lives counter typically set a relatively low limit ( < 10) on the maximum number of lives available. (Otherwise, if the limit is higher, it is probably better to just display an actual number to the player.)
You can create your own custom icon-based lives counter by following these steps:
First determine the maximum number of lives that your game will allow the player to accumulate. Next you need to create an image similar to a spritesheet that shows a row of icons representing the maximum number of lives.
For example, here is the image created for the lives counter used in the Asteroids 2084 game. It shows 5 spaceship icons, which represents the maximum number of lives in this game.
The best way to create an image like this is to find or create an icon representing one life. Determine the width of the icon, and then paste copies of it side-by-side at evenly-spaced widths to create a row of icons. Save this image as your lives counter.
For example, the spaceship icon is 25px in width (including the transparent area on both sides). Copies of the icon were placed side-by-side every 25px, so the final image of 5 icons is 125px in width (5 × 25 = 125).
Before your preload()
function, declare global variables for the current number of player lives and the maximum number of lives, and assign values to both.
You also need to declare global variables to represent the lives counter image, the width of each lives icon, and a rectangle that will be used to crop the lives counter image:
In your preload()
function, load the lives counter image:
In your create()
function, add the lives counter image by assigning it to its global variable. Also add a text label by assigning it to a local variable. If your game world is larger than your game display, be sure to make the image and text label fixed to the camera.
Phaser allows you to apply a rectangular crop to an image. Any portion of the image outside the crop rectangle will be hidden from view. The crop is a reversible visual effect — you can adjust the size of the crop whenever needed.
The crop rectangle for the lives counter should:
be positioned at the top-left corner of the lives counter image
have a width equal to the number of lives multiplied by the width of a lives icon
have the same height as the lives counter image (to show its full height)
In your create()
function (immediately after adding the lives counter image and its text label), add this code:
livesIcon
represents the width of an individual icon in the lives counter image. The icon width is calculated by dividing the width of the entire lives counter image by the maximum number of lives (i.e., the number of icons in the image).
livesCrop
is the rectangle that will be used to crop the lives counter image:
0, 0
will be the position of the crop rectangle relative to the top-left corner of the image being cropped.
lives * livesIcon
will be the width of the crop rectangle.
livesCounter.height
will be the height of the crop rectangle.
The crop()
method applies the crop rectangle to the lives counter image.
Anytime the player gains or loses a life (i.e., anytime the value of lives
changes), you need to re-calculate the width of the crop rectangle, and then update the crop of the lives counter image (to show more or fewer icons):
HINT: If desired, you could use these steps to create an icon-based counter to represent other elements of your game (such as: number of resources remaining, number of achievements earned, etc.).