Someone already asked that question, but they didn't seem to get the right answer.
This is my code:
const eggGenLoop = this.time.addEvent({
delay: 1500 - (gameState.score * 100),
callback: eggGen,
callbackScope: this,
loop: true,
});
so the delay doesn't change, clearly phaser just takes the initial gameState.score which is 0. two months ago i tried to make the same game, using plain JavaScript and setTimeout() / setInterval(), but i stumbled at the same obstacle, i hoped with phaser.js it would be easier.
As you mentioned, using this.time.addEvent
and setting delay
won't work, the reason is because the TimerEvent
is created once, on
the call this.time.addEvent(...)
.
I see two simple options (personally I would choose option 2):
Option 1)
You could instead use setTimeout
and call it recursively, and update the delay
on each call.
function setTimoutWithVariableDelta( score ){
setTimeout(
_ => {
// ... do some stuff
setTimoutWithVariableDelta( gameState.score );
},
1500 - (score * 100));
}
Depending on your code, this option might not work well (and btw.: setTimeout
, doesn't stop when the browser is in the background).
Option 2)
Or you could use the Scene
update
function.
I put the logic for this type of dynamic delay into the function callOnMuliplierInterval
, it should be straight forward. Just using the time
parameter of the update function to keep track of the delay. (here the link to the documentation)
Here is a possible example:
(Sorry it got abit long, I got carried away)
document.body.style = 'margin:0;';
var config = {
type: Phaser.AUTO,
width: 536,
height: 203,
scene: { create, update },
banner: false
};
let interval = 2000;
let lastRun = -1;
let statusText;
let score = 1;
let currentDelta = 1;
let callsCount = 0;
function create () {
statusText = this.add.text(220, 20, `Score multiplier: ${score}`)
.setFontFamily('Arial')
.setFontStyle('bold')
.setFontSize('20px');
createButton(this, 40, 20, 0xff0000, '#ffffff', .33);
createButton(this, 40, 80, 0x0000ff, '#ffffff', .66);
createButton(this, 40, 140, 0x008800, '#ffffff', 1);
}
// demo helper function for creating buttons
function createButton(scene, x, y, color, textColor, multiplier){
let button = scene.add.rectangle(x, y, 140, 40, color)
.setOrigin(0);
let buttonText = scene.add.text(0, 0, `Score: ${multiplier}`)
.setFontFamily('Arial')
.setFontStyle('bold')
.setFontSize('20px');
Phaser.Display.Align.In.Center(buttonText, button);
button
.setInteractive()
.on('pointerdown', _ => score = multiplier);
}
// this function contains the important logic
function callOnMuliplierInterval(time){
let newMessage = `Score multiplier: ${score}\n`;
newMessage += `ElapsedTime: ${(time / 1000).toFixed(0)}s\n\n`;
newMessage += `CurrentDelay: ${currentDelta}\n`;
newMessage += `NextDelay: ${interval * score}\n\n`;
newMessage += `TimesCalled: ${callsCount}`;
// Execute on: first Run or when the delay has passed
if( lastRun == -1 || lastRun + currentDelta <= time ){
lastRun = time;
currentDelta = interval * score;
// HERE YOU WOULD DO THE ACTION
callsCount++;
}
// Just update the message
statusText.setText(newMessage);
}
function update(time, delta){
callOnMuliplierInterval(time);
}
new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>