cocos2d-x CCSrollView 源码,可循环的SrollView代码

来源:互联网 发布:网络传销诈骗标语 编辑:程序博客网 时间:2024/06/11 07:04


项目需要,写一个类似于iPhone上面时钟选择的可拉动式循环选择列表,通过集成CCScrollView并更改部分代码。实现了该功能。

如果想充分了解代码,请先阅读源代码分析http://blog.csdn.net/u011225840/article/details/30033501

不考虑重构,这是我写的第一版代码,只考虑了功能性。

过两天有时间后,我会将该部分代码重构,希望大家作对比~


#include "cocos2d.h"#include "cocos-ext.h"using namespace cocos2d;using namespace cocos2d::extension;#define SCROLL_DEACCEL_RATE  0.95f#define SCROLL_DEACCEL_DIST  1.0fenum MovingDirection{Left = 1,Right = 2,Up,Down};enum Direction{CycleDirectionHorizontal=1,CycleDirectionVertical};enum Child{kLeft = 1,kMiddle,kRight};class CCCycleScrollView: public CCScrollView{public:CCCycleScrollView();virtual ~CCCycleScrollView();static CCCycleScrollView* create(const char* spriteFile,Direction direction = CycleDirectionHorizontal);bool initWithViewSize(const char* spriteFile ,Direction direction = CycleDirectionHorizontal);bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);protected://调整三个sprite的位置void adjustSprite();void deaccelerateScrolling(float dt);void relocateContainer();CCPoint findEndPoint();//有三个一样的sprite来支持循环显示CCSprite* m_sprite1;CCSprite* m_sprite2;CCSprite* m_sprite3;//每个sprite的sizeCCSize m_spriteSize;//上一次触碰点的坐标,用于判断当前移动的方向CCPoint m_lastPoint;//当前触碰点的坐标CCPoint m_nowPoint;//当前偏移对应的位置float m_nowPositionNum;//上一次移动后的移动位数int m_lastPositionNum;//上一次正向移动是否移动过bool m_lastPositiveDone;//上一次反向移动是否移动过bool m_lastNegtiveDone;//正在移动的方向MovingDirection m_moving;//滚动的限定方向Direction m_direction;//tempCCLabelTTF* temp1;CCLabelTTF* temp2;CCLabelTTF* temp3;CCLabelTTF* temp4;CCLabelTTF* temp5;CCLabelTTF* temp6;CCLabelTTF* temp7;CCLabelTTF* temp8;CCLabelTTF* temp9;void updateTemp();};


