input-keyboard-mouse-touch

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Input: Keyboard, Mouse, Touch, and Gamepad

输入:键盘、鼠标、触摸与游戏手柄

Phaser provides a unified input system accessed via
this.input
in any Scene. It supports keyboard polling and events, mouse/pointer interaction with Game Objects (click, hover, drag), multi-touch, mouse wheel, and gamepad input. Input can be handled through event listeners or by polling state each frame.
Key source paths:
src/input/InputPlugin.js
,
src/input/Pointer.js
,
src/input/keyboard/KeyboardPlugin.js
,
src/input/keyboard/keys/Key.js
,
src/input/keyboard/keys/KeyCodes.js
,
src/input/keyboard/combo/KeyCombo.js
,
src/input/gamepad/GamepadPlugin.js
,
src/input/gamepad/Gamepad.js
,
src/input/events/
,
src/input/keyboard/events/
Related skills: ../sprites-and-images/SKILL.md, ../events-system/SKILL.md, ../scenes/SKILL.md
Phaser 提供了一个统一的输入系统,可在任意Scene中通过
this.input
访问。它支持键盘轮询与事件、鼠标/指针与游戏对象的交互(点击、悬停、拖拽)、多点触摸、鼠标滚轮以及游戏手柄输入。输入可通过事件监听器或每帧轮询状态来处理。
核心源码路径:
src/input/InputPlugin.js
,
src/input/Pointer.js
,
src/input/keyboard/KeyboardPlugin.js
,
src/input/keyboard/keys/Key.js
,
src/input/keyboard/keys/KeyCodes.js
,
src/input/keyboard/combo/KeyCombo.js
,
src/input/gamepad/GamepadPlugin.js
,
src/input/gamepad/Gamepad.js
,
src/input/events/
,
src/input/keyboard/events/
相关技能: ../sprites-and-images/SKILL.md, ../events-system/SKILL.md, ../scenes/SKILL.md

Quick Start (basic keyboard + pointer input)

快速入门(基础键盘+指针输入)

js
class MyScene extends Phaser.Scene {
    create() {
        // Keyboard: create cursor keys (up, down, left, right, space, shift)
        this.cursors = this.input.keyboard.createCursorKeys();

        // Keyboard: listen for a specific key event
        this.input.keyboard.on('keydown-SPACE', (event) => {
            console.log('Space pressed');
        });

        // Pointer: listen for click/tap anywhere on the game canvas
        this.input.on('pointerdown', (pointer) => {
            console.log('Clicked at', pointer.x, pointer.y);
        });

        // Pointer: make a Game Object interactive and clickable
        const sprite = this.add.sprite(400, 300, 'player');
        sprite.setInteractive();
        sprite.on('pointerdown', (pointer, localX, localY, event) => {
            console.log('Sprite clicked at local', localX, localY);
        });
    }

    update() {
        // Poll cursor keys each frame
        if (this.cursors.left.isDown) {
            // move left
        }
        if (this.cursors.right.isDown) {
            // move right
        }
        if (Phaser.Input.Keyboard.JustDown(this.cursors.space)) {
            // fire once per press
        }
    }
}
js
class MyScene extends Phaser.Scene {
    create() {
        // 键盘:创建方向键(上、下、左、右、空格、Shift)
        this.cursors = this.input.keyboard.createCursorKeys();

        // 键盘:监听特定按键事件
        this.input.keyboard.on('keydown-SPACE', (event) => {
            console.log('Space pressed');
        });

        // 指针:监听游戏画布任意位置的点击/触摸
        this.input.on('pointerdown', (pointer) => {
            console.log('Clicked at', pointer.x, pointer.y);
        });

        // 指针:将游戏对象设置为可交互、可点击
        const sprite = this.add.sprite(400, 300, 'player');
        sprite.setInteractive();
        sprite.on('pointerdown', (pointer, localX, localY, event) => {
            console.log('Sprite clicked at local', localX, localY);
        });
    }

    update() {
        // 每帧轮询方向键状态
        if (this.cursors.left.isDown) {
            // 向左移动
        }
        if (this.cursors.right.isDown) {
            // 向右移动
        }
        if (Phaser.Input.Keyboard.JustDown(this.cursors.space)) {
            // 每次按下触发一次
        }
    }
}

Core Concepts

核心概念

The Input Plugin (this.input)

输入插件(this.input)

Accessed via
this.input
in any Scene. It is an
EventEmitter
that handles all input for that Scene.
Key properties:
  • this.input.enabled
    (boolean) - toggle input processing for the Scene
  • this.input.topOnly
    (boolean, default
    true
    ) - only emit events from the top-most Game Object under the pointer
  • this.input.keyboard
    - the KeyboardPlugin instance
  • this.input.gamepad
    - the GamepadPlugin instance
  • this.input.mouse
    - the MouseManager reference
  • this.input.activePointer
    - the most recently active Pointer
  • this.input.mousePointer
    - the mouse Pointer (pointers[0], distinct from pointer1 which is the first touch)
  • this.input.pointer1
    through
    this.input.pointer10
    - individual pointer references
  • this.input.dragDistanceThreshold
    (number, default 0) - pixels a pointer must move before drag starts
  • this.input.dragTimeThreshold
    (number, default 0) - ms a pointer must be held before drag starts
  • this.input.pollRate
    (number, default -1) - how often pointers are polled; 0 = every frame, -1 = only on movement
