精通Cocos2d-x游戏开发(基础卷)
上QQ阅读APP看书,第一时间看更新

3.16 关于update中写逻辑

我们喜欢在Update里写游戏逻辑,在每个对象的Update里做自己的事情,例如,在Update里根据当前的状态使用不同的规则来更新位置,现在是往上走还是往下走?速度大概多少?输入5运行一下,速度太慢了,输入50运行一下,速度又太快了,输入25的话,看起来速度正合适,在Win32上感觉良好。根据这种感觉,调整其他100种怪物的移动速度,最后导到其他设备上,你会发现,速度怎么不对?而且有的快有的慢,一切都乱了。

在Update里更新一些数值的时候,请乘以dt参数,这样就不会因为不同设备的帧频不同,而导致结果不同,另外也可以让显示对象的更新更加平滑。将调整好的值乘以设定的FPS(windows下默认是60),将这个值作为新的速度,然后在修改位置的地方,改成下面这样,dt的单位为秒。

void CGameObject::update(float dt)
{
    setPositionX(getPositionX() + m_MoveSpeed * dt);
}

不要把逻辑全部写在Update里,尽量让Update的逻辑清晰简单。例如,要做一个比较复杂的动作,播放一个攻击动画,当这个动画播放到第X帧的时候,对这个怪物造成伤害,如果这个怪物“挂掉”了,则切换回移动状态,并且播放移动的动画,假设它没“挂掉”,那么再攻击一次,将这个逻辑写在Update中,会比较复杂。

通过使用Action可以大大简化代码,更容易维护,也更稳定。在这里完全可以利用Cocos2d-x的Action来做这些简单的事情,如下面的代码:

void CGameObject::AttackByAnimate()
{
  //播放攻击动画,并在动画播放完成的时候调用onAttackAnimateFinish函数,该函数只判
  断目标是否还活着,如活着的就再调用一次AttackByAnimate
  CCFiniteTimeAction* seq = CCSequence::create(m_AttackAniAction,
      CCCallFunc::create(this, callfunc_selector(CGameObject::onAttackAn
       imateFinish)),
      NULL);
  //在m_AttackTick帧的时候调用onAttack对目标造成伤害
  CCFiniteTimeAction* seqattack = CCSequence::create(
      CCDelayTime::create(m_AttackTick*m_Duration),
      CCCallFuncO::create(this, callfuncO_selector(CGameObject::onAttack
       ), m_Target),
      NULL);
  //将这两个动画同步执行
  CCFiniteTimeAction* spawn = CCSpawn::create(seq, seqattack, NULL);
  spawn->setTag(GAME_CURACTION);
  runAction(spawn);
}