使用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)
删除操作指针引起的。我试图克隆动作以避免这种情况,但没有成功。
答案 0 :(得分:1)
我知道这有点晚了,你可能已经解决了这个问题,但这里有......
您的问题是您不能多次使用Action(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);
如果因某种原因需要,您也可以使用不同的速度;)