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

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

转载于:https://blog.51cto.com/farsa/1194781

cocos2d-x 自己写的一个scrollview 有待完善相关推荐

  1. 写了一个测试正则表达式的小工具

    这两天写了两个蜘蛛程序用来自动下载漫画,许多时候都是用他在网页中通过正则表达式获取关键字和信息.我用的正则表达式的工具是Expresso,这个工具无疑是目前最好的正则表达式的工具之一.但用着用着就觉得 ...

  2. python写机器人程序_用Python写的一个多线程机器人聊天程序

    本人是从事php开发的, 近来想通过php实现即时通讯(兼容windows).后来发现实现起来特别麻烦, 就想到python.听说这家伙在什么地方都能发挥作用.所以想用python来做通讯模块...所 ...

  3. 自己写的一个简单的android记事本app

    自己写的一个简单的记事本app,效果如下: 一.首先是第一个界面的编写,最上面是一个TextView,中间是一个Linearlayout中嵌套一个listview布局,最下面是一个button.下面附 ...

  4. cocos2d-xna 写的一个小游戏demo坦克大战

    最近看到网上介绍cocos2d的资料很多,看了看cocos2d也支持wp7,下载了个 Cocos2d-XNA 安装包,写个小例子玩玩,熟悉下cocos2d 程序很简单,就一个入门级的小游戏,写完后放手 ...

  5. 【用java写的一个excel签到表】

    画页面 import cn.hutool.core.date.DateUtil; import org.apache.poi.xssf.usermodel.XSSFWorkbook;import ja ...

  6. java编程游戏飞机旋转问题_用JAVA写的一个飞机游戏

    根据网上视频教程,用JAVA写的一个飞机程序.先看效果先: 改程序主要应用了面向对象的方法构建,使用了AWT技术和一些双缓冲技术 关键有几个点: 一.双缓冲技术,防止重画造成的屏幕闪烁,可以直接用 p ...

  7. 在纸上写好一个c语言程序后,上机运行的基本步骤为,c基本概念(选择题).docx

    PAGE / NUMPAGES 一.单选题 1.下面叙述中正确的是: (A) 在C语言程序中,main()函数必须放在程序的开始位置 (B) 在C语言程序中,要调用的函数必须在main()函数中定义 ...

  8. 怎样写出一个较好的高速排序程序

    写出一个较好的高速排序程序 高速排序是经常使用的排序算法之中的一个,但要想写出一个又快又准的使用程序,就不是那么简单了 须要注意的事项 首先要写正确.通常使用递归实现.其递归相当于二叉树展开,因此假设 ...

  9. linux mysql 不稳定_linux,mysql:今天写出一个十分弱智的bug!

    今天写出一个十分弱智的bug,记录一下,提醒自己以后别这种犯错,不怕丢人哈~ 在写一个分页查询记录的sql时,要根据添加的时间逆序分页输出,之前的写法是酱紫: select record.a, y.c ...

最新文章

  1. 2022-2028年小型风电产业投资及前景预测报告
  2. springMVC参数绑定与数据回显
  3. 【 FPGA 】UltraFast设计方法学:时序收敛之时序约束基本准则
  4. java连连看源代码在哪_连连看java源代码
  5. 在两个页面间翻转设置Animation动作的一些总结
  6. linux内核5.4,Linux Kernel 5.4 RC8 发布,一切都很正常
  7. 用groovy采集网页数据
  8. 同一个页面提交多个form表单方法(详细)
  9. 虎扑APP遭全网下架 原因未知
  10. Spring Cloud Ribbon 负载均衡客户端调用示例
  11. 大陆集团ADAS招聘丨老司机带你现场体验自动驾驶的快感
  12. 腾讯 监控系统服务器数据采集,腾讯天津数据中心机房监控项目
  13. 嵌入式学习步骤及方法(精典)
  14. 如何在Mac的内置词典中添加和删除单词
  15. CISCO ACL配置(目前)
  16. Linux下Vivado安装流程
  17. 大一计算机基础ppt练习题,计算机基础知识PPT练习题及答案DOC
  18. Ubuntu安装rz sz
  19. Android开发基础之控件ImageView及第三方库Glide的使用
  20. 神奇的二进制转换和运算

热门文章

  1. 面向对象之内置方法(简单)、组合。以及接口归一化设计与抽象类
  2. 201521123117 《Java程序设计》第1周学习总结
  3. python 基础学习3-函数
  4. linux shell中文显示
  5. lol简介/html
  6. ASP.NET(一):Reques对象和Response对象的区别,以及IsPostBack属性的用法
  7. Oracle11gR2 64bit+Oracle11gR2Client32bit+pl/sql 9
  8. SharePoint 2010 BCS - 简单实例(二)外部列表创建
  9. 基于开源Flash Server:Red5构建RTMP流媒体播放平台
  10. arach Linux设置静态,大神面对win7系统archlinux静态网络配置错误造成无法上网的还原办法...