[Game Development with Phaser] Timed event causing problems with interactivity

Note: there is no section nor tag for game development/phaser? Not sure whether I put this question in the right section.

After finishing the Learn Game Development with Phaser course I have started creating a game on my own, basically by editing the code that was used during the course. I still have a lot of questions, but by messing around I can solve most. However, I’m stuck now: it seems that using a timed event causes other functionality to not work anymore.

Below my code. There are three horses running around randomly. I now want to add some buttons that are interactive, like gameState.buttonMenu. However, calling setInteractive() on the button did not work.

I thought maybe there’s something wrong with the button itself, so I added the rectangles from the course to the game (from https://www.codecademy.com/paths/create-video-games-with-phaser/tracks/game-dev-learn-phaser-basics-and-physics/modules/game-dev-learn-phaser-basics/lessons/learn-phaser-basics/exercises/input). They also did not work.

However, if I comment out gameState.moveHorsesLoop and its call (see below), the interactivity DOES work. What is the cause of this? Does this.time.addEvent cause other functionality to not work? What would be a workaround?

gameState.moveHorsesLoop = this.time.addEvent({
      delay: 3000,
      callback: gameState.moveHorses,
      loop: true,
    });

gameState.moveHorsesLoop();

Full code:

const gameState = {};

class HomeScene extends Phaser.Scene {
  constructor() {
    super({ key: 'HomeScene' });
  }

  preload() {
    this.load.spritesheet("horse_eat", 'img/Horse_Eat.png', { frameWidth: 60, frameHeight: 33 });
    this.load.spritesheet("horse_idle", 'img/Horse_Idle.png', { frameWidth: 60, frameHeight: 33 });
    this.load.spritesheet("horse_run", 'img/Horse_Run.png', { frameWidth: 60, frameHeight: 33 });
    this.load.spritesheet("horse_walk", 'img/Horse_Walk.png', { frameWidth: 60, frameHeight: 33 });
    this.load.image("background", "img/PaardenspelMap2.png");
    //this.load.addFile(new WebFontFile(this.load, 'Press Start 2P'));
    WebFont.load({ google: { families: ["Roboto"] }});
    this.load.image("button_menu", "assets/ui/outline_menu_white_48dp.png");
  }

  create() {

    gameState.active = true;
    this.add.image(0, 0, "background").setOrigin(0, 0);
    this.add.text(500, 300, "Hello", { color: "#ffffff", fontSize: "50px", fontFamily: "Roboto" });

// this is the button I want to make functional
    gameState.buttonMenu = this.add.image(1200,50, "button_menu").setScale(2);

// below the code I got from the Phaser course https://www.codecademy.com/paths/create-video-games-with-phaser/tracks/game-dev-learn-phaser-basics-and-physics/modules/game-dev-learn-phaser-basics/lessons/learn-phaser-basics/exercises/input
    gameState.onColor = 0xaaffaa;
    gameState.offColor= 0xffaaaa;

    gameState.rect1 = this.add.rectangle(200, 100, 100, 100, gameState.onColor);
    gameState.rect2 = this.add.rectangle(200, 300, 100, 100, gameState.offColor);
    
    gameState.rect2.setInteractive();
    gameState.rect2.on("pointerup", function() {
      gameState.rect1.fillColor = gameState.offColor;
      gameState.rect2.fillColor = gameState.onColor;
    });
    
    gameState.rect1.setInteractive();
    gameState.rect1.on("pointerup", function() {
      gameState.rect1.fillColor = gameState.onColor;
      gameState.rect2.fillColor = gameState.offColor;
    });

// animations (copied/edited from course)
    this.anims.create({
      key: 'run',
      frames: this.anims.generateFrameNumbers('horse_run', { start: 0, end: 5 }),
      frameRate: 12,
      repeat: -1
    });

    this.anims.create({
      key: 'idle',
      frames: this.anims.generateFrameNumbers('horse_idle', { start: 0, end: 12 }),
      frameRate: 5,
      repeat: -1
    });

    this.anims.create({
      key: 'walk',
      frames: this.anims.generateFrameNumbers('horse_walk', { start: 0, end: 11 }),
      frameRate: 5,
      repeat: -1
    });

    this.anims.create({
      key: 'eat',
      frames: this.anims.generateFrameNumbers('horse_eat', { start: 0, end: 11 }),
      frameRate: 5,
      repeat: -1
    });

// here I'm adding horses randomly in the game
    gameState.horses = this.physics.add.group();
    gameState.horseGen = () => {
      const xCoord = Math.random() * 1280
      const yCoord = Math.random() * 720
      gameState.horses.create(xCoord, yCoord, "horse_idle")
    }

    gameState.horseGen();
    gameState.horseGen();
    gameState.horseGen();

// with this function I'm causing the horses to randomly move based on a timer
    gameState.moveHorses = () => {
      gameState.horses.getChildren().forEach((horse) => {
        const randNumber = Math.floor(Math.random() * 40);
        if (randNumber < 5) {
          horse.setVelocityX(30);
          horse.anims.play('run', true);
          horse.flipX = true;
        } else if (randNumber >= 5 && randNumber < 10) {
          horse.setVelocityX(-30);
          horse.anims.play('run', true);
          horse.flipX = false;
        } else if (randNumber >= 10 && randNumber < 15) {
          horse.setVelocityX(10);
          horse.anims.play('walk', true);
          horse.flipX = true;
        } else if (randNumber >= 15 && randNumber < 20) {
          horse.setVelocityX(-10);
          horse.anims.play('walk', true);
          horse.flipX = false;
        } else {
          horse.setVelocityX(0);
          horse.anims.play('idle', true);
          horse.flipX = true;
        }
      });
    };

// the timer of gameState.moveHorses()
    gameState.moveHorsesLoop = this.time.addEvent({
      delay: 3000,
      callback: gameState.moveHorses,
      loop: true,
    });

    gameState.moveHorses();
    gameState.moveHorsesLoop();

    
  }

  update() {

  }

}


const config = {
  type: Phaser.AUTO,
  width: 1280,
  height: 720,
  physics: {
    default: 'arcade',
    arcade: {
      gravity: { y: 0 },
      enableBody: true,
    }
  },
  scene: [HomeScene]
};

const game = new Phaser.Game(config);

Hey Jantien
These are things that come to mind, don’t know if they are right, but could be worth a try, either one of them or all of them, I don’t know:

  • try to add callbackScope: this, to this.time.addEvent() object parameter.

  • Instead of using this.time.addEvent() PhaserJS method, try a vanilla JS setInterval() theoretically it should work just the same.

  • It may be something related to timing, so it could be necessary using async-await.

If you open the browser console do you get any error?

Cheers,