Skip to content

State Management

dill pixel uses a simple state management system to manage the different states (or screens) in your game. For example, a simple game might have a TitleScreen, GameScreen, and GameOverScreen. Let’s see how we would include those in our game and switch between them.

Creating a Base State

To create a new state, create a new file in the src/states directory. For example, let’s create a BaseState that all of our other game states will extend. This first state should extend dill pixel’s State class and for now we’ll just add custom animateIn and animateOut methods that will fade all of our states in and out:

src/states/BaseState.ts
import { State } from 'dill-pixel';
import { gsap } from 'gsap';
import { Sprite, Text } from 'pixi.js';
import { Application } from '../Application';
export class BaseState extends State<Application> {
public async animateIn(pOnComplete: () => void): Promise<void> {
await gsap.timeline().fromTo(
this,
{
alpha: 0,
},
{
duration: 0.5,
alpha: 1,
},
);
pOnComplete();
}
public async animateOut(pOnComplete: () => void): Promise<void> {
await gsap.timeline().fromTo(
this,
{
alpha: 1,
},
{
duration: 0.5,
alpha: 0,
},
);
pOnComplete();
}
}

Creating a Screen

Next, let’s create a TitleScreen that extends our BaseState:

src/states/TitleScreen.ts
import { FlexContainer } from 'dill-pixel';
import { Point, Sprite, Text } from 'pixi.js';
import { BaseState } from './BaseState';
// The title screen is a green background with a centered title
export class TitleScreen extends BaseState {
static NAME: string = 'TitleScreen';
protected _bg: Sprite;
protected _layout: FlexContainer;
protected _title: Text;
public constructor() {
super();
}
// Create the elements
public init(pSize: Point) {
super.init(pSize);
// Create the green background
this._bg = this.add.coloredSprite(0x33aa66);
this._bg.eventMode = 'static';
// Use a flex container for the layout
this._layout = this.add.flexContainer({
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
gap: 20,
});
// Add the title text
this._title = this._layout.add.text({
value: 'Welcome to my game!',
style: {
fontFamily: 'sans-serif',
fontSize: 36,
fill: 'white',
},
anchor: 0.5,
});
this.onResize(pSize);
}
// When the screen resizes, resize the background
public onResize(pSize: Point) {
super.onResize(pSize);
if (this._bg) {
this._bg.width = this._size.x;
this._bg.height = this._size.y;
}
}
// Clean up
public destroy() {
super.destroy();
}
}

Registering States

Once all of the states have been created, they need to be registered with the game. This is done in the src/Application.ts file:

src/Application.ts
import { Application as DillPixelApplication, TransitionType } from 'dill-pixel';
// Load all of the game states
import { TitleScreen } from './state/LoadScreen';
import { GameScreen } from './state/GameScreen';
import { GameOverScreen } from './state/GameOverScreen';
export class Application extends DillPixelApplication {
...
// Register the states
protected registerStates(): void {
this.state.register(TitleScreen);
this.state.register(GameScreen);
this.state.register(GameOverScreen);
}
}

Switching Between States

To switch between states, use the transitionTo method on the game instance:

// From within the Application.ts file
this.state.transitionTo(TitleScreen.NAME) // reference by the class' NAME attribute
this.state.transitionTo('TitleScreen') // reference by the NAME attribute as a string
// From within a game state (e.g. TitleScreen.ts)
this.app.state.transitionTo(GameScreen.NAME)