用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/feliperyba/ralph-orchestra --skill dev-phaser-input-handlers命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Complete Developer workflow orchestration - task research sequence, implementation flow, validation gates, PRD synchronization, exit conditions.
Complete Game Designer workflow - skill invocation protocol, GDD creation, playtest flow with GDD review, design sessions. MUST load before starting assignments.
Complete PM Coordinator workflow - task assignment, project orchestration, PRD management, worker coordination. Use proactively when starting PM agent work.
正在显示 SKILL.md
基于 SOC 职业分类
| name | dev-phaser-input-handlers |
| description | Keyboard, mouse, touch, and gamepad input management for Phaser |
"Responsive controls for every platform and input method."
// Manual input handling without Phaser
const keys: { [key: string]: boolean } = {};
// Setup key listeners
document.addEventListener('keydown', (e) => {
keys[e.key] = true;
keys[e.code] = true;
// Manual input handling
if (e.key === 'ArrowLeft') player.x -= 5;
if (e.key === 'ArrowRight') player.x += 5;
if (e.code === 'KeyW') player.y -= 5;
});
document.addEventListener('keyup', (e) => {
keys[e.key] = false;
keys[e.code] = false;
});
// Manual mouse/touch
canvas.addEventListener('mousedown', (e) => {
shoot(e.clientX, e.clientY);
});
canvas.addEventListener('touchstart', (e) => {
const touch = e.touches[0];
shoot(touch.clientX, touch.clientY);
});
// Problems:
// - Different code paths for mouse vs touch
// - No key repeat prevention
// - No JustDown/JustUp tracking
// - Manual input state management
// - No gamepad support
// - Platform-specific issues
// Phaser handles all input types uniformly
export class GameScene extends Phaser.Scene {
private cursors!: Phaser.Types.Input.Keyboard.CursorKeys;
private gamepadIndex = 0;
private inputManager!: InputManager;
create() {
// Unified input setup - ONE system for all!
this.cursors = this.input.keyboard!.createCursorKeys();
this.inputManager = new InputManager(this);
// Pointer works for mouse AND touch automatically
this.input.on('pointerdown', (pointer: Phaser.Input.Pointer) => {
this.shoot(pointer.x, pointer.y);
});
// Gamepad auto-detected
this.input.gamepad!.on(, {
.(, pad.);
});
}
() {
move = ..();
..(move. * , move. * );
(..()) {
..();
}
}
}
Use when:
create() {
// Keyboard
this.cursors = this.input.keyboard!.createCursorKeys();
this.wasd = this.input.keyboard!.addKeys('W,A,S,D');
// Mouse
this.input.on('pointerdown', (pointer) => {
this.spawnBullet(pointer.x, pointer.y);
});
}
update() {
if (this.cursors.left.isDown) {
this.player.x -= 5;
}
}
| Need | Use |
|---|---|
| Arrow keys | createCursorKeys() |
| WASD | addKeys('W,A,S,D') |
| Click/tap | pointerdown event |
| Drag | setInteractive({ draggable: true }) |
| Gamepad | gamepadpad plugin |
export class GameScene extends Phaser.Scene {
private cursors!: Phaser.Types.Input.Keyboard.CursorKeys;
private wasd!: {
W: Phaser.Input.Keyboard.Key;
A: Phaser.Input.Keyboard.Key;
S: Phaser.Input.Keyboard.Key;
D: Phaser.Input.Keyboard.Key;
};
private jumpKey!: Phaser.Input.Keyboard.Key;
private shootKey!: Phaser.Input.Keyboard.Key;
create() {
// Arrow keys
this.cursors = this.input.keyboard!.createCursorKeys();
// WASD keys
this.wasd = ..!.() ;
. = ..!.();
. = ..!.(
....,
);
shiftKey = ..!.();
..!.(, {
.. = ;
});
..!.(, {
.. = ;
});
}
() {
(...) {
..(-);
} (...) {
..();
} {
..();
}
(... && ..!..) {
..(-);
}
(...) {
..(-);
}
(...(.)) {
..();
}
(..) {
..();
}
}
}
create() {
// Pointer (unified mouse/touch)
this.input.on('pointermove', (pointer: Phaser.Input.Pointer) => {
this.player.rotation = Phaser.Math.Angle.Between(
this.player.x, this.player.y,
pointer.x, pointer.y
);
});
this.input.on('pointerdown', (pointer: Phaser.Input.Pointer) => {
this.shoot(pointer.x, pointer.y);
});
// Dragging game objects
const box = this.add.image(400, 300, 'box');
box.setInteractive({ draggable: true });
..([box]);
..(, {
gameObject. = dragX;
gameObject. = dragY;
});
..(, {
gameObject.();
});
zone = ..(, , , );
zone.({ : });
zone.(, {
zone.();
});
zone.(, {
zone.();
});
}
export class GameScene extends Phaser.Scene {
private joystick!: {
base: Phaser.GameObjects.Image;
knob: Phaser.GameObjects.Image;
};
private joystickActive = false;
private joystickPointerId: number | null = null;
private joystickVector = { x: 0, y: 0 };
create() {
// Only show on touch devices
if (this.sys.game.device.os.android || this.sys.game.device.os.iOS) {
this.createVirtualJoystick();
}
}
createVirtualJoystick() {
const joyX = 100;
const joyY = this.scale.height - 100;
radius = ;
base = ..(joyX, joyY, radius, , );
base.();
base.();
knob = ..(joyX, joyY, , , );
knob.();
knob.();
. = { base, knob };
..(, {
dist = ...(
pointer.,
pointer.,
joyX,
joyY,
);
(dist < radius && . === ) {
. = ;
. = pointer.;
}
});
..(, {
(. && pointer. === .) {
angle = ...(
joyX,
joyY,
pointer.,
pointer.,
);
dist = .(
...(joyX, joyY, pointer., pointer.),
radius,
);
... = joyX + .(angle) * dist;
... = joyY + .(angle) * dist;
.. = (... - joyX) / radius;
.. = (... - joyY) / radius;
}
});
..(, {
(pointer. === .) {
. = ;
. = ;
... = joyX;
... = joyY;
. = { : , : };
}
});
}
() {
(.) {
..(
.. * ..,
.. * ..,
);
}
}
}
create() {
// Gamepad is auto-enabled in Phaser 3
// Check for gamepad connection
this.input.gamepad!.on('connected', (gamepad: Phaser.Input.Gamepad.Gamepad) => {
console.log('Gamepad connected:', gamepad.id);
});
this.input.gamepad!.on('disconnected', (gamepad: Phaser.Input.Gamepad.Gamepad) => {
console.log('Gamepad disconnected:', gamepad.id);
});
}
update() {
const pads = this.input.gamepad!.gamepads;
for (let i = 0; i < pads.length; i++) {
const pad = pads[i];
if (!pad || !pad.connected) continue;
// Left stick
(pad.. >= ) {
axisX = pad.[].();
axisY = pad.[].();
..(axisX * , axisY * );
}
(pad.[]?.) ..(-);
(pad.[]?.) ..();
(pad.[]?.) ..(-);
(pad.[]?.) ..();
(pad.[]?.) ..();
(pad.[]?.) ..();
(pad.[]?.) ..();
(pad.[]?.) ..();
}
}
class InputManager {
private keyboard: { cursors: Phaser.Types.Input.Keyboard.CursorKeys; wasd: any };
private gamepadIndex = 0;
private virtualJoystick = { active: false, x: 0, y: 0 };
constructor(private scene: Phaser.Scene) {
this.setupKeyboard();
this.setupGamepad();
this.setupVirtualControls();
}
private setupKeyboard() {
this.keyboard = {
cursors: this.scene.input.keyboard!.createCursorKeys(),
wasd: this.scene.input.keyboard!.addKeys('W,A,S,D')
};
}
private setupGamepad() {
...!.(, {
. = ;
});
}
() {
(...... ||
......) {
}
}
(): { : ; : } {
pad = ...!.(.);
(pad && pad. && pad.. >= ) {
{
: pad.[].(),
: pad.[].()
};
}
(..) {
{
: ..,
: ..
};
}
x = , y = ;
(.... || ....) x = -;
(.... || ....) x = ;
(.... || ....) y = -;
(.... || ....) y = ;
{ x, y };
}
(): {
.... ||
.... ||
(...!.(.)?.[]?.);
}
(): {
...(
...!.()
) || ...!.(.)?.[]?.;
}
}
() {
. = ();
}
() {
move = ..();
..(move. * , move. * );
(..()) {
..();
}
}
❌ DON'T:
✅ DO:
// Ctrl+Z to undo
this.input.keyboard!.on("keydown-Z", () => {
const ctrlKey = this.input.keyboard!.checkDown(
this.input.keyboard!.addKey("CTRL"),
100,
);
if (ctrlKey) {
this.undo();
}
});
// Double tap detection
let lastTapTime = 0;
this.input.on("pointerdown", () => {
const now = this.time.now;
if (now - lastTapTime < 300) {
this.doubleTap();
}
lastTapTime = now;
});
update() {
// Smooth movement with lerp
const targetX = this.input.activePointer.x;
const targetY = this.input.activePointer.y;
this.player.x = Phaser.Math.Linear(this.player.x, targetX, 0.1);
this.player.y = Phaser.Math.Linear(this.player.y, targetY, 0.1);
}