input-keyboard-mouse-touch
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseInput: Keyboard, Mouse, Touch, and Gamepad
输入:键盘、鼠标、触摸与游戏手柄
Phaser provides a unified input system accessed viain 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.this.input
Key source paths: , , , , , , , , ,
Related skills: ../sprites-and-images/SKILL.md, ../events-system/SKILL.md, ../scenes/SKILL.md
src/input/InputPlugin.jssrc/input/Pointer.jssrc/input/keyboard/KeyboardPlugin.jssrc/input/keyboard/keys/Key.jssrc/input/keyboard/keys/KeyCodes.jssrc/input/keyboard/combo/KeyCombo.jssrc/input/gamepad/GamepadPlugin.jssrc/input/gamepad/Gamepad.jssrc/input/events/src/input/keyboard/events/Phaser 提供了一个统一的输入系统,可在任意Scene中通过访问。它支持键盘轮询与事件、鼠标/指针与游戏对象的交互(点击、悬停、拖拽)、多点触摸、鼠标滚轮以及游戏手柄输入。输入可通过事件监听器或每帧轮询状态来处理。this.input
核心源码路径: , , , , , , , , ,
相关技能: ../sprites-and-images/SKILL.md, ../events-system/SKILL.md, ../scenes/SKILL.md
src/input/InputPlugin.jssrc/input/Pointer.jssrc/input/keyboard/KeyboardPlugin.jssrc/input/keyboard/keys/Key.jssrc/input/keyboard/keys/KeyCodes.jssrc/input/keyboard/combo/KeyCombo.jssrc/input/gamepad/GamepadPlugin.jssrc/input/gamepad/Gamepad.jssrc/input/events/src/input/keyboard/events/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 in any Scene. It is an that handles all input for that Scene.
this.inputEventEmitterKey properties:
- (boolean) - toggle input processing for the Scene
this.input.enabled - (boolean, default
this.input.topOnly) - only emit events from the top-most Game Object under the pointertrue - - the KeyboardPlugin instance
this.input.keyboard - - the GamepadPlugin instance
this.input.gamepad - - the MouseManager reference
this.input.mouse - - the most recently active Pointer
this.input.activePointer - - the mouse Pointer (pointers[0], distinct from pointer1 which is the first touch)
this.input.mousePointer - through
this.input.pointer1- individual pointer referencesthis.input.pointer10 - (number, default 0) - pixels a pointer must move before drag starts
this.input.dragDistanceThreshold - (number, default 0) - ms a pointer must be held before drag starts
this.input.dragTimeThreshold - (number, default -1) - how often pointers are polled; 0 = every frame, -1 = only on movement
this.input.pollRate
Key methods:
- - add extra pointers for multi-touch (default is 2; max 10)
addPointer(quantity) - - set custom hit area on Game Objects
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)- - use the texture frame dimensions
setHitAreaFromTexture(gameObjects, callback) - - enable or disable dragging
setDraggable(gameObjects, value) - - returns a callback for pixel-perfect hit testing
makePixelPerfect(alphaTolerance)
可在任意Scene中通过访问。它是一个,负责处理该Scene的所有输入。
this.inputEventEmitter核心属性:
- (布尔值)- 切换该Scene的输入处理
this.input.enabled - (布尔值,默认
this.input.topOnly)- 仅触发指针下方最顶层游戏对象的事件true - - KeyboardPlugin实例
this.input.keyboard - - GamepadPlugin实例
this.input.gamepad - - MouseManager引用
this.input.mouse - - 最近激活的Pointer
this.input.activePointer - - 鼠标Pointer(pointers[0],与第一个触摸的pointer1不同)
this.input.mousePointer - 至
this.input.pointer1- 各个指针的引用this.input.pointer10 - (数值,默认0)- 指针开始拖拽前必须移动的像素距离
this.input.dragDistanceThreshold - (数值,默认0)- 指针开始拖拽前必须按住的毫秒数
this.input.dragTimeThreshold - (数值,默认-1)- 指针轮询频率;0=每帧轮询,-1=仅在移动时轮询
this.input.pollRate
核心方法:
- - 添加额外指针以支持多点触摸(默认2个;最多10个)
addPointer(quantity) - - 为游戏对象设置自定义点击区域
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 object encapsulates both mouse and touch input. By default Phaser creates 2 pointers. Use for more (up to 10 total).
Pointerthis.input.addPointer(quantity)Key properties:
- ,
x- position in screen space (read fromy,position.x)position.y - ,
worldX- position translated through the most recent CameraworldY - ,
downX- position when button was presseddownY - ,
upX- position when button was releasedupY - (boolean) - true if any button is held
isDown - (boolean) - true if primary button (left click / touch) is held
primaryDown - (number) - which button was pressed/released (0=left, 1=middle, 2=right)
button - (number) - bitmask of currently held buttons (1=left, 2=right, 4=middle, 8=back, 16=forward)
buttons - (boolean) - true if input came from touch
wasTouch - (Vector2) - smoothed velocity of pointer movement
velocity - (number) - angle of movement in radians
angle - (number) - smoothed distance moved per frame
distance - ,
movementX- relative movement when pointer is lockedmovementY - ,
deltaX,deltaY- mouse wheel scroll amountsdeltaZ - (boolean) - whether pointer lock is active
locked - - the Camera this Pointer last interacted with
camera
Key methods:
- ,
leftButtonDown(),rightButtonDown(),middleButtonDown(),backButtonDown()- check specific buttonsforwardButtonDown() - ,
leftButtonReleased(),rightButtonReleased()- check recent releasemiddleButtonReleased() - - distance between down position and current/up position
getDistance() - ,
getDistanceX()- horizontal/vertical distancegetDistanceY() - - ms between down and current time or up time
getDuration() - - angle between down and current/up position
getAngle() - - recalculate worldX/worldY for a given camera
updateWorldPoint(camera) - - translate pointer position through a camera
positionToCamera(camera, output)
Pointerthis.input.addPointer(quantity)核心属性:
- ,
x- 屏幕空间中的位置(从y,position.x读取)position.y - ,
worldX- 经过最近Camera转换后的位置worldY - ,
downX- 按键按下时的位置downY - ,
upX- 按键释放时的位置upY - (布尔值)- 若有任意按键被按住则为true
isDown - (布尔值)- 若主按键(左键点击/触摸)被按住则为true
primaryDown - (数值)- 按下/释放的按键编号(0=左键,1=中键,2=右键)
button - (数值)- 当前按住按键的位掩码(1=左键,2=右键,4=中键,8=后退,16=前进)
buttons - (布尔值)- 若输入来自触摸则为true
wasTouch - (Vector2)- 指针移动的平滑速度
velocity - (数值)- 移动方向的弧度值
angle - (数值)- 每帧移动的平滑距离
distance - ,
movementX- 指针锁定时的相对移动量movementY - ,
deltaX,deltaY- 鼠标滚轮的滚动量deltaZ - (布尔值)- 指针锁定是否激活
locked - - 该Pointer最近交互的Camera
camera
核心方法:
- ,
leftButtonDown(),rightButtonDown(),middleButtonDown(),backButtonDown()- 检查特定按键状态forwardButtonDown() - ,
leftButtonReleased(),rightButtonReleased()- 检查最近是否释放了特定按键middleButtonReleased() - - 按下位置与当前/释放位置之间的距离
getDistance() - ,
getDistanceX()- 水平/垂直距离getDistanceY() - - 按下到当前时间或释放时间的毫秒数
getDuration() - - 按下位置与当前/释放位置之间的角度
getAngle() - - 为指定Camera重新计算worldX/worldY
updateWorldPoint(camera) - - 将指针位置通过Camera转换
positionToCamera(camera, output)
Interactive Game Objects (setInteractive)
可交互游戏对象(setInteractive)
Call to enable input on a Game Object. This uses the texture frame as the hit area by default.
gameObject.setInteractive()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 , , , , , Key objects:
updownleftrightspaceshiftjs
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(boolean)isUp - (number)
keyCode - ,
altKey,ctrlKey,shiftKey(boolean) - modifier state when pressedmetaKey - (number) - ms held in previous down-up cycle
duration - ,
timeDown(number) - timestampstimeUp - (number) - repeat count while held
repeats - (boolean) - if true, fires 'down' event on each repeat
emitOnRepeat - (boolean) - can this key be processed
enabled
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 ScenesCommon KeyCodes: , , , , , , , , , , , , , , . Access via etc.
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方向键返回包含、、、、、 Key对象的实例:
updownleftrightspaceshiftjs
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 - (布尔值)- 若为true,每次重复时触发'down'事件
emitOnRepeat - (布尔值)- 是否可处理该按键
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.SPACEMouse/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.movementYScene级指针事件(在画布任意位置触发):
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.movementYDrag 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 startsjs
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):
- Game Object:
gameObject.on('pointerdown', (pointer, localX, localY, event) => {}) - Scene per-object:
this.input.on('gameobjectdown', (pointer, gameObject, event) => {}) - Scene global:
this.input.on('pointerdown', (pointer, currentlyOver) => {})
指针事件会在三个层级触发(详情见参考文档):
- 游戏对象:
gameObject.on('pointerdown', (pointer, localX, localY, event) => {}) - Scene对象级:
this.input.on('gameobjectdown', (pointer, gameObject, event) => {}) - 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 to reserve pointer slots at startup, or call at runtime. Access via through .
config.input.activePointersthis.input.addPointer(num)this.input.pointer1pointer10js
// 可视化调试点击区域
this.input.enableDebug(gameObject);
this.input.enableDebug(gameObject, 0xff00ff);
this.input.removeDebug(gameObject);
// 让指针下方所有对象都接收事件(而非仅最顶层)
this.input.topOnly = false;
this.input.setTopOnly(false);多点触摸:在启动时设置来预留指针槽位,或在运行时调用。可通过至访问。
config.input.activePointersthis.input.addPointer(num)this.input.pointer1pointer10Gamepad Input
游戏手柄输入
Enable gamepads in the game config:
js
const config = {
input: {
gamepad: true
}
};Access via . Gamepads are available as through :
this.input.gamepadpad1pad4js
// 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.gamepadpad1pad4js
// 等待连接
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):
- : a string (each character is a key) or an array of key codes / Key objects
keys - (boolean, default true) - reset progress if wrong key is pressed
config.resetOnWrongKey - (number, default 0) - max ms between key presses; 0 = no limit
config.maxKeyDelay - (boolean, default false) - reset combo after a successful match
config.resetOnMatch - (boolean, default false) - remove combo after first match
config.deleteOnMatch
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):
- :字符串(每个字符对应一个按键)或按键编码/Key对象数组
keys - (布尔值,默认true)- 按下错误按键时重置进度
config.resetOnWrongKey - (数值,默认0)- 按键之间的最大间隔毫秒数;0=无限制
config.maxKeyDelay - (布尔值,默认false)- 匹配成功后重置组合
config.resetOnMatch - (布尔值,默认false)- 首次匹配后移除组合
config.deleteOnMatch
有关详细配置选项、API参考表和源码文件映射,请查看参考指南。