一。问题描述
今天在写游戏的时候,为了统一动画和攻击的时间,我取消了原先依靠时间来同步的想法(太烂了,总是不协调)。所以就上网搜了下,看看cocos2d-x中有没有提供这样的方法(汗。。。初学当中ing......)。很快就搜到了一篇文章,说是使用CCSprite中的displayFrame方法返回正在播放的动画帧,然后调用CCAnimate中的getFrames方法来获取正在播放动画的所有的CCSpriteFrame*帧,之后就可以通过指针比较来进行了。这个方法,文章的作者也发现了有点问题,所以在后面给出了改进的地方,displayFrame返回的实际上是新建的一个CCSpriteFrame,而不是原来的CCSpriteFrame*,说的抽象,看代码:
CCSpriteFrame* CCSprite::displayFrame(void)
{
return CCSpriteFrame::createWithTexture(m_pobTexture,
CC_RECT_POINTS_TO_PIXELS(m_obRect),
m_bRectRotated,
CC_POINT_POINTS_TO_PIXELS(m_obUnflippedOffsetPositionFromCenter),
CC_SIZE_POINTS_TO_PIXELS(m_obContentSize));
}
看出来了吧,直接是创建一个新的CCSpriteFrame对象,这么说两个对象完全不能够使用==来进行比较了。作者又想到使用CCSpriteFrame中的Texture的ID来进行比较,就算新建了一个精灵帧,用的还是自己原来的纹理m_pobTexture,看上面的代码就知道了。所以,应该能够实现,因为CCTexture里面有个getName()用来返回唯一的ID号,靠这个就应该能够进行正确的比较了,所以兴奋的去游戏中实现下。
结果,还是一样,不能同步,调试下发现,displayFrame返回的精灵帧中的纹理ID总是保持不变,这下悲催了,不知道怎么弄了。。。(不知道为什么纹理不变,难道播放动画的时候,不是将精灵的纹理替换掉,而是在原来的位置覆盖一下???不会这么烂吧??? 不明白。。。。)
二。解决问题
被逼无奈之下,我就看了下CCSprite的源码,无意之中,发现了下面的一个函数:
bool CCSprite::isFrameDisplayed(CCSpriteFrame *pFrame)
{
CCRect r = pFrame->getRect();
return (r.equals(m_obRect) &&
pFrame->getTexture()->getName() == m_pobTexture->getName() &&
pFrame->getOffset().equals(m_obUnflippedOffsetPositionFromCenter));
}
看上面的那个函数名,就知道是判断给定的精灵帧是否进行了播放。
而且这个的判断条件更加的多,不仅判断了纹理名字是否相同,还判断了矩形区域,偏移。
(:< 又不懂了,上面那个display返回的ID保持不变,这里使用纹理的ID来进行判断 ,不还是一样不能够解决吗???)
先不管这个,游戏要紧,直接拿进游戏中试一下,
oh,My god ,还真TMD的可以哎。完全同步了 ,没有一点滞留。
以下是这个解决方法的部分代码:
CCArray* spriteArray = m_pLocateSkillAction->getAnimation()->getFrames(); //其中的m_pLocateSkillAction是一个CCAnimate的对象指针
CCAnimationFrame*tempFrame = (CCAnimationFrame*)spriteArray->objectAtIndex(61) ; //这里要注意了,返回的是CCAnimationFrame的指针,不是CCSpriteFrame*
if(m_Sprite->isFrameDisplayed(tempFrame->getSpriteFrame())) //m_Sprite就是正在播放动画的那个精灵
{
........
}
三。遗留问题
上面的isFrameDisplayed中也使用到了纹理啊,而displayFrame也是用这个m_pobTexture属性的啊,为什么这里的可以,上面的displayFrame不可以,实在不明白。。。希望有高手解释下。。。(难道是所谓的动画播放搞的鬼???)