#PhaserFriday: Phaser Basics: Input and Arcade Physics

[#PhaserFriday is a running series on the HTML5 game framework Phaser covering everything from basics of sprites to creating platformer games.]

Note: all examples in this post assume you have already loaded Phaser in a browser session or development environment.

Building from the last post, we move on to input and Arcade physics…

Basic Input

Adding and removing sprites isn’t very interesting in and of itself. If we are making a game, we inevitably want a player to interact with something at some point. Be that clicking on something or pressing a button to move a character, players want to have some agency.

Pressing buttons to do things

Now that we can add sprites to the screen, we want to be able to move them about. To to that, we use the game.input functionality AND finally start to use the update function.

See, it isn’t enough to move an object just once. We want to check on some recurring basis and, if the player has supplied some input, move something according. To do that, we need to check the input in the update function.

var game = new Phaser.Game(
200, //The width in pixels
200, //The height in pixels
Phaser.AUTO, //The render system
"phaser", //The element
{
preload: preload, // The preload function
create: create, // The create function
update: update // The update function
}
);
// Create the variable outside of any one function scope
var sprite;
function preload() {}
function create() {
sprite = game.add.sprite(
50, // The x position
50, // The y position
'sprite' // The image cache-key
);
}
function update() {
// Check if the player is pressing Keyboard.LEFT
if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
// If Keyboard.LEFT is down (being pressed),
// move 'sprite' 4 pixels to the left
sprite.x -= 4;
}
}
view raw script.js hosted with ❤ by GitHub

n the above example, we are using a specialized function of game.input.keyboard called isDown that takes an argument of some Phaser.Keyboard object and checks if it is actually down (currently pressed) or not. And if it is, in our example, we move ‘sprite’ four pixels to the left.

Note: If you are not familiar, nearly all drawing systems on computers use a coordinate system of 0,0 in the upper left-hand corner and some n, n at the bottom right-hand side. Moving to the right, then, is adding to the ‘x’ position. Moving down is adding to the ‘y’ position. Subtracting (or adding negative numbers) would mean moving up or to the left as in our example.

Different buttons, different things

Adding more buttons to press is simply a matter of checking those same buttons. If we wanted to move up, we would check some button for that. For down, some button for that. For every action we wanted the player to take involving pressing a button, we would need to check for that.

var game = new Phaser.Game(
200, //The width in pixels
200, //The height in pixels
Phaser.AUTO, //The render system
"phaser", //The element
{
preload: preload, // The preload function
create: create, // The create function
update: update // The update function
}
);
// Create the variable outside of any one function scope
var sprite;
function preload() {}
function create() {
sprite = game.add.sprite(
50, // The x position
50, // The y position
'sprite' // The image cache-key
);
}
function update() {
if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
sprite.x -= 4; // Move left
}
if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
sprite.x += 4; // Move right
}
if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) {
sprite.y -= 4; // Move up
}
if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
sprite.y += 4; // Move down
}
}
view raw script.js hosted with ❤ by GitHub

In the above example, we can move the sprite around on the screen by using the arrow keys. As long as one of the four keys that are checked are ‘down’, the sprite will move in that direction. However, what if we had another sprite on the screen at the same time — and what if they collided with each other? For that, we need some physics.

How (Arcade) Physics Works

Phaser comes with three different physics systems: Arcade, Box2D, and P2. Each acts in a different way and can be used to check for a variety of issues between two items colliding on the screen.

However, for these examples, and in general, it is probably enough to use the Arcade system to detect if two or more objects might be colliding on the screen.

To enable the Arcade (or other) physics system, we start said system and, on the objects on which we want to use it, enable its “physics body.”

Note: In game design terms, a “physics body” is how some object is understood by the physics system or engine. Generally, it is how the ‘body’ is shaped, too. In the case of Phaser and Arcade physics in particular, this means a square matching the sprite’s image and some default values about how it can move.

