forked from SuooL/KungfuBoy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SelectGate.cpp
154 lines (147 loc) · 4.86 KB
/
SelectGate.cpp
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
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "SelectGate.h"
#include <math.h>
#define PI acos(-1)
//菜单的缩小比例 最小的比例是1-MENU_SCALE
#define MENU_SCALE 0.3
//菜单的倾斜度
#define MENU_ASLOPE 60.0
//calcFunction(x) 为 x/(x+a),其中a为常数
#define CALC_A 1
//动画运行时间
#define ANIMATION_DURATION 0.3f
//菜单项的大小与屏幕的比例,当然可以通过setContentSize设置
#define CONTENT_SIZE_SCALE (2.0/3)
//菜单项长度与菜单长度的比例 滑动一个菜单项长度,菜单项变化一个
#define ITEM_SIZE_SCALE (1.0/4)
/*
代码里面还有可以设置的参数,这里没有一一例出或给出函数
*/
USING_NS_CC;
bool SelectGate::init(){
if (!Layer::init())
return false;
_index = 0;
_lastIndex = 0;
this->ignoreAnchorPointForPosition(false);
_selectedItem = nullptr;
auto size = Director::getInstance()->getWinSize();
this->setContentSize(size*CONTENT_SIZE_SCALE);
this->setAnchorPoint(Point(0.5f, 0.5f));
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = CC_CALLBACK_2(SelectGate::onTouchBegan, this);
listener->onTouchMoved = CC_CALLBACK_2(SelectGate::onTouchMoved, this);
listener->onTouchEnded = CC_CALLBACK_2(SelectGate::onTouchEnded, this);
getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
return true;
};
void SelectGate::addMenuItem(cocos2d::MenuItem *item){
item->setPosition(this->getContentSize().width / 2, this->getContentSize().height / 2);
this->addChild(item);
_items.pushBack(item);
reset();
//如果希望开始没有移动效果,改成updatePosition函数即可
updatePositionWithAnimation();
return;
}
void SelectGate::updatePosition(){
auto menuSize = getContentSize();
for (int i = 0; i < _items.size(); i++){
//设置位置
float x = calcFunction(i - _index, menuSize.width / 2);
_items.at(i)->setPosition(Point(menuSize.width / 2 + x, menuSize.height / 2));
//设置zOrder,即绘制顺序
_items.at(i)->setZOrder(-abs((i - _index) * 100));
//设置伸缩比例
_items.at(i)->setScale(1.0 - abs(calcFunction(i - _index, MENU_SCALE)));
//设置倾斜,Node没有setCamera函数,将OrbitCamera的运行时间设为0来达到效果
auto orbit1 = OrbitCamera::create(0, 1, 0, calcFunction(i - _lastIndex, MENU_ASLOPE), calcFunction(i - _lastIndex, MENU_ASLOPE) - calcFunction(i - _index, MENU_ASLOPE), 0, 0);
_items.at(i)->runAction(orbit1);
}
return;
}
void SelectGate::updatePositionWithAnimation(){
//先停止所有可能存在的动作
for (int i = 0; i < _items.size(); i++)
_items.at(i)->stopAllActions();
auto menuSize = getContentSize();
for (int i = 0; i < _items.size(); i++){
_items.at(i)->setZOrder(-abs((i - _index) * 100));
float x = calcFunction(i - _index, menuSize.width / 2);
auto moveTo = MoveTo::create(ANIMATION_DURATION, Point(menuSize.width / 2 + x, menuSize.height / 2));
_items.at(i)->runAction(moveTo);
auto scaleTo = ScaleTo::create(ANIMATION_DURATION, (1 - abs(calcFunction(i - _index, MENU_SCALE))));
_items.at(i)->runAction(scaleTo);
auto orbit1 = OrbitCamera::create(ANIMATION_DURATION, 1, 0, calcFunction(i - _lastIndex, MENU_ASLOPE), calcFunction(i - _index, MENU_ASLOPE) - calcFunction(i - _lastIndex, MENU_ASLOPE), 0, 0);
_items.at(i)->runAction(orbit1);
}
scheduleOnce(schedule_selector(SelectGate::actionEndCallBack), ANIMATION_DURATION);
return;
}
void SelectGate::reset(){
_lastIndex = 0;
_index = 0;
}
void SelectGate::setIndex(int index){
_lastIndex = _index;
this->_index = index;
}
float SelectGate::getIndex(){
return _index;
}
MenuItem * SelectGate::getCurrentItem(){
if (_items.size() == 0)
return nullptr;
return _items.at(_index);
}
bool SelectGate::onTouchBegan(Touch* touch, Event* event){
//先停止所有可能存在的动作
for (int i = 0; i < _items.size(); i++)
_items.at(i)->stopAllActions();
if (_selectedItem)
_selectedItem->unselected();
auto position = this->convertToNodeSpace(touch->getLocation());
auto size = this->getContentSize();
auto rect = Rect(0, 0, size.width, size.height);
if (rect.containsPoint(position)){
return true;
}
return false;
}
void SelectGate::onTouchEnded(Touch* touch, Event* event){
auto size = getContentSize();
auto xDelta = touch->getLocation().x - touch->getStartLocation().x;
rectify(xDelta>0);
if (abs(xDelta)<size.width / 24 && _selectedItem)
_selectedItem->activate();
updatePositionWithAnimation();
return;
}
void SelectGate::onTouchMoved(Touch* touch, Event* event){
auto xDelta = touch->getDelta().x;
auto size = getContentSize();
_lastIndex = _index;
_index -= xDelta / (size.width *ITEM_SIZE_SCALE);
updatePosition();
return;
}
void SelectGate::rectify(bool forward){
auto index = getIndex();
if (index < 0)
index = 0;
if (index>_items.size() - 1)
index = _items.size() - 1;
if (forward){
index = (int)(index + 0.4);
}
else
index = (int)(index + 0.6);
setIndex((int)index);
}
void SelectGate::actionEndCallBack(float dx){
_selectedItem = getCurrentItem();
if (_selectedItem)
_selectedItem->selected();
}
float SelectGate::calcFunction(float index, float width){
return width*index / (abs(index) + CALC_A);
}