Flash游戏开发之按键控制(复合键,八方向键)

本文详细介绍了Flash游戏开发中按键处理的重要性及实现方法,特别是针对复合键处理的技巧。通过实例解析了Key类的事件与方法,展示了如何精确地控制角色的八方向移动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Flash游戏开发中,按键处理很重要,按键处理的效果,直接影响用户的游戏体验。Flash按键处理说简单就简单,说麻烦也麻烦,尤其对于复合键的处理。

我举个例子:有这样一个游戏角色移动的游戏,需要角色具有八方向移动,如果用户先按下←键,游戏角色向左移动,这时候用户又按下↓键(←键不抬起),这时候游戏角色要向左下角移动,接下来,如果用户抬起↓键(←键不抬起),游戏角色转为继续左行,如果用户抬起←键(↓键不抬起),游戏角色转为继续下行。同样的,向上,向右按键也是类似的需求,而且这时候,如果用户按下了其它的按键,或按下多于三个光标键时,最后按下的键要忽略。

对于这种涉及复合键的处理,大家可以写一个试试是否容易,或者说是否足够完美。

这就是今天想说的内容,也是我在Flash 游戏开发中对按键控制的一点小经验,希望能对从事Flash游戏开发的同行们有所帮助。

一、先熟悉一下与制作按键相关的事件和语法
1).Key

A).Key类的事件

i) onKeyDown = function() {}

当按下某按键时获得通知。同时只能由一个按键触发,如果有多个按键按下,以先后次序触发。若要使用 onKeyDown,必须创建一个侦听器对象。然后可以为 onKeyDown 定义一个函数,并使用 addListener() 向 Key 对象注册该侦听器,如下面的示例所示:


  
var  keyListener:Object  =   new  Object();
keyListener.onKeyDown 
=   function () {
    trace(
" DOWN -> Code:  " + Key.getCode() + " \tACSII:  " + Key.getAscii() + " \tKey:  " + chr(Key.getAscii()));
};
keyListener.onKeyUp 
=   function () {
    trace(
" UP -> Code:  " + Key.getCode() + " \tACSII:  " + Key.getAscii() + " \tKey:  " + chr(Key.getAscii()));
};
Key.addListener(keyListener);

ii) .onKeyUp = function() {}

当释放某按键时获得通知。同时只能由一个按键触发,如果有多个按键按下后再抬起,以最后按下的键触发。若要使用 onKeyUp,必须创建一个侦听器对象。然后可以为 onKeyUp 定义一个函数,并使用 addListener() 向 Key 对象注册该侦听器,示例同上。

这二个按键事件,在四方向游戏中,配合Key. isDown,完全够用了。今天主要重点是在八方向键的处理上,下边继续说。

B).Key类的方法
i) Key.isDown 方法
如果按下 keycode 中指定的键,则返回 true;否则返回 false
如:
car_mc.onEnterFrame  =   function () {
 
if  (Key.isDown(Key.RIGHT)) {
 
this ._x  +=   10 ;
 } 
else   if  (Key.isDown(Key.LEFT)) {
 
this ._x  -=   10 ;
 }
};

常见 keycode(是Key类的静态属性):

修饰符

属性

说明

static

BACKSPACE:Number

Backspace 键的键控代码值 (8)。

static

CAPSLOCK:Number

Caps Lock 键的键控代码值 (20)。

static

CONTROL:Number

Ctrl 键的键控代码值 (17)。

static

DELETEKEY:Number

Delete 键的键控代码值 (46)。

static

DOWN:Number

下箭头键的键控代码值 (40)。

static

END:Number

End 键的键控代码值 (35)。

static

ENTER:Number

Enter 键的键控代码值 (13)。

static

ESCAPE:Number

Esc 键的键控代码值 (27)。

static

HOME:Number

Home 键的键控代码值 (36)。

static

INSERT:Number

Insert 键的键控代码值 (45)。

static

LEFT:Number

左箭头键的键控代码值 (37)。

static

_listeners:Array [只读]

一个引用列表,引用对象是向 Key 对象注册的所有侦听器对象。

static

PGDN:Number

Page Down 键的键控代码值 (34)。

static

PGUP:Number

Page Up 键的键控代码值 (33)。

static

RIGHT:Number

右箭头键的键控代码值 (39)。

static

SHIFT:Number

Shift 键的键控代码值 (16)。

static

SPACE:Number

空格键的键控代码值 (32)。

static

TAB:Number

Tab 键的键控代码值 (9)。

static

UP:Number

上箭头键的键控代码值 (38)。


其它的字母键并没有定义成静态属性,需要使用数字的键控代码值来使用,有人写了一个所有按键的Key类,我复制在下边,可做参考:

ContractedBlock.gif ExpandedBlockStart.gif 自定义Key类
public class Key {
        public static const VK_1:uint 
= 49;
        public static const VK_2:uint 
= 50;
        public static const VK_3:uint 
= 51;
        public static const VK_4:uint 
= 52;
        public static const VK_5:uint 
= 53;
        public static const VK_6:uint 
= 54;
        public static const VK_7:uint 
= 55;
        public static const VK_8:uint 
= 56;
        public static const VK_9:uint 
= 57;
        public static const VK_0:uint 
= 48;

