cocos2dx 2.0 CCScrollView的用法以及滑动的原理

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

USING_NS_CC;
#include "cocos-ext.h"
USING_NS_CC_EXT;
// 校正滑动动画速度
#define ADJUST_ANIM_VELOCITY 800;

class HelloWorld : public cocos2d::CCLayer, public cocos2d::extension::CCScrollViewDelegate
{
public:
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  

    // there's no 'id' in cpp, so we recommand to return the exactly class pointer
    static cocos2d::CCScene* scene();
    
    // a selector callback
    void menuCloseCallback(CCObject* pSender);

    // implement the "static node()" method manually
    CREATE_FUNC(HelloWorld);
    
public:
    void scrollViewDidScroll(cocos2d::extension::CCScrollView* view);
    void scrollViewDidZoom(CCScrollView* view);
    
public:
    virtual void onEnter();
    virtual void onExit();
    
    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
    
private:
    // 当触摸事件结束时,校正CCScrollView的位置
    void adjustScrollView();
    
private:
    // 菜单回调
    void menu1Callback(CCNode *pSender);
    void menu2Callback(CCNode *pSender);
    
private:
    // 显示当前页
    CCLabelTTF* pLabel;
    
    CCScrollView *scrollView;
    
};

#endif // __HELLOWORLD_SCENE_H__