#include "CCCycleScrollView.h"CCCycleScrollView::CCCycleScrollView():m_sprite1(NULL),m_sprite2(NULL),m_sprite3(NULL),m_lastPoint(ccp(0.0f,0.0f)),m_nowPoint(ccp(0.0f,0.0f)),m_lastPositionNum(0),m_lastPositiveDone(false),m_lastNegtiveDone(false){}CCCycleScrollView::~CCCycleScrollView(){}bool CCCycleScrollView::initWithViewSize(const char* spriteFile ,Direction d ){if (CCLayer::init()){m_sprite1 = CCSprite::create(spriteFile);m_sprite1->ignoreAnchorPointForPosition(false);m_sprite1->setAnchorPoint(ccp(0.0f,0.0f));CCSize spriteSize = m_sprite1->getContentSize();temp1 = CCLabelTTF::create();temp1->setContentSize(CCSizeMake(160,320));temp1->setFontSize(80);temp1->setAnchorPoint(ccp(0.5f,0.0f));temp1->setString("10");temp1->setPosition(ccp(80.0f,0.0f));temp1->setTag(kLeft);m_sprite1->addChild(temp1); temp2 = CCLabelTTF::create();temp2->setContentSize(CCSizeMake(160,320));temp2->setFontSize(80);temp2->setAnchorPoint(ccp(0.5f,0.0f));temp2->setString("11");temp2->setPosition(ccp(240.f,0.0f));temp2->setTag(kMiddle);m_sprite1->addChild(temp2);temp3 = CCLabelTTF::create();temp3->setContentSize(CCSizeMake(160,320));temp3->setFontSize(80);temp3->setAnchorPoint(ccp(0.5f,0.0f));temp3->setString("12");temp3->setPosition(ccp(400.0f,0.0f));temp3->setTag(kRight);m_sprite1->addChild(temp3);m_sprite2 = CCSprite::create(spriteFile);m_sprite2->ignoreAnchorPointForPosition(false);m_sprite2->setAnchorPoint(ccp(0.0f,0.0f)); temp4 = CCLabelTTF::create();temp4->setContentSize(CCSizeMake(160,320));temp4->setFontSize(80);temp4->setAnchorPoint(ccp(0.5f,0.0f));temp4->setString("1");temp4->setPosition(ccp(80.0f,0.0f));temp4->setTag(kLeft);m_sprite2->addChild(temp4); temp5 = CCLabelTTF::create();temp5->setContentSize(CCSizeMake(160,320));temp5->setFontSize(80);temp5->setAnchorPoint(ccp(0.5f,0.0f));temp5->setString("2");temp5->setPosition(ccp(240.0f,0.0f));temp5->setTag(kMiddle);m_sprite2->addChild(temp5); temp6 = CCLabelTTF::create();temp6->setContentSize(CCSizeMake(160,320));temp6->setFontSize(80);temp6->setAnchorPoint(ccp(0.5f,0.0f));temp6->setString("3");temp6->setPosition(ccp(400.0f,0.0f));temp6->setTag(kRight);m_sprite2->addChild(temp6);m_sprite3 = CCSprite::create(spriteFile);m_sprite3->ignoreAnchorPointForPosition(false);m_sprite3->setAnchorPoint(ccp(0.0f,0.0f)); temp7 = CCLabelTTF::create();temp7->setContentSize(CCSizeMake(160,320));temp7->setFontSize(80);temp7->setAnchorPoint(ccp(0.5f,0.0f));temp7->setString("4");temp7->setPosition(ccp(80.f,0.0f));temp7->setTag(kLeft);m_sprite3->addChild(temp7); temp8 = CCLabelTTF::create();temp8->setContentSize(CCSizeMake(160,320));temp8->setFontSize(80);temp8->setAnchorPoint(ccp(0.5f,0.0f));temp8->setString("5");temp8->setPosition(ccp(240.0f,0.0f));temp8->setTag(kMiddle);m_sprite3->addChild(temp8); temp9 = CCLabelTTF::create();temp9->setContentSize(CCSizeMake(160,320));temp9->setFontSize(80);temp9->setAnchorPoint(ccp(0.5f,0.0f));temp9->setString("6");temp9->setPosition(ccp(400.0f,0.0f));temp9->setTag(kRight);m_sprite3->addChild(temp9);if (d==CycleDirectionHorizontal){m_sprite1->setPosition(ccp(-spriteSize.width,0.0f));m_sprite2->setPosition(ccp(0.0f,0.0f));m_sprite3->setPosition(ccp(spriteSize.width,0.0f));m_eDirection  = kCCScrollViewDirectionHorizontal;}else if(d==CycleDirectionVertical){m_sprite1->setPosition(ccp(0.0f,-spriteSize.height));m_sprite2->setPosition(ccp(0.0f,0.0f));m_sprite3->setPosition(ccp(0.0f,spriteSize.height));m_eDirection = kCCScrollViewDirectionVertical;}if (!this->m_pContainer){m_pContainer = CCLayer::create();this->m_pContainer->ignoreAnchorPointForPosition(false);this->m_pContainer->setAnchorPoint(ccp(0.0f, 0.0f));this->m_pContainer->addChild(m_sprite1);this->m_pContainer->addChild(m_sprite2);this->m_pContainer->addChild(m_sprite3);}this->setViewSize(CCSizeMake(spriteSize.width,spriteSize.height));setTouchEnabled(true);m_pTouches = new CCArray();m_pDelegate = NULL;m_bBounceable = true;m_bClippingToBounds = true;//m_pContainer->setContentSize(CCSizeZero);m_pContainer->setPosition(ccp(0.0f, 0.0f));m_fTouchLength = 0.0f;this->addChild(m_pContainer);//setContentOffset(ccp(-spriteSize.width,0));/*m_fMaxInset = ccp(spriteSize.width*300,0);m_fMinInset = ccp(-spriteSize.width*300,0);m_bBounceable = true;*/m_fMinScale = m_fMaxScale = 1.0f;m_spriteSize = spriteSize;m_direction = d;return true;}return false;}CCCycleScrollView* CCCycleScrollView::create( const char* spriteFile ,Direction d){CCCycleScrollView* pRet = new CCCycleScrollView();if (pRet && pRet->initWithViewSize(spriteFile,d)){pRet->autorelease();}else{CC_SAFE_DELETE(pRet);}return pRet;}void CCCycleScrollView::ccTouchEnded( CCTouch *pTouch, CCEvent *pEvent ){if (!this->isVisible()){return;}if (m_pTouches->count()==1){this->schedule(schedule_selector(CCCycleScrollView::deaccelerateScrolling));}m_pTouches->removeObject(pTouch);//没有touch时,需要设置状态if (m_pTouches->count() == 0){m_bDragging = false;    m_bTouchMoved = false;}}void CCCycleScrollView::ccTouchMoved( CCTouch *pTouch, CCEvent *pEvent ){CCScrollView::ccTouchMoved(pTouch,pEvent);m_nowPoint =   convertToWorldSpace(convertTouchToNodeSpace(pTouch));CCLog("The last point is %f",m_lastPoint.x);CCLog("The now point is %f",m_nowPoint.x);if (m_direction==CycleDirectionHorizontal){if (m_nowPoint.x>m_lastPoint.x){m_moving = Right;m_lastPoint = m_nowPoint;}else{m_moving= Left;m_lastPoint = m_nowPoint;}m_nowPositionNum = m_pContainer->getPositionX() / m_spriteSize.width;//CCLog("The nowNum is %d",nowPositionNum);CCLog("The offset is %f",m_pContainer->getPositionX());CCLog("The 1 is %f",m_sprite1->getPositionX());CCLog("The 2 is %f",m_sprite2->getPositionX());CCLog("The 3 is %f",m_sprite3->getPositionX());CCLog("The move is %d",m_moving);}else if (m_direction==CycleDirectionVertical){if (m_nowPoint.y>m_lastPoint.y){m_moving = Up;m_lastPoint = m_nowPoint;}else{m_moving= Down;m_lastPoint = m_nowPoint;}m_nowPositionNum = m_pContainer->getPositionY() / m_spriteSize.height;}adjustSprite();}bool CCCycleScrollView::ccTouchBegan( CCTouch *pTouch, CCEvent *pEvent ){bool result = CCScrollView::ccTouchBegan(pTouch,pEvent);m_lastPoint = convertToWorldSpace(convertTouchToNodeSpace(pTouch));CCLog("The last point is %f",m_lastPoint.x);if (m_pTouches->count()>1){return false;}return result;}void CCCycleScrollView::adjustSprite(){//正在向右移动if (m_direction==CycleDirectionHorizontal){if (m_moving==Right){if (m_nowPositionNum-m_lastPositionNum>0.5){m_lastPositiveDone=true;m_lastPositionNum++;}//if (m_lastPositiveDone){m_sprite3->setPosition(ccp(m_sprite3->getPositionX()-m_spriteSize.width*3,0));CCSprite* temp = m_sprite3;m_sprite3 = m_sprite2;m_sprite2 = m_sprite1;m_sprite1 = temp;updateTemp();m_lastPositiveDone = false;}}else if (m_moving==Left){if (m_lastPositionNum-m_nowPositionNum>=0.5){m_lastNegtiveDone=true;m_lastPositionNum--;}if (m_lastNegtiveDone){m_sprite1->setPosition(ccp(m_sprite1->getPositionX()+m_spriteSize.width*3,0));CCSprite* temp = m_sprite1;m_sprite1 = m_sprite2;m_sprite2 = m_sprite3;m_sprite3 = temp;updateTemp();m_lastNegtiveDone=false;}}}else if (m_direction==CycleDirectionVertical){if (m_moving==Up){if (m_nowPositionNum-m_lastPositionNum>0.5){m_lastPositiveDone=true;m_lastPositionNum++;}if (m_lastPositiveDone){m_sprite3->setPosition(ccp(0.0f,m_sprite3->getPositionY()-m_spriteSize.height*3));CCSprite* temp = m_sprite3;m_sprite3 = m_sprite2;m_sprite2 = m_sprite1;m_sprite1 = temp;m_lastPositiveDone = false;}}else if (m_moving==Down){if (m_lastPositionNum-m_nowPositionNum>=0.5){m_lastNegtiveDone=true;m_lastPositionNum--;}if (m_lastNegtiveDone){m_sprite1->setPosition(ccp(0.0f,m_sprite1->getPositionY()+m_spriteSize.height*3));CCSprite* temp = m_sprite1;m_sprite1 = m_sprite2;m_sprite2 = m_sprite3;m_sprite3 = temp;m_lastNegtiveDone=false;}}}}void CCCycleScrollView::updateTemp(){if (m_moving==Right){int num = atoi(((CCLabelTTF*)m_sprite2->getChildByTag(kLeft))->getString());if (num-1==0){num=13;}((CCLabelTTF*)m_sprite1->getChildByTag(kLeft))->setString(CCString::createWithFormat("%d",num-3)->getCString());((CCLabelTTF*)m_sprite1->getChildByTag(kMiddle))->setString(CCString::createWithFormat("%d",num-2)->getCString());((CCLabelTTF*)m_sprite1->getChildByTag(kRight))->setString(CCString::createWithFormat("%d",num-1)->getCString());}else if (m_moving==Left){int num = atoi(((CCLabelTTF*)m_sprite2->getChildByTag(kRight))->getString());if (num+1==13){num=0;}((CCLabelTTF*)m_sprite3->getChildByTag(kLeft))->setString(CCString::createWithFormat("%d",num+1)->getCString());((CCLabelTTF*)m_sprite3->getChildByTag(kMiddle))->setString(CCString::createWithFormat("%d",num+2)->getCString());((CCLabelTTF*)m_sprite3->getChildByTag(kRight))->setString(CCString::createWithFormat("%d",num+3)->getCString());}}void CCCycleScrollView::deaccelerateScrolling(float dt){//如果刚好在帧开始前 又有一个触摸点发生了began,造成了滚动状态,则取消并返回    if (m_bDragging)    {        this->unschedule(schedule_selector(CCCycleScrollView::deaccelerateScrolling));        return;    }    //好玩的东西来咯    float newX, newY;    CCPoint maxInset, minInset;    //CCLOG("The end distance is %f",m_tScrollDistance.x);//这里我不清楚为啥要出来,我用输出发现在move中,已经将此offset设置过了,不知为何还要设置,求大神解答。    m_pContainer->setPosition(ccpAdd(m_pContainer->getPosition(), m_tScrollDistance));          newX = m_pContainer->getPosition().x;    newY = m_pContainer->getPosition().y;        m_tScrollDistance     = ccpSub(m_tScrollDistance, ccp(newX - m_pContainer->getPosition().x, newY - m_pContainer->getPosition().y));    m_tScrollDistance     = ccpMult(m_tScrollDistance, SCROLL_DEACCEL_RATE);    this->setContentOffset(ccp(newX,newY));if (m_direction==CycleDirectionHorizontal){m_nowPositionNum = m_pContainer->getPositionX() / m_spriteSize.width;}else if (m_direction==CycleDirectionVertical){m_nowPositionNum = m_pContainer->getPositionY() / m_spriteSize.height;}this->adjustSprite();        if ((fabsf(m_tScrollDistance.x) <= SCROLL_DEACCEL_DIST &&         fabsf(m_tScrollDistance.y) <= SCROLL_DEACCEL_DIST))    {        this->unschedule(schedule_selector(CCCycleScrollView::deaccelerateScrolling));//CCLog("stop!!!!");this->relocateContainer();    }}void CCCycleScrollView::relocateContainer(){//调整位置m_pContainer->setPosition(findEndPoint());if (m_direction==CycleDirectionHorizontal){m_nowPositionNum = m_pContainer->getPositionX() / m_spriteSize.width;}else if (m_direction==CycleDirectionVertical){m_nowPositionNum = m_pContainer->getPositionY() / m_spriteSize.height;}this->adjustSprite();}cocos2d::CCPoint CCCycleScrollView::findEndPoint(){CCPoint nowPoint;nowPoint.x = m_pContainer->getPositionX();float interval = (nowPoint.x)/160;int inter = (int)interval;CCPoint newPoint;if (fabsf(interval-inter)>=0.5){if (inter<0){newPoint.x = 160*(inter-1);}else{newPoint.x = 160*(inter+1);}}else{newPoint.x = 160*inter;}CCLog("The final offset is %f",nowPoint.x);CCLog("The float is %f , the int is %d",interval,inter);CCLog("The endpoint is %f",newPoint.x);return ccp(newPoint.x,0.0f);}


未重构的代码有些恶心~~

准备将重构后的代码再贴出来,并放在github上以供大家下载测试。


0 0