Joystick 摇杆控件

本文转载至Cocos2d-x v3.2学习笔记(十)Joystick 摇杆控件

代码:

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
#ifndef __Joystick__
#define __Joystick__
 
#include "cocos2d.h"
USING_NS_CC;
 
enum  JoystickEnum
{
     DEFAULT,
     D_UP,
     D_DOWN,
     D_LEFT,
     D_RIGHT,
     D_LEFT_UP,
     D_LEFT_DOWN,
     D_RIGHT_UP,
     D_RIGHT_DOWN
};
 
class  Joystick :  public  Layer
{
     public :
         /** 启动搖杆器 */
         void  onRun();
         /** 清除数据 */
         void  onDisable();
         /** 设置死亡半径,即超出半径將摇杆器失效 */
         void  setDieRadius( float  radius);
         /** 设置无效区域半径(如果在无效区域內,將重置) */
         void  setFailRadius( float  radius);
         /** 是否显示底盘和触点 */
         void  setVisibleJoystick( bool  visible);
         /** 是否自由变换摇杆器的位置,即在屏幕上每一次按下鼠标时的坐标将是摇杆器的坐标,移动时将不改变摇杆器坐标,直到下次按下鼠标 */
         void  setAutoPosition( bool  value);
         /** 回调函数指针 */
         std::function< void (JoystickEnum)> onDirection;
         /** 静态创建函数(需要传入底盘和触点图片路径) */
         static  Joystick* create(std::string chassisPath,std::string dotPath);
         /** 初始化摇杆器(需要传入底盘和触点图片路径) */
         void  initWithJoystick(std::string chassisPath,std::string dotPath);
     protected :
         /** 有效区域半径 */
         float  _radius;
         /** 失效区域半径 */
         float  _failradius;
         /** 是否移出有效区域 */
         bool  isMoveOut;
         /** 是否存在有效区域半径 */
         bool  isDieRadius;
         /** 是否自由变换摇杆器坐标 */
         bool  isAutoPosition;
         /** 方向 */
         JoystickEnum _direction;
         /** 底盘 */
         Sprite* _chassis;
         /** 触点 */
         Sprite* _touchDot;
         EventListenerTouchOneByOne* listener;
     
         bool  onTouchBegan(Touch* touch,Event* event);
         void  onTouchMoved(Touch* touch,Event* event);
         void  onTouchEnded(Touch* touch,Event* event);
         /** 
         1、设置触点,并判断是否在无效区域内(如果在无效区域内,将重置)
         2、发送角度变化(如果不在无效区域内) */
         void  setTouchDotPosition(Vec2 vec1,Vec2 vec2);
         /** 
         1、计算摇杆器八方向
         2、发送角度变化,回调弧度变化函数 */
         void  changeAngle( Vec2 position );
         /** 回调注册的监听函数 */
         void  callDirectionFun();
         /** 重置(当弧度不是 DEFAULT时才重置) */
         void  resetState();
     
};
 
#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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include "Joystick.h"
 
Joystick* Joystick::create(std::string chassisPath,std::string dotPath)
{
     auto joystick =  new  Joystick();
     joystick->initWithJoystick(chassisPath,dotPath);
     return  joystick;
}
 
void  Joystick::initWithJoystick(std::string chassisPath,std::string dotPath)
{
     _chassis = Sprite::create(chassisPath);
     this ->addChild(_chassis,0);
     _touchDot = Sprite::create(dotPath);
     this ->addChild(_touchDot,1);
 
     isDieRadius =  false ;
     isAutoPosition =  false ;
     isMoveOut =  false ;
     _direction = DEFAULT;
}
 
void  Joystick::onRun()
{
     listener = EventListenerTouchOneByOne::create();
     listener->setSwallowTouches( false );
     listener->onTouchBegan = CC_CALLBACK_2(Joystick::onTouchBegan, this );
     listener->onTouchMoved = CC_CALLBACK_2(Joystick::onTouchMoved, this );
     listener->onTouchEnded = CC_CALLBACK_2(Joystick::onTouchEnded, this );
     this ->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this );
}
 
bool  Joystick::onTouchBegan(Touch* touch,Event* event)
{
     Vec2 locationInNode =  this ->convertToNodeSpace(touch->getLocation());
     if ( isAutoPosition )
     {
         this ->setPosition(touch->getLocation());
         return  true ;
     }
     if ( isAutoPosition== false  && isDieRadius )
     {
         if ( locationInNode.getLength() > _radius )
         {
             return  false ;
         }
     }
     _touchDot->setPosition(locationInNode);
     if ( locationInNode.getLength() > _failradius )
     {
         changeAngle(locationInNode);
     }
     return  true ;
}
void  Joystick::onTouchMoved(Touch* touch,Event* event)
{
     Vec2 locationInNode =  this ->convertToNodeSpace(touch->getLocation());
     if ( isDieRadius )
     {
         if ( locationInNode.getLength() < _radius )
         {
             if ( isMoveOut )
             {
                 _touchDot->setPosition(locationInNode);
                 isMoveOut =  false ;
             }
             setTouchDotPosition(locationInNode,_touchDot->getPosition() + touch->getDelta());
             return ;
         }
     }
     else
     {
         setTouchDotPosition(locationInNode,_touchDot->getPosition() + touch->getDelta());
         return ;
     }
     
     isMoveOut =  true ;
     _touchDot->setPosition(0,0);
     resetState();
}
void  Joystick::onTouchEnded(Touch* touch,Event* event)
{
     _touchDot->setPosition(0,0);
     isMoveOut =  false ;
     resetState();
}
 
