卡牌翻牌效果

经过测试,利用cocos2dx引擎自带的setScaleX和setFlippedX即可实现,效果比较好。
详细代码如下:

//
//  CCardNode.h
//  SlotsBase
//
//  Created by xujw on 16/5/27.
//
//  卡牌类,实现类似扑克翻牌效果,默认翻牌时间为0.5s,建议时间为0.3-1.0f

#ifndef CCardNode_h
#define CCardNode_h

#include <stdio.h>
#include "cocos2d.h"
USING_NS_CC;

#define SKEW_DEGREE 10

class CCardNode:public Node
{
public:
    typedef enum
    {
        kCardFront = 0,
        kCardBack = 1,
    }ECardState;

    typedef struct CData
    {
        std::string dataStr;
        int dataInt;
        long dataLong;
        CData(const std::string &str,int idata,long ldata)
        {
            dataStr = str;
            dataInt = idata;
            dataLong = ldata;
        };
        CData(){}
    }CardData;

public:
    CCardNode();
    ~CCardNode();

    /**
     *  创建一张卡牌
     *
     *  @param frontSpFile 正面资源图片
     *  @param backSpFile  反面资源图片
     *  @param state  显示牌面 默认显示背面
     *
     *  @return 卡牌
     */
    static CCardNode* createCard(const std::string &frontSpFile,const std::string &backSpFile,ECardState state=kCardBack);
    static CCardNode* createCard(const std::string &frontSpFile,const std::string &backSpFile,ECardState state,CardData data);
    bool init(const std::string &frontSpFile,const std::string &backSpFile,ECardState state);

    /**
     *  翻转卡牌
     */
    void turnCard();
    void turnCard(float t);
    void turnCard(std::function<void(Ref*)> callBack,float turnTime=1.0f);

    inline void setTrunCallback(std::function<void(Ref*)> callBack){_callBack = callBack;};
    inline void setTurnTime(float t){_turnTime = t;};
    inline void setCardData(CardData data){_cardData = data;};
    inline CardData getCardData() const{return _cardData;};
    inline ECardState getCardStata() const {return  _cardState;};

private:
    Sprite *_frontSp;
    Sprite *_backSp;
    float _turnTime;
    ECardState _cardState;
    std::function<void(Ref*)> _callBack;
    bool _isAct;
    CardData _cardData;
};

#endif /* CCardNode_h */

//
//  CCardNode.cpp
//  SlotsBase
//
//  Created by xujw on 16/5/27.
//
//

#include "CCardNode.h"

CCardNode::CCardNode()
:_frontSp(nullptr)
,_backSp(nullptr)
,_turnTime(0.5f)
,_callBack(nullptr)
,_isAct(false)
,_cardState(kCardBack)
,_cardData("",-1,-1.0f)
{}
CCardNode::~CCardNode()
{
    this->removeFromParentAndCleanup(true);
}

CCardNode* CCardNode::createCard(const std::string &frontSpFile, const std::string &backSpFile, ECardState state, CardData data)
{
    CCardNode *card = CCardNode::createCard(frontSpFile, backSpFile,state);
    card->setCardData(data);
    return card;
}

CCardNode* CCardNode::createCard(const std::string &frontSpFile, const std::string &backSpFile,ECardState state)
{
    CCardNode *card = new(std::nothrow) CCardNode();
    if (card && card->init(frontSpFile, backSpFile,state))
    {
        card->autorelease();
        return card;
    }

    CC_SAFE_DELETE(card);
    return nullptr;
}

bool CCardNode::init(const std::string &frontSpFile, const std::string &backSpFile,ECardState state)
{
    if (!Node::init())
    {
        return false;
    }

    _cardState = state;

    _frontSp = Sprite::create(frontSpFile);
    this->addChild(_frontSp);
    _backSp = Sprite::create(backSpFile);
    this->addChild(_backSp);

    bool disFront = _cardState==kCardFront?true:false;
    _frontSp->setVisible(disFront);
    _backSp->setVisible(!disFront);

    //MARK:设置node大小和锚点,方便计算是否点击到牌面
    this->setContentSize(_backSp->getContentSize());
    this->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
    _frontSp->setPosition(this->getContentSize()/2);
    _backSp->setPosition(_frontSp->getPosition());

    return true;
}

void CCardNode::turnCard()
{
    turnCard(_callBack,_turnTime);
}

void CCardNode::turnCard(float t)
{
    setTurnTime(t);
    turnCard(_callBack,_turnTime);
}

void CCardNode::turnCard(std::function<void (Ref *)> callBack,float t)
{
    if (_isAct)
    {
        return;
    }

    _isAct = true;
    setTurnTime(t);
    //MARK:为了每次翻牌都从右向左翻牌
    if (-1 == _frontSp->getScaleX())
    {
        _frontSp->setFlippedX(false);
        _frontSp->setScaleX(1);
    }
    if (-1 == _backSp->getScaleX())
    {
        _backSp->setFlippedX(false);
        _backSp->setScaleX(1);
    }

    if (_cardState == kCardFront)
    {
        CCLOG("当前是正面,开始翻牌到背面!");
        ScaleTo *firstPartSto = ScaleTo::create(_turnTime/2, 0, 1);
        Sequence *firstSeq = Sequence::create(Spawn::create(firstPartSto,SkewTo::create(_turnTime/2, 0, -SKEW_DEGREE), NULL),Hide::create(),CallFunc::create([=]()
           {
               _backSp->setVisible(true);
               _backSp->setFlippedX(true);
               _backSp->setScaleX(0);

               ScaleTo *secondPartSto = ScaleTo::create(_turnTime/2, -1, 1);
               Sequence *secondSeq = Sequence::create(Spawn::create(secondPartSto,SkewTo::create(_turnTime/2, 0, 0), NULL),CallFunc::create([=]()
                 {
                     //翻牌完成
                     _isAct = false;
                     _cardState = kCardBack;
                     if (_callBack)
                     {
                         _callBack(nullptr);
                     }
                 }), NULL);
               _backSp->runAction(secondSeq);

           }), NULL);

        _frontSp->runAction(firstSeq);
    }
    else
    {
        CCLOG("当前是反面,开始翻牌到正面!");
        ScaleTo *firstPartSto = ScaleTo::create(_turnTime/2, 0, 1);
        Sequence *firstSeq = Sequence::create(Spawn::create(firstPartSto,SkewTo::create(_turnTime/2, 0, -SKEW_DEGREE), NULL),Hide::create(),CallFunc::create([=]()
           {
               _frontSp->setVisible(true);
               _frontSp->setScaleX(0);
               _frontSp->setFlippedX(true);

               ScaleTo *secondPartSto = ScaleTo::create(_turnTime/2, -1, 1);
               Sequence *secondSeq = Sequence::create(Spawn::create(secondPartSto,SkewTo::create(_turnTime/2, 0, 0), NULL),CallFunc::create([=]()
                 {
                     //翻牌完成
                     _isAct = false;
                     _cardState = kCardFront;
                     if (_callBack) {
                         _callBack(nullptr);
                     }
                 }), NULL);
               _frontSp->runAction(secondSeq);

           }), NULL);

        _backSp->runAction(firstSeq);
    }
}
posted @ 2016-08-15 16:57  随风的博客  阅读(237)  评论(0编辑  收藏  举报