How to run a function each minute in Phaser 3?

Viewed 3115

I'm making a game in JavaScript, but in the class power ups, I want to create a power up each minute. The problem is that it's called in the update method of the class, and this is called each frame in the main update, so once it runs, it doesn't stop again and keeps looping. How can I make it stop and start again?

I was trying with getting the seconds like this:

Method create power up:

let time = new Date.getSeconds();
if (time >=59) {create power up}

Method update of the power up class:

this.createpowerup();

Now in the main class I call all update methods from the classes that I have:

update() {
    this.player_spaceship_object.update();    
    this.enemy_spaceship_object.update();
    this.power_up_object.update();
    this.movebackground();
}

So each frame it will be calling them, but the problem is when power up ends in zero, it creates a lot of power ups until it starts 1, theres like milliseconds to start 1, how can do this in a loop?

Power up class:

class Power_ups extends Phaser.GameObjects.Sprite {
constructor(scene) {
    super(scene, scene.player_spaceship.x, scene.player_spaceship.y, "power_up");
    //this.hi();
}
hi() {
    setInterval(this.hola,5000);
}
hola() {
    console.log("hola");
}
update() {
    this.hi();
}
}

Main class, this is the class that runs once enter to the page:

class Scene2 extends Phaser.Scene {
constructor() {
    super("Scene2");
}
create() {
    this.scoreText;
    this.timedEvent;
    this.background = this.add.tileSprite(0,0,globalThis.config.width,globalThis.config.height,"space");
    this.background.setOrigin(0,0);
    this.player_spaceship = this.physics.add.sprite(globalThis.config.width/2-50,globalThis.config.height/2,"player_spaceship");
    this.player_spaceship_object = new Player_spaceship(this);
    this.enemy_spaceship_group = this.physics.add.group();
    this.enemy_spaceship_object = new Enemy_spaceship(this);
    this.physics.add.collider(this.player_spaceship,this.enemy_spaceship_group,this.collision_player_enemy,null,this);
    this.power_up;
    this.power_up_object = new Power_ups(this);
    this.power_up_object.createpowerUp();
    
}
collision_player_enemy(player, enemy) { //parameters tells the function the objects that will collide
    this.player_spaceship_object.damage();
    this.enemy_spaceship_object.resetShip(enemy);
}
movebackground(bool = "") {
    this.background.tilePositionY = (bool === true) ? this.background.tilePositionY += 1 : this.background.tilePositionY -= 1;
}
update() {
    this.player_spaceship_object.update();    
    this.enemy_spaceship_object.update();
    this.power_up_object.update();
    this.movebackground();
}
}
3 Answers

You have a couple options with Phaser 3.

First, you could certainly add some logic to the built-in update() functionality in the scene. However, if you do so you'll need to manually keep track of the last time you added a powerup, and when you need to add another one.

For example, you might add a property to the scene to track the next time a powerup should be added, and then if the current time is equal to or after that, create a powerup, and then update the property value (current time + 1 minute).

An easier method is likely to use Phaser 3's built-in timer functionality.

On your scene, add a property to keep track of the TimerEvent, as this will allow you to later pause or stop it.

Next, in the scene's create() create the timer event.

TypeScript example:

export default class MainGame extends Phaser.Scene {
    // Store the timer so we can access it later.
    private triggerTimer: Phaser.Time.TimerEvent;

    public create(): void {
        // ...
        this.triggerTimer = this.time.addEvent({
            callback: this.timerEvent,
            callbackScope: this,
            delay: 60000, // 1000 = 1 second
            loop: true
        });
        // ...
    }

    public timerEvent(): void {
        console.log('timerEvent');
        // Create your new object here.
    }
}

Either way, in your game sprite you should remove the functionality in update() that triggers hi(), as this effectively results in your sprites creating new timers every time the scene (and therefore each sprite) updates.

If you want an event to trigger x seconds after a sprite is created, you should define the timer (via setInterval or a Phaser timer) in the constructor instead.

You need to use setInterval, See example hope it will help you.

function update(){
  console.log("your code");
}

setInterval(update, 2000);

I stringly recommend using requestAnimationFrame in order to have a slightly better timing between your UI and logic.

function powerUpEveryMinute() {
  // powerUp!!!!
  setTimeout(() => {
     requestAnimationFrame(powerUpEveryMinute);
  }, 60000);
}
requestAnimationFrame(powerUpEveryMinute);

This will call the animationFrame API. First it runs your power up, waits 1 minute and then calls the animationFrame API again with the same function and power up will be called 1 minute after this first one.

Let me know if this works

Related