Originally inspired by woubuc/phaser-cheatsheet.md, this version has been almost completely rewritten and expanded with new notes and insights to better support everyone learning and using Phaser 3.
All config is optional, but width, height and scene are recommended to add.
let config = {
type: Phaser.AUTO,
width: 1200,
height: 800,
scene: [
GameScene, EndScene
],
parent: 'game-wrapper', //<div id="game-wrapper"></div>
physics: {
default: 'arcade',
arcade: {
debug: true,
gravity: { y: 50 }
}
},
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH
},
backgroundColor: '#000000', //Set canvas background
transparent: true, //Set canvas to transparent
pixelArt: true, //If required to build a pixel art game
banner: false, // Disables the Phaser banner from console
};
let game = new Phaser.Game(config);
class GameScene extends Phaser.Scene {
constructor() {
super({key: 'GameScene', active: true});
// In PauseScene should be: {key: 'PauseScene', active: false}
},
init(data) {
// init() is not necessary
// Get the passed data from other scene
}
preload() {
// Assets to be loaded before create() is called
},
create() {
// Adding sprites, sounds, etc...
this.customFunc(); //Try customFunc.call(this) when this.func() not working
},
update() {
// Keep update on everytick
// Game logic, collision, movement, etc...
}
customFunc() {
// Create your custom function
}
}
Reference: https://www.stephengarside.co.uk/blog/phaser-3-custom-config-global-letiables/
let config = {
type: Phaser.AUTO,
width: 400,
height: 300,
~~myCustomProperty: null,~~ // No need to set here
};
let game = new Phaser.Game(config);
game.config.myCustomProperty = true; //Just set in here
console.log(game.config.myCustomProperty);
Reference: https://docs.phaser.io/phaser/concepts/scale-manager#full-screen
// Enter full screen mode
scene.scale.startFullscreen();
// Exit full screen mode
scene.scale.stopFullscreen();
// Toggle full screen mode
scene.scale.toggleFullscreen();
// Check if current game is fullscreen mode
let isFullscreen = scene.scale.isFullscreen;
preload(){
/* Optional: set a custom path */
this.load.path = 'assets/images/';
this.load.image('background', 'background.png');
this.load.audio("bgm", ["bgm.mp3"]);
this.load.spritesheet("guy", "guy-walk.png", { frameWidth: 50, frameHeight: 50 });
/* Preloading */
this.load.on('progress', function (value) {
console.log(`Loading: ${parseInt(value*100)}%`);
});
/* Preloading (With loading bar) */
let progressX = this.game.config.width / 2;
let progressY = this.game.config.height / 2;
let progressWidth = this.game.config.width * 0.8;
let progressHeight = 30;
let progressBox = this.add.rectangle(progressX, progressY, progressWidth, progressHeight, 0xffffff, 0.5).setOrigin(0.5, 0.5);
let progressBar = this.add.rectangle(progressX, progressY, progressWidth, progressHeight, 0x00A758, 1).setOrigin(0.5, 0.5);
this.load.on('progress', function (value) {
progressBar.width = progressWidth * value;
});
this.load.on('complete', function (value) {
progressBar.destroy();
progressBox.destroy();
});
}
Static image
preload() {
this.load.image('background', 'background.png');
this.load.image('background_new', 'background_new.png');
create() {
this.background = this.add.image(x, y, 'background');
// Change the texture
this.background.setTexture('background_new');
}
SVG
preload() {
this.load.svg('fireflower', 'https://cdn.phaserfiles.com/v355/assets/svg/fireflower.svg')
}
create() {
this.add.image(150, 150, 'fireflower').setScale(0.3).setOrigin(0);
}
create() {
this.background = this.add.tileSprite(0, 0, game.config.width, game.config.height, 'background').setOrigin(0, 0);
}
update() {
this.background.tilePositionX -= 1;
}
Reference: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/text/#add-text-object
function create() {
//Assigned for later use
this.label = this.add.text(x, y, "John Doe", {
fontSize: '12px',
fontFamily: 'Arial, Sans-serif',
color: '#CE721C',
backgroundColor: '#F8D38A',
padding: { left: 10, right: 50, top: 5, bottom: 5 },
stroke: '#000',
strokeThickness: 5,
align: 'center',
lineSpacing: 20, //line-height
wordWrap: { width: 450, useAdvancedWrap: true },
shadowColor: '#000',
shadowOffset: { x: 10, y: 10 },
shadowBlur: 5,
});
this.label.text = "I'm changing the text \n inside the label letiable!";
//Set text with multiple lines no need "\n'
this.label.setText([
`Correct: ${this.correct}`,
`Wrong: ${this.wrong}`,
`Score: ${this.score}`,
]);
//Set styles
this.label.setShadow(3, 3, 'rgba(0,0,0,0.5)', 2);
//Set letter spacing in 5px
this.label.setLetterSpacing(5);
//Word wrap when greater than 100px width
this.label.setWordWrapWidth(100, false);
//Set Origin
this.label.setOrigin(1, 0);
//Set Depth (z-index)
this.label.setDepth(1);
//Set visibility
this.label.setVisible(false);
//Center the text
let screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2;
let screenCenterY = this.cameras.main.worldView.y + this.cameras.main.height / 2;
this.txt = this.add.text(screenCenterX, screenCenterY, "My Text").setOrigin(0.5);
}
Method 1 - Works with Phaser v3.87 or later
preload() {
this.load.font('Lato', 'assets/fonts/Lato.otf', 'opentype');
this.load.font('Roboto', 'assets/fonts/Roboto.ttf', 'truetype');
}
create() {
this.add.text(0, 0, 'Your Font Here', {
fontFamily: 'Lato',
fontSize: '32px',
});
this.add.text(0, 80, 'Your Font Here', {
fontFamily: 'Roboto',
fontSize: 32,
});
}
Method 2 - (Legacy)
/* style.css */
@font-face {
font-family: "Roboto";
src: url('../font/Roboto.ttf');
}
/* HTML */
<div style="position:absolute; left:-1000px; visibility:hidden;">
<div style="font-family:Roboto">.</div>
<div style="font-family:Montserrat">.</div>
</div>
this.add.text(0, 0, "Your Text Here", {
fontFamily: 'Roboto'
});
Load with PNG spritesheet (Recommend) - Example 1, Example 2
preload() {
this.load.spritesheet("guy", "guy-walk.png", {
frameWidth: 50,
frameHeight: 50
});
}
create() {
this.anims.create({
key: "guyWalking",
frames: this.anims.generateFrameNumbers("guy", { frames: [ 0, 1, 2, 3 ] }),
// frames: this.anims.generateFrameNumbers("guy", {
// start: 0,
// end: 8
// }),
frameRate: 12,
repeat: -1
});
this.player = this.add.sprite(x, y, "guy");
this.player.play("guyWalking");
this.player.body.setSize(40, 40); // for better size adjustment (remove space)
this.player.body.setOffset(5, 5); // for better size adjustment (remove space)
}
Load with PNG sequence - Example
preload() {
/* Preload all image sequences */
this.load.image('explosion1', 'explosion1.png');
this.load.image('explosion2', 'explosion2.png');
this.load.image('explosion3', 'explosion3.png');
}
create() {
/* Create animation with all image sequences */
this.anims.create({
key: 'explosion',
frames: [
{ key: 'explosion1' },
{ key: 'explosion2' },
{ key: 'explosion3', duration: 50 } // You can set duration for each frame
],
frameRate: 8,
repeat: 1
});
/* Create object and play animation */
this.explosion = this.add.sprite(0, 0, 'explosion1');
this.explosion.play('explosion');
//Pause
this.explosion.anims.pause();
}
Add animation with atlas - Generator
preload() {
// Load the texture atlas
this.load.atlas('myAtlas', 'atlas.png', 'atlas.json');
}
create() {
// Apply animation from the atlas
const animationConfig = {
key: 'walking',
frames: this.anims.generateFrameNames('myAtlas', {
prefix: 'walking_',
start: 0,
end: 5,
zeroPad: 2
}),
frameRate: 10,
repeat: -1
};
this.anims.create(animationConfig);
this.player = this.physics.add.sprite(400, 300, 'myAtlas', 'walking_00');
this.player.anims.play('walking');
}
this.player.visible = false;
this.player.alpha = 0.5;
Reference: https://phaser.io/examples/v3/view/depth-sorting/z-index
/* Bring object to front */
this.player.setDepth(1);
Reference: https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Components.Origin.html
//Objects have an origin property that goes from 0 (top left) to 1 (bottom right)
//It is default in centerX(0.5) centerY(0.5)
image.originX = 0.2;
image.originY = 1;
//This sets it in the 0
image.setOrigin(0, 0);
//Objects have a scale property that defaults to 1
//Negative values essentially mirror it on the affected axis
image.setScale(1.2, 1.2)
//Objects rotation defaults is 0, but you can use Math to convert from degree
image.rotation = 0;
image.rotation = Phaser.Math.DegToRad(90);
Reference: https://phasergames.com/how-to-flip-a-sprite-in-phaser-3/
let duck1 = this.add.image(150, 150, "duck");
let duck2 = this.add.image(350, 150, "duck");
duck2.flipX = true;
gameObject.setFlip(true, false);
gameObject.toggleFlipX();
gameObject.toggleFlipY();
gameObject.resetFlip();
You may learn about the Ease functions ****such as "Bounce"
, "Back"
, "Power3"
// Adding an example sprite but you can tween pretty much anything
this.player = game.add.sprite(100, 100, 'player');
this.tweens.add({
targets: this.player,
x: 200,
y: 200,
scaleX: 0.8,
scaleY: 0.8,
//alpha: { from: 0, to: 1 }, //Use from to
alpha: Phaser.Math.FloatBetween(0, 1),
duration: Phaser.Math.Between(1500, 3000),
ease: 'Sine.easeInOut',
//repeat: 0, // -1=infinity; 0=no loop; 1=loop once; 2=loop twice...
//repeatDelay: 0, // Add delay between repeats
//yoyo: true,
//paused: true
});
// Tween for multiple objects
this.tweens.add({
targets: [this.player, this.enemies, this.boss],
alpha: 0,
duration: 1500,
});
Create a chain animation
// Create Chain
let myAnimation = this.tweens.chain({
targets: this.player,
tweens: [
{
angle: 0,
scale: 0.5,
duration: 500,
onStart() { console.log('start 1')},
onComplete() { console.log('complete 1')}
},
{
angle: 360,
scale: 1,
ease: 'Power2',
duration: 500,
onStart() { console.log('start 2')},
onComplete() { console.log('complete 2')}
}
],
repeat: -1, // Set -1 for infinite loop
delay: 5000 // Start animation after 5 seconds
});
myAnimation.stop(); // Stop the animation
Create a Timeline
// Create Timeline
let timeline = this.add.timeline([
{
at: 0, // At 0 second
tween: {
targets: this.player,
y: 400,
duration: 2000,
}
},
{
at: 2500, // At 2.5 seconds
run() {
this.player.setScale(1.5);
}
},
]);
timeline.play(); // Start playing the animation
timeline.repeat().play(); // Play with repeat (loop)
timeline.repeat(false); // Stop repeat
// Create Timeline (Version 2)
let timeline = this.add.timeline();
timeline.add({
targets: this.player,
y: 400,
duration: 300,
ease: 'Linear',
onComplete: () => { },
});
Number animation example
let scoreText = this.add.text(400, 300, '0', {
fontSize: '32px',
color: '#ffffff',
});
this.tweens.addCounter({
from: 0,
to: 1200,
duration: 3000,
ease: 'Cubic.easeOut',
onUpdate: (tween) => {
const value = Math.round(tween.getValue());
//scoreText.setText(value);
scoreText.setText(value.toLocaleString('en-US'));
}
});
Examples - Online Notes
/* NOTES: preFX only works with sprite */
this.player= this.add.sprite(0, 0, 'player')
this.player.preFX.addShine(
0.5, // speed
0.5, // gradient position (0-1)
0.7, // width of the shine
0.6 // alpha
);
this.player.preFX.addBlur(
4, // blur quality (1-8)
2.0 // blur strength
);
this.player.preFX.addBloom(
0xff0000, // color
4, // outerStrength
0, // innerStrength
false // knockout (Hide object but show only style)
);
this.player.preFX.addGlow(
0xff0000, // color
0, // offset x
0, // offset y
2, // distance/strength
1, // alpha
16 // quality (steps)
);
this.player.preFX.addShadow(
1, // x offset power, color, samples, intensity
1, // y offset
0.1, // decay (blur amount)
1, // power
0x000000, // color
12, // sample steps (quality)
1, //intensity
);
this.player.preFX.addPixelate(
4 // amount (pixel size, higher = more pixelated)
);
this.player.preFX.addVignette(
0.5, // x (horizontal position, 0-1)
0.5, // y (vertical position, 0-1)
0.7, // radius (size of the clear center area)
0.5, // strength (intensity of the effect)
0x000000 // color of the vignette
);
this.player.preFX.addGradient(
0xff0000, // color1
0x00ff00, // color2
1, // alpha
0, // fromX
0, // fromY
200, // toX
200, // toY
0, // size (Low value would be smoother)
);
this.player.preFX.addCircle(
0.5, // x (horizontal position, 0-1)
0.5, // y (vertical position, 0-1)
0.5, // radius
0x000000, // color (outside circle)
0 // alpha (0 = transparent, 1 = opaque)
);
this.player.preFX.addBokeh(
3, // radius
1, // amount
0.1, // blend (0-1)
0xffffff // color
);
Tweening the effects
create() {
let glowFX = this.player.preFX.addGlow();
//glowFX.setActive(false);
//glowFX.setActive(true);
glowFX.outerStrength = 8;
glowFX.innerStrength = 8;
this.tweens.add({ // you may also tween the glow effects
targets: glowFX,
outerStrength: 16,
innerStrength: 16,
ease: 'Sine.easeInOut',
repeat: -1,
yoyo: true,
duration: 1500,
});
}
Displacement map
preload() {
// Load your displacement map (usually a black and white texture)
this.load.image('displacement', 'displacement_map.png');
this.load.image('background', 'background.png');
}
create() {
const image = this.add.image(400, 300, 'background');
// Add displacement effect
const fx = image.preFX.addDisplacement(
'displacement', // displacement map key
2.0, // intensity x
2.0 // intensity y
);
this.tweens.add({ // Animate the displacement
targets: fx,
x: 100, // offset x
y: 100, // offset y
duration: 2000,
yoyo: true,
repeat: -1
});
}
preload() {
this.load.image('bg', 'flares.png');
}
create() {
let emitter = this.add.particles(300, 200, 'flares', {
frame: 'white',
blendMode: 'ADD',
lifespan: 1200,
gravityY: -100,
scale: { start: 0.3, end: 0 },
emitting: false
});
emitter.start();
emitter.addEmitZone({ source: new Phaser.Geom.Circle(0, -20, 90) });
}
Use Case (Play once only)
preload () {
this.load.image('particle', 'assets/img/particle_shape.png');
}
create () {
const particles = this.add.particles(100, 100, 'particle', {
speed: { min: 100, max: 200 },
angle: { min: 0, max: 360 },
scale: { start: 1.5, end: 0 },
blendMode: 'NORMAL',
lifespan: 500,
gravityY: 50,
quantity: 2,
});
// Stop emitting after 100ms
this.time.delayedCall(100, () => {
particles.stop();
});
// Destroy the particle system after 2 seconds
this.time.delayedCall(2000, () => {
particles.destroy();
});
}
preload() {
this.bgm = this.load.audio("bgm", ["bgm.mp3"]);
}
create() {
// Assign it so we can reference it
this.bgm = this.sound.add("bgm", { loop: false });
this.bgm.loop = true;
this.bgm.play();
}
create() {
// Mute all sounds
this.game.sound.mute = true;
// Set volumn of a soundtrack
this.bgm.volume = 0.5;
}
create(){
this.input.setDefaultCursor('url(img/cursor.cur), pointer');
}
create(){
/* Set Multitouch limits (default: 1) */
this.input.addPointer(3); //3 multitouch
/* Onclick event */
this.player.setInteractive();
this.player.on('pointerup', function(){
console.log('Clicked');
});
/* Disable events */
this.player.disableInteractive();
/* Custom clickable area */
this.player.setInteractive({
hitArea: new Phaser.Geom.Rectangle(-50, -60, 220, 360),
hitAreaCallback: Phaser.Geom.Rectangle.Contains,
useHandCursor: true,
});
/* All other input properties */
this.player.setInteractive({
draggable: true,
cursor: 'pointer',
pixelPerfect: true,
useHandCursor: true,
hitArea: new Phaser.Geom.Rectangle(0, 0, 100, 100),
dragStartCallback: function() {
// Code to execute when drag starts
},
dragEndCallback: function() {
// Code to execute when drag ends
}
});
}
Example of Drag and Drop
create(){
const button = this.add.image(200, 100, 'button');
button.setInteractive({ draggable: true })
button.on('dragstart', function (pointer) {
this.setTint(0xc1c1c1);
});
button.on('drag', function (pointer, dragX, dragY) {
console.log('drag', dragX, dragY)
this.x = dragX;
this.y = dragY;
});
button.on('dragend', function (pointer) {
this.clearTint();
});
}
create() {
/* Onclick event */
this.keyboard = this.input.keyboard.createCursorKeys();
}
update() {
if(this.keyboard.left.isDown){
this.player.x += -2;
}
if(this.keyboard.right.isDown){
this.player.x += 2;
}
if(this.keyboard.up.isDown){
this.player.y += -2;
}
if(this.keyboard.down.isDown){
this.player.y += 2;
}
}
/* Logic */
this.input.keyboard.on('keydown-W', () => {
// Event listener pattern: "keydown + {KEY}"
});
/* Example */
this.input.keyboard.on('keydown-SPACE', () => {
// Space key-down events
});
this.input.keyboard.on('keyup-SPACE', () => {
// Space key-up events
});
Adding DOM Elements - Demo
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'game-wrapper', // Must have a parent
dom: { // Enable DOM plugin
createContainer: true
},
scene: MainScene
};
// How to use
create() {
let heading = this.add.dom(400, 300).createFromHTML(`<h1 style="background-color: lightblue;">Hello, World!</h1>`);
heading.addListener('click');
heading.on('click', () => {
alert('DOM H1 clicked!');
});
}
/* Similar to setTimeOut() */
this.time.addEvent({
delay: 3000,
loop: false,
callback: function() {
console.log('function run after 3 seconds');
},
callbackScope: this
});
/* Similar to setInterval() */
this.time.addEvent({
delay: 1000,
loop: true,
callback: function() {
console.log('Keep looping on every seconds');
},
callbackScope: this
});
let timerCountdown = 60;
let myTimer = this.time.addEvent({
delay: 1000,
loop: true,
callback: function() {
timerCountdown -= 1;
console.log(timerCountdown);
},
});
/* Use of delay */
this.time.delayedCall(60*1000, function() {
myTimer.remove();
console.log('Timeout');
});
Reference: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/random/
//Random integer
let value = Phaser.Math.Between(min, max);
//Random floating point number
let value = Phaser.Math.FloatBetween(min, max);
Reference: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/containerlite/
/*** Default container ***/
this.add.container(x, y, [this.player, this.name]);
//Create a container
let container = this.add.container(300, 300);
//Add game object
container.add(this.player);
//Remove game object
container.remove(this.player);
/*** Advanced container plugin ***/
preload() {
this.load.plugin('rexcontainerliteplugin', '<https://cdn.jsdelivr.net/gh/rexrainbow/phaser3-rex-notes@latest/dist/rexcontainerliteplugin.min.js>', true);
}
create() {
let container = this.add.rexContainerLite(300, 300);
container.setOrigin(0.5, 0.5); //only work with plugin
}
Reference: https://photonstorm.github.io/phaser3-docs/Phaser.Cameras.Scene2D.CameraManager.html
create() {
// Set background color
this.cameras.main.setBackgroundColor('#000000');
// Set boundary so that it would hide the black background
this.cameras.main.setBounds(0, 0, 800, 600);
// Add camera(s)
this.camera1 = this.cameras.main.setSize(400, 600);
this.camera2 = this.cameras.add(400, 0, 400, 600); // splitscreen
// Start follow camera
this.camera1.startFollow(this.player1);
this.camera2.startFollow(this.player2);
this.camera2.setFollowOffset(-100, 0); //(x,y)
// Stop follow camera
this.camera1.stopFollow();
// Set attributes
this.camera1.zoom = 1.5; // 1=no zoom, >1=zoom in, <1=zoom our
this.camera1.x = 300;
this.camera1.centerOn(0, 0); //center x,y as coordinate instead of left top x,y
// Camera animation
this.camera1.pan(300, 300, 2000, 'Sine.easeInOut');
this.camera1.zoomTo(1.5, 3000, 'Sine.easeInOut');
}
Camera Effects
create() {
// Shaking effects
this.cameras.main.shake(200, 0.01); // (duration, intensity)
// Fade in/out effects
this.cameras.main.fadeOut(1000, 0, 0, 0); // Black fade out
this.cameras.main.fadeIn(1000, 0, 0, 0); // Fade in from black
// Flash effects
this.cameras.main.flash(500); // (duration)
// Zoom effects
this.cameras.main.zoomTo(1.25, 1500); // (zoom level, duration)
// Pan effects
this.cameras.main.pan(500, 500, 1500, 'Sine.easeInOut'); // (x, y, duration, ease)
this.cameras.main.rotateTo(Math.PI, false, 1000, 'Power2'); // (180 degrees, shortestPath(auto-nearest), duration, ease)
// Make camera follow a game object
this.cameras.main.startFollow(player, true);
this.cameras.main.startFollow(player, true, 0.1, 0.1); // Smooth following
this.cameras.main.stopFollow();
}
Use Case 1 - Following the Player
create() {
this.player = this.physics.add.sprite(0, 0, 'block');
this.player.setCollideWorldBounds(true);
this.cameras.main.startFollow(this.player);
this.cameras.main.setFollowOffset(0, 0); // 0,0 refers to center screen
this.cameras.main.setBounds(0, 0, 1920*2, 1080*2);
this.physics.world.setBounds(0, 0, 1920*2, 1080*2);
}
Reference: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/scenemanager/
// Move to "SceneB"
this.scene.start('SceneB');
// Include PauseScene in the scenes
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
scene: [GameScene, PauseScene]
};
// In 'MainScene'
this.scene.pause().launch('PauseScene');
//game.scene.pause('GameScene').launch('PauseScene'); // alternative
// In 'PauseScene'
this.scene.stop().resume('GameScene');
//game.scene.stop('PauseScene').resume('GameScene'); // alternative
In pauseScene.js
class PauseScene extends Phaser.Scene {
constructor(){
super({ key: 'PauseScene', active: false });
}
create(){
let _this = this;
// Add a background rectangle to cover the screen
this.background = this.add.rectangle(0, 0, this.game.config.width, this.game.config.height, '0x000000', 0.8).setOrigin(0);
background.setInteractive(); //to disable click events from the GameScene
// Add a "Resume" button
this.btnResume = this.add.text(400, 300, 'Resume', { fontSize: '32px', fill: '#fff' }).setOrigin(0.5);
this.btnResume.setInteractive();
this.btnResume.on('pointerup', function(){
_this.scene.stop().resume('GameScene');
});
}
}
this.input.keyboard.once('keydown-SPACE', () => {
this.cameras.main.fadeOut(1000, 0, 0, 0); // fade to black
});
this.cameras.main.once(Phaser.Cameras.Scene2D.Events.FADE_OUT_COMPLETE, (cam, effect) => {
this.scene.start('MainScene');
});
Method 1
// In 'MainScene'
this.myValue = 0;
// From 'OtherScene'
this.scene.get('MainScene').myValue;
Method 2
// In 'MainScene'
this.scene.launch('OtherScene', {
mainScene: this, // pass current scene
myValue: myValue, // pass other values
});
// From 'OtherScene'
init(data) {
this.mainScene = data.mainScene; // get previous scene
this.myValue = data.myValue; // get other passed values
}
create() { ... }
let btn_close = this.add.image(0, 0, 'btn_close');
//Perform a button click
btn_close.emit('pointerup', { x: btn_close.x, y: btn_close.y });
// Create arcade sprite
this.player = this.physics.add.sprite(300, 630, 'player');
this.player.body.setSize(40, 40); // for better size adjustment (remove space)
this.player.body.setOffset(5, 5); // for better size adjustment (remove space)
this.player.setCollideWorldBounds(true); // always inside screen
this.player.setBounce(0); // set rebouncing force
// Get the player body attributes
let velocityX = this.player.body.velocity.x;
// Create some static sprite (Won't apply the gravity and velocity)
this.coin = this.physics.add.staticSprite(390, 500, 'coin'); // set immovable object
// Or same with above
this.coin = this.physics.add.sprite(390, 500, 'coin');
coin.body.setImmovable(true);
coin.body.allowGravity = false;
// Create platforms
this.platforms = this.physics.add.staticGroup();
this.ground = this.platforms.create(x, y, 'ground');
this.ground.setOrigin(0, 0);
this.ground.refreshBody();
// Set custom collision directions
this.ground.body.checkCollision.left = false;
this.ground.body.checkCollision.right = false;
this.ground.body.checkCollision.up = true; // Just make top collision work, jump over it
this.ground.body.checkCollision.down = false;
// Player is now able to stand on the platform
this.physics.add.collider(this.player, this.platforms);
// Detect two object colliding
this.physics.add.overlap(this.player, this.coin, this.callback); // callback() {...}
// One-liner
this.physics.add.overlap(this.player, this.coin, (player, coin) => {
coin.body.enable = false; // Disable the physics, make it trigger only once
this.tweens.add({
targets: coin,
alpha: 0,
duration: 500,
onComplete: () => {
coin.destroy();
}
});
});
// Fix object - Pin it stick to camera
this.scoreText = this.add.text(100, 100, `Score: 10,000`, {
fontSize: '26px',
fontFamily: 'sans-serif',
color: '#FFFFFF',
});
this.scoreText.setScrollFactor(0); // Make object sticky to camera
Document: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/bbcodetext/
preload() {
this.load.plugin('rexbbcodetextplugin', 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexbbcodetextplugin.min.js', true);
}
create() {
this.add.rexBBCodeText(100, 100, "I'm [b][color=#FF0000]changing[/color][/b] the text \n inside the label letiable!", {
fontSize: '30px',
fontFamily: 'Arial, Sans-serif',
backgroundColor: '#F8D38A',
padding: { left: 50, right: 50, top: 10, bottom: 10 },
stroke: '#000',
strokeThickness: 5,
align: 'center',
lineSpacing: 10,
wordWrap: { width: 450, useAdvancedWrap: true },
});
}
Document: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/ui-scrollablepanel/
preload() {
// Load Rex UI Plugin
this.load.scenePlugin({
key: 'rexuiplugin',
url: 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexuiplugin.min.js',
sceneKey: 'rexUI'
});
}
create() {
const scrollablePanel = this.rexUI.add.scrollablePanel({
x: 400,
y: 300,
width: 200,
height: 400,
scrollMode: 'y', // vertical scrolling
background: this.rexUI.add.roundRectangle(0, 0, 2, 2, 10, 0x1B5B9B),
panel: {
child: this.rexUI.add.sizer({
orientation: 'y', // vertical scrolling bar
space: { item: 10 },
})
.add(
this.add.text(0, 0, 'Very long text 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', {
wordWrap: { width: 150, useAdvancedWrap: true },
})
)
.add(
this.add.text(0, 0, 'Another elements\n')
)
},
slider: {
track: this.rexUI.add.roundRectangle({
width: 20,
radius: 10,
color: '0x666666',
}),
thumb: this.rexUI.add.roundRectangle({
radius: 13,
color: '0x888888',
}),
},
})
.layout();
}
Reference: https://github.com/rexrainbow/phaser3-rex-notes/blob/master/docs/docs/moveto.md
preload(){
this.load.plugin('rexmovetoplugin', 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexmovetoplugin.min.js', true);
}
create(){
this.player.walk = this.plugins.get('rexmovetoplugin').add(this.player[i], {
speed: 50,
rotateToTarget: false
});
this.player.walk.moveTo(200, 200);
}
Reference: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/webfontloader/#__code_10
constructor() {
super({
key: 'examples',
pack: {
files: [{
type: 'plugin',
key: 'rexwebfontloaderplugin',
url: 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexwebfontloaderplugin.min.js',
start: true
}]
}
});
}
preload(){
/* Load plugin */
this.plugins.get('rexwebfontloaderplugin').addToScene(this);
this.load.rexWebFont({
google: {
families: ['VT323']
},
custom: {
families: ['My Font', 'My Other Font:n3,n5,n7'],
urls: ['/fonts.css']
},
});
}