游戏编程中的小技巧:游戏输入的处理

一. 游戏的输入设备

游戏的输入设备,指的是日常玩家用于控制游戏的一些外部/内部设备:PC机和家用游戏机的键盘,鼠标,手柄;移动机上则以触摸,重力感应,摄像头的手势识别为主;还有最近用于AR/VR的设备,如WiiMote,Kinect,VR眼镜一体机,索尼PlayStation vr等。这些在游戏中已经成为玩家获取游戏体验感的重要来源。既要简化用户对游戏的操作,又要能够提升游戏对用户输入反馈的处理能力,这是提升游戏体验感的一个重要方面。

目前对于端游和手游的输入模式主要分为两种:数字和模拟。数字形式的输入只有两种状态:按下去,没有按。不存在介于两者之间的情况;而模拟形式则是对用户的输入返回一个特定区间的值,一般是介于 -1 ~ 1 之间,对于一些比较复杂的操作,或者格斗类游戏的组合键下主要使用模拟形式。

当然,针对玩家日益提升的游戏能力,游戏中也需要考虑对“同时按键”和“序列按键”的支持。这种需求在格斗类,角色扮演类,体育类游戏中用的很多,例如拳皇和街霸中的各种连续技,组合技,NBA2k19中各种运球投篮动作等。

二. 数字输入

除了文本类游戏,现今大多数图形类游戏又不再使用标准输入,因为控制台是不会长时间开启,大多数游戏会使用一些库来封装对这些设备输入的查询,例如Simple DirectMedia layer(SDL)的跨平台库。当用户进行按键控制时,系统会将该按键对应的索引置为true,从而反馈到游戏中。

但仅仅这样是不够的,我们知道游戏和软件系统不一样,用户往往会在同一时间,甚至在短短1s内使用多个按键,而且游戏一般运行在30FPS ~ 60FPS之间,用户在这一帧按下的操作,通常在往后的几帧中得到显示和反馈,这就是玩家所说的“按键延迟”的一种情况,在网络不好的时候尤为突出。

目前较好的优化方法是追踪游戏上下帧的状态。
游戏编程中的小技巧:游戏输入的处理_第1张图片
这样我们可以只针对用户的操作提前进行处理而不是等到用户已经操作后再进行处理,这会大大降低游戏的流畅度。(还有一种情况,如果游戏中需要“充能”操作,即长按某个按键蓄力,我们可以在“用户刚刚输入”时开始赋予初始值,每一帧增加定量,知道“用户刚刚松开”后完成“充能”)。

三. 模拟输入

模拟输入会反馈一组范围值,因为输入后的数值波动非常开,在整个游戏之中系统不一定能及时处理到反馈而值就已经消失了,或者当玩家没有使用手柄时,实际上模拟输入的值也不会是0,这就是输入偏差。基于这样一般虚拟输入不会直接应用到角色的移动中。不过凡事没有绝对,我们可以采用一种“模拟输入过滤”的方式来消除偏差。

游戏编程中的小技巧:游戏输入的处理_第2张图片
在手柄摇杆中,半径为整个可移动范围的半径的10%内,所有返回的值均置为0,即相当于静止;当半径处于10% ~ 100%时才视为有效。

但是对于一些游戏来说,对用户操作非常敏感,那么就无法利用到低于10%的值,那么我们可以换一种方法,可以使用向量运算来完成无效区域的过滤。

vector2 inp = get user input
float len = inp.length()
float pct = (len - minValue) / (maxValue - minValue)

这样就能充分利用0 ~ 100%的有效区域。

四. 基于事件机制的输入

针对一般的游戏场景,游戏本身是不会主动反馈信息给用户的。那么对于输入系统来说,很多的代码都会“轮询”输入,比如主动检查某某键是否触发对应的操作,那么每一帧都要去调用,去轮询,不仅代码量大,而且容易消耗内存,产生一定的BUG。

相比于让代码“轮询”,还不如我们一开始就设置一个事件机制推送系统。在基于事件的游戏系统下,每一部分的代码都需要注册其关心的事件通知,当输入事件发生时,系统发出通知到所有已注册的代码,它们在收到通知后会立即执行其相应操作。当然,轮询是不可避免的,我们只能将多个地方的轮询汇总成一个地方进行轮询,降低内存消耗。

五. 依赖字典映射的输入

字典,是由一系列“Key-value”值组成的集合。在游戏系统中使用字典会提升遍历的速度。在这个系统中,Key就是绑定的名字(如“Horizontal”,“Jump”,“Fire”),Value则是按钮的信息,包括对应的按键和按键对应的触发时机。

每一帧,输入系统都会检查这个字典的所有键值,并判断此时Key所对应的状态,然后再进行更改。字典首先会将更改的操作提供给UI系统,UI系统会判断哪些UI会受到这些操作的影响,然后再传递到游戏中进一步的处理。(注意,比如“B”按键,有可能同时对应背包系统快捷键以及游戏场景的某个操作,这时必须先判断UI层 --游戏场景层)。

六. 移动设备的输入

随着游戏向移动端的大量涌入,大多数游戏也需要开发出移动端。相比于PC端,移动端的输入方式有限,但是又要尽量做到PC端一样的操作复杂度,在输入系统上也需要花费一定的时间去设计完善。

1.触屏和手势

触屏,是所有移动端游戏的首选输入方式。通过玩家手指与屏幕的交互,来达到像PC上玩家用鼠标控制游戏的精准度。不过大多数的移动设备支持了多点触摸,这是和鼠标的一个较大不同点。多点触摸的好处是能让玩家在移动端上对游戏进行快捷流畅的操作,又能在这基础上增加操作的复杂度,提升移动端游戏的可玩性。

手势操作,是目前移动端基于触屏衍生的一种操作。玩家通过双指及以上的手势操作来达到一些快捷的功能实现,比如“两指缩放”,“双击放大缩小”等。除了系统自带的手势识别功能,我们也可以自定义一些复杂度较低的新操作:在Android上
我们可以用“Gestures Bulider”程序,在IOS上,我们可以写一个类继承“UIGestureRecognizer”来实现。

在检测用户的手势上,最常用的就是“罗宾算法”(Rubine 算法),它是由早期笔画识别发展而来,对于该算法就不详细展开讲了,各位有兴趣的可以手动百度一下。

2.加速器和陀螺仪

加速器,检测移动设备在坐标轴上的加速度。例如,当你竖着拿手机的时候,向上移动,就会得到y轴方向的加速度,当你平放手机,向上移动,就会得到z轴方向的加速度。

陀螺仪,则是检测移动设备的轴向旋转。比如我们在玩赛车类的游戏时(狂野飙车8),玩家控制赛车的转向,就是利用手机的陀螺仪来感知手机的轴向,从而实现对游戏的控制,这样相对于触屏控制来说玩家的操作性更高更流畅。

本文是基于《游戏编程与算法技巧》一书,进行个人的总结和改进。如有侵权问题,望原作者及时告知我并解决。

你可能感兴趣的:(游戏开发)