经过测试,利用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);
}
}