Table of Contents

手势

中级 程序员

手势(Gesture)是预定义的指针模式。Stride 可以识别手势并触发相应的事件。例如,在策略游戏中,玩家可以用拖动手势将单位拖放到战场上。手势可以使用一根或多根手指。

Note

配置文件中所有的长度、速度和误差范围都必须使用归一化的值。

开启手势识别

默认情况下,输入系统不会识别手势,因为这会占用 CPU 时间。

要开启手势识别:

  1. 为要识别的手势创建配置类的实例。例如,对于拖动手势,请创建 @'Stride.Input.GestureConfigDrag' 的实例。
  2. 配置类参数。
  3. 将手势配置添加到 @'Stride.Input.InputManager.Gestures' 集合中。
Warning

激活某个手势的识别后,就无法再修改该手势的参数。如果需要修改,请从 @'Stride.Input.InputManager.Gestures' 集合中删除该手势,并使用新参数创建新的条目。

关闭手势识别

从 InputManager.Gestures 集合中删除该手势。

手势识别

当输入系统检测到手势时,它会将一个 @'Stride.Input.GestureEvent' 添加到 InputManager.GestureEvents 列表中。该事件包含手势及其状态的信息,例如位置和使用的手指数量。

Note

每个手势都有其关联的手势事件类(见下文)。

GestureEvent.Type 字段指示识别出的是哪种手势。然后你可以将基础手势事件转换为该手势特有的事件类型,以获取与手势类型相关的事件信息。

Stride 可以同时检测多个手势,因此一次更新中事件列表可能包含多个条目。

该列表会在每次更新时清空,因此你无需手动清除。

配置手势

在 @'Stride.Input.GestureConfig' 类中,你可以配置的参数包括:

  • 手势使用的手指数量

  • 手势使用的轻点(Tap)次数和时长

  • 手势方向

Note

每个手势都有自己的配置类和特定的配置参数(见下文)。

手势类型

Stride 支持两种主要的手势类型:

  • 离散手势(轻点、轻弹、长按)触发单个事件。

  • 连续手势(拖动和复合手势)在用户改变手势方向时触发一系列事件。

离散手势

轻点(Tap)

轻点手势

用户触摸屏幕并快速移开手指。

配置类:@'Stride.Input.GestureConfigTap'

事件类:@'Stride.Input.GestureEventTap'

手势过程中屏幕上的手指数量不能变化。要设置轻点所需的手指数量,请修改 @'Stride.Input.GestureConfig.RequiredNumberOfFingers'。

Tip

为了区分单次轻点和多次轻点,系统会在轻点事件中使用延迟。要禁用此功能,请将 GestureConfigTap.MaximumTimeBetweenTaps 字段设置为 0。

轻弹(Flick)

轻弹手势

用户触摸屏幕,快速进行一次直线平移,然后收起手指。

配置类:@'Stride.Input.GestureConfigFlick'

事件类:@'Stride.Input.GestureEventFlick'

手势过程中屏幕上的手指数量不能变化。

要为轻动手势设置最小长度,请使用 GestureConfigFlick.MinimumFlickLength。

要将轻弹方向限制为垂直或水平,请使用 GestureConfigFlick.FlickShape。

长按(Long press)

长按手势

用户触摸屏幕并保持按压,在一段时间内不移开手指(默认时间为一秒)。

配置类:GestureConfigLongPress

事件类:GestureEventLongPress

手势过程中屏幕上的手指数量不能变化。

要更改长按手势的最小按压时长,请修改 GestureConfigLongPress.RequiredPressTime。

连续手势

拖动(Drag)

拖动手势

用户触摸屏幕,进行一次平移,然后收起手指。

配置类:GestureConfigDrag

事件类:GestureEventDrag

手势过程中屏幕上的手指数量不能变化。

要检测更小的拖动,请减小 GestureConfigDrag.MinimumDragDistance。

要将拖动方向限制为垂直或水平,请使用 GestureConfigDrag.DragShape。

复合(Composite)

平移手势 缩放手势 旋转手势

用户用两根手指触摸屏幕并独立移动它们。

配置类:@'Stride.Input.GestureConfigComposite'

事件类:@'Stride.Input.GestureEventComposite'

复合手势要求屏幕上恰好有两根手指。当系统检测到以下三种基本动作之一时触发:

  • 平移(Translation):用户将两根手指沿相同方向一起移动。
  • 缩放(Scale):用户将两根手指移近或移远。
  • 旋转(Rotation):用户围绕一个中心点旋转两根手指。

手势状态

手势始终处于以下四种状态之一:

  • Began(开始)

  • Changed(变化)

  • Ended(结束)

  • Occurred(已发生)

离散手势(轻点、轻弹、长按)始终为 occurred 状态。连续手势(拖动和复合手势)始终以 began 状态开始,随后是任意多个 changed 状态,最后以 ended 状态结束。

要查询手势的当前状态,请使用触发的手势事件的 GestureEvent.State 字段。

示例代码

激活或停用手势识别

要创建要识别的手势的配置:

// 创建要识别的手势的配置
var singleTapConfig = new GestureConfigTap();

// 开始轻点手势识别
Input.Gestures.Add(singleTapConfig);

// 创建要识别的手势的配置
var doubleTapConfig = new GestureConfigTap(2, 1);

// 开始双击手势识别
Input.Gestures.Add(doubleTapConfig);

// 停止轻点手势识别
Input.Gestures.Remove(singleTapConfig);

// 停止所有手势识别
Input.Gestures.Clear();

配置手势

每个配置类都有一个无参构造函数,对应默认的手势配置。对于经常修改的参数,你可以使用专用的构造函数。

Warning

我们不建议你修改其他字段,因为这可能会破坏输入系统。但如果确实需要,可以通过相应的属性进行修改。

// 默认手势配置
var singleTapConfig = new GestureConfigTap();

// 使用专用构造函数个性化手势配置
var doubleTapConfig = new GestureConfigTap(2, 2);

// 通过直接访问所需属性来个性化手势配置
// 请确保你清楚自己在做什么!修改此设置可能会破坏输入系统
var noLatencyTap = new GestureConfigTap() { MaximumTimeBetweenTaps= TimeSpan.Zero };

访问手势事件

你可以使用 InputManager.GestureEvents 集合访问已识别手势触发的事件列表。该集合会在每次更新时自动清空。

var currentFrameGestureEvents = Input.GestureEvents;

识别手势类型

使用 GestureEvent.Type 字段识别手势类型,然后将其转换为相应的事件类型,以获取有关该事件的额外信息。

foreach( var gestureEvent in Input.GestureEvents)
{
   	// 判断事件是否来自轻点手势
	if (gestureEvent.Type != GestureType.Tap)
		continue;
   
	// 转换为特定的轻点事件类
	GestureEventTap  tapEvent = (GestureEventTap) gestureEvent;
	
    // 访问轻点事件特有的字段
    log.Info("Tap position: {0}.", tapEvent.TapPosition);
}

识别手势状态

使用 GestureEvent.State 字段获取手势事件状态。

switch(compositeGestureEvent.State)
{
case GestureState.Began:
	image.ComputePreview();
	break;
case GestureState.Changed:
	image.TransformPreview(compositeGestureEvent.TotalScale, compositionGestureEvent.TotalRotation);
	break;
case GestureState.Ended:
	image.TransformRealImage(compositeGestureEvent.TotalScale, compositionGestureEvent.TotalRotation);
	break;
default:
	break;
}

另请参阅