触摸:一窝带编号的“光标”
触屏看客最省事,设备就是手指头。但翻译到程序里,触摸反而是几台设备里最“多线程”的:光标全屏只有一个,手指能同时落下好几根,每根有自己的轨迹、自己的生灭。Bevy 的安排照旧是“流水 + 快照”:流水是 TouchInput 消息(带相位 Started/Moved/Ended/Canceled),快照是资源 Touches——把每根在场的手指按 id 记账。
rust
/// 落指即插旗:触点的窗口坐标走光标同一条反算路
fn taps(
touches: Res<Touches>,
camera: Single<(&Camera, &GlobalTransform)>,
mut flag: Single<(&mut Transform, &mut Visibility), With<Flag>>,
mut target: ResMut<DashTarget>,
mut last_count: Local<usize>,
) {
let (camera, camera_transform) = *camera;
for touch in touches.iter_just_pressed() {
let Ok(point) = camera.viewport_to_world_2d(camera_transform, touch.position()) else {
continue;
};
let (flag_transform, flag_visibility) = &mut *flag;
flag_transform.translation = point.extend(0.5);
**flag_visibility = Visibility::Visible;
target.0 = Some(point.x.clamp(-STAGE_HALF, STAGE_HALF));
println!(
"场记:{} 号手指点了 ({:.0}, {:.0}),旗插上了。",
touch.id(),
point.x,
point.y
);
}
// 同时按着几根手指?Touches 替每个触点记着账
let count = touches.iter().count();
if count != *last_count {
*last_count = count;
if count > 1 {
println!("场记:台口同时按着 {count} 根手指。");
}
}
}Listing 17-7:落指即插旗——Touches 按手指记账(examples/listing-17-07.rs)
读法处处是熟面孔:
- 三问换成了三个迭代器。
iter_just_pressed()(本帧新落下的手指)、iter_just_released()(本帧抬起的)、iter()(所有按着的),跟ButtonInput的三问一一对应,只是每一问吐出的是零到多根手指; - 每根手指是一个
Touch,身上有id()(落下时分配,抬起前不变——跨帧追踪就靠它)、position()(当前位置)、delta()(本帧挪了多少)、distance()(离落点的累计位移)。双指缩放这类手势,本质就是对两个 id 的position做几何; - 坐标与光标同一个体系。
position()给的是窗口坐标,于是上一节那条“反算世界”的路原封不动能走——Listing 17-7 的插旗代码与鼠标版逐行同构,连dash系统都是原样照搬; - 多一种生灭:
Canceled。手指没抬、追踪却被系统掐了——窗口失焦、iOS 检测到设备贴上了脸。做拖拽手势时记得把它当“松手”处理,否则会留下一根永远按着的幽灵手指。
console
cargo run -p ch17-input --example listing-17-07text
老雷:触屏看客请上手。点哪儿走哪儿,几根手指我们都数着。跟手柄那节一样交个底:本书的写作机器没有触屏,跑起来 Touches 恒为空,上面就是全部输出——鼠标点击不会伪装成触摸。这一节的写法以 bevy_input 源码和官方示例 examples/input/touch_input.rs 为据;带触屏的笔记本或安卓设备(第 38 章部署移动端时会回来)上,每根手指落下都会插旗并报出它的 id,两根手指同按会看到“台口同时按着 2 根手指”。
还有一族更高层的手势消息:
PinchGesture(双指缩放)、RotationGesture(双指旋转)、DoubleTapGesture、PanGesture,由系统的手势识别器直接折算好递来。源码标注得很清楚:目前只在 macOS 与 iOS 可用(iOS 还须显式开启)——跨平台游戏别拿它当唯一通道,老老实实用Touches自己算。
至此四路看客的方言都会说了:键盘的三问、鼠标的反算、手柄的模拟量、触屏的多指记账。只剩一个问题——这四套话,怎么不打架地塞进同一台戏?