I'm trying to add a fade to black event to my game. It triggers after a certain dialogue is triggered, and causes the screen to fade to black and then switch to another scene. I started by creating a big, black sprite that covers the entire screen, the set its alpha to 0. Here is the code that makes the fade work:
this.line1.setText('Scally: Its been a long day Peef. Ready to hit the hay?');
this.line2.setText('Press A for: Yeah I am ready to sleep. or Press D for: Naw, I am gonna stay up a bit more.');
this.time.addEvent({
delay: 2500,
callback: () => this.blackFade.setAlpha(0.2),
callback: () => console.log("1"),
callbackScope: this,
});
this.time.addEvent({
delay: 4500,
callback: () => this.blackFade.setAlpha(0.4),
callback: () => console.log("2"),
callbackScope: this,
});
this.time.addEvent({
delay: 6500,
callback: () => this.blackFade.setAlpha(0.6),
callback: () => console.log("3"),
callbackScope: this,
});
this.time.addEvent({
delay: 8500,
callback: () => this.blackFade.setAlpha(0.8),
callback: () => console.log("4"),
callbackScope: this,
});
this.time.addEvent({
delay: 10500,
callback: () => this.blackFade.setAlpha(1),
callback: () => console.log("5"),
callbackScope: this,
});
this.time.addEvent({
delay: 12500,
callback: () => this.scene.switch('bedRoomDay2'),
callbackScope: this,
});
As I have this code in the update method, I'm having an issue where the timer events are triggered multiple times, causing the screen to only darken a little with occasional darker flashes before switching scenes, never becoming completely black. Is there a way to ensure that the timer events only trigger once, preferably without moving the code out of the update method?
If it helps, I'm using Phaser 3 in VSCode employing arcade physics.
Well you would need a helper variable to prevent multiple calls, and instead of the timer
, I would recommend using one simply tween
call, since the tween would update the alpha
property in a smooth fashion.
Both mentioned concepts are demonstrated in the following example.
Small fade-out Demo:
document.body.style = 'margin:0;';
var config = {
width: 536,
height: 183,
scene: {
create,
update,
}
};
function create () {
this.label = this.add.text(10,10, 'Use Spacebar, to Fade WhiteBox')
.setScale(1.5)
.setOrigin(0)
.setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
// Fade Status Varible Initialize
this.isFading = false;
this.spacebar = this.input.keyboard.addKey('space');
// Game Object to fade
this.add.rectangle(268, 91, 200, 50, 0xffffff);
this.blackFade = this.add.rectangle(268, 91, 200, 50, 0);
this.blackFade.setAlpha(0);
}
function update(){
// Only start fading, if fading is not taking place
if(!this.isFading && Phaser.Input.Keyboard.JustDown(this.spacebar)){
if(this.blackFade.alpha == 0){
this.isFading = true;
this.tweens.add({
targets: this.blackFade,
alpha: 1,
duration: 6000,
onComplete: () => {
// reset variable
this.isFading = false;
this.label.setText('Use Spacebar, to show WhiteBox');
},
repeat: 0,
});
} else {
// fade reset only for demo
this.blackFade.alpha = 0;
this.label.setText('Use Spacebar, to Fade WhiteBox');
}
}
}
new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>
Update:
There are several way to let the black screen linger, but the easy one is simply to increase the duration
and/or the alpha
value of the tween. the alpha
value will the
Small fade-out & linger Demo:
Setting alpha
to 2
this means, that half of the tween duration
about ~3000ms the screen will be black. if you need less us can adjust the alpha
property.
document.body.style = 'margin:0;';
var config = {
width: 536,
height: 183,
scene: {
create,
update,
}
};
function create () {
this.label = this.add.text(10,10, 'Use Spacebar, to Fade WhiteBox')
.setScale(1.5)
.setOrigin(0)
.setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
// Fade Status Varible Initialize
this.isFading = false;
this.spacebar = this.input.keyboard.addKey('space');
// Game Object to fade
this.add.rectangle(268, 91, 200, 50, 0xffffff);
this.blackFade1 = this.add.rectangle(218, 91, 100, 50, 0);
this.blackFade1.setAlpha(0);
this.blackFade2 = this.add.rectangle(318, 91, 100, 50, 0);
this.blackFade2.setAlpha(0);
}
function update(){
// Only start fading, if fading is not taking place
if(!this.isFading && Phaser.Input.Keyboard.JustDown(this.spacebar)){
if(this.blackFade1.alpha == 0){
this.isFading = true;
this.tweens.add({
targets: this.blackFade1,
alpha: 2,
duration: 8000,
onComplete: () => {
// reset variable
this.isFading = false;
this.label.setText('Use Spacebar, to show WhiteBox');
},
repeat: 0,
});
this.tweens.add({
targets: this.blackFade2,
alpha: 1,
duration: 8000,
onComplete: () => {
// reset variable
// this.isFading = false;
// this.label.setText('Use Spacebar, to show WhiteBox');
},
repeat: 0,
});
} else {
// fade reset only for demo
this.blackFade1.alpha = 0;
this.blackFade2.alpha = 0;
this.label.setText('Use Spacebar, to Fade WhiteBox');
}
}
}
new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>
Or: simply call a timer from the
onComplete
callback.