Insect Invaders: Game freezing on win

Working on this Insect. Invader Game, everything was working fine until step 21, where I added motion to the enemies. It still works okay, but. when I destroy all the enemies, the text below is supposed to. display. It used to, but upon finishing the tutorial, it doesn’t display the. text anymore. Here is the if statement:

if (numOfTotalEnemies() === 0) {
gameState.active = false;
this.physics.pause();
this.pelletsLoop.destroy();
this.add.text(210, 250, “You Win!”, {
fontSize: “30px”,
fill: “#000000”,
});
} else
gameState.enemies.getChildren().forEach((bug) => {
bug.x += gameState.enemyVelocity;
});
gameState.leftMostBug = sortedEnemies()[0];
gameState.rightMostBug = sortedEnemies()[sortedEnemies().length - 1];
if (gameState.leftMostBug.x < 10 || gameState.rightMostBug.x > 440) {
gameState.enemyVelocity *= -1;
gameState.enemies.getChildren().forEach((enemy) => {
enemy.y += 10;
});
}
}
}

What did I miss? Full code below:

function preload() {
this.load.image(
“bug1”,
https://content.codecademy.com/courses/learn-phaser/Bug%20Invaders/bug_1.png
);
this.load.image(
“bug2”,
https://content.codecademy.com/courses/learn-phaser/Bug%20Invaders/bug_2.png
);
this.load.image(
“bug3”,
https://content.codecademy.com/courses/learn-phaser/Bug%20Invaders/bug_3.png
);
this.load.image(
“platform”,
https://content.codecademy.com/courses/learn-phaser/physics/platform.png
);
this.load.image(
“codey”,
https://content.codecademy.com/courses/learn-phaser/Bug%20Invaders/codey.png
);
this.load.image(
“bugPellet”,
https://content.codecademy.com/courses/learn-phaser/Bug%20Invaders/bugPellet.png
);
this.load.image(
“bugRepellent”,
https://content.codecademy.com/courses/learn-phaser/Bug%20Invaders/bugRepellent.png
);
}

// Helper Methods below:
// sortedEnemies() returns an array of enemy sprites sorted by their x coordinate
function sortedEnemies() {
const orderedByXCoord = gameState.enemies
.getChildren()
.sort((a, b) => a.x - b.x);
return orderedByXCoord;
}
// numOfTotalEnemies() returns the number of total enemies
function numOfTotalEnemies() {
const totalEnemies = gameState.enemies.getChildren().length;
return totalEnemies;
}

const gameState = {
enemyVelocity: 1,
};

function create() {
// When gameState.active is true, the game is being played and not over. When gameState.active is false, then it’s game over
gameState.active = true;

// When gameState.active is false, the game will listen for a pointerup event and restart when the event happens
this.input.on(“pointerup”, () => {
if (gameState.active === false) {
this.scene.restart();
}
});

// Creating static platforms
const platforms = this.physics.add.staticGroup();
platforms.create(225, 490, “platform”).setScale(1, 0.3).refreshBody();

// Displays the initial number of bugs, this value is initially hardcoded as 24
gameState.scoreText = this.add.text(175, 482, “Bugs Left: 24”, {
fontSize: “15px”,
fill: “#000000”,
});

// Uses the physics plugin to create Codey
gameState.player = this.physics.add.sprite(225, 450, “codey”).setScale(0.5);

// Create Collider objects
gameState.player.setCollideWorldBounds(true);
this.physics.add.collider(gameState.player, platforms);

// Creates cursor objects to be used in update()
gameState.cursors = this.input.keyboard.createCursorKeys();

// Add new code below:
gameState.enemies = this.physics.add.group();
for (let yVal = 1; yVal < 4; yVal++) {
for (let xVal = 1; xVal < 9; xVal++) {
gameState.enemies
.create(50 * xVal, 50 * yVal, “bug1”)
.setScale(0.6)
.setGravityY(-200);
}
}
const pellets = this.physics.add.group();
const genPellet = () => {
let randomBug = Phaser.Utils.Array.GetRandom(
gameState.enemies.getChildren()
);
pellets.create(randomBug.x, randomBug.y, “bugPellet”);
};
gameState.pelletsLoop = this.time.addEvent({
delay: 300,
callback: genPellet,
callbackScope: this,
loop: true,
});

this.physics.add.collider(pellets, platforms, (pellet) => {
pellet.destroy();
});
this.physics.add.collider(pellets, gameState.player, () => {
gameState.enemyVelocity = 1;
gameState.active = false;
gameState.pelletsLoop.destroy();
this.physics.pause();
this.add.text(210, 250, “Game Over \n Click to restart”, {
fontSize: “15px”,
fill: “#000000”,
});
});
gameState.bugRepellent = this.physics.add.group();
this.physics.add.collider(
gameState.enemies,
gameState.bugRepellent,
(bug, repellent) => {
bug.destroy();
repellent.destroy();
gameState.scoreText.setText(Bugs Left: ${numOfTotalEnemies()});
}
);
this.physics.add.collider(gameState.enemies, gameState.player, () => {
gameState.active = false;
gameState.enemyVelocity = 1;
this.physics.pause();
this.add.text(210, 250, “Game Over \n Click to restart”, {
fontSize: “15px”,
fill: “#000000”,
});
});
}

