cocos2dx触摸摇杆

最近想做格斗游戏,那么就要有摇杆控件,不想去看别人的代码就自己写了个摇杆控件,实现起来很简单。


话不多说,看代码:

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(); //启动

1408606310243864.gif


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

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(); //启动

1408606352236053.gif


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

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(); //启动

1408606384119875.gif


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

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(); //启动

1408606989191417.gif


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

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(); //启动

1408606470587043.gif


来源网址:http://www.cnblogs.com/Richard-Core/p/3915898.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值