Key methods:
  • addPointer(quantity)
    - add extra pointers for multi-touch (default is 2; max 10)
  • setHitArea(gameObjects, hitArea, hitAreaCallback)
    - set custom hit area on Game Objects
  • setHitAreaCircle(gameObjects, x, y, radius, callback)
  • setHitAreaEllipse(gameObjects, x, y, width, height, callback)
  • setHitAreaRectangle(gameObjects, x, y, width, height, callback)
  • setHitAreaTriangle(gameObjects, x1, y1, x2, y2, x3, y3, callback)
  • setHitAreaFromTexture(gameObjects, callback)
    - use the texture frame dimensions
  • setDraggable(gameObjects, value)
    - enable or disable dragging
  • makePixelPerfect(alphaTolerance)
    - returns a callback for pixel-perfect hit testing
可在任意Scene中通过
this.input
访问。它是一个
EventEmitter
,负责处理该Scene的所有输入。
核心属性:
  • this.input.enabled
    (布尔值)- 切换该Scene的输入处理
  • this.input.topOnly
    (布尔值,默认
    true
    )- 仅触发指针下方最顶层游戏对象的事件
  • this.input.keyboard
    - KeyboardPlugin实例
  • this.input.gamepad
    - GamepadPlugin实例
  • this.input.mouse
    - MouseManager引用
  • this.input.activePointer
    - 最近激活的Pointer
  • this.input.mousePointer
    - 鼠标Pointer(pointers[0],与第一个触摸的pointer1不同)
  • this.input.pointer1
    this.input.pointer10
    - 各个指针的引用
  • this.input.dragDistanceThreshold
    (数值,默认0)- 指针开始拖拽前必须移动的像素距离
  • this.input.dragTimeThreshold
    (数值,默认0)- 指针开始拖拽前必须按住的毫秒数
  • this.input.pollRate
    (数值,默认-1)- 指针轮询频率;0=每帧轮询,-1=仅在移动时轮询
核心方法:
  • addPointer(quantity)
    - 添加额外指针以支持多点触摸(默认2个;最多10个)
  • setHitArea(gameObjects, hitArea, hitAreaCallback)
    - 为游戏对象设置自定义点击区域
  • setHitAreaCircle(gameObjects, x, y, radius, callback)
  • setHitAreaEllipse(gameObjects, x, y, width, height, callback)
  • setHitAreaRectangle(gameObjects, x, y, width, height, callback)
  • setHitAreaTriangle(gameObjects, x1, y1, x2, y2, x3, y3, callback)
  • setHitAreaFromTexture(gameObjects, callback)
    - 使用纹理帧的尺寸
  • setDraggable(gameObjects, value)
    - 启用或禁用拖拽
  • makePixelPerfect(alphaTolerance)
    - 返回一个用于像素级精确点击测试的回调函数

Pointers

指针(Pointers)

A
Pointer
object encapsulates both mouse and touch input. By default Phaser creates 2 pointers. Use
this.input.addPointer(quantity)
for more (up to 10 total).
Key properties:
  • x
    ,
    y
    - position in screen space (read from
    position.x
    ,
    position.y
    )
  • worldX
    ,
    worldY
    - position translated through the most recent Camera
  • downX
    ,
    downY
    - position when button was pressed
  • upX
    ,
    upY
    - position when button was released
  • isDown
    (boolean) - true if any button is held
  • primaryDown
    (boolean) - true if primary button (left click / touch) is held
  • button
    (number) - which button was pressed/released (0=left, 1=middle, 2=right)
  • buttons
    (number) - bitmask of currently held buttons (1=left, 2=right, 4=middle, 8=back, 16=forward)
  • wasTouch
    (boolean) - true if input came from touch
  • velocity
    (Vector2) - smoothed velocity of pointer movement
  • angle
    (number) - angle of movement in radians
  • distance
    (number) - smoothed distance moved per frame
  • movementX
    ,
    movementY
    - relative movement when pointer is locked
  • deltaX
    ,
    deltaY
    ,
    deltaZ
    - mouse wheel scroll amounts
  • locked
    (boolean) - whether pointer lock is active
  • camera
    - the Camera this Pointer last interacted with
Key methods:
  • leftButtonDown()
    ,
    rightButtonDown()
    ,
    middleButtonDown()
    ,
    backButtonDown()
    ,
    forwardButtonDown()
    - check specific buttons
  • leftButtonReleased()
    ,
    rightButtonReleased()
    ,
    middleButtonReleased()
    - check recent release
  • getDistance()
    - distance between down position and current/up position
  • getDistanceX()
    ,
    getDistanceY()
    - horizontal/vertical distance
  • getDuration()
    - ms between down and current time or up time
  • getAngle()
    - angle between down and current/up position
  • updateWorldPoint(camera)
    - recalculate worldX/worldY for a given camera
  • positionToCamera(camera, output)
    - translate pointer position through a camera