function update() {
if (gameState.active) {
// If the game is active, then players can control Codey
if (gameState.cursors.left.isDown) {
gameState.player.setVelocityX(-160);
} else if (gameState.cursors.right.isDown) {
gameState.player.setVelocityX(160);
} else {
gameState.player.setVelocityX(0);
}

// Execute code if the spacebar key is pressed
if (Phaser.Input.Keyboard.JustDown(gameState.cursors.space)) {
  gameState.bugRepellent
    .create(gameState.player.x, gameState.player.y, "bugRepellent")
    .setGravityY(-400);
}

// Add logic for winning condition and enemy movements below:
if (numOfTotalEnemies() === 0) {
  gameState.active = false;
  this.physics.pause();
  this.pelletsLoop.destroy();
  this.add.text(210, 250, "You Win!", {
    fontSize: "30px",
    fill: "#000000",
  });
} else
  gameState.enemies.getChildren().forEach((bug) => {
    bug.x += gameState.enemyVelocity;
  });
gameState.leftMostBug = sortedEnemies()[0];
gameState.rightMostBug = sortedEnemies()[sortedEnemies().length - 1];
if (gameState.leftMostBug.x < 10 || gameState.rightMostBug.x > 440) {
  gameState.enemyVelocity *= -1;
  gameState.enemies.getChildren().forEach((enemy) => {
    enemy.y += 10;
  });
}

}
}

const config = {
type: Phaser.AUTO,
width: 450,
height: 500,
backgroundColor: “b9eaff”,
physics: {
default: “arcade”,
arcade: {
gravity: { y: 200 },
enableBody: true,
},
},
scene: {
preload,
create,
update,
},
};

const game = new Phaser.Game(config);

To preserve code formatting in forum posts, see: [How to] Format code in posts

Consider making the following two changes:

  • First Change:
// You wrote:
this.pelletsLoop.destroy();

// Change it to:
gameState.pelletsLoop.destroy();
  • Second Change: You don’t have any curly braces after the else keyword. If there is only one statement after an if or else, then curly braces can be omitted in JavaScript (though it is generally a good idea to use curly braces even if there is only one statement in the block). In your code, I assume (I can’t view the project instructions) all the statements after the else keyword are supposed to be part of the else block, so you should use curly braces.

Look for the following comments in the following snippet to see where the changes need to be made:

//*** <-- THIS LINE ***//

//*** <--OPENING CURLY BRACE FOR else ***//

//*** <--CLOSING CURLY BRACE FOR else ***// 

SNIPPET:

function update() {
    if (gameState.active) {
        // If the game is active, then players can control Codey
        if (gameState.cursors.left.isDown) {
            gameState.player.setVelocityX(-160);
        } else if (gameState.cursors.right.isDown) {
            gameState.player.setVelocityX(160);
        } else {
            gameState.player.setVelocityX(0);
        }
        
        // Execute code if the spacebar key is pressed
        if (Phaser.Input.Keyboard.JustDown(gameState.cursors.space)) {
            gameState.bugRepellent
            .create(gameState.player.x, gameState.player.y, "bugRepellent")
            .setGravityY(-400);
        }
        
        // Add logic for winning condition and enemy movements below:
        if (numOfTotalEnemies() === 0) {
            gameState.active = false;
            this.physics.pause();
            gameState.pelletsLoop.destroy(); //*** <-- THIS LINE ***//
            this.add.text(210, 250, "You Win!", {
                fontSize: "30px", fill: "#000000", 
            });
        } else { //*** <--OPENING CURLY BRACE FOR else ***//
            gameState.enemies.getChildren().forEach((bug) => {
            bug.x += gameState.enemyVelocity; 
            });
            gameState.leftMostBug = sortedEnemies()[0];
            gameState.rightMostBug = sortedEnemies()[sortedEnemies().length - 1];
            if (gameState.leftMostBug.x < 10 || gameState.rightMostBug.x > 440) {
                gameState.enemyVelocity *= -1;
                gameState.enemies.getChildren().forEach((enemy) => {
                enemy.y += 10;
                });
            }
        }  //*** <--CLOSING CURLY BRACE FOR else ***// 
    }
}

