类似关卡选择的这种功能游戏中经常看到,比如帮助场景,选择关卡,通过滑动的方式选择一些其他的东西等等。今天我们实现关卡的选择是使用CCScrollView这个类。当然还有一些其他的方法,比如使用cocostudio的page view也可以。我先说下整体的思路,CCScrollView这个类是继承自CCLayer的,本身的触摸事件有些bug,所以网上一般将这个层的touch事件处理为false,而使用它的父节点来处理触摸事件,我们也是采用这个做法。先定义一个LevelScene类,将CCScrollView加入进来,然后再定义一个layer层,这个层里边放的就是一些关卡的图片,然后将layer这个层作为CCScrollView的内容添加进去。好了,现在看代码吧。
1 | /*关卡选择类的头文件*/ |
2 | #ifndef _LEVEL_SCENE_H_ |
3 | #define _LEVEL_SCENE_H_ |
4 | #include "cocos2d.h" |
5 | //包含以下的头文件 |
6 | #include "cocos-ext.h" |
7 | |
8 | using namespace cocos2d::extension; |
9 | using namespace cocos2d; |
10 | |
11 | class LevelScene : public CCLayer |
12 | { |
13 | public : |
14 | bool init(); |
15 | CREATE_FUNC(LevelScene); |
16 | //以下是注册触摸事件和实现各种的touch函数 |
17 | void registerWithTouchDispatcher(); |
18 | bool ccTouchBegan(CCTouch * touch,CCEvent * pEvent); |
19 | void ccTouchMoved(CCTouch * touch,CCEvent * pEvent); |
20 | void ccTouchEnded(CCTouch * touch,CCEvent * pEvent); |
21 | //最后这个函数来校验每个关卡的位置,是各个关卡都位于屏幕的中央 |
22 | void adjustScrollView( float offset); |
23 | private : |
24 | //将CCScrollView作为自己的层添加进来 |
25 | CCScrollView * m_scrollView; |
26 | //触摸点的位置 |
27 | CCPoint m_touchPoint; |
28 | //CCScrollView的便宜量 |
29 | CCPoint m_offsetPoint; |
30 | //当前为第几个关卡 |
31 | int m_nCurPage; |
32 | }; |
33 | #endif |
1 | /*关卡选择类的具体实现*/ |
2 | #include "LevelScene.h" |
3 | #include <math.h> //用到了fabs()函数,用来求绝对值的 |
4 | |
5 | bool LevelScene::init() |
6 | { |
7 | bool bRet = false ; |
8 | do |
9 | { |
10 | CC_BREAK_IF(!CCLayer::init()); |
11 | |
12 | CCSize winSize = CCDirector::sharedDirector()->getWinSize(); |
13 | |
14 | //CCScrollView继承自CCLayer,传入的参数是view size的大小 |
15 | //view size也就是人看到的大小,content size也就是内容的大小 |
16 | //这里设置为整个屏幕的大小,也就是我们通过设备的整个屏幕去看里边的内容 |
17 | CCScrollView * scrollView = CCScrollView::create(CCSize(winSize.width,winSize.height)); |
18 | //等同于如下的语句 |
19 | /*CCScrollView * scrollView = CCScrollView::create(); |
20 | scrollView->setViewSize(CCSize(winSize.width,winSize.height));*/ |
21 | |
22 | //以下是CCScrollView的一些常用函数,但是我们这里都不会用到,实现的思路不同 |
23 | //设置是否有反弹的效果,反弹就是当超出scrollview的大小的时候回到原来的位置 |
24 | //scrollView->setBounceable(true); |
25 | //CCScrollView默认锚点是在(0,0)处 |
26 | //scrollView->ignoreAnchorPointForPosition(false); |
27 | //scrollView->setPosition(ccp(winSize.width/2,winSize.height/2)); |
28 | //设置滑动方向 |
29 | //kCCScrollViewDirectionHorizontal——水平滑动 |
30 | //kCCScrollViewDirectionVertical——垂直滑动 |
31 | //scrollView->setDirection(kCCScrollViewDirectionBoth); |
32 | |
33 | //创建一个CCLayer,将内容添加到CCLayer中,然后将这个layer添加到scrollview中 |
34 | CCLayer * layer = CCLayer::create(); |
35 | for ( int i = 0;i<5;i++) |
36 | { |
37 | CCString * string = CCString::createWithFormat( "%d.jpg" ,i+1); |
38 | CCSprite * sprite = CCSprite::create(string->getCString()); |
39 | //将所有的精灵都放到屏幕的中间显示 |
40 | sprite->setPosition(ccpAdd(ccp(winSize.width/2,winSize.height/2), |
41 | ccp(winSize.width*i,0))); |
42 | layer->addChild(sprite); |
43 | } |
44 | //设置scrollView中的内容,必须先设置内容再设置内容的大小 |
45 | scrollView->setContainer(layer); |
46 | //setContentSize()设置内容区的大小 |
47 | scrollView->setContentSize(CCSize(winSize.width*5,winSize.height)); |
48 | |
49 | //我们屏蔽scrollView这个层的触摸,采用其他的实现方法 |
50 | scrollView->setTouchEnabled( false ); |
51 | //设置里边内容的偏移量 |
52 | scrollView->setContentOffset(CCPoint(0,0)); |
53 | |
54 | //让本层来接受触摸事件 |
55 | this ->setTouchEnabled( true ); |
56 | |
57 | this ->addChild(scrollView); |
58 | |
59 | m_scrollView = scrollView; |
60 | this ->m_nCurPage = 0; |
61 | |
62 | bRet = true ; |
63 | } |
64 | while (0); |
65 | |
66 | return bRet; |
67 | } |
68 | |
69 | void LevelScene::registerWithTouchDispatcher() |
70 | { |
71 | CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate( this ,0, true ); |
72 | } |
73 | |
74 | bool LevelScene::ccTouchBegan(CCTouch * touch,CCEvent * pEvent) |
75 | { |
76 | //用开始的触摸点和scroll的偏移量初始化以下的成员变量 |
77 | this ->m_touchPoint = touch->getLocation(); |
78 | this ->m_offsetPoint = this ->m_scrollView->getContentOffset(); |
79 | |
80 | //以下的这一点特别要注意,大家可以先注释掉以下的这句话然后运行程序,会发现如果触摸不是很快 |
81 | //的时候不会有什么问题,但是如果触摸进行的很快,关卡的位置偏移的就不会正确,以下的代码正是解决这个问题到 |
82 | if (( int ) this ->m_offsetPoint.x%(( int )CCDirector::sharedDirector()->getWinSize().width) == 0) |
83 | { |
84 | return true ; |
85 | } |
86 | return false ; |
87 | } |
88 | |
89 | /*以下代码的整体含义就是当手指移动的时候,让关卡跟随手指移动,当移动结束的时候,判断结束点和开始 |
90 | 触摸点的位置,对关卡的位置做相应的处理*/ |
91 | |
92 | //设置关卡跟随手指的方向移动 |
93 | void LevelScene::ccTouchMoved(CCTouch * touch,CCEvent * pEvent) |
94 | { |
95 | CCPoint point = touch->getLocation(); |
96 | CCPoint direction = ccpSub(point, this ->m_touchPoint); |
97 | |
98 | //CCPoint spriteDirection = ccpAdd(this->m_offsetPoint,direction); |
99 | //只在x方向偏移 |
100 | CCPoint spriteDirection = CCPoint(direction.x+ this ->m_offsetPoint.x,0); |
101 | this ->m_scrollView->setContentOffset(spriteDirection); |
102 | } |
103 | |
104 | //以下的代码是重点,当结束触摸的时候,为了使关卡显示在屏幕的中间,我们需要这么做 |
105 | void LevelScene::ccTouchEnded(CCTouch * touch,CCEvent * pEvent) |
106 | { |
107 | CCPoint endPoint = touch->getLocation(); |
108 | float distance = endPoint.x- this ->m_touchPoint.x; |
109 | //手指移动的距离小于20的时候,就将偏移量作为0处理 |
110 | if ( fabs (distance) < 20) |
111 | { |
112 | this ->adjustScrollView(0); |
113 | } |
114 | else |
115 | { |
116 | //将偏移量作为参数传进来 |
117 | this ->adjustScrollView(distance); |
118 | } |
119 | } |
120 | |
121 | //调整关卡的最终位置 |
122 | void LevelScene::adjustScrollView( float offset) |
123 | { |
124 | CCSize winSize = CCDirector::sharedDirector()->getWinSize(); |
125 | // 我们根据 offset 的实际情况来判断移动效果 |
126 | //如果手指往左划,offset大于0,说明页面在减小,往右增大 |
127 | if (offset < 0) |
128 | m_nCurPage ++; |
129 | else if (offset > 0) |
130 | m_nCurPage --; |
131 | |
132 | //不允许超出最左边的一页和最右边的一页 |
133 | if (m_nCurPage < 0) |
134 | m_nCurPage = 0; |
135 | else if (m_nCurPage > 4) |
136 | m_nCurPage = 4; |
137 | |
138 | CCPoint adjustPoint = ccp(-winSize.width * m_nCurPage , 0); |
139 | //这个函数比setContentOffset多了一个参数,第二个参数是设置时间的,就是用多长的时间来改变偏移量 |
140 | this ->m_scrollView->setContentOffsetInDuration(adjustPoint, 0.3f); |
141 | } |
1 | bool HelloWorld::init() |
2 | { |
3 | // |
4 | // 1. super init first |
5 | if ( !CCLayer::init() ) |
6 | { |
7 | return false ; |
8 | } |
9 | |
10 | CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); |
11 | |
12 | //添加背景图片 |
13 | CCSprite * sprite = CCSprite::create( "background.png" ); |
14 | sprite->setPosition(ccp(visibleSize.width/2,visibleSize.height/2)); |
15 | this ->addChild(sprite); |
16 | |
17 | //添加CCScrollView层 |
18 | LevelScene * scrollView = LevelScene::create(); |
19 | this ->addChild(scrollView); |
20 | |
21 | return true ; |
}
本文由 小 塔 原创,皂茄花,转载请保留文章出处!