# Phaser 3 Cheatsheet 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. ## Starting a new game All config is optional, but width, height and scene are recommended to add. ```jsx let config = { type: Phaser.AUTO, width: 1200, height: 800, scene: [ GameScene, EndScene ], parent: 'game-wrapper', //
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); ``` ## Creating a game state object ```jsx 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 } } ``` ### Working with globals Reference: https://www.stephengarside.co.uk/blog/phaser-3-custom-config-global-letiables/ ```jsx 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); ``` ### Fullscreen Reference: https://docs.phaser.io/phaser/concepts/scale-manager#full-screen ```jsx // 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; ``` ## Basic Usage ### Loading an image/music/asset ```jsx 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(); }); } ``` ### Adding an image **Static image** ```jsx 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** ```jsx 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); } ``` ### Adding tileSprite / looping background ```jsx 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 ```jsx 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); } ``` ### Adding Custom Font **Method 1 - Works with Phaser [v3.87](https://github.com/phaserjs/phaser/discussions/6943) or later** ```jsx 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)** ```css /* style.css */ @font-face { font-family: "Roboto"; src: url('../font/Roboto.ttf'); } ``` ```html /* HTML */
.
.
``` ```jsx this.add.text(0, 0, "Your Text Here", { fontFamily: 'Roboto' }); ``` ### Adding spritesheet animation **Load with PNG spritesheet (Recommend) - [Example 1](https://labs.phaser.io/edit.html?src=src\animation\create%20animation%20from%20sprite%20sheet.js), [Example 2](https://codesandbox.io/p/sandbox/sprite-sheet-animation-using-phaser-3-ui2w0?file=%2Findex.html%3A24%2C9)** ```jsx 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](https://labs.phaser.io/edit.html?src=src\\animation\\animation%20from%20png%20sequence.js) ```jsx 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](https://gammafp.com/tool/atlas-packer/)** ```jsx 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'); } ``` ## Basic Styles ### Set Alpha(opacity) & Visible ```jsx 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 ```jsx /* Bring object to front */ this.player.setDepth(1); ``` ## Transform Objects ### Objects origin (anchor) Reference: https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Components.Origin.html ```jsx //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 ```jsx //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 ```jsx //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/ ```jsx 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(); ``` ## Animations ### Tweening You may learn about the [Ease functions](https://rexrainbow.github.io/phaser3-rex-notes/docs/site/ease-function/) ****such as `"Bounce"`, `"Back"`, `"Power3"` ```jsx // 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** ```jsx // 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** ```jsx // 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** ```jsx 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')); } }); ``` ### Use of shader (preFX / postFX) **Examples - [Online Notes](https://rexrainbow.github.io/phaser3-rex-notes/docs/site/shader-builtin/)** ```jsx /* 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** ```jsx 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** ```jsx 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 }); } ``` ### Particles effects ```jsx 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) ```jsx 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(); }); } ``` ## Sounds ### Playing music ```jsx 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(); } ``` ### Muted Sounds ```jsx create() { // Mute all sounds this.game.sound.mute = true; // Set volumn of a soundtrack this.bgm.volume = 0.5; } ``` ## User Inputs ### Set custom cursor ```jsx create(){ this.input.setDefaultCursor('url(img/cursor.cur), pointer'); } ``` ### Mouse & touch input ```jsx 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 ```jsx 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 ```jsx 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; } } ``` ```jsx /* 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 }); ``` ## Add HTML into the game ### Adding DOM Elements - [Demo](https://labs.phaser.io/edit.html?src=src\game%20objects\dom%20element\css%20text.js) ```jsx 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(`

Hello, World!

`); heading.addListener('click'); heading.on('click', () => { alert('DOM H1 clicked!'); }); } ``` ## Time Events ### Set time events ```jsx /* 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 ```jsx 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'); }); ``` ## Generating random numbers Reference: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/random/ ```jsx //Random integer let value = Phaser.Math.Between(min, max); //Random floating point number let value = Phaser.Math.FloatBetween(min, max); ``` ## Working with container (group) Reference: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/containerlite/ ```jsx /*** 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', '', true); } create() { let 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 ```jsx 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** ```jsx 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** ```jsx 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/ ```jsx // Move to "SceneB" this.scene.start('SceneB'); ``` ### Pause Game with popup box ```jsx // 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** ```jsx 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'); }); } } ``` ### Scene transition effects ```jsx 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'); }); ``` ### Data from other scenes **Method 1** ```jsx // In 'MainScene' this.myValue = 0; // From 'OtherScene' this.scene.get('MainScene').myValue; ``` **Method 2** ```jsx // 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() { ... } ``` ## Perform a action/events ```jsx 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 }); ``` ## Arcade Physics 2D ### Collider (Overlap) ```jsx // 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 ``` --- # Plugins ## BBCode Text Plugin Document: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/bbcodetext/ ```jsx 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 }, }); } ``` ## Scrollable Panel Plugin Document: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/ui-scrollablepanel/ ```jsx 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(); } ``` ## Move To Plugin Reference: https://github.com/rexrainbow/phaser3-rex-notes/blob/master/docs/docs/moveto.md ```jsx 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); } ``` ## Webfont Loader Plugin Reference: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/webfontloader/#__code_10 ```jsx 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'] }, }); } ```