联系客服:400-805-1963

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

 

返回游戏开发教程...