使用cocos2d-x和c ,我正在尝试播放和暂停精灵的动画。
我正在使用Cocos2dx的3.15.1版。
我有一个名为PlayerSprite
的类,它是从cocos2d::Sprite
类中脱离的。在PlayerSprite
初始化中,我已经使用以下代码设置了动画:
SpriteBatchNode* playerSpriteBatch = SpriteBatchNode::create("player.png");
SpriteFrameCache* spriteFrameCache = SpriteFrameCache::getInstance();
spriteFrameCache->addSpriteFramesWithFile("player.plist");
Vector<SpriteFrame*> animFrames(2);
char str[18] = { 0 };
for (int i = 1; i < 3; i++) {
sprintf(str, "player_idle_%d.png", i);
SpriteFrame* frame = spriteFrameCache->getSpriteFrameByName(str);
animFrames.pushBack(frame);
}
Animation* idleAnim = Animation::createWithSpriteFrames(animFrames, 0.8f);
self->idleAction = self->runAction(RepeatForever::create(Animate::create(idleAnim)));
self->idleAction->setTag(0);
当我运行代码时,它可以正常工作,并且动画循环正确。
在我的void update()
方法中,我试图暂停/播放基于玩家正在移动或闲置的天气动作/动画。
我使用以下代码执行此操作:
const bool isIdleActionRunning = this->getNumberOfRunningActionsByTag(0) > 0 ? true : false;
const bool isMoving = !vel.isZero();
if (!isMoving && !isIdleActionRunning) {
// Player is idle AND animation is not running
// Run animation
this->runAction(idleAction);
} else if (isMoving && isIdleActionRunning) {
// Player is moving but animation is running
// Pause animation
this->stopActionByTag(0);
}
当我现在运行此代码时,我的角色就会掉下来,一旦他击中了gound,我就会在this->runAction(idleAction);
上遇到一个错误:
访问违规阅读位置0xddddde5
我相信这是由于this->stopActionByTag(0)
删除动作指针而引起的。我试图克隆行动以避免这种情况,但没有成功。
我知道这有点晚了,您可能已经解决了这个问题,但是...
您的问题是您不能多次使用一个操作实例(iDleaction)。因此,一旦您运行并将其删除,它将被释放并且无法使用。因此,您现在有2个选项,
- 在运行动作之前,每次都会创建一个新的iDleaction操作。
-
或,保留了一个闲置,永远不要运行它。相反,创建此闲置的克隆,并每次运行一个新的克隆。即。
idleAction->retain(); const bool isIdleActionRunning = this->getNumberOfRunningActionsByTag(0) > 0 ? true : false; const bool isMoving = !vel.isZero(); if (!isMoving && !isIdleActionRunning) { // Player is idle AND animation is not running // Run animation Action idleActionClone = idleAction->clone(); this->runAction(idleActionClone); } else if (isMoving && isIdleActionRunning) { // Player is moving but animation is running // Pause animation this->stopActionByTag(0); }
解决方案:调用retain()
以保持您的动作。
这是COCOS2D-X的内存管理问题。
在RepeatForever
类的create()
函数中(从Ref
派生),参考计数设置为1,并且在返回对象之前有一系列代码ret->autorelease()
,这意味着该对象将在此帧的末端自动释放。
您称为runAction()
函数与创建的帧相同,操作由ActionManager
保留,其参考计数设置为2,然后在框架末端1(Autorelease)。
停止它后,它由ActionManager
发布,参考计数设置为0,并且已删除。此后,您使用了操作,这将是一种违规方法。
*编辑:当删除PlayerSprite
或泄漏时,不要忘记手动释放动作。
停止操作时,它将从内存中回收。为了再次发挥作用,您必须重新创建它。因此,您可以制作创建者功能,从而返回动画。不利的一面是您每次都会重新创建动画,并且它也会从一开始播放(从技术上讲,您可以倒带)。
,但我已经开发了一种更简单的技术来暂停/简历动画:
假设您有一个动作:
action = MoveBy::create(5.0f, Vec2(50, 100));
现在,您可以将此动作嵌入这样的速度动作:
action = Speed::create(MoveBy::create(5.0f, Vec2(50, 100)), 1.0f);
1.0f-是速度,因此是正常的动作率。现在暂停致电:
action->setSpeed(0.0f);
和恢复:
action->setSpeed(1.0f);
,如果您出于某种原因或其他原因需要使用不同的速度;)