zoukankan      html  css  js  c++  java
  • cocos2dx

    接上一节内容: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();
        }
    }

    这样就实现了点击左半屏移动,右半屏实现攻击。效果如下

  • 相关阅读:
    JDK5后的特性整理
    正向代理与反向代理的区别与异同
    我所用过的nginx的功能
    网页端消息推送之推与拉
    在一个py脚本中调用另外一个py脚本中的类或函数
    import与from ... import ...的区别
    python 读取文件
    shell中的特殊变量IFS
    shell 重定向以及文件描述符
    shell下读取文件数据
  • 原文地址:https://www.cnblogs.com/stratrail/p/5038485.html
Copyright © 2011-2022 走看看