指针
初级 程序员
指针(Pointer)是设备屏幕上与手指触摸对应的点。支持多点触控功能的设备支持多个同时存在的指针。
在桌面平台上,可以使用左键模拟指针。有关鼠标输入的更多信息,请参见鼠标。
Stride 如何处理指针输入
用户触摸屏幕或点击左键。
Stride 创建一个指针。
Stride 为该指针分配与特定手指对应的指针 ID。
指针每次发生变化时,Stride 都会用该指针创建一个新的指针事件。
对于每根新的手指,Stride 会创建具有新指针 ID 的新指针。
Note
每个指针事件只包含一个指针的信息。如果同一次更新中有多个指针同时发生变化,Stride 会为每个指针创建单独的事件。
Warning
每个操作系统处理指针变化的方式不同。这意味着相同的手指手势在不同平台上可能生成略有不同的指针事件序列。例如,当手指触摸屏幕但没有移动时,Android 不会创建新的指针事件。更多信息请查阅你的操作系统文档。
你可以启用手势识别来检测长按、轻点等手势。更多信息请参见手势。
PointerEvent 类
PointerEvent 用于报告指针事件。它包含当前的指针状态和时间信息。指针每次发生变化时都会触发该事件。
你可以使用 InputManager.PointerEvents 访问自上次更新以来的指针事件列表。Stride 按时间顺序列出指针事件。该列表会在每次更新时清空,因此你无需手动清除。
获取指针信息
你可以使用以下属性获取触发事件的指针信息:
| 属性 | 说明 |
|---|---|
| PointerEvent.PointerId | 指示触发事件的指针 ID。 |
Warning
指针 ID 只在单次 Pressed->Moved->Released 指针事件序列期间有效。 同一根手指每次触摸屏幕时可能具有不同的 ID(即使动作非常快)。
Warning
每个操作系统都有自己为指针分配 ID 的方式。 指针 ID 的值与对应的手指之间没有关联。
要检查指针事件是由鼠标还是触摸触发的,请使用:
bool isTriggeredByMouse = event.Pointer is IMouseDevice
获取指针位置
你可以以归一化坐标或绝对坐标获取指针位置。
归一化坐标
@'Stride.Input.PointerEvent.Position' 以归一化的 X 和 Y 坐标返回指针位置,而不是以像素为单位的实际屏幕尺寸。这意味着指针位置可适配任何分辨率,你无需为不同分辨率编写单独的代码。
- (0,0):指针位于屏幕左上角
- (1,1):指针位于屏幕右下角
绝对坐标
PointerEvent.AbsolutePosition 以绝对 X 和 Y 坐标(以像素为单位的实际屏幕尺寸)返回指针位置。例如,如果指针位于屏幕左上角,值为 (0,0);如果指针位于右下角,值取决于屏幕分辨率(例如 1280, 720)。
获取指针事件
使用 PointerEvent.EventType 检查指针事件。
指针事件有五种类型:
- Pressed:手指触摸了屏幕。
- Moved:手指在屏幕上移动。
- Released:手指离开了屏幕。
- Canceled:指针序列被取消。当应用程序被中断时可能发生这种情况;例如,手机应用可能会被来电打断。
Note
单个指针的指针事件序列始终以 Pressed 事件开始,随后可能有一个或多个 Moved 事件,并始终以 Released 或 Canceled 事件结束。
获取增量值
PointerEvent.DeltaTime 获取自上一个 @'Stride.Input.PointerEvent' 以来经过的时间。
你可以以归一化坐标或绝对坐标获取增量位置。
归一化增量值
PointerEvent.DeltaPosition 以归一化的 X、Y 坐标获取自上一个 @'Stride.Input.PointerEvent' 以来的位置变化。
Note
在指针事件序列的开始处(即指针状态为按下时),增量值始终为空。
绝对增量值
PointerEvent.DeltaPosition 以绝对 (X,Y) 坐标获取自上一个 @'Stride.Input.PointerEvent' 以来的位置变化。
示例代码
此脚本跟踪指针移动并打印其位置:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Stride.Core.Mathematics;
using Stride.Engine;
namespace Stride.Input.Tests
{
public class PointerTestScript : AsyncScript
{
public override async Task Execute()
{
var pointerPositions = new Dictionary<int, Vector2>();
while (true)
{
await Script.NextFrame();
foreach (var pointerEvent in Input.PointerEvents)
{
switch (pointerEvent.EventType)
{
case PointerEventType.Pressed:
pointerPositions[pointerEvent.PointerId] = pointerEvent.Position;
break;
case PointerEventType.Moved:
pointerPositions[pointerEvent.PointerId] = pointerEvent.Position;
break;
case PointerEventType.Released:
case PointerEventType.Canceled:
pointerPositions.Remove(pointerEvent.PointerId);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
var positionsStr = pointerPositions.Values.Aggregate("", (current, pointer) => current + (pointer.ToString() + ", "));
Log.Info("There are currently {0} pointers on the screen located at {1}", pointerPositions.Count, positionsStr);
}
}
}
}