Thank you for letting me know about code formatting. I am new to. coding, so little mistakes like that need to be corrected.

Having made those changes, the codes still freezes whenever my character destroys the last bug. Everything that worked before still works with the changes you suggested, so no ham done? I appreciate you having a look any it anyway.

Can you copy/paste your latest code here? I copy/pasted and ran your code in the online Phase 3 labs environment, and it didn’t freeze after destroying the last bug. Instead, it displayed the “You Win!” message and mouse click began new game.

This is what I have. Still getting the same result. Not sure why it works for you.

function preload() {
  this.load.image(
    "bug1",
    "https://content.codecademy.com/courses/learn-phaser/Bug%20Invaders/bug_1.png"
  );
  this.load.image(
    "bug2",
    "https://content.codecademy.com/courses/learn-phaser/Bug%20Invaders/bug_2.png"
  );
  this.load.image(
    "bug3",
    "https://content.codecademy.com/courses/learn-phaser/Bug%20Invaders/bug_3.png"
  );
  this.load.image(
    "platform",
    "https://content.codecademy.com/courses/learn-phaser/physics/platform.png"
  );
  this.load.image(
    "codey",
    "https://content.codecademy.com/courses/learn-phaser/Bug%20Invaders/codey.png"
  );
  this.load.image(
    "bugPellet",
    "https://content.codecademy.com/courses/learn-phaser/Bug%20Invaders/bugPellet.png"
  );
  this.load.image(
    "bugRepellent",
    "https://content.codecademy.com/courses/learn-phaser/Bug%20Invaders/bugRepellent.png"
  );
}

// Helper Methods below:
// sortedEnemies() returns an array of enemy sprites sorted by their x coordinate
function sortedEnemies() {
  const orderedByXCoord = gameState.enemies
    .getChildren()
    .sort((a, b) => a.x - b.x);
  return orderedByXCoord;
}
// numOfTotalEnemies() returns the number of total enemies
function numOfTotalEnemies() {
  const totalEnemies = gameState.enemies.getChildren().length;
  return totalEnemies;
}

const gameState = {
  enemyVelocity: 1,
};

function create() {
  // When gameState.active is true, the game is being played and not over. When gameState.active is false, then it's game over
  gameState.active = true;

  // When gameState.active is false, the game will listen for a pointerup event and restart when the event happens
  this.input.on("pointerup", () => {
    if (gameState.active === false) {
      this.scene.restart();
    }
  });

  // Creating static platforms
  const platforms = this.physics.add.staticGroup();
  platforms.create(225, 490, "platform").setScale(1, 0.3).refreshBody();

  // Displays the initial number of bugs, this value is initially hardcoded as 24
  gameState.scoreText = this.add.text(175, 482, "Bugs Left: 24", {
    fontSize: "15px",
    fill: "#000000",
  });

  // Uses the physics plugin to create Codey
  gameState.player = this.physics.add.sprite(225, 450, "codey").setScale(0.5);

  // Create Collider objects
  gameState.player.setCollideWorldBounds(true);
  this.physics.add.collider(gameState.player, platforms);

  // Creates cursor objects to be used in update()
  gameState.cursors = this.input.keyboard.createCursorKeys();

  // Add new code below:
  gameState.enemies = this.physics.add.group();
  for (let yVal = 1; yVal < 4; yVal++) {
    for (let xVal = 1; xVal < 9; xVal++) {
      gameState.enemies
        .create(50 * xVal, 50 * yVal, "bug1")
        .setScale(0.6)
        .setGravityY(-200);
    }
  }
  const pellets = this.physics.add.group();
  const genPellet = () => {
    let randomBug = Phaser.Utils.Array.GetRandom(
      gameState.enemies.getChildren()
    );
    pellets.create(randomBug.x, randomBug.y, "bugPellet");
  };
  gameState.pelletsLoop = this.time.addEvent({
    delay: 300,
    callback: genPellet,
    callbackScope: this,
    loop: true,
  });

  this.physics.add.collider(pellets, platforms, (pellet) => {
    pellet.destroy();
  });
  this.physics.add.collider(pellets, gameState.player, () => {
    gameState.enemyVelocity = 1;
    gameState.active = false;
    gameState.pelletsLoop.destroy();
    this.physics.pause();
    this.add.text(210, 250, "Game Over \n Click to restart", {
      fontSize: "15px",
      fill: "#000000",
    });
  });
  gameState.bugRepellent = this.physics.add.group();
  this.physics.add.collider(
    gameState.enemies,
    gameState.bugRepellent,
    (bug, repellent) => {
      bug.destroy();
      repellent.destroy();
      gameState.scoreText.setText(`Bugs Left: ${numOfTotalEnemies()}`);
    }
  );
  this.physics.add.collider(gameState.enemies, gameState.player, () => {
    gameState.active = false;
    gameState.enemyVelocity = 1;
    this.physics.pause();
    this.add.text(210, 250, "Game Over \n Click to restart", {
      fontSize: "15px",
      fill: "#000000",
    });
  });
}