Pointer
对象封装了鼠标和触摸输入。默认情况下Phaser会创建2个指针。可使用
this.input.addPointer(quantity)
添加更多指针(最多10个)。
核心属性:
  • x
    ,
    y
    - 屏幕空间中的位置(从
    position.x
    ,
    position.y
    读取)
  • worldX
    ,
    worldY
    - 经过最近Camera转换后的位置
  • downX
    ,
    downY
    - 按键按下时的位置
  • upX
    ,
    upY
    - 按键释放时的位置
  • isDown
    (布尔值)- 若有任意按键被按住则为true
  • primaryDown
    (布尔值)- 若主按键(左键点击/触摸)被按住则为true
  • button
    (数值)- 按下/释放的按键编号(0=左键,1=中键,2=右键)
  • buttons
    (数值)- 当前按住按键的位掩码(1=左键,2=右键,4=中键,8=后退,16=前进)
  • wasTouch
    (布尔值)- 若输入来自触摸则为true
  • velocity
    (Vector2)- 指针移动的平滑速度
  • angle
    (数值)- 移动方向的弧度值
  • distance
    (数值)- 每帧移动的平滑距离
  • movementX
    ,
    movementY
    - 指针锁定时的相对移动量
  • deltaX
    ,
    deltaY
    ,
    deltaZ
    - 鼠标滚轮的滚动量
  • locked
    (布尔值)- 指针锁定是否激活
  • camera
    - 该Pointer最近交互的Camera
核心方法:
  • leftButtonDown()
    ,
    rightButtonDown()
    ,
    middleButtonDown()
    ,
    backButtonDown()
    ,
    forwardButtonDown()
    - 检查特定按键状态
  • leftButtonReleased()
    ,
    rightButtonReleased()
    ,
    middleButtonReleased()
    - 检查最近是否释放了特定按键
  • getDistance()
    - 按下位置与当前/释放位置之间的距离
  • getDistanceX()
    ,
    getDistanceY()
    - 水平/垂直距离
  • getDuration()
    - 按下到当前时间或释放时间的毫秒数
  • getAngle()
    - 按下位置与当前/释放位置之间的角度
  • updateWorldPoint(camera)
    - 为指定Camera重新计算worldX/worldY
  • positionToCamera(camera, output)
    - 将指针位置通过Camera转换

Interactive Game Objects (setInteractive)

可交互游戏对象(setInteractive)

Call
gameObject.setInteractive()
to enable input on a Game Object. This uses the texture frame as the hit area by default.
js
// Default hit area from texture
sprite.setInteractive();

// Custom shape hit areas (Rectangle, Circle, Ellipse, Triangle, Polygon)
sprite.setInteractive(new Phaser.Geom.Circle(32, 32, 32), Phaser.Geom.Circle.Contains);
sprite.setInteractive(new Phaser.Geom.Ellipse(50, 50, 100, 60), Phaser.Geom.Ellipse.Contains);
sprite.setInteractive(new Phaser.Geom.Triangle(0,64,32,0,64,64), Phaser.Geom.Triangle.Contains);
sprite.setInteractive(new Phaser.Geom.Polygon(points), Phaser.Geom.Polygon.Contains);

// Pixel-perfect hit testing (expensive — use sparingly)
sprite.setInteractive({ pixelPerfect: true, alphaTolerance: 1 });
sprite.setInteractive(this.input.makePixelPerfect());
// With alpha tolerance (default 1):
sprite.setInteractive(this.input.makePixelPerfect(150));

// Config object with multiple options
sprite.setInteractive({
    draggable: true,
    dropZone: false,
    useHandCursor: true,
    cursor: 'pointer',
    pixelPerfect: true,
    alphaTolerance: 1
});

// Containers must specify a shape or call setSize first
container.setSize(200, 200);
container.setInteractive();
调用
gameObject.setInteractive()
可启用游戏对象的输入功能。默认情况下使用纹理帧作为点击区域。
js
// 默认使用纹理作为点击区域
sprite.setInteractive();

// 自定义形状点击区域(矩形、圆形、椭圆、三角形、多边形)
sprite.setInteractive(new Phaser.Geom.Circle(32, 32, 32), Phaser.Geom.Circle.Contains);
sprite.setInteractive(new Phaser.Geom.Ellipse(50, 50, 100, 60), Phaser.Geom.Ellipse.Contains);
sprite.setInteractive(new Phaser.Geom.Triangle(0,64,32,0,64,64), Phaser.Geom.Triangle.Contains);
sprite.setInteractive(new Phaser.Geom.Polygon(points), Phaser.Geom.Polygon.Contains);

// 像素级精确点击测试(性能开销大——谨慎使用)
sprite.setInteractive({ pixelPerfect: true, alphaTolerance: 1 });
sprite.setInteractive(this.input.makePixelPerfect());
// 设置透明度容差(默认1):
sprite.setInteractive(this.input.makePixelPerfect(150));

