qq229449388 发表于 2017-11-16 01:34:53

羔羊引擎之键控对象(想了解格斗游戏业务快进来)

本帖最后由 qq229449388 于 2017-11-28 23:12 编辑

这节教程讲的内容使用的羔羊引擎api是刚更新的1.15版本,请大家下载最新版本
讲到键控,什么是键控,我最不喜欢装逼了,只是不想标题太长,就是键盘控制一个对象。
这一节要说说键盘跟游戏交互的那些事,大家都知道as3可以侦听键盘事件。大家请看下面的demo,用键盘的WSAD控制上下左右方向,用T进行攻击

http://zsh.gyarea.com/GYLiteLesson/swfs/lesson9/GYLiteAPI.swf
有关系的几个api分别是,KeyBoard,KeyBoardEvent。老司机都知道,侦听键盘,一定要用舞台来统一侦听,为了避免侦听错乱,抢夺键盘,失去焦点的情况。
而在羔羊引擎里面,提供了封装过的键盘管理类GYKeyBoard,是一个单例,如果要使用键盘控制,请给对象实现IKeyBoardObject接口,我看看这个接口的3个方法
function keyFocus():Boolean;
                function kDown(keyCode:uint):void;
                function kUp(keyCode:uint):void;

keyFocus,需要返回一个Boolean类型,表示此对象侦听的时候,是不是独占键盘
kDown,看名字就知道,当键按下的时候,就会自动调用此方法,参数keyCode则是KeyBoard里面的常量
kUp,就是抬起的时候自动调用的

那么是不是实现接口就相当于侦听了,当然不是,实现了此接口只表示这个对象具有侦听键盘的功能,它仍然需要进行侦听,才会有键盘操控的功能,使用GYKeyBoard.getInstance()得到这个类的单例,用addKeyListener,移除用removeKeyListener,如下
GYKeyboard.getInstance().addKeyListener(实现了IKeyBoardObject的对象);GYKeyBoard里面提供了ctrl,alt,shift等当前是否按下,当然使用isKeyDown(键码),可以得这个键当前是否按下,返回的是按下的时间戳,如果当前没按下,则返回-1。最后一个侦听的对象,优先判断进行键盘判断,如果此对象独占键盘,则后面的对象不能响应键盘的操作。

说到这里,羔羊引擎的键盘类是不是很简单,但是这一节也太简单了,所以再说说用键盘控制的游戏人物的业务。

常用键盘的游戏,就要数格斗游戏了,我们说说横版格斗游戏,键盘操控人物以及人物动作切换到一些游戏业务。如果你还没看过第六节的序列图教程,就请先去学习一下第六节的序列图教程,因为下面我将用序列图做格斗游戏的人物动作切换。

在制作前期,先准备好资源,我们现在要制作一个游戏人物,一般是要先定制这个人物有几个动作,我们先简单地定制3个动作,0 站立 1 奔跑 2 攻击。在一些大型的游戏里面还会有各种设计的动作,例如飞行,前冲,跳跃,技能1,技能2等。
美术资源我们为3个动作准备了以下序列图
站立

奔跑

攻击

除此之外,我们需要为这些动作,定制对应的配置,什么是配置?配置就是对于这个动作的一些规格描述,格式由具体动作的设计来定,例如我简单的定制这个动作的配置有offsetX,offsetY,isReserveEnd。
offsetX:这动作图片相对于原点X的偏移量
offsetY:这动作图片相对于原点Y的偏移量
isReserveEnd:是否播放到尽头之后,反向播放,这个属性在第六节讲解GYSeqImage类时说过,就是对应的功能,这样我们就有以下Object类型的配置,当然这个动作的序列图也可以作为属性,定义为bmps,这就是一个动作的配置,如下。
动作:{isReserveEnd:true,offsetX:-72,offsetY:-148,bmps:null}
因为刚刚上面说过有3个动作,所以这时,配置得是一个数组了
[动作1,动作2,动作3]
动作1对应就是Object配置了,如果还有其他设计需求,我们得给这个人物加配置属性,所以我们得先让这个数组定义为一个属性stsArr,如果按照自己的需求,就可以再增加关于人物的其他属性,如下
{stsArr:[动作1,动作2,动作3],其他属性:xxx}
总而言之,配置格式按自己的需求,只要能取得的对应动作的配置就可以了
下面我们需要创建一个人物类,因为要使用GYSeqImage播放序列图,我们直接继承GYSeqImage,重写其中一两个方法

