Phaser 输入处理 #

输入系统概述 #

Phaser 提供了统一的输入系统,支持键盘、鼠标、触摸和游戏手柄等多种输入设备。

text
┌─────────────────────────────────────────────────────────────┐
│                    输入系统架构                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Input Manager                                              │
│  ├── Keyboard                                              │
│  │   ├── Keys                                             │
│  │   └── Combos                                           │
│  ├── Pointer                                               │
│  │   ├── Mouse                                            │
│  │   └── Touch                                            │
│  ├── Gamepad                                               │
│  │   ├── Pads                                             │
│  │   └── Buttons                                          │
│  └── Interactive Objects                                   │
│      ├── Sprites                                          │
│      └── Zones                                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

键盘输入 #

方向键 #

javascript
create() {
  this.cursors = this.input.keyboard.createCursorKeys();
}

update() {
  if (this.cursors.left.isDown) {
    console.log('Left arrow pressed');
  }
  
  if (this.cursors.right.isDown) {
    console.log('Right arrow pressed');
  }
  
  if (this.cursors.up.isDown) {
    console.log('Up arrow pressed');
  }
  
  if (this.cursors.down.isDown) {
    console.log('Down arrow pressed');
  }
}

自定义按键 #

javascript
create() {
  this.keyW = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W);
  this.keyA = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A);
  this.keyS = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S);
  this.keyD = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D);
  
  this.spaceKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);
  this.enterKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.ENTER);
}

update() {
  if (Phaser.Input.Keyboard.JustDown(this.keyW)) {
    console.log('W key just pressed');
  }
  
  if (this.keyA.isDown) {
    console.log('A key is down');
  }
  
  if (Phaser.Input.Keyboard.JustUp(this.keyS)) {
    console.log('S key just released');
  }
}

按键码 #

javascript
Phaser.Input.Keyboard.KeyCodes.A
Phaser.Input.Keyboard.KeyCodes.B
Phaser.Input.Keyboard.KeyCodes.SPACE
Phaser.Input.Keyboard.KeyCodes.ENTER
Phaser.Input.Keyboard.KeyCodes.ESC
Phaser.Input.Keyboard.KeyCodes.SHIFT
Phaser.Input.Keyboard.KeyCodes.CONTROL
Phaser.Input.Keyboard.KeyCodes.ALT
Phaser.Input.Keyboard.KeyCodes.ONE
Phaser.Input.Keyboard.KeyCodes.F1
Phaser.Input.Keyboard.KeyCodes.BACKSPACE
Phaser.Input.Keyboard.KeyCodes.DELETE
Phaser.Input.Keyboard.KeyCodes.TAB

批量添加按键 #

javascript
create() {
  this.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,
    space: Phaser.Input.Keyboard.KeyCodes.SPACE
  });
}

update() {
  if (this.keys.left.isDown) {
    this.player.x -= 5;
  }
  
  if (this.keys.right.isDown) {
    this.player.x += 5;
  }
  
  if (Phaser.Input.Keyboard.JustDown(this.keys.space)) {
    this.player.jump();
  }
}

键盘事件 #

javascript
create() {
  this.input.keyboard.on('keydown', (event) => {
    console.log('Key down:', event.key, event.keyCode);
  });
  
  this.input.keyboard.on('keyup', (event) => {
    console.log('Key up:', event.key, event.keyCode);
  });
  
  this.input.keyboard.on('keydown-A', (event) => {
    console.log('A key pressed');
  });
  
  this.input.keyboard.on('keydown-SPACE', (event) => {
    console.log('Space pressed');
  });
}

组合键 #

javascript
create() {
  this.keyA = this.input.keyboard.addKey('A');
  this.keyB = this.input.keyboard.addKey('B');
}

update() {
  if (this.keyA.isDown && this.keyB.isDown) {
    console.log('A + B combo!');
  }
  
  const shiftKey = this.input.keyboard.addKey('SHIFT');
  if (shiftKey.isDown && Phaser.Input.Keyboard.JustDown(this.keyA)) {
    console.log('Shift + A combo!');
  }
}

捕获按键 #

