Skip to content

Instantly share code, notes, and snippets.

@louisho5
Forked from woubuc/phaser-cheatsheet.md
Last active September 29, 2024 08:20
Show Gist options
  • Save louisho5/d6318b784c9bf280f15385d144dbda58 to your computer and use it in GitHub Desktop.
Save louisho5/d6318b784c9bf280f15385d144dbda58 to your computer and use it in GitHub Desktop.

Phaser 3 Cheatsheet

This is the content from the original Phaser cheatsheet, the site of which went down. I'm editing outdated information as I come across it.

Starting a new game

All config is optional, but width, height and scene is recommended to add.

var config = {
    type: Phaser.AUTO,
    width: 1920,
    height: 1080,
    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',
    pixelArt: true,  //If required to build a pixel art game
};

var game = new Phaser.Game(config);

Creating a game state object

Reference: https://github.com/photonstorm/phaser3-examples/blob/master/public/src/depth%20sorting/bring%20to%20top.js

class GameScene extends Phaser.Scene {

    constructor() {
        super({key: 'GameScene', active: true});      //In PauseScene should be:  {key: 'PauseScene', active: false}
    },

    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
    }
    
}

Working with globals

Reference: https://www.stephengarside.co.uk/blog/phaser-3-custom-config-global-variables/

var config = {
    type: Phaser.AUTO,
    width: 400,
    height: 300,
    myCustomProperty: true
};  
var game = new Phaser.Game(config);
game.config.myCustomProperty = true;

Using local storage

Reference: http://www.w3schools.com/html/html5_webstorage.asp

//It can only store strings
localStorage.setItem('itemKey', 'myContent');

//Then you just get the string you stored!
var itemKey = localStorage.getItem('itemKey');
console.log(itemKey);

//You can store entire objects by doing this:
localStorage.setItem('myObject', JSON.stringify(myObject));

//Then you just get the object you stored!
var myObject = JSON.parse(localStorage.getItem('myObject'));
console.log(myObject);

Loading an image/music/asset

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) */
    var progressX = this.game.config.width / 2;
    var progressY = this.game.config.height / 2;
    var progressWidth = this.game.config.width * 0.8;
    var progressHeight = 30;
    var progressBox = this.add.rectangle(progressX, progressY, progressWidth, progressHeight, 0xffffff, 0.5).setOrigin(0.5, 0.5);
    var 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;
    });
}

Adding spritesheet animation

Reference 1: https://codesandbox.io/s/sprite-sheet-animation-using-phaser-3-ui2w0
Reference 2: https://labs.phaser.io/edit.html?src=src\animation\animation%20from%20png%20sequence.js

preload() {
    this.load.spritesheet("guy",  "guy-walk.png",  {
    	frameWidth: 50,
    	frameHeight: 50
    });
}
create() {
    this.anims.create({
    	key:  "guyWalking",
    	frames:  this.anims.generateFrameNumbers("guy",  {
            start:  0,
            end:  8,
            first:  0
    	}),
    	frameRate:  12,
    	repeat:  -1
    });
    this.add.sprite(x, y, "guy").play("guyWalking");
}

///////// OR /////////

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 }
        ],
        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();
}

Adding an image

Reference: http://docs.phaser.io/Phaser.Image.html

create() {
    this.add.image(x, y, 'MyImage');
}

Adding tileSprite / looping background

create() {
    this.background = this.add.tileSprite(0, 0, game.config.width, game.config.height, 'background').setOrigin(0, 0);
}
update() {
    this.background.tilePositionX -= 1;
}

Adding text

Reference: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/text/#add-text-object

function create() {
    //Assigned for later use
    var label = game.add.text(x, y, "John Doe", {
        fontSize: '10px',
        fontFamily: 'Sans-serif',
	color: '#fff',
        stroke: '#000',
        strokeThickness: 5,
	align: 'center',
        lineSpacing: 20,  //line-height
	wordWrap: { width: 450, useAdvancedWrap: true },
    });
    label.text = "I'm changing the text inside the label var!";
    
    //Center the text
    var screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2;  
    var screenCenterY = this.cameras.main.worldView.y + this.cameras.main.height / 2;
    var txt = game.add.text(screenCenterX, screenCenterY, "My Text");
    txt.setOrigin(0.5);
    
    //Set styles
    label.setShadow(3, 3, 'rgba(0,0,0,0.5)', 2);
    
    //Set letter spacing in 5px
    label.setLetterSpacing(5);
    
    //Word wrap when greater than 100px width
    label.setWordWrapWidth(100, false);
}

Adding Custom Font

/* 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'
});

Set Alpha(opacity) & Visible

this.player.visible = false;
this.player.alpha = 0.5;

Change z-index / Bring to front

Reference: https://phaser.io/examples/v3/view/depth-sorting/z-index

/* Bring object to front */
this.player.setDepth(1);

Generating random numbers

Reference: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/random/

//Random integer
var value = Phaser.Math.Between(min, max);
//Random floating point number
var value = Phaser.Math.FloatBetween(min, max);

Objects origin (anchor)

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);

Scaling an object

//Objects have a scale property that defaults to 1
//Negative values essentially mirror it on the affected axis
image.setScale(1.2, 1.2)

Rotate an object

//Objects rotation defaults is 0, but you can use Math to convert from degree
image.rotation = 0;
image.rotation = Phaser.Math.DegToRad(90);