// 包含多个选项的配置对象
sprite.setInteractive({
    draggable: true,
    dropZone: false,
    useHandCursor: true,
    cursor: 'pointer',
    pixelPerfect: true,
    alphaTolerance: 1
});

// 容器必须先指定形状或调用setSize
container.setSize(200, 200);
container.setInteractive();

Common Patterns

常见模式

Keyboard Input (cursors, addKey, isDown, JustDown)

键盘输入(方向键、addKey、isDown、JustDown)

Cursor keys return an object with
up
,
down
,
left
,
right
,
space
,
shift
Key objects:
js
this.cursors = this.input.keyboard.createCursorKeys();

// In update():
if (this.cursors.up.isDown) { /* held */ }
if (this.cursors.space.isDown) { /* held */ }
addKey creates a Key object for any key:
js
// By string name
const keyW = this.input.keyboard.addKey('W');
// By key code
const keySpace = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);
// With options: addKey(key, enableCapture, emitOnRepeat)
const keyA = this.input.keyboard.addKey('A', true, false);
addKeys creates multiple keys at once:
js
// Comma-separated string returns { W, S, A, D } Key objects
const keys = this.input.keyboard.addKeys('W,S,A,D');
if (keys.W.isDown) { /* ... */ }

// Object form with custom names
const keys = this.input.keyboard.addKeys({
    up: Phaser.Input.Keyboard.KeyCodes.W,
    down: Phaser.Input.Keyboard.KeyCodes.S,
    left: Phaser.Input.Keyboard.KeyCodes.A,
    right: Phaser.Input.Keyboard.KeyCodes.D
});
Polling vs events:
js
// Polling in update() - check every frame
if (keyW.isDown) { /* key is currently held */ }
if (keyW.isUp) { /* key is currently released */ }

// JustDown - returns true only once per press, resets after check
if (Phaser.Input.Keyboard.JustDown(keyW)) { /* fire once */ }
if (Phaser.Input.Keyboard.JustUp(keyW)) { /* released once */ }

// checkDown with duration - throttled polling
if (this.input.keyboard.checkDown(keySpace, 250)) {
    // true at most once every 250ms while held
}

// Event-driven: listen for specific key
this.input.keyboard.on('keydown-SPACE', (event) => { /* ... */ });
this.input.keyboard.on('keyup-SPACE', (event) => { /* ... */ });

// Event-driven: listen for any key
this.input.keyboard.on('keydown', (event) => {
    console.log(event.key); // native DOM KeyboardEvent
});

// Event on a Key object itself
const spaceBar = this.input.keyboard.addKey('SPACE');
spaceBar.on('down', (key, event) => { /* Key object + native event */ });
spaceBar.on('up', (key, event) => { /* ... */ });
Key object properties:
  • isDown
    /
    isUp
    (boolean)
  • keyCode
    (number)
  • altKey
    ,
    ctrlKey
    ,
    shiftKey
    ,
    metaKey
    (boolean) - modifier state when pressed
  • duration
    (number) - ms held in previous down-up cycle
  • timeDown
    ,
    timeUp
    (number) - timestamps
  • repeats
    (number) - repeat count while held
  • emitOnRepeat
    (boolean) - if true, fires 'down' event on each repeat
  • enabled
    (boolean) - can this key be processed
Prevent browser default behavior:
js
// Capture specific keys to prevent browser scrolling etc.
this.input.keyboard.addCapture('SPACE,UP,DOWN,LEFT,RIGHT');
this.input.keyboard.addCapture([ 32, 37, 38, 39, 40 ]);
this.input.keyboard.removeCapture('SPACE');
// Note: captures are global across all Scenes
Common KeyCodes:
BACKSPACE(8)
,
TAB(9)
,
ENTER(13)
,
SHIFT(16)
,
CTRL(17)
,
ALT(18)
,
ESC(27)
,
SPACE(32)
,
LEFT(37)
,
UP(38)
,
RIGHT(39)
,
DOWN(40)
,
A-Z(65-90)
,
ZERO-NINE(48-57)
,
F1-F12(112-123)
. Access via
Phaser.Input.Keyboard.KeyCodes.SPACE
etc.
方向键返回包含
up
down
left
right
space
shift
Key对象的实例:
js
this.cursors = this.input.keyboard.createCursorKeys();

// 在update()中:
if (this.cursors.up.isDown) { /* 按住 */ }
if (this.cursors.space.isDown) { /* 按住 */ }
addKey为任意按键创建一个Key对象:
js
// 通过字符串名称
const keyW = this.input.keyboard.addKey('W');
// 通过按键编码
const keySpace = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);
// 带选项:addKey(key, enableCapture, emitOnRepeat)
const keyA = this.input.keyboard.addKey('A', true, false);
addKeys一次性创建多个按键:
js
// 逗号分隔的字符串返回{ W, S, A, D } Key对象
const keys = this.input.keyboard.addKeys('W,S,A,D');
if (keys.W.isDown) { /* ... */ }

