cocos2d-x 自己写的一个scrollview 有待完善
更新:HHH   时间:2023-1-7


 直接上代码,根据cocos2d-x 扩展库中的代码改编的。

 

  1. // 
  2. //  MScrollView.h 
  3. //  Test ScrollView 
  4. // 
  5. //  Created by Za aa on 13-4-25. 
  6. // 
  7. // 
  8.  
  9. #ifndef _MScrollView_h 
  10. #define _MScrollView_h 
  11. #include "cocos2d.h" 
  12. using namespace cocos2d; 
  13. //触摸误差 
  14. const int TOUCH_DELTA = 5; 
  15. //设置图片修正时的移动速度 
  16. const float MOVE_SPEED = 1000; 
  17. class MScrollView : public cocos2d::CCLayerColor 
  18. public
  19.     MScrollView(); 
  20.     ~MScrollView(); 
  21.     virtual bool init(); 
  22.     //复写绘图函数,每帧调用,添加了区域剔除 
  23.     void visit(); 
  24.     //CREATE_FUNC(MScrollView); 
  25.      
  26.     //自定义-------- 
  27.     //从多个精灵创建 
  28.     static MScrollView * CreateWithSprite(float gap,CCSprite * p_w_picpathSprite,...); 
  29.      
  30.     //修改剔除区域 
  31.     void setClipSize(float width,float height); 
  32.      
  33.     //修改响应区域 
  34.     void setTouchRect(CCRect touchRect){m_touchRect = touchRect;}; 
  35.      
  36.     //根据间距初始化子层精灵 
  37.     bool initGapForChild(float gap); 
  38.      
  39.     //修正动画的函数 
  40.     void RAnimation(CCPoint pt); 
  41.      
  42.     //拖动精灵,跟随手指移动改变位置 
  43.     void draySprite(float delta); 
  44.      
  45.     //滚动到某一页的函数 
  46.     void gotoPageAnimation(float page); 
  47.   
  48.     //页面滚动动画,moveto 动画 
  49.     void ScrollAnimation(CCPoint offset,float time)    ; 
  50.      
  51.     //updata,用于如果拖动就停止moveto 动作 
  52.     void MoveToAnimation(float dt ); 
  53.      
  54.     // 添加一个回调函数,用于停止动画 
  55.     void StopMoveToAnimation(); 
  56.      
  57.     //重写触屏相关函数----                       
  58.     virtual void registerWithTouchDispatcher(); 
  59.     virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event); 
  60.     virtual void ccTouchMoved(CCTouch* touch, CCEvent* event); 
  61.     virtual void ccTouchEnded(CCTouch* touch, CCEvent* event); 
  62.     virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent); 
  63. private
  64.     //是否按下后移动 
  65.     bool m_dragging; 
  66.     //按下的点 
  67.     CCPoint m_touchDownPoint; 
  68.     //抬起点 
  69.     CCPoint m_touchUpPoint; 
  70.     //当前的触电 
  71.     CCPoint m_touchCurPoint; 
  72.     //子层容器,用于滚动显示 
  73.     CCLayer * m_Container; 
  74.     //保存所有精灵 
  75.     CCArray * m_spriteArray; 
  76.     //总页数 
  77.     int m_page; 
  78.     //当前页数 
  79.     int m_curpage; 
  80.     //偏移动画的时间 
  81.     float m_time; 
  82.     //显示区域 
  83.   //  CCRect m_view; 
  84.     //显示区域,区域外的将被剪切 
  85.     CCSize m_clipSize; 
  86.     //接收事件的区域 
  87.     CCRect m_touchRect; 
  88.     //点击后的回调函数 
  89.     SEL_CallFunc m_fun; 
  90.  
  91. }; 
  92.  
  93.  
  94. #endif 

 

  1. // 
  2. //  MScrollView.cpp 
  3. //  Test ScrollView 
  4. // 
  5. //  Created by Za aa on 13-4-25. 
  6. // 
  7. // 
  8.  
  9. #include "MScrollView.h" 
  10. MScrollView::MScrollView() 
  11.      
  12. MScrollView::~MScrollView() 
  13.     //清空数组 
  14.     m_spriteArray->release(); 
  15.     
  16. MScrollView * MScrollView::CreateWithSprite(float gap,CCSprite *p_w_picpathSprite, ...) 
  17.     MScrollView * pRet = new MScrollView(); 
  18.     if (pRet && pRet->init())  
  19.     { 
  20.         //创建array,用于保存所有sprite 
  21.         pRet->m_spriteArray= CCArray::create(); 
  22.         CC_SAFE_RETAIN(pRet->m_spriteArray); 
  23.         //----------------------------------------------- 
  24.         //将省略的sprite添加进m_spriteArray 和 mscrollview中 
  25.         //---------------------------------------------- 
  26.          
  27.         //定义一个params变量,实际是一个指针,用于定位可变行参变量  
  28.         va_list params; 
  29.         //执行本宏后,params指向第一个可变信参,p_w_picpathSprite为最后一个确定行参  
  30.         va_start(params, p_w_picpathSprite); 
  31.          
  32.         //定义一个ccsprite 接收参数 
  33.         CCSprite * pNow = p_w_picpathSprite; 
  34.          
  35.         while (true
  36.         { 
  37.             if (pNow) 
  38.             { 
  39.                 //添加进数组和层----- 
  40.                 pRet->m_spriteArray->addObject(pNow); 
  41.                 pRet->m_Container->addChild(pNow); 
  42.                 //去下一个值 
  43.                 pNow = va_arg(params, CCSprite *); 
  44.             } 
  45.             else 
  46.             { 
  47.                 break
  48.             } 
  49.              
  50.         } 
  51.         //清空 
  52.         va_end(params); 
  53.          
  54.         //排列ccprite 
  55.         pRet->initGapForChild(gap); 
  56.          
  57.         ////////////添加完成//////// 
  58.         pRet->autorelease(); 
  59.         return pRet;  
  60.     } \ 
  61.     else  
  62.     {  
  63.         delete pRet;  
  64.         pRet = NULL;  
  65.         return NULL;  
  66.     }  
  67.      
  68.  
  69.  
  70.  
  71. bool MScrollView::init() 
  72.     ////////////////////////////// 
  73.     // 1. super init first 
  74.    // if ( !CCLayerColor::init() ) 
  75.     if ( !CCLayerColor::CCLayerColor::initWithColor(ccc4(0xff,0x00,0x00,0x80), 100, 100)) 
  76.     { 
  77.         return false
  78.     } 
  79.        //开启触屏响应 
  80.     this->setTouchEnabled(true); 
  81.      
  82.     //添加显示容器 
  83.     m_Container = CCLayer::create(); 
  84.     m_Container->setAnchorPoint(ccp(0.0f,0.0f)); 
  85.     m_Container->setPosition(ccp(0.0f, 0.0f)); 
  86.     this->addChild(m_Container); 
  87.      
  88.     //修改响应区域,默认是全屏 
  89.     CCSize screen = CCDirector::sharedDirector()->getWinSize(); 
  90.     setTouchRect(CCRectMake(0, 0, screen.width, screen.height)); 
  91.      
  92.     //修改显示区域,默认为全屏 
  93.     this->setContentSize(screen); 
  94.      
  95.     //修改剪切区域,默认为全屏 
  96.     setClipSize(screen.width,screen.height); 
  97.      
  98.     //默认回调函数为空 
  99.     m_fun =NULL; 
  100.     return true
  101.      
  102. void MScrollView::visit() 
  103.     if (!m_bIsVisible) 
  104.     { 
  105.         return
  106.     } 
  107.     kmGLPushMatrix(); 
  108.     if (m_pGrid && m_pGrid->isActive()) 
  109.     { 
  110.         m_pGrid->beforeDraw(); 
  111.         this->transformAncestors(); 
  112.     } 
  113.     this->transform(); 
  114.     //默认情况下,剪裁是禁用的 
  115.     glEnable(GL_SCISSOR_TEST);//启用剪裁测试 
  116.      
  117.     float s = this->getScale();//当前layer缩放的倍数 
  118.     s *= CCDirector::sharedDirector()->getContentScaleFactor();//获取缩放倍率 
  119.     CCPoint screenPos = this->convertToWorldSpace(this->getParent()->getPosition()); 
  120.     //默认不设置Scissor的大小是整个视图的大小 
  121.     glScissor((GLint)screenPos.x, (GLint)screenPos.y, (GLsizei)(m_clipSize.width*s), (GLsizei)(m_clipSize.height*s)); 
  122.      
  123.     //子节点处理 
  124.     if(m_pChildren) 
  125.     { 
  126.         ccArray *arrayData = m_pChildren->data; 
  127.         unsigned int i=0; 
  128.          
  129.         for( ; i < arrayData->num; i++ ) 
  130.         { 
  131.             CCNode *child =  (CCNode*)arrayData->arr[i]; 
  132.             if ( child->getZOrder() < 0 ) 
  133.             { 
  134.                 child->visit(); 
  135.             } 
  136.             else 
  137.             { 
  138.                 break
  139.             } 
  140.         } 
  141.         this->draw(); 
  142.         for( ; i < arrayData->num; i++ ) 
  143.         { 
  144.             CCNode* child = (CCNode*)arrayData->arr[i]; 
  145.             child->visit(); 
  146.         } 
  147.          
  148.     } else 
  149.     { 
  150.         this->draw(); 
  151.     } 
  152.      
  153.     glDisable(GL_SCISSOR_TEST);//禁用剪裁测试 
  154.      
  155.     if ( m_pGrid && m_pGrid->isActive()) 
  156.     { 
  157.         m_pGrid->afterDraw(this); 
  158.     } 
  159.      
  160.     kmGLPopMatrix(); 
  161.      
  162.     // 
  163.      
  164.  
  165. void MScrollView::setClipSize(float width,float height) 
  166.     m_clipSize = CCSizeMake(width,height); 
  167. //TODO: 载显示容器中排列精灵 
  168. bool MScrollView::initGapForChild(float gap) 
  169.     //用于判读是否有元素 
  170.     if (m_spriteArray==NULL) return false
  171.     ///////////修改各个元素的位置 
  172.    //初始化当前页 
  173.     m_curpage = 0; 
  174.     //初始化总页数 
  175.     m_page = m_spriteArray->count(); 
  176.      
  177.     CCSprite * sp = (CCSprite *)m_spriteArray->objectAtIndex(0); 
  178.    float spwidth = sp->boundingBox().size.width/2.0f; 
  179.     float spheight = sp->boundingBox().size.height/2.0f; 
  180.     //获取一个中心点 
  181.     CCPoint pt = ccp(this->boundingBox().size.width/2.0f-spwidth, 
  182.                      this->boundingBox().size.height/2.0f-spheight); 
  183.     float tY=pt.y; 
  184.     sp->setAnchorPoint(ccp(0,0)); 
  185.     sp->setPosition(pt); 
  186.      
  187.     for (int i = 1 ; i<m_page; i++) 
  188.     { 
  189.         spwidth = sp->boundingBox().size.width; 
  190.         pt =ccp(sp->getPositionX()+spwidth+gap,tY); 
  191.               
  192.       sp = (CCSprite *)m_spriteArray->objectAtIndex(i); 
  193.         sp->setAnchorPoint(ccp(0,0)); 
  194.         sp->setPosition(pt); 
  195.          
  196.     } 
  197.      
  198.      
  199. //TODO: 滚动修正 
  200. void MScrollView::RAnimation(CCPoint pt) 
  201.     int _page = m_curpage; 
  202.      
  203.     //判断移动的方向 
  204.     float f =pt.x; 
  205.     if(f>0) 
  206.     { 
  207.         // 向左移动 
  208.         CCLog("zuo "); 
  209.         _page ++; 
  210.                   
  211.     } 
  212.     else 
  213.     { 
  214.         //向→移动 
  215.         CCLog("you"); 
  216.         _page --; 
  217.         
  218.     } 
  219.      
  220.     if ( !(_page>m_page-1 || _page<0)) 
  221.     { 
  222.          m_curpage = _page; 
  223.     } 
  224.     CCLog("_page is : %d",_page); 
  225.     CCLog(" page is : %d",m_page); 
  226.     CCLog(" curpage is : %d",m_curpage); 
  227.     gotoPageAnimation(m_curpage); 
  228.  
  229. //TODO: 拖动精灵,跟随手指移动改变位置 
  230. void MScrollView::draySprite(float delta) 
  231.     this->m_Container->setPosition(ccpAdd(this->m_Container->getPosition(), ccp(delta,0))); 
  232. }  
  233. //TODO: 滚动到某一页的动画 
  234. void MScrollView::gotoPageAnimation(float page) 
  235.     if (m_page == 0 ) return
  236.     //获得当前页的精灵 
  237.     CCSprite * sp  = (CCSprite *)this->m_spriteArray->objectAtIndex(page); 
  238.     //多移动一小段距离让sprite载正中间 
  239.     float _width = sp->boundingBox().size.width * 0.5f; 
  240.     _width = m_clipSize.width * 0.5f - _width; 
  241.      
  242.     //获取要到达的点 
  243.     CCPoint gotoPoint =ccp(-sp->getPositionX()+_width,this->m_Container->getPositionY()); 
  244.     //计算移动到点的时间 
  245.     float _length = ccpDistance(gotoPoint,m_Container->getPosition()); 
  246.      
  247.     float _time = _length / MOVE_SPEED; 
  248.     //滚动到指定点 
  249.      
  250.     ScrollAnimation(gotoPoint,_time); 
  251.      
  252.      
  253. //页面滚动动画,moveto 动画 
  254.  void MScrollView::ScrollAnimation(CCPoint offset,float time) 
  255.     //如果是拖动就停止这个动作 
  256.     if (m_dragging) 
  257.     { 
  258.         this->unschedule(schedule_selector(MScrollView::MoveToAnimation)); 
  259.         return
  260.     } 
  261.     /////////////// 
  262.     //创建移动动画 
  263.     ////////////// 
  264.     CCFiniteTimeAction * scroll,*expire; 
  265.     scroll = CCMoveTo::create(time,offset); 
  266.     //添加一个回调函数 
  267.       expire = CCCallFuncN::create(this, callfuncN_selector(MScrollView::StopMoveToAnimation)); 
  268.     //运行moveto动画 
  269.     m_Container->runAction(CCSequence::create(scroll, expire, NULL)); 
  270.     //开启拖动判读 
  271.      this->schedule(schedule_selector(MScrollView::MoveToAnimation)); 
  272.      
  273.      
  274.  
  275. //updata,用于如果拖动就停止moveto 动作 
  276. void  MScrollView:: MoveToAnimation(float dt ) 
  277.     if (m_dragging) 
  278.     { 
  279.         this->m_Container->unscheduleAllSelectors(); 
  280.  
  281.         return
  282.     } 
  283.     
  284. // // 添加一个回调函数,用于停止动画 
  285. void MScrollView:: StopMoveToAnimation() 
  286. //   this->unschedule(schedule_selector(MoveToAnimation)); 
  287.     this->m_Container->unscheduleAllSelectors(); 
  288. //消息注册 
  289. void MScrollView::registerWithTouchDispatcher() 
  290.     CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, false); 
  291. bool MScrollView::ccTouchBegan(cocos2d::CCTouch *touch, cocos2d::CCEvent *event) 
  292.     if (!this->isVisible()) {return false;} 
  293.     //记录按下的点 
  294.     m_touchDownPoint = CCDirector::sharedDirector()->convertToGL(touch->locationInView()); 
  295.      
  296.     if (!m_touchRect.containsPoint(m_touchDownPoint)){return false;} 
  297.      
  298.     m_dragging = true
  299.     CCLog("CCtouchBegan"); 
  300.    //  
  301.      
  302.     return true
  303.      
  304.  void MScrollView::ccTouchMoved(CCTouch* touch, CCEvent* event) 
  305.     CCLog("ccTouchMoved"); 
  306.     if (!this->isVisible()){return;} 
  307.      
  308.     m_touchCurPoint = CCDirector::sharedDirector()->convertToGL(touch->locationInView()); 
  309.     if (!m_touchRect.containsPoint(m_touchCurPoint)) 
  310.     { 
  311.         m_dragging = false
  312.         return ; 
  313.     } 
  314.     //如果不是按下后移动 
  315.     if(m_dragging) 
  316.     { 
  317.         CCPoint moveDelta = ccpSub(m_touchCurPoint, m_touchDownPoint); 
  318.         draySprite(moveDelta.x); 
  319.         m_dragging = false
  320.  
  321.     } 
  322.     else 
  323.     { 
  324.         draySprite(touch->getDelta().x); 
  325.     } 
  326.      
  327.    // CCLog("ccTouchMoved,x is %f::y is %f",x,y); 
  328. void MScrollView::ccTouchEnded(CCTouch* touch, CCEvent* event) 
  329.     if (!this->isVisible()){return;} 
  330.      m_touchUpPoint = CCDirector::sharedDirector()->convertToGL(touch->locationInView()); 
  331.     if (!m_touchRect.containsPoint(m_touchUpPoint)){ m_dragging = false;return ;} 
  332.     //判定是点击还是滑动,如果是点击执行点击函数,如果是滑动执行调整动画 
  333.     
  334.     float off = ccpDistance(m_touchDownPoint,m_touchUpPoint); 
  335.     if (off < TOUCH_DELTA) 
  336.     { 
  337.         //触发点击事件 
  338.         m_fun; 
  339.         CCLog("touchclick"); 
  340.         
  341.     } 
  342.     else 
  343.     { 
  344.         //  滑动纠正 
  345.         //触发滑动动画 
  346.         RAnimation(ccpSub(m_touchDownPoint,m_touchUpPoint)); 
  347.     } 
  348.   
  349.  
  350.      
  351.      
  352. void MScrollView::ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent) 
  353.      

 

返回游戏开发教程...