定义Role,首先我们需要想好需要的属性,经过思考,我需要以下属性
private var _cfg:Object;//角色配置
                private var _sts:int;//当前状态
                private var _stsLock:Boolean;//当前状态是否锁定
                private var _nowStsObj:Object;//当前状态的配置
                private var _direct:int;//当前行走方向
                private var _matrixDirect:int;//当前左右方向,因为横版反向图片要反转
                private var _matrixChange:Boolean;//是否转向
                private var _moveSpdX:int,_moveSpdY:int;//位移分速度
                private var _moveSpd:int;//位移速度
                private var _operSts:int;//操作的状态
                private var _offsetX:int;//偏移x
                private var _offsetY:int;//偏移y
                private var _frameW:int;//帧宽
                private var _frameH:int;//帧高

另外切换状态的时候,我们需要设置配置
纯文本查看 复制代码
public function setSts(sts:int):void
                {
                        if(_sts == sts)return;
                        _sts = sts;
                        _nowStsObj = _cfg.stsArr;
                        reserveEnd = _nowStsObj.isReserveEnd;
                        source = _nowStsObj.bmps;
                        _offsetX = _nowStsObj.offsetX;
                        _offsetY = _nowStsObj.offsetY;
                        _frameW = _nowStsObj.bmps.realWidth;
                        _frameH = _nowStsObj.bmps.realHeight;
                        var w:int=70;
                        var h:int=w*0.3;
                        graphics.clear();
                        graphics.beginFill(0,0.5);
                        graphics.drawEllipse(-w>>1,-h>>1,w,h);
                        graphics.endFill();
                        resetMatrix();
                        archorY = -_offsetY;
                        if(_sts != 1)
                              _direct = -1;
                        
                        stsLock(_sts == ATTACK);
                }以上代码,具体就不一句一句说了,大概说下功能
1、配置保存到变量
2、绘制影子,一般使用位图效率比较好,我偷懒一下,这里得说明一下游戏业务,格斗人物的影子,这不只有装饰的作用,这有定位的作用,影子一般在脚下,脚下一般是精灵的原点,所以影子是最好的对坐标的标志,而做动作编辑器,就很需要这个标志了。
3、stsLock方法,状态锁定,意思为是否状态锁定不能切换,在格斗游戏里面,有很多时候,当前状态不能马上被切换,所以定制了一个stsLock方法,来统一处理
private function stsLock(val:Boolean):void
                {
                        if(_stsLock == val)return;
                        _stsLock = val;
                        kUp(999);
                }

kUp,键抬起方法,待会讲解键盘控制人物的逻辑时再说,先跳过

Role类的其他几个方法,都有注释,实际上主角的逻辑,跟需求,以及自己思考的流程很有关系,不是千篇一律,但是有一个问题必须要注意,就是不能实时更改显示状态,必须放置下一帧,因为当一个人物被攻击的时候,这一帧的遍历检测还没结束,有可能被多个人攻击,如果被攻击就里面切换状态,则会影响其他人的攻击。所以,在当前帧只能计算状态、伤害等,真正切换状态放置在下一帧。

下面讲解一下键盘控制人物,基本逻辑都一样,代码如下
public function keyFocus():Boolean
                {
                        return true;
                }
                public function kDown(keyCode:uint):void
                {
                        if(_stsLock)return;
                        if(_keyBoard.isKeyDown(Keyboard.A))
                        {
                              _operSts = ATTACK;
                              return;
                        }
                        if(_keyBoard.isKeyDown(Keyboard.UP))
                        {
                              if(_keyBoard.isKeyDown(Keyboard.RIGHT))
                                        setDirect(2);
                              else if(_keyBoard.isKeyDown(Keyboard.LEFT))
                                        setDirect(8);
                              else
                                        setDirect(1);
                        }
                        else if(_keyBoard.isKeyDown(Keyboard.RIGHT))
                        {
                              if(_keyBoard.isKeyDown(Keyboard.DOWN))
                                        setDirect(4);
                              else
                                        setDirect(3);
                        }
                        else if(_keyBoard.isKeyDown(Keyboard.DOWN))
                        {
                              if(_keyBoard.isKeyDown(Keyboard.LEFT))
                                        setDirect(6);
                              else
                                        setDirect(5);
                        }
                        else if(_keyBoard.isKeyDown(Keyboard.LEFT))
                        {
                              setDirect(7);
                        }
                }
                public function kUp(keyCode:uint):void
                {
                        if(_stsLock)
                              return;
                        var k:GYKeyboard = GYKeyboard.getInstance();
                        if(k.isKeyDown(Keyboard.A) || k.isKeyDown(Keyboard.UP) || k.isKeyDown(Keyboard.DOWN) || k.isKeyDown(Keyboard.LEFT) || k.isKeyDown(Keyboard.RIGHT))
                        {
                              kDown(999);
                              return;
                        }
                        _operSts = STAND;
                }

