最近想实现一种选择关卡的特效,关卡就是一本书摆在屏幕中间,翻开一页,就是一关,再翻一页就是下一关,网上找了好多也没有,索性自己研究吧,花了几天还是搞出来了,主要是要自己绘制图形,利用update方法,一帧一帧来绘制,直接贴代码吧,动态图截起来太麻烦了。
头文件:
#include "cocos2d.h"
#include "cocos-ext.h"
USING_NS_CC;
USING_NS_CC_EXT;
class CoverView : public Node{
private:
//书的左右边
std::stack<Node* > card_left;
std::stack<Node* > card_right;
//上一关与下一关
Node* lastLevel;
Node* thisLevel;
//已旋转的角度
float angle;
//是左滑还是右滑
bool isRight;
//是否松手
bool isHandOff;
//是否结束动画
bool isShiftDone;
//到哪一关了
int whichLevel;
public:
CoverView();
~CoverView();
static CoverView* create(Rect swBox, Size slSize ,float disDistance , float disScale );
virtual bool init(Rect swBox , Size slSize , float disDistance , float disScale);
virtual bool onTouchBegin(Touch* pTouch, Event* pEvent);
virtual void onTouchMoved(Touch* pTouch, Event* pEvent);
virtual void onTouchEnded(Touch* pTouch, Event* pEvent);
void update(float dt);
void initData();
void initCard(int cardNum);
void adjustCardScale(Point adjustPoint);
int getCurLevel();
void addCard(Node * card);
void addCard(Node * card, int zOrder);
void addCard(Node* card, int zOrder, int tag);
void addLevel(Node * level);
void addLevel(Node * level, int zOrder);
void addLevel(Node* level, int zOrder, int tag);
void turnToLevel(int whichLevel);
CC_SYNTHESIZE(Point , swPosition , SwPosition);//scrollView 位置
CC_SYNTHESIZE(Size , swSize , SwSize);//scrollView大小
CC_SYNTHESIZE(Size , slSize , SlSize);//scrollLayer 大小
CC_SYNTHESIZE(float , disDistance , DisDistance);//card距离间隔
CC_SYNTHESIZE(float , disScale , DisScale);//card缩放间隔
CC_SYNTHESIZE(Rect , swBox , SwBox);//scrollview 边框
CC_SYNTHESIZE(Layer* , scrollLayer , scrollLayer);//scrollView的containLayer
CC_SYNTHESIZE(int , cardNum , CardNum);//card索引
CC_PROPERTY(Point , offsetPosition , OffsetPosition);//card起始位置
CC_SYNTHESIZE(Point, slayerPosition, SlayerPosition);//sontainLayer的位置
EventListenerTouchOneByOne* Listener;
private:
Size wSize;
Array* levelArray;
ScrollView* scrollView;
};
.c文件
#include "CoverView.h"
#define PI 3.14159
using namespace std;
CoverView::CoverView()
{
}
CoverView::~CoverView()
{
CC_SAFE_RELEASE_NULL(levelArray);
}
CoverView* CoverView::create(Rect swBox, Size slSize , float disDistance , float disScale)
{
CoverView* cover = new CoverView();
if(cover && cover->init(swBox,slSize,disDistance,disScale))
{
cover->autorelease();
return cover;
}
CC_SAFE_DELETE(cover);
return NULL;
}
bool CoverView::init(Rect swBox , Size slSize , float disDistance , float disScale)
{
if(!Node::init()) return false;
this->swBox = swBox;
this->swPosition = swBox.origin;
this->swSize = swBox.size;
this->slSize = slSize;
this->disDistance = disDistance;
this->disScale = disScale;
Listener=EventListenerTouchOneByOne::create();
Listener->onTouchBegan=CC_CALLBACK_2(CoverView::onTouchBegin, this);
Listener->onTouchMoved=CC_CALLBACK_2(CoverView::onTouchMoved, this);
Listener->onTouchEnded=CC_CALLBACK_2(CoverView::onTouchEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(Listener, this);
initData();
scheduleUpdate();
return true;
}
void CoverView::update(float dt){
//调整angle数值
if(angle>360){
angle-=360;
}
if(angle<-360){
angle+=360;
}
if (isHandOff&&!isShiftDone) {
Node* card;
bool hasValue=true;
if(isRight&&!card_right.empty()){
card=card_right.top();
}else if(!isRight&&!card_left.empty()){
card=card_left.top();
}else{
CCLOG("未初始化");
hasValue=false;
}
if(hasValue){
thisLevel=(Node*)levelArray->getObjectAtIndex(whichLevel+isRight);
lastLevel=(Node*)levelArray->getObjectAtIndex(whichLevel-1+isRight);
if(angle>=-90&&angle<=-30){
//合于右侧
//合并动画
angle+=dt*100;
card->setRotationSkewY(angle);
thisLevel->setScaleX(-sin((-angle-30)/2*PI/180)/sin(PI/3));
thisLevel->setRotationSkewY(-(90+(-angle-30)/2+30));
lastLevel->setScaleX((sin((angle+150)/2*PI/180)/sin(PI/3)));
lastLevel->setRotationSkewY(-(90-(150+angle)/2-30));
}else if(angle>=-150&&angle<90){
//合于左侧
//合并动画
angle-=dt*100;
card->setRotationSkewY(angle);
thisLevel->setScaleX(-sin((-angle-30)/2*PI/180)/sin(PI/3));
thisLevel->setRotationSkewY(-(90+(-angle-30)/2+30));
lastLevel->setScaleX((sin((angle+150)/2*PI/180)/sin(PI/3)));
lastLevel->setRotationSkewY(-(90-(150+angle)/2-30));
}
if (angle>=-30) {
isShiftDone=true;
card->setRotationSkewY(-30);
thisLevel->setScaleX(-0/sin(PI/3));
thisLevel->setRotationSkewY(-(90+0/2+30));
lastLevel->setScaleX((sin((120)/2*PI/180)/sin(PI/3)));
lastLevel->setRotationSkewY(-(90-(120)/2-30));
if(!isRight&&!card_left.empty()){
whichLevel--;
thisLevel->setZOrder(-1000);
//左侧的书出栈一页进入右侧栈
CCLOG("左侧的书出栈一页进入右侧栈");
card->setZOrder(0);
card_left.pop();
card_right.push(card);
}
}
if (angle<=-150) {
isShiftDone=true;
card->setRotationSkewY(-150);
thisLevel->setScaleX(-sin((150-30)/2*PI/180)/sin(PI/3));
thisLevel->setRotationSkewY(-(90+(150-30)/2+30));
lastLevel->setScaleX((sin((-150+150)/2*PI/180)/sin(PI/3)));
lastLevel->setRotationSkewY(-(90-(150-150)/2-30));
if(isRight&&!card_right.empty()){
whichLevel++;
lastLevel->setZOrder(-1000);
//右侧的书出栈一页进入左侧栈
CCLOG("右侧的书出栈一页进入左侧栈");
card->setZOrder(0);
card_right.pop();
card_left.push(card);
}
}
}
}
}
void CoverView::initCard(int cardNum){
char* url="白色方块.png";
for(int i = 0 ; i< cardNum ; i++)
{Sprite* player = Sprite::create(url);
this->addCard(player);
}
}
void CoverView::initData()
{
wSize = Director::getInstance()->getWinSize();
levelArray = Array::create();
levelArray->retain();
cardNum = 0;
isRight=true;
isHandOff=true;
isShiftDone=true;
whichLevel=0;
offsetPosition = Point(swSize.width/2,swSize.height/2);
scrollLayer = Layer::create();
scrollLayer->setAnchorPoint(Point::ZERO);
scrollLayer->setPosition(Point::ZERO);
scrollLayer->setContentSize(slSize);
slayerPosition = Point::ZERO;
scrollView = ScrollView::create(swSize,scrollLayer);
scrollView->setAnchorPoint(Point::ZERO);
scrollView->setContentOffset(Point(0,0));
scrollView->setTouchEnabled(false);
addChild(scrollView,1);
}
bool CoverView::onTouchBegin(Touch* pTouch, Event* pEvent)
{
if(isShiftDone){
isHandOff=false;
Point curPoint = pTouch->getLocation();
if(curPoint.x<wSize.width/2){
isRight=false;
angle=-150;
}else{
isRight=true;
angle=-30;
}
if(whichLevel+isRight>0&&whichLevel+isRight<cardNum+1){
thisLevel=(Node*)levelArray->getObjectAtIndex(whichLevel+isRight);
lastLevel=(Node*)levelArray->getObjectAtIndex(whichLevel-1+isRight);
thisLevel->setPosition(offsetPosition.x+170, offsetPosition.y-200);
thisLevel->setAnchorPoint(Point(1,0));
thisLevel->setScaleX(!isRight);
thisLevel->setRotationSkewY(0);
lastLevel->setPosition(offsetPosition.x-170, offsetPosition.y-200);
lastLevel->setAnchorPoint(Point(0,0));
lastLevel->setScaleX(isRight);
lastLevel->setRotationSkewY(0);
return true;
}
}
return false;
}
void CoverView::onTouchMoved(Touch* pTouch, Event* pEvent)
{
Point scroll_prepoint = pTouch->getPreviousLocation();
Point scroll_movepoint = pTouch->getLocation();
if(swBox.containsPoint(scroll_movepoint))
{
Point adjustPoint = scroll_movepoint-scroll_prepoint;
adjustCardScale(adjustPoint);
}
}
void CoverView::onTouchEnded(Touch* pTouch, Event* pEvent)
{
isShiftDone=false;
isHandOff=true;
}
void CoverView::adjustCardScale(Point adjustPoint)
{
float scale = adjustPoint.x/swSize.width*360;
thisLevel=(Node*)levelArray->getObjectAtIndex(whichLevel+isRight);
lastLevel=(Node*)levelArray->getObjectAtIndex(whichLevel-1+isRight);
if(isRight&&!card_right.empty()){
Node* card = card_right.top();
card->setZOrder(1000);
angle+=scale;
//固定角度内才可以旋转
if(angle<=-30&&angle>=-150){
card->setRotationSkewY(angle);
if(angle>-90){
thisLevel->setZOrder(500);
lastLevel->setZOrder(2000);
}else{
thisLevel->setZOrder(2000);
lastLevel->setZOrder(500);
}
thisLevel->setScaleX(-sin((-angle-30)/2*PI/180)/sin(PI/3));
thisLevel->setRotationSkewY(-(90+(-angle-30)/2+30));
lastLevel->setScaleX((sin((angle+150)/2*PI/180)/sin(PI/3)));
lastLevel->setRotationSkewY(-(90-(150+angle)/2-30));
}
}else if(!isRight&&!card_left.empty()){
Node* card = card_left.top();
card->setZOrder(1000);
angle+=scale;
//固定角度内才可以旋转
if(angle<=-30&&angle>=-150){
card->setRotationSkewY(angle);
if(angle>-90){
thisLevel->setZOrder(500);
lastLevel->setZOrder(2000);
}else{
thisLevel->setZOrder(2000);
lastLevel->setZOrder(500);
}
thisLevel->setScaleX(-sin((-angle-30)/2*PI/180)/sin(PI/3));
thisLevel->setRotationSkewY(-(90+(-angle-30)/2+30));
lastLevel->setScaleX((sin((angle+150)/2*PI/180)/sin(PI/3)));
lastLevel->setRotationSkewY(-(90-(150+angle)/2-30));
}
}
}
void CoverView::turnToLevel(int whichLevel)
{
this->whichLevel=whichLevel;
for (int i=0; i<whichLevel; i++) {
Node* card=card_right.top();
card_right.pop();
card_left.push(card);
}
}
void CoverView::addCard(Node * card)
{
int zOrder = cardNum;
this->addCard(card, zOrder, 0);
}
void CoverView::addCard(Node * card, int zOrder)
{
this->addCard(card, zOrder,0);
}
void CoverView::addCard(Node* card, int zOrder, int tag)
{
float positionX = offsetPosition.x;
//float scale = 1 - disScale*cardNum;
card->setAnchorPoint(Point(0,0));
card->setPosition(Point(positionX,offsetPosition.y-300));
card->setRotationSkewY(-30);
//card->setScale(scale);
scrollLayer->addChild(card , zOrder,tag);
cardNum++;
card_right.push(card);
//CCLog("crad%d:[%f , %f]",cardNum,card->getPositionX(),card->getPositionY());
}
void CoverView::addLevel(Node * level)
{
int zOrder = -1000;
this->addLevel(level, zOrder, 0);
}
void CoverView::addLevel(Node * level, int zOrder)
{
this->addLevel(level, zOrder,0);
}
void CoverView::addLevel(Node* level, int zOrder, int tag)
{
float positionX = offsetPosition.x;
//float scale = 1 - disScale*cardNum;
level->setPosition(offsetPosition.x-170, offsetPosition.y-200);
level->setAnchorPoint(Point(0,0));
level->setScaleX(1);
levelArray->addObject(level);
scrollLayer->addChild(level , zOrder,tag);
//CCLog("crad%d:[%f , %f]",cardNum,card->getPositionX(),card->getPositionY());
}
int CoverView::getCurLevel()
{
return whichLevel;
}
void CoverView::setOffsetPosition(Point var)
{
// offsetPosition = var;
// Ref* obj = NULL;
// cardNum = 0;
// CCARRAY_FOREACH(cardArray,obj)
// {
// Node* card = (Node*) obj;
// float positionX = offsetPosition.x + disDistance*cardNum;
// card->setPosition(Point(positionX,offsetPosition.y));
// cardNum++;
// }
// adjustCardScale(Point::ZERO);
}
Point CoverView::getOffsetPosition()
{
return offsetPosition;
}