Cocos2d-x学习(七):cocos2d-x中ScrollView的简单实现

来源:互联网 发布:windows redmine 迁移 编辑:程序博客网 时间:2024/05/02 00:07

在游戏关卡选择,道具店之中经常会用到类似于ScrollView的控件,之前用AndEngine引擎的时候简单的实现了一个,(AndEngine滑动菜单传送门),考虑到手头的游戏以后也会用到,就先用cocos2d-x简单的实现了一下!原理非常类似,android中的app(比如微博,qq)也是类似的原理!


1.设计思路

自定义ScrollView继承于CCLayer,固定其每页的大小(ios上假设480x320),每一页是一个子层(也是继承于CCLayer),由使用者根据需求丰富,依次水平方向添加到ScrollView中(垂直方向的原理类似)!在ScrollView中实现触摸监听,如果是滑动事件,执行滚屏的操作,并且在触摸事件完成后跳转到当前页;如果是点击事件,则根据当前页交由子层处理。

2.ScrollView类

[cpp] view plaincopy
  1. <span style="font-size:16px;">#ifndef ScrollView_ScrollView_h  
  2. #define ScrollView_ScrollView_h  
  3.   
  4. #include "cocos2d.h"  
  5.   
  6. USING_NS_CC;  
  7.   
  8. // 屏幕尺寸  
  9. const float WINDOW_WIDTH = 480.0f;  
  10. const float WINDOW_HEIGHT = 320.0f;  
  11.   
  12. // 触摸误差  
  13. const int TOUCH_DELTA = 5;  
  14.   
  15. class ScrollView: public CCLayer  
  16. {  
  17. private:  
  18.     // 按下点  
  19.     CCPoint m_TouchDownPoint;  
  20.     // 抬起点 配合使用判断是否为点击事件  
  21.     CCPoint m_TouchUpPoint;  
  22.     // 当前触摸点  
  23.     CCPoint m_TouchCurPoint;  
  24.       
  25. private:  
  26.     // 总页数  
  27.     int m_Page;  
  28.     // 当前显示页  
  29.     int m_CurPage;  
  30.       
  31. private:  
  32.     // 存储所有页层  
  33.     CCArray *m_PageLayer;  
  34.       
  35. private:  
  36.     // 跳转页  
  37.     void goToPage();  
  38.       
  39. public:  
  40.     ScrollView();  
  41.     ~ScrollView();  
  42.       
  43.     virtual bool init();  
  44.       
  45.     LAYER_NODE_FUNC(ScrollView);  
  46.   
  47. public:  
  48.     // 初始化相关  
  49.     virtual void onEnter();  
  50.     virtual void onExit();  
  51.       
  52.     // 触摸事件相关  
  53.     virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);  
  54.     virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);  
  55.     virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);  
  56.     virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);  
  57.       
  58. public:  
  59.     // 添加页  
  60.     void addPage(CCLayer *pPageLayer);  
  61.   
  62. };  
  63.   
  64. #endif  
  65. </span>  
CCPoint 成员是为了判断触摸事件相关,

addPage(CCLayer *pLayer) 是提供的外部接口,向ScrollView中添加子层,

void goToPage() 在触摸事件完成后根据当前偏移量跳转到指定页码

CCArray *m_PageLayer 用来存储所有的子层

3.判断规则

(1) 移动事件

根据触摸的点与当前ScrollView所在位置,得到ScrollView的偏移量

[cpp] view plaincopy
  1. <span style="font-size:16px;">void ScrollView::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)  
  2. {  
  3.     // 移动  
  4.     CCPoint touchPoint = CCDirector::sharedDirector()->convertToGL(pTouch->locationInView());  
  5.     CCPoint posPoint = CCPointMake(getPositionX() + touchPoint.x - m_TouchCurPoint.x, getPositionY());  
  6.     setPosition(posPoint);  
  7.     m_TouchCurPoint = touchPoint;  
  8. }  
  9. </span>  

(2) 触摸事件完成

得到用户按下和抬起的坐标偏移量,和触摸误差作比较,如果大于触摸误差,则认为是滑动;如果小于触摸误差,则认为是点击。

如果是点击,则交由当前的子层处理

如果是滑动,则根据滑动的偏移量来决定是否滑动到哪一页

[cpp] view plaincopy
  1. <span style="font-size:16px;">void ScrollView::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)  
  2. {  
  3.     m_TouchUpPoint = CCDirector::sharedDirector()->convertToGL(pTouch->locationInView());  
  4.     // 计算按下和抬起的偏移量  
  5.     float off = (m_TouchUpPoint.x - m_TouchDownPoint.x) * (m_TouchUpPoint.x - m_TouchDownPoint.x) + (m_TouchUpPoint.y - m_TouchDownPoint.y) * (m_TouchUpPoint.y - m_TouchDownPoint.y);  
  6.       
  7.     if (off < (TOUCH_DELTA * TOUCH_DELTA)) {  
  8.         // 点击  
  9.         // 向子Layer发送Click消息  
  10.         ((CCLayer*) m_PageLayer->objectAtIndex(m_CurPage))->ccTouchBegan(pTouch, pEvent);  
  11.     }  
  12.     else {  
  13.         // 滑动结束  
  14.         int offset = getPositionX() - m_CurPage * (-WINDOW_WIDTH);  
  15.         if (offset > WINDOW_WIDTH / 2) {  
  16.             // 上一页  
  17.             if (m_CurPage > 0) {  
  18.                 --m_CurPage;  
  19.             }  
  20.         }  
  21.         else if (offset < -WINDOW_WIDTH / 2) {  
  22.             // 下一页  
  23.             if (m_CurPage < (m_Page - 1)) {  
  24.                 ++m_CurPage;  
  25.             }  
  26.         }  
  27.   
  28.         // 执行跳转动画  
  29.         goToPage();  
  30.     }  
  31. }</span>  

4.测试

写了一个测试层TestLayer,主要用来测试接收触摸事件

[cpp] view plaincopy
  1. <span style="font-size:16px;">bool TestLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)  
  2. {  
  3.     CCLOG("I am %d", getTag());  
  4.       
  5.     return true;  
  6. }</span>  
简单的输出一个标记,可根据需求再具体分发触摸事件

5.用法

循环了10个子层,每层随机了一个背景色,用来区别各个子层,分别加入到ScrollView对象中

[cpp] view plaincopy
  1. <span style="font-size:16px;">bool ScrollViewScene::init()  
  2. {  
  3.     bool bRet = false;  
  4.       
  5.     do {  
  6.         CC_BREAK_IF(!CCScene::init());  
  7.           
  8.         ScrollView *scrollView = ScrollView::node();  
  9.           
  10.         CCSize winSize = CCDirector::sharedDirector()->getWinSize();  
  11.         for (int i=0; i<10; ++i) {  
  12.             CCLayer *layer = TestLayer::node();  
  13.             layer->setAnchorPoint(CCPointZero);  
  14.             layer->setTag(i);  
  15.             scrollView->addPage(layer);  
  16.         }  
  17.           
  18.         this->addChild(scrollView);  
  19.           
  20.         bRet = true;  
  21.     } while (0);  
  22.       
  23.     return bRet;  
  24. }</span>  

效果如图



示例代码下载


原创粉丝点击