// 自定义名称的对象形式
const keys = this.input.keyboard.addKeys({
    up: Phaser.Input.Keyboard.KeyCodes.W,
    down: Phaser.Input.Keyboard.KeyCodes.S,
    left: Phaser.Input.Keyboard.KeyCodes.A,
    right: Phaser.Input.Keyboard.KeyCodes.D
});
轮询 vs 事件:
js
// 在update()中轮询——每帧检查
if (keyW.isDown) { /* 当前按键被按住 */ }
if (keyW.isUp) { /* 当前按键已释放 */ }

// JustDown——每次按下仅返回true一次,检查后重置
if (Phaser.Input.Keyboard.JustDown(keyW)) { /* 触发一次 */ }
if (Phaser.Input.Keyboard.JustUp(keyW)) { /* 释放时触发一次 */ }

// checkDown带时长——节流式轮询
if (this.input.keyboard.checkDown(keySpace, 250)) {
    // 按住时每250ms最多触发一次
}

// 事件驱动:监听特定按键
this.input.keyboard.on('keydown-SPACE', (event) => { /* ... */ });
this.input.keyboard.on('keyup-SPACE', (event) => { /* ... */ });

// 事件驱动:监听任意按键
this.input.keyboard.on('keydown', (event) => {
    console.log(event.key); // 原生DOM键盘事件
});

// Key对象自身的事件
const spaceBar = this.input.keyboard.addKey('SPACE');
spaceBar.on('down', (key, event) => { /* Key对象 + 原生事件 */ });
spaceBar.on('up', (key, event) => { /* ... */ });
Key对象属性:
  • isDown
    /
    isUp
    (布尔值)
  • keyCode
    (数值)
  • altKey
    ,
    ctrlKey
    ,
    shiftKey
    ,
    metaKey
    (布尔值)- 按下时的修饰键状态
  • duration
    (数值)- 上一次按下-释放周期的按住时长(毫秒)
  • timeDown
    ,
    timeUp
    (数值)- 时间戳
  • repeats
    (数值)- 按住期间的重复次数
  • emitOnRepeat
    (布尔值)- 若为true,每次重复时触发'down'事件
  • enabled
    (布尔值)- 是否可处理该按键
阻止浏览器默认行为:
js
// 捕获特定按键以阻止浏览器滚动等行为
this.input.keyboard.addCapture('SPACE,UP,DOWN,LEFT,RIGHT');
this.input.keyboard.addCapture([ 32, 37, 38, 39, 40 ]);
this.input.keyboard.removeCapture('SPACE');
// 注意:捕获对所有Scene全局生效
常见KeyCodes:
BACKSPACE(8)
,
TAB(9)
,
ENTER(13)
,
SHIFT(16)
,
CTRL(17)
,
ALT(18)
,
ESC(27)
,
SPACE(32)
,
LEFT(37)
,
UP(38)
,
RIGHT(39)
,
DOWN(40)
,
A-Z(65-90)
,
ZERO-NINE(48-57)
,
F1-F12(112-123)
。可通过
Phaser.Input.Keyboard.KeyCodes.SPACE
等方式访问。

Mouse/Pointer Click and Hover

鼠标/指针点击与悬停

Scene-level pointer events (fire anywhere on the canvas):
js
this.input.on('pointerdown', (pointer, currentlyOver) => {
    // pointer: Pointer object, currentlyOver: array of interactive Game Objects under pointer
});
this.input.on('pointerup', (pointer, currentlyOver) => { /* ... */ });
this.input.on('pointermove', (pointer, currentlyOver) => { /* ... */ });
this.input.on('wheel', (pointer, currentlyOver, deltaX, deltaY, deltaZ) => { /* ... */ });
Game Object pointer events (require setInteractive):
js
sprite.setInteractive();

// pointerdown on this specific object
sprite.on('pointerdown', (pointer, localX, localY, event) => {
    // localX/localY are relative to the Game Object's top-left
    // event.stopPropagation() prevents the event from going further
});

sprite.on('pointerup', (pointer, localX, localY, event) => { /* ... */ });
sprite.on('pointermove', (pointer, localX, localY, event) => { /* ... */ });
sprite.on('pointerover', (pointer, localX, localY, event) => { /* ... */ });
sprite.on('pointerout', (pointer, event) => { /* ... */ });
sprite.on('wheel', (pointer, deltaX, deltaY, deltaZ, event) => { /* ... */ });
Right-click handling:
js
this.input.on('pointerdown', (pointer) => {
    if (pointer.rightButtonDown()) {
        // right-click
    }
});

// Disable context menu
this.input.mouse.disableContextMenu();
Pointer lock (FPS-style mouse capture):
js
// Request lock on click
this.input.on('pointerdown', () => {
    this.input.mouse.requestPointerLock();
});

this.input.on('pointerlockchange', (event, locked) => {
    // locked: boolean
});

