In this post, we’re going to look at implementing a “click-to-move” style control scheme, as seen in games such as RuneScape and Diablo.
This control setup is particularly useful for games that require cross-platform support. In other words games that work on mobile as well as they do on desktop.
This tutorial assumes you have a modern development environment setup for Phaser 3. If you don’t, follow the link to read my tutorial on how to do so!
After setting up your project, preload in a couple assets. For my example I use the following:
- A cat to act as our player
- A bouncing arrow to indicate where we’re going
After preloading your assets, head over to your main game scene (in my case GameScene
). Below is the code I used:
import {Scene, Math as pMath} from 'phaser';
const {Vector2} = pMath;
class GameScene extends Scene {
constructor() {
super("scene-game");
}
create() {
// Set a nice background colour
this.cameras.main.setBackgroundColor(0x3399FF);
// Add and adjust our sprite
this.cat = this.physics.add.sprite(10, 10, 'cat-like');
this.cat.body.setAllowGravity(false);
this.cat.setScale(0.5);
// Adding an arrow is optional, but a nice touch
this.arrow = this.physics.add.sprite(0, 0, 'arrow');
this.arrow.body.setAllowGravity(false);
this.arrow.setVisible(false);
this.arrow.setScale(2);
this.arrow.play({ key: 'arrow-osc', repeat: -1 });
// Initialize our target position as a 2D vector
this.target = new Vector2();
// When the user releases the screen...
this.input.on('pointerup', (pointer) => {
// Get the WORLD x and y position of the pointer
const {worldX, worldY} = pointer;
// Assign the world x and y to our vector
this.target.x = worldX;
this.target.y = worldY;
// Position the arrow at our world x and y
this.arrow.body.reset(worldX, worldY);
this.arrow.setVisible(true);
// Start moving our cat towards the target
this.physics.moveToObject(this.cat, this.target, 200);
});
}
update() {
// If the cat is moving...
if (this.cat.body.speed > 0) {
// Calculate it's distance to the target
const d = pMath.Distance.Between(this.cat.x, this.cat.y, this.target.x, this.target.y);
// If it's close enough,
if (d < 4) {
// Reset it's body so it stops, hide our arrow
this.cat.body.reset(this.target.x, this.target.y);
this.arrow.setVisible(false);
}
}
}
}
export default GameScene;
The important components to take note of in this example are:
- The
this.physics.moveToObject()
call - The distance calculation between the cat and the target
- The
this.cat.body.reset()
call
this.physics.moveToObject(this.cat, this.target, 200)
This is used to set the cat’s velocity. In our case we’re passing in three parameters: the game object we want to move, followed by the target object we’re moving to, followed by the speed at which we want our cat to move.
pMath.Distance.Between(this.cat.x, this.cat.y, this.target.x, this.target.y)
In this case, pMath
is simply a reference to Phaser.Math
. The Distance.Between()
function accepts four arguments: the first position’s x and y, and the second position’s x and y, and returns the distance between the two. Later in our code we check to see if the distance is less than 4, so we can detect when the cat is close enough to our target. Which leads me to our next important function:
this.cat.body.reset(this.target.x, this.target.y)
This function halts the object at the given x and y. So in our case, when the distance comes within an acceptable range (4), the cat’s position will be set to the target’s x and y, and any acceleration or velocity will be removed.
I hope this tutorial was helpful to you! If you make a game using any of the techniques discussed in my articles, feel free to Tweet it at me on Twitter (@saricden).
As always, happy hacking!
Love Kirk M. (@saricden)