function update() {
  if (gameState.active) {
    // If the game is active, then players can control Codey
    if (gameState.cursors.left.isDown) {
      gameState.player.setVelocityX(-160);
    } else if (gameState.cursors.right.isDown) {
      gameState.player.setVelocityX(160);
    } else {
      gameState.player.setVelocityX(0);
    }

    // Execute code if the spacebar key is pressed
    if (Phaser.Input.Keyboard.JustDown(gameState.cursors.space)) {
      gameState.bugRepellent
        .create(gameState.player.x, gameState.player.y, "bugRepellent")
        .setGravityY(-400);
    }

    // Add logic for winning condition and enemy movements below:
    if(numOfTotalEnemies() === 0) {
      this.physics.pause();
      this.pelletsLoop.destroy();
      gameState.active = false;
      this.add.text (210, 250, 'You Win!', {fontSize: '30px', fill: '#000000',
  });
    } else if (numOfTotalEnemies() < 3) {
gameState.pelletsLoop.timeScale = 0.5;
gameState.enemies.getChildren().forEach((bug) => {
        bug.x += gameState.enemyVelocity;
      });
    gameState.leftMostBug = sortedEnemies()[0];
    gameState.rightMostBug = sortedEnemies()[sortedEnemies().length - 1];
    if (gameState.leftMostBug.x < 10 || gameState.rightMostBug.x > 440) {
      gameState.enemyVelocity *= -1;
      gameState.enemies.getChildren().forEach((enemy) => {
        enemy.y += 10;
      });
    }
    } else {
      gameState.enemies.getChildren().forEach((bug) => {
        bug.x += gameState.enemyVelocity;
      });
    gameState.leftMostBug = sortedEnemies()[0];
    gameState.rightMostBug = sortedEnemies()[sortedEnemies().length - 1];
    if (gameState.leftMostBug.x < 10 || gameState.rightMostBug.x > 440) {
      gameState.enemyVelocity *= -1;
      gameState.enemies.getChildren().forEach((enemy) => {
        enemy.y += 10;
      });
    }
  }
  }
}

const config = {
  type: Phaser.AUTO,
  width: 450,
  height: 500,
  backgroundColor: "b9eaff",
  physics: {
    default: "arcade",
    arcade: {
      gravity: { y: 200 },
      enableBody: true,
    },
  },
  scene: {
    preload,
    create,
    update,
  },
};

const game = new Phaser.Game(config);

You forgot to change the line highlighted by the red arrow:
scrn1

// You wrote:
this.pelletsLoop.destroy();

// Change it to:
gameState.pelletsLoop.destroy();

Now, it should work.


Also, the code for your else if (numOfTotalEnemies() < 3) block and your else block is identical except for a single statement.

gameState.pelletsLoop.timeScale = 0.5;

You could get rid of the else if block and just write it as:

} else { 
            if (numOfTotalEnemies() < 3) {
                   gameState.pelletsLoop.timeScale = 0.5;
            } 
            gameState.enemies.getChildren().forEach((bug) => {
            bug.x += gameState.enemyVelocity; 
            });
            gameState.leftMostBug = sortedEnemies()[0];
            gameState.rightMostBug = sortedEnemies()[sortedEnemies().length - 1];
            if (gameState.leftMostBug.x < 10 || gameState.rightMostBug.x > 440) {
                gameState.enemyVelocity *= -1;
                gameState.enemies.getChildren().forEach((enemy) => {
                enemy.y += 10;
                });
            }
        } 
1 Like

It works now! Thank you.

Sorry to add extra bother, but where would be a good place to start if I wanted to learn more about when to use “gameState,” and when to use 'this?" I am still not sure, having completed the intro to JavaScript and nearly completing this Phaser module. It’s a mistake I keep making.