// Read relative movement while locked
// pointer.movementX, pointer.movementY
Scene级指针事件(在画布任意位置触发):
js
this.input.on('pointerdown', (pointer, currentlyOver) => {
    // pointer:Pointer对象,currentlyOver:指针下方的可交互游戏对象数组
});
this.input.on('pointerup', (pointer, currentlyOver) => { /* ... */ });
this.input.on('pointermove', (pointer, currentlyOver) => { /* ... */ });
this.input.on('wheel', (pointer, currentlyOver, deltaX, deltaY, deltaZ) => { /* ... */ });
游戏对象级指针事件(需调用setInteractive):
js
sprite.setInteractive();

// 特定对象上的pointerdown事件
sprite.on('pointerdown', (pointer, localX, localY, event) => {
    // localX/localY是相对于游戏对象左上角的坐标
    // event.stopPropagation()阻止事件进一步传播
});

sprite.on('pointerup', (pointer, localX, localY, event) => { /* ... */ });
sprite.on('pointermove', (pointer, localX, localY, event) => { /* ... */ });
sprite.on('pointerover', (pointer, localX, localY, event) => { /* ... */ });
sprite.on('pointerout', (pointer, event) => { /* ... */ });
sprite.on('wheel', (pointer, deltaX, deltaY, deltaZ, event) => { /* ... */ });
右键处理:
js
this.input.on('pointerdown', (pointer) => {
    if (pointer.rightButtonDown()) {
        // 右键点击
    }
});

// 禁用上下文菜单
this.input.mouse.disableContextMenu();
指针锁定(FPS风格鼠标捕获):
js
// 点击时请求锁定
this.input.on('pointerdown', () => {
    this.input.mouse.requestPointerLock();
});

this.input.on('pointerlockchange', (event, locked) => {
    // locked:布尔值
});

// 锁定时读取相对移动量
// pointer.movementX, pointer.movementY

Drag and Drop

拖拽与放置

js
const sprite = this.add.sprite(400, 300, 'item');
sprite.setInteractive();
this.input.setDraggable(sprite);

// Or use config:
// sprite.setInteractive({ draggable: true });

// Drag events on the Scene input
this.input.on('dragstart', (pointer, gameObject) => {
    gameObject.setTint(0xff0000);
});

this.input.on('drag', (pointer, gameObject, dragX, dragY) => {
    gameObject.x = dragX;
    gameObject.y = dragY;
});

this.input.on('dragend', (pointer, gameObject) => {
    gameObject.clearTint();
});

// Drop zones
const zone = this.add.zone(600, 300, 200, 200).setRectangleDropZone(200, 200);

this.input.on('drop', (pointer, gameObject, dropZone) => {
    gameObject.x = dropZone.x;
    gameObject.y = dropZone.y;
});

this.input.on('dragenter', (pointer, gameObject, dropZone) => { /* ... */ });
this.input.on('dragleave', (pointer, gameObject, dropZone) => { /* ... */ });
this.input.on('dragover', (pointer, gameObject, dropZone) => { /* ... */ });
Game Object-level drag events are also available:
js
sprite.on('drag', (pointer, dragX, dragY) => {
    sprite.x = dragX;
    sprite.y = dragY;
});
sprite.on('dragstart', (pointer, dragX, dragY) => { /* ... */ });
sprite.on('dragend', (pointer, dragX, dragY) => { /* ... */ });
sprite.on('drop', (pointer, dropZone) => { /* ... */ });
Drag thresholds:
js
this.input.dragDistanceThreshold = 16; // must move 16px before drag starts
this.input.dragTimeThreshold = 200;    // must hold 200ms before drag starts
js
const sprite = this.add.sprite(400, 300, 'item');
sprite.setInteractive();
this.input.setDraggable(sprite);

// 或使用配置:
// sprite.setInteractive({ draggable: true });

// Scene输入上的拖拽事件
this.input.on('dragstart', (pointer, gameObject) => {
    gameObject.setTint(0xff0000);
});

this.input.on('drag', (pointer, gameObject, dragX, dragY) => {
    gameObject.x = dragX;
    gameObject.y = dragY;
});

this.input.on('dragend', (pointer, gameObject) => {
    gameObject.clearTint();
});

// 放置区域
const zone = this.add.zone(600, 300, 200, 200).setRectangleDropZone(200, 200);

this.input.on('drop', (pointer, gameObject, dropZone) => {
    gameObject.x = dropZone.x;
    gameObject.y = dropZone.y;
});

this.input.on('dragenter', (pointer, gameObject, dropZone) => { /* ... */ });
this.input.on('dragleave', (pointer, gameObject, dropZone) => { /* ... */ });
this.input.on('dragover', (pointer, gameObject, dropZone) => { /* ... */ });
游戏对象级的拖拽事件也可用:
js
sprite.on('drag', (pointer, dragX, dragY) => {
    sprite.x = dragX;
    sprite.y = dragY;
});
sprite.on('dragstart', (pointer, dragX, dragY) => { /* ... */ });
sprite.on('dragend', (pointer, dragX, dragY) => { /* ... */ });
sprite.on('drop', (pointer, dropZone) => { /* ... */ });
拖拽阈值:
js
this.input.dragDistanceThreshold = 16; // 开始拖拽前必须移动16像素
this.input.dragTimeThreshold = 200;    // 开始拖拽前必须按住200毫秒