javascript
create() {
  this.input.keyboard.addCapture([
    Phaser.Input.Keyboard.KeyCodes.SPACE,
    Phaser.Input.Keyboard.KeyCodes.UP,
    Phaser.Input.Keyboard.KeyCodes.DOWN
  ]);
  
  this.input.keyboard.addCapture('W,A,S,D');
}

removeCapture() {
  this.input.keyboard.removeCapture(Phaser.Input.Keyboard.KeyCodes.SPACE);
}

禁用/启用键盘 #

javascript
this.input.keyboard.enabled = false;
this.input.keyboard.enabled = true;

this.input.keyboard.disableGlobalCapture();
this.input.keyboard.enableGlobalCapture();

鼠标输入 #

鼠标指针 #

javascript
create() {
  this.input.on('pointerdown', (pointer) => {
    console.log('Mouse down at:', pointer.x, pointer.y);
    console.log('Button:', pointer.leftButtonDown(), pointer.rightButtonDown());
  });
  
  this.input.on('pointerup', (pointer) => {
    console.log('Mouse up at:', pointer.x, pointer.y);
  });
  
  this.input.on('pointermove', (pointer) => {
    console.log('Mouse moved to:', pointer.x, pointer.y);
  });
  
  this.input.on('pointerover', (pointer) => {
    console.log('Pointer entered game');
  });
  
  this.input.on('pointerout', (pointer) => {
    console.log('Pointer left game');
  });
}

鼠标按钮 #

javascript
this.input.on('pointerdown', (pointer) => {
  if (pointer.leftButtonDown()) {
    console.log('Left button');
  }
  
  if (pointer.rightButtonDown()) {
    console.log('Right button');
  }
  
  if (pointer.middleButtonDown()) {
    console.log('Middle button');
  }
  
  if (pointer.backButtonDown()) {
    console.log('Back button');
  }
  
  if (pointer.forwardButtonDown()) {
    console.log('Forward button');
  }
});

this.input.on('wheel', (pointer, deltaX, deltaY, deltaZ) => {
  console.log('Wheel:', deltaY);
  if (deltaY > 0) {
    console.log('Scrolling down');
  } else {
    console.log('Scrolling up');
  }
});

指针属性 #

javascript
this.input.on('pointerdown', (pointer) => {
  console.log('Position:', pointer.x, pointer.y);
  console.log('World position:', pointer.worldX, pointer.worldY);
  console.log('Previous position:', pointer.prevPosition.x, pointer.prevPosition.y);
  console.log('Velocity:', pointer.velocity.x, pointer.velocity.y);
  console.log('Delta:', pointer.deltaX, pointer.deltaY);
  console.log('Duration:', pointer.getDuration());
  console.log('Distance:', pointer.getDistance());
  console.log('Angle:', pointer.angle);
  console.log('Is down:', pointer.isDown);
  console.log('Buttons:', pointer.buttons);
});

多指针 #

javascript
const config = {
  input: {
    activePointers: 3
  }
};

create() {
  this.input.on('pointerdown', (pointer) => {
    console.log('Pointer ID:', pointer.id);
  });
  
  const pointer1 = this.input.pointer1;
  const pointer2 = this.input.pointer2;
  
  console.log('Pointer 1:', pointer1.x, pointer1.y);
  console.log('Pointer 2:', pointer2.x, pointer2.y);
}

触摸输入 #

触摸事件 #

javascript
create() {
  this.input.on('pointerdown', (pointer) => {
    console.log('Touch started');
  });
  
  this.input.on('pointermove', (pointer) => {
    console.log('Touch moved');
  });
  
  this.input.on('pointerup', (pointer) => {
    console.log('Touch ended');
  });
  
  this.input.on('gameover', (pointer) => {
    console.log('Pointer left game area');
  });
  
  this.input.on('gameout', (pointer) => {
    console.log('Pointer entered game area');
  });
}

多点触控 #

javascript
const config = {
  input: {
    activePointers: 4,
    touch: {
      capture: true
    }
  }
};

create() {
  this.input.on('pointerdown', (pointer) => {
    console.log(`Touch ${pointer.id} at ${pointer.x}, ${pointer.y}`);
  });
  
  this.input.addPointer(3);
}

