输入
游戏代码只查动作(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() 的动作在那里只是不会被键盘触发。