cocos2dx - v2.3.3編輯器骨骼動畫


接上一節內容:cocos2dx - v2.3.3編輯器簡單使用及不同分辨率適配

本節主要Cocos骨骼動畫的創建及使用

 

一、新建

  用Cocos Studio工具新建一個狀態欄項目。如下圖:

    

  當然也可以新建一個空的Cocos項目,然后在 文件->新建文件 中選擇骨骼動畫來創建新的骨骼動畫,如下圖

    

  因為這里只講簡單用法,着重使用,所有直接創建英雄示例動畫。

 

二、添加動畫

  選擇動畫模式,並點擊如下播放按鈕,可以看到現在默認的動畫。

    

  示例中只有ALL動畫,我們需要將每個動畫按起始結束幀率分開,添加如下動畫:

    

  這樣就有了休閑動畫(default),跑步動畫(run),攻擊動畫(attack),受傷動畫(injure),死亡動畫(death)。

 

這里還是額外在講下骨骼動畫記錄的使用。

  1、首先如下在右邊的幀查看中 添加起始幀

    

  2、直接改變預覽顯示中的骨骼對應的位置或者,旋轉等,這時編輯器就會自動記錄當前幀的各自狀態。

  3、在間隔一定的幀率再添加對應的結束幀,然后設置坐標等。這樣在起始結束幀就可以對應的播放動畫了。

注意事項:

  默認情況下,新添加的幀只會記錄以下左圖幾個數據,如果我們需要記錄類似顯示隱藏,透明度等數據,需要在調整數據前將右圖的開始記錄動畫選項勾上。

            

  這樣就會對修改的其他數據進行記錄了,如下圖

    

 

三、導出到項目

  同樣的,在編輯好動畫之后,我們需要跟上一節一樣導出到游戲項目的Resource目錄下

為了方便管理,我們這里也把玩家單獨提出一個類來。

 

#ifndef __CPlayer_H__
#define __CPlayer_H__

#include "cocos2d.h"
#include "cocostudio/CocoStudio.h"
USING_NS_CC;
using namespace cocostudio::timeline;

enum enAction
{
    ACT_NONE,        //
    ACT_DEFAULT,    // 待機        
    ACT_RUN,        // 跑步
    ACT_ATTACK,        // 攻擊
    ACT_INJURE,        // 受傷
    ACT_DEATH,        // 死亡
};

class CPlayer : public Node
{
public:
    // implement the "static create()" method manually
    CREATE_FUNC(CPlayer);

    virtual bool init();

    void Move(float deltaX);

    void Reset();

    void Attack();

private:
    void PlayAction(enAction nAction);

    CPlayer();
    ~CPlayer();


    Node*            m_pNode;
    enAction        m_nActType;
    ActionTimeline*     m_pAction;
};


#endif __CPlayer_H__
#include "Player.h"


CPlayer::CPlayer() :m_pNode(NULL), m_pAction(NULL), m_nActType(ACT_NONE)
{
}


CPlayer::~CPlayer()
{
    m_pNode = NULL;
    if (m_pAction)
    {
        m_pAction->release();
        m_pAction = NULL;
    }
}

bool CPlayer::init()
{ 
    std::string filePath = "Hero.csb";
    m_pNode = CSLoader::createNode(filePath);
    if (m_pNode)
    {
        m_pAction = CSLoader::createTimeline(filePath);
        if (m_pAction)
        {
            m_pAction->retain();
            m_pNode->runAction(m_pAction);

            PlayAction(enAction::ACT_DEFAULT);
        }
        this->addChild(m_pNode);
        return true;
    }
    return false;
}

void CPlayer::Move(float deltaX)
{
    if (m_nActType != ACT_DEFAULT && m_nActType != ACT_RUN)
    {
        return;
    }
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
#define isFloatZero(a)  ((a) > -0.000001f && (a) < 0.0000001f)
    if (!isFloatZero(deltaX))
    { 
        float delta = deltaX<0 ? -2 : 2;
        // 計算移動后的位置
        float desX = this->getPositionX() + delta;
        if (desX<origin.x)
        {
            desX = origin.x;
        }
        if (desX>origin.x + visibleSize.width)
        {
            desX = origin.x + visibleSize.width;
        }
        this->setScaleX(deltaX<0 ? -1 : 1);
        this->setPositionX(desX);
    }
    PlayAction(ACT_RUN);
}

void CPlayer::Attack()
{
    PlayAction(ACT_ATTACK);
}
void CPlayer::Reset()
{
    PlayAction(enAction::ACT_DEFAULT);
}

void CPlayer::PlayAction(enAction nAction)
{
    if (m_pAction)
    {
        if (m_nActType == nAction || m_nActType == ACT_ATTACK)
        {
            return;
        }
        m_nActType = nAction; 
        switch (nAction)
        {
        case ACT_DEFAULT:
            m_pAction->play("default",true);
            break;
        case ACT_RUN:
            m_pAction->play("run", true);
            break;
        case ACT_ATTACK:
            {
                m_pAction->play("attack", false);
                std::function<void()> func = [this](){
                    m_pAction->play("default", true);
                    m_nActType = ACT_DEFAULT;
                };
                m_pAction->setLastFrameCallFunc(func);
            }
            break;
        case ACT_INJURE:
            m_pAction->play("injure", false);
            break;
        case ACT_DEATH:
            m_pAction->play("death", false);
            break;
        default:
                break;
        } 
    }
}
View Code

 

這樣在戰斗中,添加了對應的頭文件后,我們就可以正常添加使用了。

    // 加載玩家實體
    m_pPlayer = CPlayer::create();
    // 設置位置
    m_pPlayer->setPosition(Vec2(visibleSize.width / 2 + origin.x, 80 + origin.y));
    // 添加到節點上
    this->addChild(m_pPlayer, 1);

然后在點擊屏幕的事件我們也做下修改。

bool HelloWorld::onTouchBegan(Touch *pTouch, Event *unused_event)
{
    if (m_pPlayer)
    {
        // 防止超出屏幕
        Size visibleSize = Director::getInstance()->getVisibleSize();
        Vec2 origin = Director::getInstance()->getVisibleOrigin();
        if (pTouch->getLocation().x>visibleSize.width*0.5 + origin.x)
        {
            m_pPlayer->Attack();
        }
        else
        {
            m_pPlayer->Move(pTouch->getDelta().x);
        }
    }
    return true;
}

void HelloWorld::onTouchMoved(Touch *pTouch, Event *pEvent)
{
    if (m_pPlayer)
    {
        // 點擊左半屏幕
        Size visibleSize = Director::getInstance()->getVisibleSize();
        Vec2 origin = Director::getInstance()->getVisibleOrigin();
        if (pTouch->getLocation().x < visibleSize.width*0.5 + origin.x)
        {  
            m_pPlayer->Move(pTouch->getDelta().x);
        }
    }
}

void HelloWorld::onTouchEnded(Touch *pTouch, Event *pEvent)
{
    if (m_pPlayer)
    {
        m_pPlayer->Reset();
    }
}

這樣就實現了點擊左半屏移動,右半屏實現攻擊。效果如下


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM