2017-09-27 124 views
0

使用Cocos2d-x和C++,我試圖播放和暫停一個精靈的動畫。在Cocos2d上的雪碧暫停/恢復動作/動畫

我使用的是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)刪除ACTI在指針上。我試圖克隆這個行爲來避免這種情況,但沒有成功。

回答

0

當您停止操作時,它將從內存中回收。爲了再次發揮作用,你必須重新創建它。所以你可以創建一個創建者函數,它返回你的動畫。缺點是你每次都在重新創建動畫,它也會從頭開始播放(技術上你可以倒帶它)。

但我已經開發了一個簡單的技術暫停/恢復動畫:

比方說,你有一個動作:

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

你也可以用不同的速度,如果你需要它出於某種原因或其他)

+0

我想你誤解了,我認爲這種方法不適用於動畫 – Acidic

+0

你必須在Speed中嵌入Animate :: create。我認爲它應該有效,因爲Animate也是Action。 – Makalele

1

我知道這是一個有點遲了,你可能已經解決了這個問題,但這裏有...

你的問題是你不能多次使用Action(idleAction)的一個實例。所以,一旦你運行並刪除它,它就會被釋放並且不能被使用。所以,你現在有2個選項,

  • 要麼每次在運行動作之前創建一個新的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

解決方法:撥打retain(),讓您的行動。

這是cocos2d-x的內存管理問題。

在你RepeatForevercreate()功能(來自Ref導出),引用計數被置爲1並且存在的代碼ret->autorelease()線返回對象,這意味着該對象將自動在此結束被釋放之前幀。

您稱爲runAction()起作用創建它在同一幀中,動作是由ActionManager保留,它的參考計數在所述框架(自動釋放)的端部設置爲2,然後1。

在您停止它之後,它將被ActionManager發佈,引用計數設置爲0並將其刪除。在此之後,您使用您的操作,它將是訪問衝突方法。

*編輯:當PlayerSprite被刪除或者它是泄漏時,不要忘記手動發佈操作。