var game = new Phaser.Game(
200, //The width in pixels
200, //The height in pixels
Phaser.AUTO, //The render system
"phaser", //The element
{
preload: preload, // The preload function
create: create, // The create function
update: update // The update function
}
);
// Create the variable outside of any one function scope
var sprite;
function preload() {}
function create() {
// Start the Arcade physics system
game.physics.startSystem(Phaser.Physics.ARCADE);
sprite = game.add.sprite(
50, // The x position
50, // The y position
'sprite' // The image cache-key
);
// Enable Arcade physics on 'sprite'
game.physics.arcade.enable(sprite);
}
function update() {}
view raw script.js hosted with ❤ by GitHub

Velocity

With a physics system enabled, we can move sprites in a new way. Instead of using the pixel movements of adding or subtracting numbers, we can use the concept of velocity.

Note: Within the general study of physics, a velocity is some speed and a direction. Things like gravity, for example, can be described in terms of velocity.

var game = new Phaser.Game(
200, //The width in pixels
200, //The height in pixels
Phaser.AUTO, //The render system
"phaser", //The element
{
preload: preload, // The preload function
create: create, // The create function
update: update // The update function
}
);
// Create the variable outside of any one function scope
var sprite;
function preload() {}
function create() {
// Start the Arcade physics system
game.physics.startSystem(Phaser.Physics.ARCADE);
sprite = game.add.sprite(
50, // The x position
50, // The y position
'sprite' // The image cache-key
);
// Enable Arcade physics on 'sprite'
game.physics.arcade.enable(sprite);
}
function update() {
sprite.body.velocity.x = 0;
if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
sprite.body.velocity.x = -40; // Move left
}
if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
sprite.body.velocity.x = 40; // Move right
}
}
view raw script.js hosted with ❤ by GitHub

Note in the above example, velocity works via some object’s body and, like the pixel movements on the screen, matches the negative and positive changes (i.e. negative for up and left, positive for right and down).

Collision detection

In video game design terms, “collision detection” is critically important. Within a physics system, we need to know if a character is touching some spikes, is about to be hit by a barrel, or if bullets are impacting something.

To detect a collision with the Arcade system in Phaser, we use game.physics.arcade.collide and provide it with either two objects or groups. If any of the entries used as arguments are colliding, the function will return true. Put within the update function, we check to see in each loop if this is happening and then do something about about as a result.

Separation

In its most common form, game.physics.arcade.collide is simply two collections or objects and acts, upon detecting a collision between any of the objects, to separate them. Without any other instructions, it simply does that.

However, if we want a more detailed check from the Arcade physics system, we can also supply two more arguments to game.physics.arcade.collide: collision and process callbacks. If we want to perform some actions when things collide other than simply separating them, we can supply a function that is called when a collision is detected. If on the other hand, we wanted to add to the rules of collision, for example they collide AND their health is at a certain amount, we can add some extra process function that would make some decision and return true or false as a result.

var game = new Phaser.Game(
200, //The width in pixels
200, //The height in pixels
Phaser.AUTO, //The render system
"phaser", //The element
{
preload: preload, // The preload function
create: create, // The create function
update: update // The update function
}
);
// Create the variables outside of any one function scope
var sprite;
var sprite2;
function preload() {}
function create() {
// Set the 'game.stage' to a color
game.stage.backgroundColor = '#2d2d2d';
// Start the Arcade physics system
game.physics.startSystem(Phaser.Physics.ARCADE);
sprite = game.add.sprite(
50, // The x position
20, // The y position
'sprite' // The image cache-key
);
sprite2 = game.add.sprite(
50, // The x position
150, // The y position
'sprite' // The image cache-key
);
// Enable Arcade physics on 'sprite'
game.physics.arcade.enable(sprite);
// Enable Arcade physics on 'sprite2'
game.physics.arcade.enable(sprite2);
// Make sure 'sprite' does not leave the world
sprite.body.collideWorldBounds = true;
// Make sure 'sprite2' does not leave the world
sprite2.body.collideWorldBounds = true;
// Set a velocity for 'sprite'
sprite.body.velocity.y = 40;
// Set an equal velocity for 'sprite2'
sprite2.body.velocity.y = -40;
}
function update() {
// Check if 'sprite' and 'sprite2' collide with each other
game.physics.arcade.collide(
sprite, // The first entry
sprite2, // The entry to check against
collisionCallback, // The collision callback
processCallback // The process callback
);
}
function collisionCallback(object1, object2) {
// When they collide, set the background to a different color
game.stage.backgroundColor = '#992d2d';
}
function processCallback() {
// Within the process callback, we can test for extra things.
// For example, if we wanted to check if their health matched
// of if they were of different enemy types, we can do that here.
//
// For what ever we test, we need to return either true or false.
}
view raw script.js hosted with ❤ by GitHub

