为了完美处理玩家可能的多按键输入(比如按了3个甚至4个方向键),试了几个方法效果都不好,花了不少时间。最后还是决定先用数组缓存玩家的按键,然后再响应。

先介绍下逻辑。

判断方向的基本原则:每当用户按下一个方向键,就把它的keyCode存进数组(数组里不可以有重复);每当一个方向键弹起,则把keyCode从数组里清除。若数组里只有一个键,那就是轴方向运动;两个键,两种情况:如果是复合键,就是斜方向运动;如果是一个A一个D这样一组相反键,则只响应先按的那个,物体只做轴方向运动。三个或四个键只响应数组里最先按的那一组复合键,做斜方向运动。

使用数组的好处在于可以处理复杂的多按键情况(无论是玩家有意乱按还是无意多按的),大大提高手感。例如这样一组输入:先后按下A、W、D再释放A,之后按下S并释放W、D。玩家最可能的意图是,先左上走,然后改为右上,最后改为下。这样的按键手感方便但是就造成一般的if...else判断方法很难响应。因为Flash里始终只不断给出最后一个键按下的消息,新的按键消息会不断把以前的按键消息“冲”掉。而且同时按3个或4个键在if...else里判断很麻烦,即使建立了类似AisDown这样的变量来追踪以前的按键。而使用有序且不重复的数组则可以解决这些问题。

逻辑完成了,就开始动手了。

这里以ASDW为例。ASDW的keyCode分别为65、83、68、87。比较巧的是,代表x轴的keyCode都是6x,代表y轴的都是8x,这个在后面的判断有用。复合按键代表的斜方向可以由两键keyCode相加得到。由此代表8个方向的数值如下图:



画一个在8个方向都有若干帧运动动画的MC,将每个方向的第一帧设置标签名“D方向数”(如向右下方运动的帧标签为“D151”),再在每个方向的最后一帧写上gotoAndPlay(“D方向数”),好让在该方向的运动动画连续播放。如下图:



画完之后把这个MC链接好,让AS可以使用。我给它导出的类名为Dir。这样动画的准备工作就做好了。开个AS文件定义Dir。为它加两个成员dirx和diry,再给它加一个ENTER_FRAME的侦听函数,让Dir在每一帧进入的时候在x和y轴方向都分别以dirx和diry递增。

新建一个类来专门负责侦听方向键。我这个类目前叫dirSemiFinal2,有四个成员:man、dirArr、step和cur。man是Dir类的一个实例,是舞台上走的小人(目前是箭头);dirArr是存放按键的数组;step和cur是步长和小人的当前运动方向。

函数onDirEvent负责侦听ASDW四个键。若是有键按下了,先检查数组里有没有存,存过了就什么都不做,直接返回;没有就存进去。有键弹起了,就从数组清除。数组若是被存取了,则调用setDir函数来分析存取后的数组,判断是否需要更改小人的运动方向。

原则很简单:只响应数组里最先按的那一个键或那一组复合键。这样是不是只需要判断数组里的第一个键或找出第一组复合键的方向,并让小人在该方向运动就行了呢?差不多是的,只是还有一个小麻烦。

要更改小人的运动状态有两个工作要做:一是改动它的dirx和diry,让它真正动起来,这个没问题。二是调用对应的gotoAndPlay(“D方向数”),让小人播放在该方向上走的动画。这样问题就来了:如果存取后的数组表示的运动方向和之前一样(例如按了A再按D,或按了AWD释放D),函数就不应该再调用gotoAndPlay()了,否则会造成小人的行走动画还没放完就又从头开始放了。所以实际写代码的时候除了找出当前小人应有的运动方向,还要再验证一下小人是不是已经在这个方向上运动了,如果是的话,直接返回就行了。

另外还有一个地方要注意:小人停止运动后的指向也需要支持8方向。这需要用到Timer类。当玩家释放第二按键之后开始计时,人物先暂时维持在斜方向运动。若在一定时间内将第一按键也释放了,则视为两键同时释放,人物停留在斜方向。若时间到达之后第一按键没有释放,则视为玩家改斜向为直向运动,人物开始轴向运动。目前暂定这个延迟时间为50ms。短了手感不好;长了斜转直反应慢,画面流畅性和手感亦大降。

详细的setDir函数代码比较复杂比较长,这里就不螯述了,有需要的朋友可以读读,注释都写得很明白了。^-^