update() {
  const pointers = this.input.manager.pointers;
  pointers.forEach((pointer, index) => {
    if (pointer.isDown) {
      console.log(`Pointer ${index}: ${pointer.x}, ${pointer.y}`);
    }
  });
}

手势识别 #

javascript
create() {
  this.input.on('pointerdown', (pointer) => {
    this.touchStartX = pointer.x;
    this.touchStartY = pointer.y;
    this.touchStartTime = this.time.now;
  });
  
  this.input.on('pointerup', (pointer) => {
    const deltaX = pointer.x - this.touchStartX;
    const deltaY = pointer.y - this.touchStartY;
    const deltaTime = this.time.now - this.touchStartTime;
    
    if (Math.abs(deltaX) > 50 && Math.abs(deltaY) < 30) {
      if (deltaX > 0) {
        console.log('Swipe right');
      } else {
        console.log('Swipe left');
      }
    }
    
    if (Math.abs(deltaY) > 50 && Math.abs(deltaX) < 30) {
      if (deltaY > 0) {
        console.log('Swipe down');
      } else {
        console.log('Swipe up');
      }
    }
    
    if (deltaTime < 200 && Math.abs(deltaX) < 10 && Math.abs(deltaY) < 10) {
      console.log('Tap');
    }
    
    if (deltaTime > 500 && Math.abs(deltaX) < 10 && Math.abs(deltaY) < 10) {
      console.log('Long press');
    }
  });
}

捏合缩放 #

javascript
create() {
  this.input.on('pointermove', this.handlePinch, this);
}

handlePinch(pointer) {
  if (this.input.pointer1.isDown && this.input.pointer2.isDown) {
    const p1 = this.input.pointer1;
    const p2 = this.input.pointer2;
    
    const distance = Phaser.Math.Distance.Between(p1.x, p1.y, p2.x, p2.y);
    
    if (this.lastPinchDistance) {
      const scale = distance / this.lastPinchDistance;
      this.camera.zoom *= scale;
    }
    
    this.lastPinchDistance = distance;
  }
}

游戏对象交互 #

启用交互 #

javascript
create() {
  const sprite = this.add.sprite(400, 300, 'button');
  
  sprite.setInteractive();
  
  sprite.setInteractive({
    useHandCursor: true,
    pixelPerfect: true,
    alphaTolerance: 1
  });
  
  sprite.setInteractive(new Phaser.Geom.Rectangle(0, 0, 100, 50), Phaser.Geom.Rectangle.Contains);
  
  sprite.setInteractive(new Phaser.Geom.Circle(50, 50, 50), Phaser.Geom.Circle.Contains);
}

交互事件 #

javascript
const sprite = this.add.sprite(400, 300, 'button').setInteractive();

sprite.on('pointerdown', (pointer, localX, localY, event) => {
  console.log('Clicked on sprite');
  console.log('Local coordinates:', localX, localY);
});

sprite.on('pointerup', (pointer, localX, localY, event) => {
  console.log('Released on sprite');
});

sprite.on('pointerover', (pointer, localX, localY, event) => {
  sprite.setTint(0xcccccc);
});

sprite.on('pointerout', (pointer, event) => {
  sprite.clearTint();
});

sprite.on('pointermove', (pointer, localX, localY, event) => {
  console.log('Moving over sprite');
});

sprite.on('wheel', (pointer, deltaX, deltaY, deltaZ, event) => {
  console.log('Wheel on sprite:', deltaY);
});

拖拽功能 #

javascript
const sprite = this.add.sprite(400, 300, 'draggable')
  .setInteractive({ draggable: true });

this.input.setDraggable(sprite);

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();
});

this.input.on('dragenter', (pointer, gameObject, dropZone) => {
  console.log('Entered drop zone');
});

this.input.on('dragleave', (pointer, gameObject, dropZone) => {
  console.log('Left drop zone');
});

this.input.on('drop', (pointer, gameObject, dropZone) => {
  console.log('Dropped on zone');
});

拖拽区域限制 #

javascript
const sprite = this.add.sprite(400, 300, 'draggable')
  .setInteractive({ draggable: true });

this.input.setDraggable(sprite);

this.input.on('drag', (pointer, gameObject, dragX, dragY) => {
  dragX = Phaser.Math.Clamp(dragX, 50, 750);
  dragY = Phaser.Math.Clamp(dragY, 50, 550);
  
  gameObject.x = dragX;
  gameObject.y = dragY;
});

放置区域 #

javascript
const zone = this.add.zone(600, 300, 100, 100)
  .setRectangleDropZone(100, 100);

const graphics = this.add.graphics();
graphics.lineStyle(2, 0xffff00);
graphics.strokeRect(zone.x - 50, zone.y - 50, 100, 100);

const sprite = this.add.sprite(100, 300, 'item')
  .setInteractive({ draggable: true });

this.input.setDraggable(sprite);

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

游戏手柄 #

检测手柄 #

javascript
create() {
  this.input.gamepad.once('connected', (pad) => {
    console.log('Gamepad connected:', pad.id);
    this.gamepad = pad;
  });
  
  if (this.input.gamepad.total > 0) {
    this.gamepad = this.input.gamepad.getPad(0);
  }
}

手柄按钮 #

javascript
update() {
  if (this.gamepad) {
    if (this.gamepad.A) {
      console.log('A button pressed');
    }
    
    if (this.gamepad.B) {
      console.log('B button pressed');
    }
    
    if (this.gamepad.X) {
      console.log('X button pressed');
    }
    
    if (this.gamepad.Y) {
      console.log('Y button pressed');
    }
    
    if (this.gamepad.left) {
      console.log('D-pad left');
    }
    
    if (this.gamepad.right) {
      console.log('D-pad right');
    }
    
    if (this.gamepad.up) {
      console.log('D-pad up');
    }
    
    if (this.gamepad.down) {
      console.log('D-pad down');
    }
  }
}

摇杆 #

javascript
update() {
  if (this.gamepad) {
    const leftStick = this.gamepad.leftStick;
    console.log('Left stick:', leftStick.x, leftStick.y);
    
    const rightStick = this.gamepad.rightStick;
    console.log('Right stick:', rightStick.x, rightStick.y);
    
    if (Math.abs(leftStick.x) > 0.1) {
      this.player.setVelocityX(leftStick.x * 200);
    }
    
    if (Math.abs(leftStick.y) > 0.1) {
      this.player.setVelocityY(leftStick.y * 200);
    }
  }
}

手柄事件 #

javascript
create() {
  this.input.gamepad.on('down', (pad, button, index) => {
    console.log('Button down:', index);
  });
  
  this.input.gamepad.on('up', (pad, button, index) => {
    console.log('Button up:', index);
  });
  
  this.input.gamepad.on('A', (value) => {
    console.log('A button:', value);
  });
}

update() {
  if (this.gamepad) {
    const leftTrigger = this.gamepad.L2;
    const rightTrigger = this.gamepad.R2;
    
    if (leftTrigger > 0) {
      console.log('Left trigger:', leftTrigger);
    }
  }
}

虚拟控制器 #

创建虚拟摇杆 #

javascript
class VirtualJoystick extends Phaser.GameObjects.Container {
  constructor(scene, x, y, radius) {
    super(scene, x, y);
    
    this.radius = radius;
    
    this.base = scene.add.circle(0, 0, radius, 0x000000, 0.5);
    this.thumb = scene.add.circle(0, 0, radius * 0.4, 0xffffff, 0.8);
    
    this.add([this.base, this.thumb]);
    
    this.pointer = null;
    this.vector = { x: 0, y: 0 };
    
    this.setInteractive(new Phaser.Geom.Circle(0, 0, radius), Phaser.Geom.Circle.Contains);
    
    this.on('pointerdown', this.startDrag, this);
    scene.input.on('pointermove', this.drag, this);
    scene.input.on('pointerup', this.endDrag, this);
  }
  
  startDrag(pointer) {
    this.pointer = pointer;
  }
  
  drag(pointer) {
    if (this.pointer !== pointer) return;
    
    const dx = pointer.x - this.x;
    const dy = pointer.y - this.y;
    const distance = Math.sqrt(dx * dx + dy * dy);
    
    if (distance < this.radius) {
      this.thumb.setPosition(dx, dy);
      this.vector.x = dx / this.radius;
      this.vector.y = dy / this.radius;
    } else {
      const angle = Math.atan2(dy, dx);
      this.thumb.setPosition(
        Math.cos(angle) * this.radius,
        Math.sin(angle) * this.radius
      );
      this.vector.x = Math.cos(angle);
      this.vector.y = Math.sin(angle);
    }
  }
  
  endDrag(pointer) {
    if (this.pointer !== pointer) return;
    
    this.pointer = null;
    this.thumb.setPosition(0, 0);
    this.vector.x = 0;
    this.vector.y = 0;
  }
}

create() {
  this.joystick = new VirtualJoystick(this, 100, 500, 50);
  this.add.existing(this.joystick);
}

update() {
  if (this.joystick.vector.x !== 0 || this.joystick.vector.y !== 0) {
    this.player.setVelocity(
      this.joystick.vector.x * 200,
      this.joystick.vector.y * 200
    );
  }
}

创建虚拟按钮 #

javascript
class VirtualButton extends Phaser.GameObjects.Container {
  constructor(scene, x, y, key, label) {
    super(scene, x, y);
    
    this.key = key;
    this.isPressed = false;
    
    this.circle = scene.add.circle(0, 0, 30, 0x444444, 0.8);
    this.text = scene.add.text(0, 0, label, {
      fontSize: '20px',
      fill: '#ffffff'
    }).setOrigin(0.5);
    
    this.add([this.circle, this.text]);
    
    this.setInteractive(new Phaser.Geom.Circle(0, 0, 30), Phaser.Geom.Circle.Contains);
    
    this.on('pointerdown', () => {
      this.isPressed = true;
      this.circle.setFillStyle(0x888888, 0.8);
    });
    
    this.on('pointerup', () => {
      this.isPressed = false;
      this.circle.setFillStyle(0x444444, 0.8);
    });
    
    this.on('pointerout', () => {
      this.isPressed = false;
      this.circle.setFillStyle(0x444444, 0.8);
    });
  }
}

create() {
  this.jumpButton = new VirtualButton(this, 700, 500, 'jump', 'A');
  this.add.existing(this.jumpButton);
}

update() {
  if (this.jumpButton.isPressed) {
    this.player.jump();
  }
}

输入配置 #

全局配置 #

javascript
const config = {
  input: {
    keyboard: true,
    mouse: true,
    touch: true,
    gamepad: true,
    activePointers: 1
  }
};

触摸配置 #

javascript
const config = {
  input: {
    touch: {
      capture: true,
      target: null
    }
  }
};

完整示例 #

移动控制 #

javascript
class GameScene extends Phaser.Scene {
  create() {
    this.player = this.physics.add.sprite(400, 300, 'player');
    
    this.cursors = this.input.keyboard.createCursorKeys();
    
    this.wasd = 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
    });
    
    this.spaceKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);
    
    this.input.on('pointerdown', (pointer) => {
      this.player.setPosition(pointer.x, pointer.y);
    });
  }
  
  update() {
    const speed = 200;
    
    if (this.cursors.left.isDown || this.wasd.left.isDown) {
      this.player.setVelocityX(-speed);
    } else if (this.cursors.right.isDown || this.wasd.right.isDown) {
      this.player.setVelocityX(speed);
    } else {
      this.player.setVelocityX(0);
    }
    
    if (this.cursors.up.isDown || this.wasd.up.isDown) {
      this.player.setVelocityY(-speed);
    } else if (this.cursors.down.isDown || this.wasd.down.isDown) {
      this.player.setVelocityY(speed);
    } else {
      this.player.setVelocityY(0);
    }
    
    if (Phaser.Input.Keyboard.JustDown(this.spaceKey)) {
      this.player.jump();
    }
  }
}

下一步 #

现在你已经掌握了输入处理,接下来学习 物理引擎,了解如何使用物理引擎实现碰撞和运动!

最后更新:2026-03-29