散仙
阅读权限 3
积分 1908
侠名
UID 42
主题
帖子
精华
好友
银子
金子
贡献
威望
推广
活跃
荣耀
注册时间 2017-11-7
最后登录 1970-1-1
在线时间 小时
个人主页
|
【游客模式】——注册会员,加入11RIA 闪客社区吧!一起见证Flash的再次辉煌……
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 qq229449388 于 2017-11-28 23:12 编辑
这节教程讲的内容使用的羔羊引擎api是刚更新的1.15版本,请大家下载最新版本
讲到键控,什么是键控,我最不喜欢装逼了,只是不想标题太长,就是键盘控制一个对象。
这一节要说说键盘跟游戏交互的那些事,大家都知道as3可以侦听键盘事件。大家请看下面的demo,用键盘的WSAD控制上下左右方向,用T进行攻击
有关系的几个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;//帧高
- 另外切换状态的时候,我们需要设置配置
- [Actionscript3] 纯文本查看 复制代码
- public function setSts(sts:int):void
- {
- if(_sts == sts)return;
- _sts = sts;
- _nowStsObj = _cfg.stsArr[sts];
- reserveEnd = _nowStsObj.isReserveEnd;
- source = _nowStsObj.bmps;
- _offsetX = _nowStsObj.offsetX;
- _offsetY = _nowStsObj.offsetY;
- _frameW = _nowStsObj.bmps[0].realWidth;
- _frameH = _nowStsObj.bmps[0].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[_sts]();
在此,格斗游戏的人物操控已经讲解完毕,总结一下制作思路
1、设计配置
2、准备资源
3、设计人物逻辑代码,主要有3点
(1)状态切换,实现具体状态的判断,例如具体的判断,例如跳跃、死亡、受击不能切换到其他状态,诸如此类的状态判断
(2)键盘侦听,实现按键的逻辑
(3)loop函数内,设计核心逻辑,完成各个状态的逻辑
下次有机会将会给大家说一下,场景逻辑业务
|
|