Scene Integration
Best practices for integrating martini-kit with Phaser scenes.
Basic Setup
import Phaser from 'phaser';
import { GameRuntime, defineGame } from '@martini-kit/core';
import { PhaserAdapter } from '@martini-kit/phaser';
import { LocalTransport } from '@martini-kit/transport-local';
// Define game
const game = defineGame({
setup: ({ playerIds }) => ({
players: Object.fromEntries(
playerIds.map(id => [id, { x: 400, y: 300, health: 100 }])
)
}),
actions: {
move: {
apply(state, context, input: { x: number; y: number }) {
const player = state.players[context.targetId];
if (player) {
player.x = input.x;
player.y = input.y;
}
}
}
}
});
// Phaser scene
export class GameScene extends Phaser.Scene {
private runtime!: GameRuntime;
private adapter!: PhaserAdapter;
private playerManager!: SpriteManager;
constructor() {
super({ key: 'GameScene' });
}
create() {
// Create transport
const transport = new LocalTransport({
roomId: 'game-' + Date.now(),
isHost: true
});
// Create runtime
this.runtime = new GameRuntime(game, transport, {
isHost: true,
playerIds: [transport.getPlayerId()]
});
// Create adapter
this.adapter = new PhaserAdapter(this.runtime, this);
// Setup game objects
this.createPlayers();
this.createInput();
// Cleanup on scene shutdown
this.events.once('shutdown', () => {
this.cleanup();
});
}
private createPlayers() {
this.playerManager = this.adapter.createSpriteManager({
onCreate: (key, data) => this.add.sprite(data.x, data.y, 'player'),
onCreatePhysics: (sprite) => {
this.physics.add.existing(sprite);
}
});
// Create initial players (host only)
if (this.adapter.isHost()) {
this.playerManager.add(`player-${this.adapter.myId}`, {
x: 400,
y: 300
});
}
}
private createInput() {
const inputManager = this.adapter.createInputManager();
inputManager.loadProfile('platformer');
this.inputManager = inputManager;
}
update() {
// Process input
this.inputManager?.update();
// Game logic here
}
private cleanup() {
// Destroy managers
this.playerManager?.destroy();
this.adapter?.destroy();
this.runtime?.destroy();
}
} Multi-Scene Games
Lobby + Game Scenes
class LobbyScene extends Phaser.Scene {
create() {
// Create runtime in lobby
this.runtime = new GameRuntime(lobbyGame, transport, config);
this.adapter = new PhaserAdapter(this.runtime, this);
// Store in registry for other scenes
this.registry.set('runtime', this.runtime);
this.registry.set('adapter', this.adapter);
// Start game button
this.add.text(400, 300, 'Click to Start', { fontSize: '32px' })
.setInteractive()
.on('pointerdown', () => {
this.scene.start('GameScene');
});
}
}
class GameScene extends Phaser.Scene {
create() {
// Retrieve from registry
this.runtime = this.registry.get('runtime');
this.adapter = new PhaserAdapter(this.runtime, this);
// Setup game
this.createPlayers();
}
shutdown() {
// Clean up adapter but keep runtime
this.adapter.destroy();
}
} Best Practices
✅ Do
- Create runtime once - Share across scenes via registry
- Create new adapter per scene - Scene-specific
- Cleanup in shutdown - Call
destroy()methods - Use scene events - For lifecycle management
- Store in instance variables - Not global
❌ Don’t
- Don’t create multiple runtimes - One per game session
- Don’t forget cleanup - Memory leaks
- Don’t share adapters - Scene-specific
- Don’t use global variables - Use scene registry
See Also
- PhaserAdapter - Main adapter API
- GameRuntime - Runtime API
- Quick Start Guide - Setup tutorial