Three Levels of Pointer Events

指针事件的三个层级

Pointer events fire at three levels (see reference for details):
  1. Game Object:
    gameObject.on('pointerdown', (pointer, localX, localY, event) => {})
  2. Scene per-object:
    this.input.on('gameobjectdown', (pointer, gameObject, event) => {})
  3. Scene global:
    this.input.on('pointerdown', (pointer, currentlyOver) => {})
指针事件会在三个层级触发(详情见参考文档):
  1. 游戏对象
    gameObject.on('pointerdown', (pointer, localX, localY, event) => {})
  2. Scene对象级
    this.input.on('gameobjectdown', (pointer, gameObject, event) => {})
  3. Scene全局
    this.input.on('pointerdown', (pointer, currentlyOver) => {})

Input Debug, topOnly, and Multi-touch Config

输入调试、topOnly与多点触摸配置

js
// Debug visualize hit areas
this.input.enableDebug(gameObject);
this.input.enableDebug(gameObject, 0xff00ff);
this.input.removeDebug(gameObject);

// Let all objects under pointer receive events (not just top-most)
this.input.topOnly = false;
this.input.setTopOnly(false);
Multi-touch: set
config.input.activePointers
to reserve pointer slots at startup, or call
this.input.addPointer(num)
at runtime. Access via
this.input.pointer1
through
pointer10
.
js
// 可视化调试点击区域
this.input.enableDebug(gameObject);
this.input.enableDebug(gameObject, 0xff00ff);
this.input.removeDebug(gameObject);

// 让指针下方所有对象都接收事件(而非仅最顶层)
this.input.topOnly = false;
this.input.setTopOnly(false);
多点触摸:在启动时设置
config.input.activePointers
来预留指针槽位,或在运行时调用
this.input.addPointer(num)
。可通过
this.input.pointer1
pointer10
访问。

Gamepad Input

游戏手柄输入

Enable gamepads in the game config:
js
const config = {
    input: {
        gamepad: true
    }
};
Access via
this.input.gamepad
. Gamepads are available as
pad1
through
pad4
:
js
// Wait for connection
this.input.gamepad.once('connected', (pad) => {
    console.log('Gamepad connected:', pad.id);
});

// If already connected, check total
if (this.input.gamepad.total > 0) {
    const pad = this.input.gamepad.pad1;
}
Polling gamepad state in update():
js
update() {
    const pad = this.input.gamepad.pad1;
    if (!pad) return;

    // D-pad (boolean properties)
    if (pad.up) { /* d-pad up */ }
    if (pad.down) { /* d-pad down */ }
    if (pad.left) { /* d-pad left */ }
    if (pad.right) { /* d-pad right */ }

    // Face buttons (boolean) - Xbox naming convention
    if (pad.A) { /* bottom button (Xbox A / PS X) */ }
    if (pad.B) { /* right button (Xbox B / PS Circle) */ }
    if (pad.X) { /* left button (Xbox X / PS Square) */ }
    if (pad.Y) { /* top button (Xbox Y / PS Triangle) */ }

    // Shoulder buttons (float 0-1)
    if (pad.L1 > 0) { /* left shoulder top (LB) */ }
    if (pad.L2 > 0) { /* left shoulder bottom / trigger (LT) */ }
    if (pad.R1 > 0) { /* right shoulder top (RB) */ }
    if (pad.R2 > 0) { /* right shoulder bottom / trigger (RT) */ }

    // Analog sticks (Vector2, values -1 to 1)
    const lx = pad.leftStick.x;  // left stick horizontal
    const ly = pad.leftStick.y;  // left stick vertical
    const rx = pad.rightStick.x;
    const ry = pad.rightStick.y;

    // Raw axis/button access
    pad.getAxisValue(0);    // float
    pad.getButtonValue(0);  // float 0-1
    pad.isButtonDown(0);    // boolean
    pad.setAxisThreshold(0.1); // ignore values below threshold
}
Gamepad events:
js
// Plugin-level events (any gamepad)
this.input.gamepad.on('connected', (pad, event) => { /* ... */ });
this.input.gamepad.on('disconnected', (pad, event) => { /* ... */ });
this.input.gamepad.on('down', (pad, button, value) => { /* any button on any pad */ });
this.input.gamepad.on('up', (pad, button, value) => { /* ... */ });

// Gamepad-instance events
pad.on('down', (index, value, button) => { /* button on this specific pad */ });
pad.on('up', (index, value, button) => { /* ... */ });
Vibration (experimental, hardware/browser dependent):
js
if (pad.vibration) {
    pad.vibration.playEffect('dual-rumble', {
        duration: 200,
        strongMagnitude: 1.0,
        weakMagnitude: 0.5
    });
}
在游戏配置中启用游戏手柄:
js
const config = {
    input: {
        gamepad: true
    }
};
通过
this.input.gamepad
访问。游戏手柄可通过
pad1
pad4
获取:
js
// 等待连接
this.input.gamepad.once('connected', (pad) => {
    console.log('Gamepad connected:', pad.id);
});

