zoukankan      html  css  js  c++  java
  • cocos2d-x CCSrollView 源代码,可循环的SrollView代码


    项目须要。写一个类似于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.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上以供大家下载測试。


  • 相关阅读:
    leetcode 309. Best Time to Buy and Sell Stock with Cooldown
    leetcode 714. Best Time to Buy and Sell Stock with Transaction Fee
    leetcode 32. Longest Valid Parentheses
    leetcode 224. Basic Calculator
    leetcode 540. Single Element in a Sorted Array
    leetcode 109. Convert Sorted List to Binary Search Tree
    leetcode 3. Longest Substring Without Repeating Characters
    leetcode 84. Largest Rectangle in Histogram
    leetcode 338. Counting Bits
    git教程之回到过去,版本对比
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/6811217.html
Copyright © 2011-2022 走看看