Sceny
Cykl życia sceny, SceneManager, dane startowe, fabryki obiektów i automatyczne sprzątanie przy shutdown.
Cykl życia sceny#
text
preload() → create() → update(dt) / fixedUpdate(dt) → shutdown()
| Faza | Kiedy | Po co |
|---|---|---|
preload() | Przed create | Deklaracja i ładowanie assetów (declareAssets) |
create() | Raz, po załadowaniu | Budowanie świata gry |
update(dt) | Co klatkę | Logika gry |
fixedUpdate(dt) | Co stały krok | Fizyka i deterministyczna logika |
shutdown() | Przy zmianie sceny | Sprzątanie (silnik robi większość za Ciebie) |
Definiowanie sceny#
ts
import { Scene, type AssetDescriptor } from '@engine'
export class GameScene extends Scene {
constructor() {
super('game')
}
declareAssets(assets: AssetDescriptor[]) {
super.declareAssets([
{ id: 'hero', type: 'spritesheet', src: '/assets/hero.png', frameWidth: 32, frameHeight: 32 },
{ id: 'coin', type: 'image', src: '/assets/coin.png' },
{ id: 'pickup', type: 'audio', src: '/assets/pickup.ogg' }
])
}
async preload() {
await this.getAssets().load()
}
create() {
this.createSprite('hero', { x: 100, y: 300, tags: ['player'] })
this.createText('score', { x: 16, y: 16, text: '0', fontSize: '18px', color: '#fff' })
}
update(dt: number) {
const player = this.findByTag('player')[0]
if (this.getInput().isActionDown('move-right')) {
player.translate(220 * dt, 0)
}
}
}
Rejestracja i przełączanie#
ts
engine.registerScene(new MenuScene())
engine.registerScene(new GameScene())
engine.start('menu')
engine.startScene('game', { level: 3 })
engine.stopScene('menu')
SceneManager pilnuje unikalności id — duplikat rzuca błąd przy rejestracji.
ts
const scenes = engine.getScenes()
scenes.has('game')
scenes.getActiveSceneId()
scenes.switch('menu', 'game', { level: 1 })
scenes.list()
Dane startowe#
Scena odbiera dane przez getData<T>():
ts
class GameScene extends Scene {
create() {
const { level } = this.getData<{ level: number }>()
this.createText('level', { x: 16, y: 16, text: `Poziom ${level}` })
}
}
engine.startScene('game', { level: 5 })
Fabryki obiektów#
ts
createObject(options?): GameObject
createSprite(textureId: string, options?): GameObject
createText(text: string, options?): GameObject
createRect(width, height, options): GameObject
createEllipse(radius, options): GameObject
Wyszukiwanie i grupy#
ts
getObject<T>(id: string): T | undefined
find(predicate); findAll(predicate)
findByName(name); findByTag(tag); findByTags(tags, mode?)
group(name: string): Group
getGroupMembers(name); getGroups()
each(fn: (object: GameObject) => void): void
ts
const enemies = this.findByTag('enemy')
const bosses = this.findByTags(['enemy', 'boss'], 'all')
this.group('projectiles')
for (const bullet of this.getGroupMembers('projectiles')) {
bullet.translate(400 * dt, 0)
}
Sprzątanie przy shutdown#
shutdown() sceny automatycznie czyści:
- rejestr obiektów i indeks tagów,
- grupy,
- subskrypcje zdarzeń przypisane do sceny,
- tweeny (
stopAll), - dźwięki właściciela (
stopOwner), - uchwyty assetów (
releaseOwner).
ts
class GameScene extends Scene {
shutdown() {
this.saveProgress()
}
}
Informacja
Nie musisz ręcznie usuwać obiektów przy zmianie sceny — silnik zrobi to za Ciebie. Własny shutdown() służy tylko do logiki biznesowej (zapis, statystyki, analytics).
Animacje klatkowe#
ts
this.playAnimation(player, 'hero:run')
this.pauseAnimation(player, true)
this.setFrame(player, 3)
this.getAnimationState(player)
this.stopAnimation(player)
Klucz animacji ma format <assetId>:<key> i jest rejestrowany przez backend podczas ładowania spritesheeta.