        public static const VK_A:uint 
= 65;
        public static const VK_B:uint 
= 66;
        public static const VK_C:uint 
= 67;
        public static const VK_D:uint 
= 68;
        public static const VK_E:uint 
= 69;
        public static const VK_F:uint 
= 70;
        public static const VK_G:uint 
= 71;
        public static const VK_H:uint 
= 72;
        public static const VK_I:uint 
= 73;
        public static const VK_J:uint 
= 74;
        public static const VK_K:uint 
= 75;
        public static const VK_L:uint 
= 76;
        public static const VK_M:uint 
= 77;
        public static const VK_N:uint 
= 78;
        public static const VK_O:uint 
= 79;
        public static const VK_P:uint 
= 80;
        public static const VK_Q:uint 
= 81;
        public static const VK_R:uint 
= 82;
        public static const VK_S:uint 
= 83;
        public static const VK_T:uint 
= 84;
        public static const VK_U:uint 
= 85;
        public static const VK_V:uint 
= 86;
        public static const VK_W:uint 
= 87;
        public static const VK_X:uint 
= 88;
        public static const VK_Y:uint 
= 89;
        public static const VK_Z:uint 
= 90;
                
        public static const VK_F1:uint 
= 112;
        public static const VK_F2:uint 
= 113;
        public static const VK_F3:uint 
= 114;
        public static const VK_F4:uint 
= 115;
        public static const VK_F5:uint 
= 116;
        public static const VK_F6:uint 
= 117;
        public static const VK_F7:uint 
= 118;
        public static const VK_F8:uint 
= 119;
        public static const VK_F9:uint 
= 120;
        public static const VK_F10:uint 
= 121;
        public static const VK_F11:uint 
= 122;
        public static const VK_F12:uint 
= 123;
        public static const VK_F13:uint 
= 124;
        public static const VK_F14:uint 
= 125;
        public static const VK_F15:uint 
= 126;
        
        
        
/* numpad */
        public static const VK_NUMPAD_0:uint 
= 96;
        public static const VK_NUMPAD_1:uint 
= 97;
        public static const VK_NUMPAD_2:uint 
= 98;
        public static const VK_NUMPAD_3:uint 
= 99;
        public static const VK_NUMPAD_4:uint 
= 100;
        public static const VK_NUMPAD_5:uint 
= 101;
        public static const VK_NUMPAD_6:uint 
= 102;
        public static const VK_NUMPAD_7:uint 
= 103;
        public static const VK_NUMPAD_8:uint 
= 104;
        public static const VK_NUMPAD_9:uint 
= 105;
        public static const VK_NUMPAD_MULTIPLY:uint 
= 106;//*
        public static const VK_NUMPAD_ADD:uint = 107;//+
        public static const VK_NUMPAD_ENTER:uint = 108;//enter
        public static const VK_NUMPAD_SUBTRACT:uint = 109;//-
        public static const VK_NUMPAD_DECIMAL:uint = 110;//.
        public static const VK_NUMPAD_DIVIDE:uint = 111;///
        
        public static const VK_BACKSPACE:uint 
= 8;//backspace
        public static const VK_TAB:uint = 9;//tab
        public static const VK_ENTER:uint = 13;//main ENTER
        public static const VK_SHIFT:uint = 16;//shift
        public static const VK_CONTROL:uint = 17;//ctrl
        public static const VK_ESCAPE:uint = 27;//esc
        public static const VK_SPACE:uint = 32;//space
        
        public static const VK_CAPS_LOCK:uint 
= 20;//caps lock
        public static const VK_NUM_LOCK:uint = 144;//num lock
        public static const VK_SCROLL_LOCK:uint = 145;//scroll lock
        
        public static const VK_PAUSE:uint 
= 19;//pause / break
        public static const VK_PAGE_UP:uint = 33;//page up
        public static const VK_PAGE_DOWN:uint = 34;//page down
        public static const VK_END:uint = 35;//end
        public static const VK_HOME:uint = 36;//home
        public static const VK_INSERT:uint = 45;//insert
        public static const VK_DELETE:uint = 46;//delete
        
        public static const VK_LEFT:uint 
= 37;//left arrow
        public static const VK_UP:uint = 38;//up arrow
        public static const VK_RIGHT:uint = 39;//right arrow
        public static const VK_DOWN:uint = 40;//down arrow
        
        public static const VK_WINDOWS:uint 
= 91;//windows
        public static const VK_MENU:uint = 93;//menu
}

ii) Key.getCode 方法
返回按下的 最后一个键的键控代码值,并且不会区分字母的大小字,即使用此方法时,任何一个按键,只有一个Code值。

2).MovieClip的事件

i) MovieClip.onKeyDown
当影片剪辑 具有输入焦点并且用户按下某个键时调用。

ii) MovieClip.onKeyUp
当释放按键时调用。仅当影片剪辑的输入焦点被启用和设置后, onKeyUp 事件处理函数才能起作用。即要求影片剪辑 具有输入焦点。