// 若已连接,检查总数
if (this.input.gamepad.total > 0) {
    const pad = this.input.gamepad.pad1;
}
在update()中轮询游戏手柄状态:
js
update() {
    const pad = this.input.gamepad.pad1;
    if (!pad) return;

    // 方向键(布尔属性)
    if (pad.up) { /* 方向键上 */ }
    if (pad.down) { /* 方向键下 */ }
    if (pad.left) { /* 方向键左 */ }
    if (pad.right) { /* 方向键右 */ }

    // 面部按键(布尔值)- Xbox命名规范
    if (pad.A) { /* 底部按键(Xbox A / PS X) */ }
    if (pad.B) { /* 右侧按键(Xbox B / PS Circle) */ }
    if (pad.X) { /* 左侧按键(Xbox X / PS Square) */ }
    if (pad.Y) { /* 顶部按键(Xbox Y / PS Triangle) */ }

    // 肩键(浮点值0-1)
    if (pad.L1 > 0) { /* 左肩上侧(LB) */ }
    if (pad.L2 > 0) { /* 左肩下侧/扳机(LT) */ }
    if (pad.R1 > 0) { /* 右肩上侧(RB) */ }
    if (pad.R2 > 0) { /* 右肩下侧/扳机(RT) */ }

    // 摇杆(Vector2,值范围-1至1)
    const lx = pad.leftStick.x;  // 左摇杆水平方向
    const ly = pad.leftStick.y;  // 左摇杆垂直方向
    const rx = pad.rightStick.x;
    const ry = pad.rightStick.y;

    // 原始轴/按键访问
    pad.getAxisValue(0);    // 浮点值
    pad.getButtonValue(0);  // 浮点值0-1
    pad.isButtonDown(0);    // 布尔值
    pad.setAxisThreshold(0.1); // 忽略阈值以下的值
}
游戏手柄事件:
js
// 插件级事件(任意游戏手柄)
this.input.gamepad.on('connected', (pad, event) => { /* ... */ });
this.input.gamepad.on('disconnected', (pad, event) => { /* ... */ });
this.input.gamepad.on('down', (pad, button, value) => { /* 任意手柄的任意按键 */ });
this.input.gamepad.on('up', (pad, button, value) => { /* ... */ });

// 游戏手柄实例事件
pad.on('down', (index, value, button) => { /* 该特定手柄的按键 */ });
pad.on('up', (index, value, button) => { /* ... */ });
振动(实验性,依赖硬件/浏览器):
js
if (pad.vibration) {
    pad.vibration.playEffect('dual-rumble', {
        duration: 200,
        strongMagnitude: 1.0,
        weakMagnitude: 0.5
    });
}

Key Combos

按键组合

Listen for a sequence of keys:
js
// String-based combo
this.input.keyboard.createCombo('PHASER');

// Array of key codes (Konami code)
this.input.keyboard.createCombo(
    [ 38, 38, 40, 40, 37, 39, 37, 39, 66, 65, 13 ],
    { resetOnMatch: true }
);

// Listen for match
this.input.keyboard.on('keycombomatch', (keyCombo, event) => {
    console.log('Combo matched!');
});
createCombo(keys, config):
  • keys
    : a string (each character is a key) or an array of key codes / Key objects
  • config.resetOnWrongKey
    (boolean, default true) - reset progress if wrong key is pressed
  • config.maxKeyDelay
    (number, default 0) - max ms between key presses; 0 = no limit
  • config.resetOnMatch
    (boolean, default false) - reset combo after a successful match
  • config.deleteOnMatch
    (boolean, default false) - remove combo after first match
For detailed configuration options, API reference tables, and source file maps, see the reference guide.
监听按键序列:
js
// 字符串形式的组合
this.input.keyboard.createCombo('PHASER');

// 按键编码数组(科乐美代码)
this.input.keyboard.createCombo(
    [ 38, 38, 40, 40, 37, 39, 37, 39, 66, 65, 13 ],
    { resetOnMatch: true }
);

// 监听匹配事件
this.input.keyboard.on('keycombomatch', (keyCombo, event) => {
    console.log('Combo matched!');
});
createCombo(keys, config):
  • keys
    :字符串(每个字符对应一个按键)或按键编码/Key对象数组
  • config.resetOnWrongKey
    (布尔值,默认true)- 按下错误按键时重置进度
  • config.maxKeyDelay
    (数值,默认0)- 按键之间的最大间隔毫秒数;0=无限制
  • config.resetOnMatch
    (布尔值,默认false)- 匹配成功后重置组合
  • config.deleteOnMatch
    (布尔值,默认false)- 首次匹配后移除组合
有关详细配置选项、API参考表和源码文件映射,请查看参考指南