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