Phaser 3: How to stop scene?

Viewed 534

This is a code from one of Codecademy's practice. I am trying to end scene when the option text says Play again. Basically what I want is that a specific option will allow me to exit the scene and enter a new one. (ie when the game is over) I tried using

if (optionText==="Play again"){
        optionBox.on('pointerup', function() {
          this.scene.stop("game")
      
      })}

I have commented out the code at line 116

but it only crashed the code.

let gameState = {}

function preload () {
  // load in background and characters
  this.load.image('bg',     'https://content.codecademy.com/projects/learn-phaser/cyoa/background.png');
  this.load.image('knight', 'https://content.codecademy.com/projects/learn-phaser/cyoa/knight.png');
  this.load.image('orc',    'https://content.codecademy.com/projects/learn-phaser/cyoa/orc.png');
  this.load.image('wizard', 'https://content.codecademy.com/projects/learn-phaser/cyoa/wizard.png');
}
function create(){
  gameState.background=this.add.image(0,0,"bg")
  gameState.background.setOrigin(0,0);
  gameState.character=renderCharacter(this,"knight");
  initializePage(this);
  const firstPage=fetchPage(1);
  displayPage(this,firstPage)
}
function renderCharacter(scene,key){
  if (gameState.character){
    gameState.character.destroy();}
    gameState.character=scene.add.image(270,340,key);
        gameState.character.setOrigin(0.5,1);
    gameState.character.setScale(0.7); }



function initializePage(scene) {
  // create options list and background
  // and saves them into gameState

  if (!gameState.options) {
    // create options list
    // if it doesn't exist
    gameState.options = [];
  }

  if (!gameState.narrative_background) {
    // create narrative background
    // if it doesn't exist
    gameState.narrative_background = scene.add.rectangle(10, 360, 430, 170, 0x000);
  gameState.narrative_background.setOrigin(0, 0);
  }
}

function destroyPage() {
  // wipe out narrative text and options

  if (gameState.narrative) {
    // destroy narrative if it exists
    gameState.narrative.destroy();
  }

  for (let option of gameState.options) {
    // destroy options if they exist
    option.optionBox.destroy();
    option.optionText.destroy();
  }
}

function displayPage(scene, page) {
  renderCharacter(scene,page.character);
  const narrativeStyle = { fill: '#ffffff', fontStyle: 'italic', align: 'center', wordWrap: { width: 340 }, lineSpacing: 8};
  
  // display general page character
  // & narrative here:
  gameState.narrative = scene.add.text(65, 380, page.narrative, narrativeStyle);

  // for-loop creates different options

  // need the index i for spacing the boxes
  for (let i=0; i<page.options.length; i++) {
    let option = page.options[i];

    // color in the option box
    const optionBox = scene.add.rectangle(40 + i * 130, 470, 110, 40, 0xb39c0e, 0)
    optionBox.strokeColor = 0xb39c0e;
    optionBox.strokeWeight = 2;
    optionBox.strokeAlpha = 1;
    optionBox.isStroked = true;
    optionBox.setOrigin(0, 0)
    

    // add in the option text
    const baseX = 40 + i * 130;
    const optionText = scene.add.text(baseX, 480, option.option, { fontSize:14, fill: '#b39c0e', align: 'center', wordWrap: {width: 110}});
    const optionTextBounds = optionText.getBounds()

    // centering each option text
    optionText.setX(optionTextBounds.x + 55 - (optionTextBounds.width / 2));
    optionText.setY(optionTextBounds.y + 10 - (optionTextBounds.height / 2));

    // add in gameplay functionality
    optionBox.setInteractive()
    // for options here

optionBox.on('pointerout', function() {
 this.optionBox.setStrokeStyle(1, 0xb38c03, 1);
this.optionText.setColor('#b39c0e');},  {optionBox, optionText })
  optionBox.on('pointerover', function() {
 this.optionBox.setStrokeStyle(2, 0xffe014, 1);this.optionText.setColor('#ffe014');}
, { optionBox, optionText })
    optionBox.on('pointerup',function(){
      const newPage=this.option.nextPage;
      if (newPage!==undefined){
        destroyPage()
        displayPage(scene,fetchPage(newPage));
      }

    },{option})

 gameState.options.push({
    optionBox,optionText
  })
    
  }
  /* this did NOT work
    if (optionText==="Play again"){
        optionBox.on('pointerup', function() {
          this.scene.stop("game")
      
      })}*/
}

const config = {
  type: Phaser.WEBGL,
  parent: 'phaser-game',
  backgroundColor: 0xfea0fd,
  width: 450,
  height: 550,
  scene: {
    preload,
    create,
  }
};

const game = new Phaser.Game(config);

function fetchPage(page) {


   const pages = [
     {
      character: 'orc',
      page: 1,
      narrative: 'Orc: Hello?',
      options: [
        { option: 'Say Hi',   nextPage: 2 },
        { option: 'Play again',   nextPage: 41 },
      ]
    },



  return pages.find(function(e) { if(e.page == page) return e });
}
1 Answers

I assume you shorted the code for us, so ignoreing the missing ] on line 150 and the missing page number 41 in the pages constant on line 141+.

I would say the problem is not the this.scene.stop("game"), although I would just use this.scene.stop(), if you want the stop the current scene (in to a Reference ).

You can see the problem, if you uncomment the code and check the browser console, an error like:

"...Uncaught ReferenceError: optionText is not defined..."

should be visible. That indicates the real issue, it is that optionText ist not defined. Without diving to deep into your code here are some fixes to get it to work:

  • Move the whole block into the for loop. (just above the } on line 115)

  • change if(optionText=== "Play again") to if(optionText.text === "Play again")since optionText is a text object not a string.

  • Add a the scene object as context to the optionBox.on('pointerup',... eventlistener like this:

      optionBox.on('pointerup', function () {
          this.scene.stop("game")
      }, scene)
    

and it should "work".

btw.: If you have Errors/Problems/... with html/javscript always check the browser console, this can help you find the error much faster.

Related