二、Flash中对按键捕获处理,拔开按键的迷雾

1).Flash中,如果你使用Key.onKeyDown 事件侦听器,则不管焦点在Flash内的那个对象上,按键均能被捕获,这里有一种情况,当先后按下多个键(二个以上的按键)时,onKeyDown事件是按先后次序触发的,而onKeyUp事件只能由最后按下的键触发。举例:
我先按下A键,再接着按下S键,同时A键不抬起,则这时候,onKeyDown先被A键触发一次,接着被S键触发一次,而这时候,不管你把那个键抬起, onKeyUp事件始终是由最后按下的那个键触发的。这点一定要注意,这时候A键的onKeyUp事件已经被后按的键“冲”掉了,就算抬起A键,onKeyUp也不会被触发。可以使用本文开头那段代码测试就知道了。

2).使用 Key.isDown,可以知道有那些键被按下,不管按键的先后(其实是有先后的,只是先后时间差别太小,isDown方法并判断不出先后次序,要判断次序,需要借助其它方法),只要按下,此方法就能检测出,如:

ContractedBlock.gif ExpandedBlockStart.gif
var keyListener:Object = new Object();
keyListener.onKeyDown 
= function() {
    trace(
"DOWN -> Code: "+Key.getCode()+"\tACSII: "+Key.getAscii()+"\tKey: "+chr(Key.getAscii()));
    
if (Key.isDown(65)) {
        trace(
"按下a键");
    }
    
if (Key.isDown(83)) {
        trace(
"按下s键");
    }
    
if (Key.isDown(68)) {
        trace(
"按下d键");
    }
    
if (Key.isDown(70)) {
        trace(
"按下f键");
    }
};
keyListener.onKeyUp 
= function() {
    trace(
"UP -> Code: "+Key.getCode()+"\tACSII: "+Key.getAscii()+"\tKey: "+chr(Key.getAscii()));
};
Key.addListener(keyListener);

当你先后同时按下a,s,d,f这四个键时,都会被检测到。
利用这点,我们就可以制作游戏中的复合键,比如八方向键,或快捷键,如Ctrl+F等。

3).如果同时按下了多个键,那么如何知道先后次序呢?
还记得 Key. getCode的用法说明吗?“返回按下的最后一个键的键控代码值”,同样的,此方法也不能获得按键的先后次序,但是它可以获得最后一个按键,使用它的这一特性,我们可以写出自己的检测类,用来当按下多键时,检测按键的次序。如:

ContractedBlock.gif ExpandedBlockStart.gif
var keyList:String = "按键次序:";
var keyListener:Object = new Object();
keyListener.onKeyDown 
= function() {
    trace(
"DOWN -> Code: "+Key.getCode()+"\tACSII: "+Key.getAscii()+"\tKey: "+chr(Key.getAscii()));
    
if (Key.isDown(65)) {
        trace(
"按下a键");
    }
    
if (Key.isDown(83)) {
        trace(
"按下s键");
    }
    
if (Key.isDown(68)) {
        trace(
"按下d键");
    }
    
if (Key.isDown(70)) {
        trace(
"按下f键");
    }

    //总是把最后的按键,添加在按键列表中,如果列表中已存在,就不添加,注意不可见按键得变换方法,如光标键
    
if (keyList.indexOf(chr(Key.getAscii()), 0)<0) {
        keyList 
+= chr(Key.getAscii());
    }
    trace(keyList);
};
keyListener.onKeyUp 
= function() {
    trace(
"UP -> Code: "+Key.getCode()+"\tACSII: "+Key.getAscii()+"\tKey: "+chr(Key.getAscii()));
};
Key.addListener(keyListener);

使用此段代码,你可以尝试着同时按下a,s,d,f键,可以看看按键次序。

4).其实Flash按键的难于处理,主要是在于复合键的处理上,在多复合键中,如果用户有意按下多键,如何抛弃或“不理睬”不想关注的按键呢?
比如光标键吧,我们想在按下左光标+上光标键时,人物向左上角斜方向移动,那如果这时候,用户又按下向下的光标键呢,或者又按了其它的字母键呢?这时候往往会出现我们不想要的结果。即最后按键会干扰已按下的组合键。处理这种情况,除了写较复杂的if判断之外,就可以使用上边说的检测按键次序,这样只有前两个按键有效,后边再按下的键就无效,从而达到控制的目的。

5).其实很多时候,我们是通过光标控制一个MovieClip的移动的,那么如果在此使用MovieClip的按键事件下处理按键,就要注意MovieClip是与焦点相关的,如果有多个对象,那就得处理焦点一定在要移动的对象上头,按键才有效,除此之外,它的按键事件使用原理同Key的按键事件原理,所以大多数时候,我们并不使用MovieClip的按键事件,而改用MovieClip.onEnterFrame来侦听按键。下边我给了一个示例,就是使用的这个方法。

三、八方向按键示例  新窗口打开>>



四、八方向按键源码下载

点此下载(6K)>>

转载于:https://www.cnblogs.com/yao/archive/2007/05/14/746332.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值