Flipping an object

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();

Tweening

//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
});

// Create Chain
var 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: 'power1',
            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 Timeline
var 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

Glow effects

create() {
    var 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,
    });
}

Particles effects

preload() {
    this.load.image('bg', 'flares.png');
}
create() {
    var 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();
    });
}

Playing music

create() {
    //Assign it so we can reference it 
    var music= this.sound.add("bgm", { loop: false });
    music.loop = true;
    music.play();
}

Muted Sounds

preload() {
    this.bgm = this.load.audio("bgm",  ["bgm.mp3"]);
}
create() {
    //Mute all sounds
    this.game.sound.mute = true;
    
    //Set volumn of a soundtrack
    this.bgm.volume = 0.5;
}

Set custom cursor

create(){
    this.input.setDefaultCursor('url(img/cursor.cur), pointer');
}

Mouse & touch input

create(){
    /* Onclick event */
    this.player.setInteractive();
    this.player.on('pointerup', function(){
        console.log('Clicked');
    });
    
    /* Disable events */
    this.player.disableInteractive();
    
    /* All 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();
    });
}

Keyboard input

Keycodes: http://docs.phaser.io/Keyboard.js.html#sunlight-1-line-557

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;
    }
}

Time events

/* 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
});

Managing game timer

var timerCountdown = 60;
var 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');
});

Working with container (group)

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
var 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() {
    var container = this.add.rexContainerLite(300, 300);
    container.setOrigin(0.5, 0.5); //only work with plugin
}

Adding camera to sprites

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);
	
	// 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);
}

Use Case (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);
}

Managing game scene

Reference: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/scenemanager/

//Move to "SceneB"
this.scene.start('SceneB');

Pause Game with popup box

// 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').start('PauseScene');

// In 'PauseScene'
this.scene.stop().resume('GameScene');
game.scene.stop('PauseScene').resume('GameScene');

In pauseScene.js

class PauseScene extends Phaser.Scene {

    constructor(){
        super({ key: 'PauseScene', active: false });
    }

    create(){
        var _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');
        });
    }

}

Data from other scenes

// In 'MainScene'
this.myValue = 0;

// From 'OtherScene'
this.scene.get('MainScene').myValue;

Perform a action/events

var 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 });

Adding physics to Sprites (legacy)

Reference: http://docs.phaser.io/Phaser.Physics.Arcade.html

function create() {
    //First we start the system
    game.physics.startSystem(Phaser.Physics.ARCADE);

    //We then create our sprite & enable physics on it
    sprite = game.add.sprite(x, y, 'key');
    game.physics.enable(sprite, Phaser.Physics.ARCADE);

    //Now our sprite has an object body as a property
    sprite.body.velocity.setTo(x, y);
    sprite.body.bounce.set(0.8);
}

Handling Collision (legacy)

Reference: http://docs.phaser.io/Phaser.Physics.Arcade.html#collide

function update() {
    //You can collide a group with itself
    game.physics.arcade.collide(sprites);
    
    //You can call a function when a collision happens
    game.physics.arcade.collide(sprites, monsters, callback);
    
    //You can perform additional checks with a processCallback
    //If it returns false the collision will not happen
    game.physics.arcade.collide(sprites, monsters, null, processCallback);

    //Or you can check if two bodies overlap. This method avoids the impact
    //between then, keeping their velocities and properties
    game.physics.arcade.overlap(sprites, monsters, callback);
    
    //You can perform the following collisions:
    //Sprite vs Sprite or
    //Sprite vs Group or
    //Group  vs Group or
    //Sprite vs Tilemap Layer or
    //Group  vs Tilemap Layer
}

Camera (legacy)

Reference: http://docs.phaser.io/Phaser.Camera.html

//Lets follow a sprite named 'missile'
game.camera.follow(missile);

//Once the missile explodes, maybe we want to reset the camera
game.camera.reset();

//Something cool is happening, let's pan the camera there
game.camera.x = 500;

Particles (legacy)

Reference: http://docs.phaser.io/Phaser.Particles.Arcade.Emitter.html

emitter = game.add.emitter(x, y, maxParticles);
emitter.makeParticles('image');
emitter.setAlpha(min, max, rate, easing, yoyo);

//To use gravity on the emitter, start the physics system
game.physics.startSystem(Phaser.Physics.ARCADE);
emitter.gravity = 200;
emitter.start();

Debugging (legacy)

Reference: http://docs.phaser.io/Phaser.Utils.Debug.html

//Print debug text
game.debug.text(game.time.physicsElapsed, 10, 20);

//Print debug body information
game.debug.bodyInfo(player, 10, 20);

//Show the sprite's hitbox as a green rectangle
game.debug.body(player);

Plugin: rexmovetoplugin

Reference: https://github.com/rexrainbow/phaser3-rex-notes/blob/master/docs/docs/moveto.md

preload(){
    /* Load plugin */
    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);     
}

Plugin: rexwebfontloaderplugin

Reference: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/webfontloader/#__code_10
Sample: https://codepen.io/rexrainbow/pen/vjqmXp

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']
        },
    });
}

Contribute!

Any contributions are welcome. I'm not really planning to update it myself since I'm a relative beginner with Phaser, I just noticed that the cheatsheet that was talked about everywhere was down so I figured I'd make it available again properly (the github repo of the original site doesn't format the code correctly).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment