Skip to content

输入 ​

游戏代码只查动作(jump、left……),不关心动作来自键盘、触摸还是屏幕按钮。动作在启动参数 actions 里定义,每个动作可以有多个绑定。

ts
import { key, Node2D, pointerPress, rect, Scene, v } from 'sapling2d'

declare module 'sapling2d' {
  interface ActionRegistry {
    jump: true
  }
}

/** 可点击的按钮:inputPickable + hitArea(Sprite2D 不设 hitArea 时用贴图范围) */
class Button extends Node2D {
  presses = 0

  override ready() {
    this.inputPickable = true
    this.hitArea = rect(-100, -40, 200, 80) // 局部坐标
    this.clicked.connect(() => this.presses++, this) // 按下和抬起都在区域内
  }
}

export class Controls extends Scene {
  jumps = 0
  button!: Button

  override ready() {
    this.button = this.add(new Button({ position: v(375, 1200) }))
  }

  override process() {
    // 被按钮处理掉的点击不会触发 pointerPress() 绑定
    if (this.tree.input.isActionJustPressed('jump')) this.jumps++
  }
}

// 启动参数:startGame({ main: Controls, actions: { jump: [pointerPress(), key('Space')] } })

测试里模拟输入:

ts
const g = await createTestGame({ main: Controls, actions: { jump: [pointerPress(), key('Space')] } })
g.tap(375, 1200) // 设计坐标;推进 2 帧(按下、抬起)
g.tap(100, 300) // 空白处:触发 jump
g.pressKey('Space')
expect(g.scene.button.presses).toBe(1)
expect(g.scene.jumps).toBe(2)

动作 ​

  • 查询:isActionPressed、isActionJustPressed、isActionJustReleased。
  • 用声明合并给动作名加类型:declare module 'sapling2d' { interface ActionRegistry { jump: true } },拼错动作名就编译不过。
  • isActionJustPressed 在 process 里按帧算,在 physicsProcess 里按物理步算。屏幕刷新率高于 60Hz 时有的帧没有物理步,所以跳跃这类按键放在 physicsProcess 里处理不会丢。

绑定 ​

绑定来源
pointerPress()屏幕上任意一处没被节点处理的按下("点屏幕开始游戏")
key('Space')键盘(内置插件,三个入口都默认安装)
屏幕按钮、摇杆@sapling2d/touch 插件
tilt('left')倾斜传感器,sapling2d/motion 插件

几个来源同时作用时,动作的力度(0–1)取最大值;摇杆和倾斜会给出中间值,用 getActionStrength、getAxis、getVector 读取。

可点击的节点 ​

Node2D 设 inputPickable = true 后能收到指针:信号 pointerDown、pointerMove、pointerUp、clicked。点击区域是 hitArea;Sprite2D 不设时用贴图范围。被节点处理掉的点击不会触发 pointerPress()。

无头测试里贴图宽高是 0

需要点击的精灵,在测试里显式设 hitArea。

小游戏没有键盘事件,但游戏代码不用区分:绑定了 key() 的动作在那里只是不会被键盘触发。

MIT 许可证