实现文件

  1 #include "HelloWorldScene.h"
  2 #include "SimpleAudioEngine.h"
  3 
  4 using namespace cocos2d;
  5 using namespace CocosDenshion;
  6 USING_NS_CC_EXT;
  7 
  8 CCScene* HelloWorld::scene()
  9 {
 10     // 'scene' is an autorelease object
 11     CCScene *scene = CCScene::create();
 12     
 13     // 'layer' is an autorelease object
 14     HelloWorld *layer = HelloWorld::create();
 15 
 16     // add layer as a child to scene
 17     scene->addChild(layer);
 18 
 19     // return the scene
 20     return scene;
 21 }
 22 CCLayer *layer;
 23 CCSprite *sprite2;
 24 // on "init" you need to initialize your instance
 25 bool HelloWorld::init()
 26 {
 27     //////////////////////////////
 28     // 1. super init first
 29     if ( !CCLayer::init() )
 30     {
 31         return false;
 32     }
 33 
 34     /////////////////////////////
 35     // 2. add a menu item with "X" image, which is clicked to quit the program
 36     //    you may modify it.
 37 
 38     // add a "close" icon to exit the progress. it's an autorelease object
 39     
 40     
 41     // ask director the window size
 42     CCSize size = CCDirector::sharedDirector()->getWinSize();
 43 
 44     layer = CCLayerColor::create(ccc4(123, 23, 235,255));
 45     layer->setAnchorPoint(CCPointZero);
 46     layer->setPosition(CCPointZero);
 47 
 48 
 49     // CCScrollView
 50     scrollView = CCScrollView::create(CCSizeMake(480, 320), layer);
 51     
 52    // scrollView->setBounceable(false);
 53     
 54     
 55     CCSprite *sprite1 = CCSprite::create("HelloWorld.png");
 56     sprite2 = CCSprite::create("HelloWorld.png");
 57     CCSprite *sprite3 = CCSprite::create("HelloWorld.png");
 58     
 59     // Menu
 60     //CCMenuItemSprite *menuItem1 = CCMenuItemSprite::create(sprite1, sprite1, this, menu_selector(HelloWorld::menu1Callback));
 61 //    CCMenuItemSprite *menuItem1 = CCMenuItemSprite::create(sprite1, sprite1, this, NULL);
 62 //    menuItem1->setPosition(ccpAdd(CCPointZero, ccp(size.width / 2, size.height / 2)));
 63 //    
 64 //    CCMenuItemSprite *menuItem2 = CCMenuItemSprite::create(sprite2, sprite2, this, NULL);
 65 //    menuItem2->setPosition(ccpAdd(ccp(480, 0), ccp(size.width / 2, size.height / 2)));
 66 //    
 67 //    CCMenu *menu = CCMenu::create(menuItem1, menuItem2, NULL);
 68 //    
 69 //    menu->setPosition(CCPointZero);
 70 //    layer->addChild(menu);
 71     
 72     sprite1->setPosition(ccpAdd(CCPointZero, ccp(size.width / 2, size.height / 2)));
 73     sprite2->setPosition(ccpAdd(ccp(480, 0), ccp(size.width / 2, size.height / 2)));
 74     sprite3->setPosition(ccpAdd(ccp(960, 0), ccp(size.width / 2, size.height / 2)));
 75 
 76     layer->addChild(sprite1);
 77     layer->addChild(sprite2);
 78     layer->addChild(sprite3);
 79     
 80     
 81     
 82     
 83     layer->setContentSize(CCSizeMake(960, 320));
 84     
 85     sprite1->setScale(0.5);
 86     sprite2->setScale(0.5);
 87     
 88     scrollView->setPosition(CCPointZero);
 89     scrollView->setContentOffset(CCPointZero);
 90    
 91     scrollView->setContentSize(CCSizeMake(480*3, 320));
 92     scrollView->setContainer(layer);
 93     
 94    
 95     scrollView->setDirection(kCCScrollViewDirectionHorizontal);
 96     scrollView->setDelegate(this);
 97     
 98     this->addChild(scrollView);
 99 
100     
101     
102     return true;
103 }
104 
105 void HelloWorld::menuCloseCallback(CCObject* pSender)
106 {
107     CCDirector::sharedDirector()->end();
108 
109 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
110     exit(0);
111 #endif
112 }
113 
114 void HelloWorld::scrollViewDidScroll(cocos2d::extension::CCScrollView *view)
115 {
116 }
117 
118 void HelloWorld::scrollViewDidZoom(cocos2d::extension::CCScrollView *view)
119 {
120 }
121 
122 void HelloWorld::onEnter()
123 {
124     CCLayer::onEnter();
125     // 这里的第三个参数一定要设置成false,
126     // true 即HelloWorld层吞噬掉触摸事件
127     // false 即HelloWorld层与CCScrollView对象先后处理触摸事件
128   //  CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 1, false);
129 }
130 
131 void HelloWorld::onExit()
132 {
133     CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
134     CCLayer::onExit();
135 }
136 
137 bool HelloWorld::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
138 {
139       auto postion=   pTouch->getLocation();
140       auto p2= layer->convertToNodeSpace(postion);
141 //    printf("p1.x=%f,p1.y=%f
",postion.x,postion.y);
142 //    printf("p2.x=%f,p2.y=%f
",p2.x,p2.y);
143     
144     auto rect =sprite2->boundingBox();
145     if(rect.containsPoint(p2)){
146         int ffff=0;
147         ffff++;
148       //  printf("摸到了
");
149     }
150     
151     int ffffr=0;
152     ffffr++;
153 
154     
155     return true;
156 }
157 
158 void HelloWorld::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
159 {
160    // CCLOG("move");
161 }
162 
163 void HelloWorld::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
164 {
165     adjustScrollView();
166 }
167 
168 void HelloWorld::ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
169 {
170     adjustScrollView();
171 }
172 
173 void HelloWorld::adjustScrollView()
174 {
175      // 关闭CCScrollView中的自调整
176     scrollView->unscheduleAllSelectors();
177     
178     int x = scrollView->getContentOffset().x;
179     int offset = (int) x % 480;
180     
181     printf("x=%d,offset=%d
",x,offset);
182     // 调整位置
183     CCPoint adjustPos;
184     // 调整动画时间
185     float adjustAnimDelay;
186     
187     if (offset < -240) {
188         // 计算下一页位置,时间
189         adjustPos = ccpSub(scrollView->getContentOffset(), ccp(480 + offset, 0));
190         adjustAnimDelay = (float) (480 + offset) / ADJUST_ANIM_VELOCITY;
191         printf("-240调整后的坐标=%f
",adjustPos.x);
192     }
193     else {
194         // 计算当前页位置,时间
195         adjustPos = ccpSub(scrollView->getContentOffset(), ccp(offset, 0));
196         
197         
198         // 这里要取绝对值,否则在第一页往左翻动的时,保证adjustAnimDelay为正数
199         adjustAnimDelay = (float) abs(offset) / ADJUST_ANIM_VELOCITY;
200         
201         
202         printf("现在的位移=%f
",scrollView->getContentOffset().x);
203         
204         printf(">240调整后的坐标=%f
",adjustPos.x);
205     }
206     
207     
208     // 调整位置
209     scrollView->setContentOffsetInDuration(adjustPos, adjustAnimDelay);
210 }
211 
212 void HelloWorld::menu1Callback(cocos2d::CCNode *pSender)
213 {
214     CCLOG("menu1Callback");
215 }
216 
217 void HelloWorld::menu2Callback(cocos2d::CCNode *pSender)
218 {
219     CCLOG("menu2Callback");
220 }

这里主要研究的是他的显示,以及当滑动停止的时候,有个加速度还要滑动一段,具体如何实现,是研究的CCScrollView源码,如下

 1 void CCScrollView::deaccelerateScrolling(float dt)
 2 {
 3     if (m_bDragging)
 4     {
 5         this->unschedule(schedule_selector(CCScrollView::deaccelerateScrolling));
 6         return;
 7     }
 8     
 9     float newX, newY;
10     CCPoint maxInset, minInset;
11     
12     m_pContainer->setPosition(ccpAdd(m_pContainer->getPosition(), m_tScrollDistance));
13     
14     if (m_bBounceable)
15     {
16         maxInset = m_fMaxInset;
17         minInset = m_fMinInset;
18     }
19     else
20     {
21         maxInset = this->maxContainerOffset();
22         minInset = this->minContainerOffset();
23     }
24     printf("maxinset.x=%f,mininset.x=%f
",maxInset.x,minInset.x);
25     //96,-1056
26     
27     //check to see if offset lies within the inset bounds
28     newX     = MIN(m_pContainer->getPosition().x, maxInset.x);
29     newX     = MAX(newX, minInset.x);
30     newY     = MIN(m_pContainer->getPosition().y, maxInset.y);
31     newY     = MAX(newY, minInset.y);
32     
33     newX = m_pContainer->getPosition().x;
34     newY = m_pContainer->getPosition().y;
35     
36     m_tScrollDistance     = ccpSub(m_tScrollDistance, ccp(newX - m_pContainer->getPosition().x, newY - m_pContainer->getPosition().y));
37     m_tScrollDistance     = ccpMult(m_tScrollDistance, SCROLL_DEACCEL_RATE);
38     this->setContentOffset(ccp(newX,newY));
39     
40     if ((fabsf(m_tScrollDistance.x) <= SCROLL_DEACCEL_DIST &&
41          fabsf(m_tScrollDistance.y) <= SCROLL_DEACCEL_DIST) ||
42         newY > maxInset.y || newY < minInset.y ||
43         newX > maxInset.x || newX < minInset.x ||
44         newX == maxInset.x || newX == minInset.x ||
45         newY == maxInset.y || newY == minInset.y)
46     {
47         this->unschedule(schedule_selector(CCScrollView::deaccelerateScrolling));
48         this->relocateContainer(true);
49     }
50 }

每次坐标增加

m_tScrollDistance,但是
m_tScrollDistance会每次变为0.95*m_tScrollDistance,达到减速的效果
原文地址:https://www.cnblogs.com/xiaonanxia/p/5360516.html