I’m trying to create a modal scene for my phaser 3 project. here is my current code in modal.js
:
class modal extends Phaser.Scene { // constructor constructor() { super("Modal"); } preload() { this.load.image("header", "Assets/popUpTop.png"); this.load.image("x", "Assets/x.png"); } init(data) { this.modalName = data.modalName; } create() { // create a white rounded rectangle as modal background var bgGrafics = this.make.graphics(); bgGrafics.fillStyle(0xffffff, 1); bgGrafics.fillRoundedRect(0, 0, gameConfig.width / 3, gameConfig.height / 1.7, 51); bgGrafics.generateTexture("modalBg", gameConfig.width / 3, gameConfig.height / 1.7); this.modalBg = this.add.sprite(gameConfig.width / 2, gameConfig.height / 2, "modalBg"); this.modalBg.setScale(1.05); this.headerBg = this.add.image(0, 0, "header"); this.headerBg.setScale((this.modalBg.width * 1.05 / this.headerBg.width), (1 + (0.05 * this.modalBg.height / this.headerBg.height))); this.closeBtn = new RoundedButton(this, 0, 0, 43, "x", 1.3, () => {this.close()}); // RoundedButton is a custom class that extends Phaser.GameObjects.Container this.add.existing(this.closeBtn); // help modal if(this.modalName === 'help') { // add content of help modal } // profile modal else if(this.modalName === 'profile') { // add content of profile modal } // confirm spin modal else if(this.modalName === 'spin') { // add content of confirm modal } Phaser.Display.Align.In.TopRight(this.closeBtn, this.modalBg); Phaser.Display.Align.In.TopCenter( this.headerBg, this.modalBg ); } close() { this.scene.stop('Modal'); this.scene.run('PlayGame'); } }
as you can see in my code, I’m trying to add different contents to modal based on modelName
but I couldn’t find a way to change modal height based on it’s content.
how can I do this?
Advertisement
Answer
A solution is, to use the function setWordWrapWidth
from gameObject Phaser.GameObjects.TextStyle
(link to the documentation) to limit the width
, then setting the content of the text
gameObject and finally getting and using the height
property of the text
gameObject.
With the width
and height
of the text
gameObject (calculated from Phaser), you can simply render the graphics
object, with the correct size (I also would add some padding). If you want/need to generate the texture, you would have to delete it each time, since the size might have changed.
Here is a short demo:
(I’m generating the texture, since it is in the original code, but I would simply use the graphics
gameObject.)
document.body.style = 'margin:0;'; const TEXT_SHORT = 'Hello World.'.repeat(8); const TEXT_LONG = TEXT_SHORT.repeat(2); class Main extends Phaser.Scene { constructor() { super("Main"); } create() { let buttonShortText = this.add.rectangle(10, 10, 80, 40, 0xcdcdcd) .setOrigin(0) .setInteractive() .on('pointerdown', () => this.scene.start('Modal', { name: 'SHORT', text: TEXT_SHORT, padding: 10, maxWidth: 200 })); // x,y Position are not relevant since they will be change on align let helperLabel = this.add.text(0, 0, 'SHORT').setColor('#000000'); Phaser.Display.Align.In.Center(helperLabel, buttonShortText); let buttonLongText = this.add.rectangle(100, 10, 80, 40, 0xcdcdcd) .setOrigin(0) .setInteractive() .on('pointerdown', () => this.scene.start('Modal', { name: 'SHORT', text: TEXT_LONG, padding: 20, maxWidth: 400 })); // x,y Position are not relevant since they will be change on align let helperLabel2 = this.add.text(0, 0, 'LONG').setColor('#000000'); Phaser.Display.Align.In.Center(helperLabel2, buttonLongText); } } class Modal extends Phaser.Scene { constructor() { super("Modal"); } init(data) { this._name = data.name; this._text = data.text + 'nnClick to Close'; this._maxWidth = data.maxWidth; this._padding = data.padding; } create() { this.add.rectangle(0, 0, config.width, config.height, 0xcdcdcd, .5) .setOrigin(0) .setInteractive() .on('pointerdown', () => this.scene.start('Main')); // x,y Position are not relevant since they will be change on align this.content = this.add.text(0, 0, this._text).setColor('#000000'); this.content.setWordWrapWidth(this._maxWidth - (2 * this._padding)); this.content.setDepth(10); let bgHeight = this.content.height + (2 * this._padding); let graphics = this.make.graphics({ add: false }); graphics.fillStyle(0xffffff); graphics.fillRect(0, 0, this._maxWidth, bgHeight, 0xffffff); // Remove the texture is it was generated and has a different size. if (this.textures.exists('bgModal')) { this.textures.remove('bgModal'); } graphics.generateTexture('bgModal', this._maxWidth, bgHeight); this.bgImage = this.add.image(config.width / 2, config.height / 2, 'bgModal'); // Center Text onto the Background Phaser.Display.Align.In.Center(this.content, this.bgImage); } } var config = { type: Phaser.CANVAS, width: 536, height: 183, scene: [Main, Modal] }; new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>