Scene Transitions
Many times in your game you'll want to smoothly go from one scene to the next, or provide a custom effect when transitioning!
Using Pre-Defined Scene Transitions
It is generally recommended that you define you scenes up front, when you do you have the opportunity to also specify the in/out transitions for a scene.
in
transitions play when the target scene has started, and will play the effect until theduration
in milliseconds is completeout
transitions play before the current scene is deactivated, the transition must complete before deactivation.
If no in/out
transition is specified for a scene it will hard cut from one to the other.
ts
constgame = newex .Engine ({scenes : {scene1 : {scene :MyScene ,transitions : {in : newex .FadeInOut ({duration : 500,direction : 'in',color :ex .Color .Black }),out : newex .FadeInOut ({duration : 500,direction : 'out',color :ex .Color .Black })}},scene2 : {scene :MyOtherScene ,transitions : {in : newex .FadeInOut ({duration : 500,direction : 'in',color :ex .Color .Black }),out : newex .FadeInOut ({duration : 500,direction : 'out',color :ex .Color .Black })}}}});game .goToScene ('scene1');
ts
constgame = newex .Engine ({scenes : {scene1 : {scene :MyScene ,transitions : {in : newex .FadeInOut ({duration : 500,direction : 'in',color :ex .Color .Black }),out : newex .FadeInOut ({duration : 500,direction : 'out',color :ex .Color .Black })}},scene2 : {scene :MyOtherScene ,transitions : {in : newex .FadeInOut ({duration : 500,direction : 'in',color :ex .Color .Black }),out : newex .FadeInOut ({duration : 500,direction : 'out',color :ex .Color .Black })}}}});game .goToScene ('scene1');
or using the add scene api
ts
constgame = newex .Engine ();game .add ('scene1', {scene :MyScene ,transitions : {in : newex .FadeInOut ({duration : 500,direction : 'in',color :ex .Color .Black }),out : newex .FadeInOut ({duration : 500,direction : 'out',color :ex .Color .Black })}});
ts
constgame = newex .Engine ();game .add ('scene1', {scene :MyScene ,transitions : {in : newex .FadeInOut ({duration : 500,direction : 'in',color :ex .Color .Black }),out : newex .FadeInOut ({duration : 500,direction : 'out',color :ex .Color .Black })}});
Click canvas to transition!
Transition Options
Transitions have a few tricks up their sleeves, you can control duration, direction, easing function, whether to hide any loaders, or block user input during the transition
ts
consttransition = newex .Transition ({/*** Transition duration in milliseconds*/duration : 1000,/*** Optionally hides the loader during the transition** If either the out or in transition have this set to true, then the loader will be hidden.** Default false*/hideLoader : false,/*** Optionally blocks user input during a transition** Default false*/blockInput : false,/*** Optionally specify a easing function, by default linear*/easing :ex .EasingFunctions .Linear ,/*** Optionally specify a transition direction, by default 'out'** * For 'in' direction transitions start at 1 and complete is at 0* * For 'out' direction transitions start at 0 and complete is at 1*/direction : 'out',})
ts
consttransition = newex .Transition ({/*** Transition duration in milliseconds*/duration : 1000,/*** Optionally hides the loader during the transition** If either the out or in transition have this set to true, then the loader will be hidden.** Default false*/hideLoader : false,/*** Optionally blocks user input during a transition** Default false*/blockInput : false,/*** Optionally specify a easing function, by default linear*/easing :ex .EasingFunctions .Linear ,/*** Optionally specify a transition direction, by default 'out'** * For 'in' direction transitions start at 1 and complete is at 0* * For 'out' direction transitions start at 0 and complete is at 1*/direction : 'out',})
Overriding Transitions
There are 2 ways to override pre-defined transitions
goToScene('myscene', { destinationIn: ..., sourceOut: ... })
takes the highest precedence and will override any transition- Extending Scene.onTransition you can provide dynamic transitions depending on your scene's state
typescript
class MyCustomScene extends ex.Scene {onTransition(direction: "in" | "out") {return new ex.FadeInOut({direction,color: ex.Color.Violet,duration: 2000});}}
typescript
class MyCustomScene extends ex.Scene {onTransition(direction: "in" | "out") {return new ex.FadeInOut({direction,color: ex.Color.Violet,duration: 2000});}}
FadeInOut
This transition does exactly as it sounds, you can specific a duration in milliseconds and it will fade in the specified direction
. FadeInOut uses the color Color.Black by default.
- The
direction: 'in'
direction means the transition will start fully opaque (non-transparent), then transition to fully transparent. - The
direction: 'out'
direction means the transition will start fully transparent, then transition to fully opaque (non-transparent).
CrossFade
CrossFade can only be used on the `in`` transition for a scene, this is because it needs to screenshot the previous scene in order to cross fade it.
You can specific a duration in milliseconds and it will fade in the specified direction
. CrossFade takes a screen shot of the previous scene and blends that into the current scene.
- The
direction: 'in'
direction means the transition will start fully opaque (non-transparent), then transition to fully transparent. - The
direction: 'out'
direction means the transition will start fully transparent, then transition to fully opaque (non-transparent).
Click canvas to transition!
Starting Scene Transition
Sometimes you want a special start transition for the beginning of your game after loading. You may want to match the color, do something special, etc.
This can be done on the Engine.start by providing a start transition
typescript
game.start('scene1',{inTransition: startTransition});
typescript
game.start('scene1',{inTransition: startTransition});
Custom built Transitions
Transitions are really an Entity with a TransformComponent and GraphicsComponent that take up the entire screen and draw on top of everything by default z = Infinity
.
To build your own custom transition, extend Transition and implement the stubbed methods
For example this is CrossFade's implementation
typescript
export class CrossFade extends Transition {engine: Engine;image: HTMLImageElement;screenCover: Sprite;constructor(options: TransitionOptions & CrossFadeOptions) {super(options);this.name = `CrossFade#${this.id}`;}override async onPreviousSceneDeactivate(scene: Scene<unknown>) {this.image = await scene.engine.screenshot(true);}override onInitialize(engine: Engine): void {this.engine = engine;const bounds = engine.screen.getWorldBounds();this.transform.pos = vec(bounds.left, bounds.top);this.screenCover = ImageSource.fromHtmlImageElement(this.image).toSprite();this.graphics.add(this.screenCover);this.transform.scale = vec(1 / engine.screen.pixelRatio, 1 / engine.screen.pixelRatio);this.graphics.opacity = this.progress;}override onStart(_progress: number): void {this.graphics.opacity = this.progress;}override onReset() {this.graphics.opacity = this.progress;}override onEnd(progress: number): void {this.graphics.opacity = progress;}override onUpdate(progress: number): void {this.graphics.opacity = progress;}}
typescript
export class CrossFade extends Transition {engine: Engine;image: HTMLImageElement;screenCover: Sprite;constructor(options: TransitionOptions & CrossFadeOptions) {super(options);this.name = `CrossFade#${this.id}`;}override async onPreviousSceneDeactivate(scene: Scene<unknown>) {this.image = await scene.engine.screenshot(true);}override onInitialize(engine: Engine): void {this.engine = engine;const bounds = engine.screen.getWorldBounds();this.transform.pos = vec(bounds.left, bounds.top);this.screenCover = ImageSource.fromHtmlImageElement(this.image).toSprite();this.graphics.add(this.screenCover);this.transform.scale = vec(1 / engine.screen.pixelRatio, 1 / engine.screen.pixelRatio);this.graphics.opacity = this.progress;}override onStart(_progress: number): void {this.graphics.opacity = this.progress;}override onReset() {this.graphics.opacity = this.progress;}override onEnd(progress: number): void {this.graphics.opacity = progress;}override onUpdate(progress: number): void {this.graphics.opacity = progress;}}