刚刚已经讲解过IGYKeyBoardObject接口了
以上3个都是接口方法
人物的键盘肯定是独占的,所以keyFocus返回true
kDown则是判断当前的按键情况,我设计的方向是8个,从1开始顺时针,上,右上,右,右下,下,左下,左,左上
setDirect方法则是切换方向,因为斜线速度和横向速度纵向速度不一样。还有图片翻转也会在此根据方向判断
private function setDirect(dir:int):void
                {
                        if(_stsLock)return;
                        if(_direct == dir)return;
                        _direct = dir;
                        _operSts = RUN;
                        var m:int;
                        if(dir==0)
                        {
                              _operSts=1;
                              _moveSpdY=0;
                              _moveSpdX=0;
                              return;
                        }
                        if(dir==1)
                        {
                              _moveSpdY=-_moveSpd;
                              _moveSpdX=0;
                        }
                        else if(dir==2)
                        {
                              _moveSpdX=Math.SQRT1_2*_moveSpd;
                              _moveSpdY=-_moveSpdX;
                              m = 1;
                        }
                        else if(dir==3)
                        {
                              _moveSpdX=_moveSpd;
                              _moveSpdY=0;
                              m = 1;
                        }
                        else if(dir==4)
                        {
                              _moveSpdY=_moveSpdX=Math.SQRT1_2*_moveSpd;
                              m = 1;
                        }
                        else if(dir==5)
                        {
                              _moveSpdY=_moveSpd;
                              _moveSpdX=0;
                              m = -1;
                        }
                        else if(dir==6)
                        {
                              _moveSpdY=Math.SQRT1_2*_moveSpd;
                              _moveSpdX=-_moveSpdY;
                              m = -1;
                        }
                        else if(dir==7)
                        {
                              _moveSpdX=-_moveSpd;
                              _moveSpdY=0;               
                              m = -1;
                        }
                        else
                        {
                              _moveSpdX=_moveSpdY=-Math.SQRT1_2*_moveSpd;
                        }
                        if(m == 0 || _matrixDirect == m)return;
                        _matrixChange = true;
                        _matrixDirect = m;
                }

keyUp方法则是按键抬起,当按键抬起的时候,我们要重新判断当前按键状态,来确定要切换的人物状态,所以keyUp内又再一次判断按键情况,如果有键按下,则再次调用keyDown

下面看看人物逻辑核心
override protected function loop(t:Number):void
                {
                        super.loop(t);
                        stsCheck();
                        if(_sts == 1)//执行逻辑,当前只有奔跑有逻辑
                              running();
                }这是每帧执行的逻辑,super.loop(t)则是序列图播放的父类函数,下面增加了两个逻辑
stsCheck则是每帧去判断状态情况
running就是逻辑方法,因为目前只有奔跑有特殊的逻辑,其他状态都是播放序列帧,如果丰富游戏内容则需要根据sts状态来调用不同的逻辑,例如
if(_sts == 1)
……
else if(_sts == 2)
……
else if(_sts == 3)
……
也可以使用Dictionary进行键值对应,直接一个状态对应一个方法
stsDict();

在此,格斗游戏的人物操控已经讲解完毕,总结一下制作思路
1、设计配置
2、准备资源
3、设计人物逻辑代码,主要有3点
(1)状态切换,实现具体状态的判断,例如具体的判断,例如跳跃、死亡、受击不能切换到其他状态,诸如此类的状态判断
(2)键盘侦听,实现按键的逻辑
(3)loop函数内,设计核心逻辑,完成各个状态的逻辑

下次有机会将会给大家说一下,场景逻辑业务
**** Hidden Message *****





diazynez 发表于 2018-8-22 18:35:23

emm链接到的地址都是失效的天地会

yuandym 发表于 2018-8-26 17:56:48

赞#:),,,,,,,,,,,,,,,,
页: [1]
查看完整版本: 羔羊引擎之键控对象(想了解格斗游戏业务快进来)

感谢所有支持论坛的朋友:下面展示最新的5位赞助和充值的朋友……更多赞助和充值朋友的信息,请查看:永远的感谢名单

SGlW(66139)、 anghuo(841)、 whdsyes(255)、 longxia(60904)、 囫囵吞澡(58054)

下面展示总排行榜的前3名(T1-T3)和今年排行榜的前3名的朋友(C1-C3)……更多信息,请查看:总排行榜今年排行榜

T1. fhqu1462(969)、 T2. lwlpluto(14232)、 T3. 1367926921(962)  |  C1. anghuo(147)、 C2. fdisker(27945)、 C3. 囫囵吞澡(58054)