Energy transference (i.e. hitting things with other things)

Sure, we can move objects using velocity, but what if we wanted to collide things moving at different speeds? Instead of having them cancel each other out, what if we had objects moving at different speeds or with different masses? What would happen then?

Within many physics systems (including the Arcade on in Phaser), this is known as “energy transference.” Think of it in terms of some fast moving thing hitting something sitting still. Energy is transferred between the objects.

var game = new Phaser.Game(
200, //The width in pixels
200, //The height in pixels
Phaser.AUTO, //The render system
"phaser", //The element
{
preload: preload, // The preload function
create: create, // The create function
update: update // The update function
}
);
// Create the variables outside of any one function scope
var sprite;
var sprite2;
function preload() {}
function create() {
// Start the Arcade physics system
game.physics.startSystem(Phaser.Physics.ARCADE);
sprite = game.add.sprite(
50, // The x position
50, // The y position
'sprite' // The image cache-key
);
sprite2 = game.add.sprite(
50, // The x position
100, // The y position
'sprite' // The image cache-key
);
// Enable Arcade physics on 'sprite'
game.physics.arcade.enable(sprite);
// Enable Arcade physics on 'sprite2'
game.physics.arcade.enable(sprite2);
// Make sure 'sprite' does not leave the world
sprite.body.collideWorldBounds = true;
// Make sure 'sprite2' does not leave the world
sprite2.body.collideWorldBounds = true;
}
function update() {
sprite.body.velocity.y = 0;
if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) {
sprite.body.velocity.y = -40; // Move up
}
if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
sprite.body.velocity.y = 40; // Move down
}
// Check if 'sprite' and 'sprite2' collide with each other
game.physics.arcade.collide(sprite, sprite2);
}
view raw script.js hosted with ❤ by GitHub

In the above example, energy is transferred between the objects upon their collision. When one moving (via velocity) object touches another, the amount of change as divided by their mass is transferred.

What if we didn’t want both objects to move, though? Is there a way to make an immovable object?

Immovable objects (and how to move them)

Sometimes, we want to have objects that obey the physics rules, but we don’t want them to move as a result of collisions. These are immovable — and, yes, they can be moved, too.

In the case of Arcade physics in Phaser, we set this option as a boolean on the sprites themselves using body.immovable. Once set, the object will not be acted upon as a result of collisions. It can still be moved using its coordinates or using its velocity, though, but will “absorb” any energy transferred to it when it collides or or other things run into it.

var game = new Phaser.Game(
200, //The width in pixels
200, //The height in pixels
Phaser.AUTO, //The render system
"phaser", //The element
{
preload: preload, // The preload function
create: create, // The create function
update: update // The update function
}
);
// Create the variables outside of any one function scope
var sprite;
var sprite2;
function preload() {}
function create() {
// Start the Arcade physics system
game.physics.startSystem(Phaser.Physics.ARCADE);
sprite = game.add.sprite(
50, // The x position
50, // The y position
'sprite' // The image cache-key
);
sprite2 = game.add.sprite(
50, // The x position
100, // The y position
'sprite' // The image cache-key
);
// Enable Arcade physics on 'sprite'
game.physics.arcade.enable(sprite);
// Enable Arcade physics on 'sprite2'
game.physics.arcade.enable(sprite2);
// Make sure 'sprite' does not leave the world
sprite.body.collideWorldBounds = true;
// Set 'sprite2' to be immovable
sprite2.body.immovable = true;
}
function update() {
sprite.body.velocity.y = 0;
if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) {
sprite.body.velocity.y = -40; // Move up
}
if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
sprite.body.velocity.y = 40; // Move down
}
// Check if 'sprite' and 'sprite2' collide with each other
game.physics.arcade.collide(sprite, sprite2);
}
view raw script.js hosted with ❤ by GitHub