接上一篇
在这里我们将我们的主角导入,并通过虚拟摇杆控制他
在游戏的设计中,我们尽量做到逻辑代码和视觉表现的代码分离,否则设计到后期整个代码一团糟,无论是维护还是开发新内容都是困难重重.
(我就被某教程的有限状态机(FSM)和动画载入混到一起,结果坑掉了自己的代码)
Role是基础的角色类,包括了移动,攻击,受到攻击,死亡等等的动画及判断动画.
还加入了BodyBox和HitBox,这两个具体作用后续再说
源码中你可以看到
/* 以下是攻击序列动画,需要用creatAttackAnimation创建,会在动作执行中间添加攻击判定和受伤飘字等*/
CC_SYNTHESIZE_RETAIN(Action*, m_pnomalattacka, NomalAttackA); //角色普通攻击A时动画帧序列
CC_SYNTHESIZE_RETAIN(Action*, m_pnomalattackb, NomalAttackB); //角色普通攻击B时动画帧序列
CC_SYNTHESIZE_RETAIN(Action*, m_pnomalattackc, NomalAttackC); //角色普通攻击C时动画帧序列
CC_SYNTHESIZE_RETAIN(Action*, m_pnomalattackd, NomalAttackD); //角色普通攻击D时动画帧序列
CC_SYNTHESIZE_RETAIN(Action*, m_pchange, Change); //角色蓄力时的动画序列
CC_SYNTHESIZE_RETAIN(Action*, m_pchangeattack, ChangeAttack); //角色蓄力攻击时的动画序列
等各种定义
具体的执行代码基本由这个组成
void Role::runIdleAction()
{
if(changeState(ACTION_STATE_IDLE))
{
this->runAction(m_pidleaction);
}
}
由此可以看到,主要功能就是播放一个动作
这个是从缓存中载入动画,为此我们需要在GameLayer.cpp的init中加入
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("Boy.plist","Boy.pvr.ccz");
优先载入缓存,之后只需要调用就好了,我在这里写了好几个载入方式,这个是最基本的从0开始,只有3个参数,用于载入普通移动动画还有跳跃之类的.特点是中间不需要插入回调判断(受到敌人攻击或自己攻击判定回调),由于是从0开始的,一次可以将所有的动画读取完.回调函数没法插入,只能在后面加入.
稍微改变下,再多输入一个参数(如下),使得下方的i从framCountBegan开始,我们可以在连续squence中插入回调函数,更加精准进行攻击判定
Animation* Role::createAttackAnimation(const char* formatStr, int frameCountBegan, int frameCountEnd,int fps)
{
Vector<SpriteFrame*> pFrames;
for(int i = frameCountBegan; i < frameCountEnd; i++ )
{
const char* imgName = String::createWithFormat(formatStr, i)->getCString();
SpriteFrame *pFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName(imgName);
pFrames.insert(i-frameCountBegan,pFrame);
}
return Animation::createWithSpriteFrames(pFrames, 1.0f / fps);
}
当然我们的角色可以改变状态必须是不和之前状态相同并且没有死.
如果死了那么就不要动了
bool Role::changeState(ActionState actionState)
{
if(currActionState == ACTION_STATE_DEAD || currActionState == actionState)
{
return false;
}
this->stopAllActions();
this->currActionState = actionState;
return true;
}
我们应该给角色一个可以受到攻击的范围用于受击判定.最简单的方法是用一个BoundingBox,之后我们只要判断攻击框和受攻击的框有没有相交就好了.
BoundingBox Role::createBoundingBox(Vec2 origin, Size size)
{
BoundingBox boundingBox;
boundingBox.original.origin= origin;
boundingBox.original.size= size;
boundingBox.actual.origin = this->getPosition() + boundingBox.original.origin;
boundingBox.actual.size= size;
return bound