Wejście (InputManager)
Akcje zamiast kodów klawiszy, stan klawiatury, pointer i remapowanie. Jak czytać wejście w komponentach i scenach.
Akcje, nie klawisze#
Logika gry czyta akcje (move-left, jump, interact), nigdy surowe kody klawiszy. Dzięki temu remapowanie sterowania nie dotyka kodu rozgrywki.
update(dt: number) {
const input = this.getInput()
if (input.isActionDown('move-left')) this.player.translate(-240 * dt, 0)
if (input.isActionPressed('jump')) this.jump()
if (input.isActionReleased('interact')) this.closeDialog()
}
| Metoda | Znaczenie |
|---|---|
isActionDown(action) | Akcja trzymana w tej klatce |
isActionPressed(action) | Akcja wciśnięta w tej klatce (edge) |
isActionReleased(action) | Akcja puszczona w tej klatce (edge) |
To samo dla surowych kodów: isKeyDown, isKeyPressed, isKeyReleased.
API#
attach(port); detach(); isAttached(); update()
isKeyDown(code); isKeyPressed(code); isKeyReleased(code)
isActionDown(action); isActionPressed(action); isActionReleased(action)
getPointer(): PointerState
getPointerPosition(); getPointerWorldPosition()
setActionMap(map); getActionMap(); remapAction(action, codes)
Domyślna mapa akcji#
defaultInputMap: move-up, move-down, move-left, move-right, interact, jump, restart, menu, pause, time-slow, time-fast, time-normal, mute.
Remapowanie#
const input = this.getInput()
input.remapAction('jump', ['Space', 'KeyW', 'ArrowUp'])
input.setActionMap({
'move-left': ['KeyA'],
'move-right': ['KeyD'],
jump: ['Space'],
interact: ['KeyE'],
pause: ['Escape']
})
Przykład: ekran ustawień sterowania#
class ControlsScene extends Scene {
private listeningFor: string | null = null
startRebind(action: string) {
this.listeningFor = action
}
update() {
if (!this.listeningFor) return
const input = this.getInput()
for (const code of ['KeyW', 'KeyA', 'KeyS', 'KeyD', 'Space', 'KeyE']) {
if (input.isKeyPressed(code)) {
input.remapAction(this.listeningFor, [code])
this.listeningFor = null
break
}
}
}
}
Pointer#
const pointer = this.getInput().getPointer()
const screen = this.getInput().getPointerPosition()
const world = this.getInput().getPointerWorldPosition()
if (pointer.isDown) {
this.spawnAt(world.x, world.y)
}
getPointerWorldPosition() uwzględnia pozycję i zoom kamery — kliknięcie trafia w świat gry, nie w ekran.
Informacja
Adapter blokuje domyślne zachowanie przeglądarki (scrollowanie spacją, strzałkami) tylko w obszarze gry. Poza canvasem strona działa normalnie.
Przykład: komponent sterowania#
export class PlayerController extends Component {
phase = 'input' as const
private speed = 260
onUpdate(dt: number) {
const input = this.owner.getInput()
const vx = (input.isActionDown('move-right') ? 1 : 0) - (input.isActionDown('move-left') ? 1 : 0)
const vy = (input.isActionDown('move-down') ? 1 : 0) - (input.isActionDown('move-up') ? 1 : 0)
const len = Math.hypot(vx, vy) || 1
this.owner.translate((vx / len) * this.speed * dt, (vy / len) * this.speed * dt)
}
}
Normalizacja wektora sprawia, że ruch po skosie nie jest szybszy niż w poziomie.