上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); }