zoukankan      html  css  js  c++  java
  • 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,达到减速的效果
  • 相关阅读:
    Java数据结构与算法之---求两个数的最大公约数(欧几里得算法)
    Linux下面配置文件~/.bash_profile
    Java数据结构之回溯算法的递归应用迷宫的路径问题
    Java数据结构之对称矩阵的压缩算法---
    Java数据结构之字符串模式匹配算法---KMP算法2
    Java数据结构之字符串模式匹配算法---KMP算法
    Java数据结构之字符串模式匹配算法---Brute-Force算法
    Java数据结构之表的增删对比---ArrayList与LinkedList之一
    Java数据结构之队列的实现以及队列的应用之----简单生产者消费者应用
    Java堆栈的应用1----------堆栈的自定义实现以及括号匹配算法的Java实现
  • 原文地址:https://www.cnblogs.com/xiaonanxia/p/5360516.html
Copyright © 2011-2022 走看看