在Cocos2d中暂停/恢复Sprite上的动作/动画

时间:2017-09-27 11:42:49

标签: c++ animation cocos2d-x sprite

使用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);处收到错误说:

  

访问冲突读取位置0xDDDDDDE5

我认为这是由this->stopActionByTag(0)删除操作指针引起的。我试图克隆动作以避免这种情况,但没有成功。

2 个答案:

答案 0 :(得分:1)

我知道这有点晚了,你可能已经解决了这个问题,但这里有......

您的问题是您不能多次使用Action(idleAction)的一个实例。因此,一旦您运行并删除它,它就会被释放并且无法使用。所以,你现在有两个选择,

  • 每次运行操作之前都要创建一个新的idleAction操作。
  • 或者,保留一个idleAction并且永远不会运行它。相反,创建此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);
    }
    

答案 1 :(得分:0)

当你停止行动时,它会从记忆中回收。为了再次播放动作,您必须重新创建它。所以你可以创建一个创建函数,它返回你的动画。缺点是你每次都要重新制作动画,它也会从头开始播放(技术上你可以回放它)。

但是我开发了一种更简单的技术来暂停/恢复动画:

让我们说你有行动:

action = MoveBy::create(5.0f, Vec2(50, 100));

现在,您可以将此操作嵌入到Speed操作中,如下所示:

action = Speed::create(MoveBy::create(5.0f, Vec2(50, 100)), 1.0f);

1.0f - 是速度,所以它的正常动作率。现在暂停只是打电话:

action->setSpeed(0.0f);

并恢复:

action->setSpeed(1.0f);

如果因某种原因需要,您也可以使用不同的速度;)