void  Joystick::setTouchDotPosition(Vec2 vec1,Vec2 vec2)
{
     _touchDot->setPosition(vec2);
     if ( _failradius>0 )
     {
         if ( vec1.getLength() < _failradius )
         {
             resetState();
             return ;
         }
     }
     changeAngle(vec1);
}
 
void  Joystick::setDieRadius( float  radius)
{
     _radius = radius;
     isDieRadius =  true ;
}
 
void  Joystick::setAutoPosition( bool  value)
{
     isAutoPosition = value;
}
 
void  Joystick::setFailRadius( float  radius)
{
     _failradius = radius;
}
 
void  Joystick::onDisable()
{
     this ->_eventDispatcher->removeEventListener(listener);
     isDieRadius =  false ;
     isAutoPosition =  false ;
     isMoveOut =  false ;
}
 
void  Joystick::changeAngle( Vec2 position )
{
     auto angle = CC_RADIANS_TO_DEGREES(position.getAngle());
     if (angle > -22.5 && angle < 22.5)
     {
         _direction=D_RIGHT;
     }
     else  if (angle > 22.5 && angle < 67.5)
     {
         _direction=D_RIGHT_UP;
     }
     else  if (angle > 67.5 && angle < 112.5)
     {
         _direction=D_UP;
     }
     else  if (angle > 112.5 && angle < 157.5)
     {
         _direction=D_LEFT_UP;
     }
     else  if ((angle > 157.5 && angle < 180)||(angle < -157.5 && angle > -180))
     {
         _direction=D_LEFT;
     }
     else  if (angle < -112.5 && angle > -157.5)
     {
         _direction=D_LEFT_DOWN;
     }
     else  if (angle < -67.5 && angle > -112.5)
     {
         _direction=D_DOWN;
     }
     else  if (angle < -22.5 && angle > -67.5)
     {
         _direction=D_RIGHT_DOWN;
     }
     callDirectionFun();
}
 
void  Joystick::callDirectionFun()
{
     if ( onDirection )
     {
         onDirection(_direction);
     }
}
 
void  Joystick::resetState()
{
     if (_direction != DEFAULT)
     {
         _direction = DEFAULT;
         callDirectionFun();
     }
}
 
void  Joystick::setVisibleJoystick( bool  visible)
{
     _chassis->setVisible(visible);
     _touchDot->setVisible(visible);
}

当然,如果有用到的朋友可以自己修改。这只是最简单的实现。

 

下面有效果图,不过加载比较慢

 

普通模式:

1
2
3
4
5
auto joystick = Joystick::create( "rocker.png" , "rocker_joy.png" ); //通过两张图片初始化控件
this ->addChild(joystick);
joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200)); //設置初始位置  
joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection, this ); //角度变化更新(onDirection(JoystickEnum enums))
joystick->onRun(); //启动

 

存在死亡半径模式:(超出死亡半径将触点重置初始位置,移动失效)

1
2
3
4
5
6
auto joystick = Joystick::create( "rocker.png" , "rocker_joy.png" ); //通过两张图片初始化控件
this ->addChild(joystick);
joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200)); //设置初始位置
joystick->setDieRadius(60); //设置死亡半径(外圈)
joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection, this ); //角度变化更新(onDirection(JoystickEnum enums))
joystick->onRun(); //启动

 

设置失效半径:(在失效半径内将不会触发角度改变事件)

1
2
3
4
5
6
7
auto joystick = Joystick::create( "rocker.png" , "rocker_joy.png" ); //通过两张图片初始化控件
this ->addChild(joystick);
joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200)); //设置初始位置
joystick->setDieRadius(60); //设置死亡半径(外圈)
joystick->setFailRadius(30); //设置失效半径(內圈) 
joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection, this ); //角度变化更新(onDirection(JoystickEnum enums))
joystick->onRun(); //启动

 

设置自由变换位置:以鼠标按下的坐标为初始位置

1
2
3
4
5
6
auto joystick = Joystick::create( "rocker.png" , "rocker_joy.png" ); //通过两张图片初始化控件
this ->addChild(joystick);
joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200)); //设置初始位置
joystick->setAutoPosition( true ); //是否自由改变坐标
joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection, this ); //角度变化更新
joystick->onRun(); //启动

 

设置隐藏摇杆:(不显示摇杆底盘和触点,一般会设置成自由改变位置)

1
2
3
4
5
6
7
auto joystick = Joystick::create( "rocker.png" , "rocker_joy.png" ); //通过两张图片初始化控件
this ->addChild(joystick);
joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200)); //设置初始位置
joystick->setAutoPosition( true ); //是否自由改变坐标
joystick->setVisibleJoystick( false ); //是否显示
joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection, this ); //角度变化更新
joystick->onRun(); //启动

 

转载于:https://www.cnblogs.com/dudu580231/p/4569916.html

你可能感兴趣的:(javascript,前端,游戏)