假设想充分了解代码,请先阅读源码分析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.0f enum 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的size CCSize 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; //temp CCLabelTTF* 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上以供大家下载測试。