最近想做格斗游戏,那么就要有摇杆控件,不想去看别人的代码就自己写了个摇杆控件,实现起来很简单。
话不多说,看代码:
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
@H_404_77@
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
{
:
/**启动搖杆器*/
void
onRun();
/**清除数据*/
onDisable();
/**设置死亡半径,即超出半径將摇杆器失效*/
setDieRadius(
float
radius);
/**设置无效区域半径(如果在无效区域內,將重置)*/
setFailRadius(
radius);
/**是否显示底盘和触点*/
setVisibleJoystick(
bool
visible);
/**是否自由变换摇杆器的位置,即在屏幕上每一次按下鼠标时的坐标将是摇杆器的坐标,移动时将不改变摇杆器坐标,直到下次按下鼠标*/
setAutoPosition(
value);
/**回调函数指针*/
std::function<
(JoystickEnum)>onDirection;
static
Joystick*create(std::stringchassisPath,std::stringdotPath);
/**初始化摇杆器(需要传入底盘和触点图片路径)*/
initWithJoystick(std::stringchassisPath,std::stringdotPath);
protected
:
/**有效区域半径*/
_radius;
/**失效区域半径*/
_failradius;
/**是否移出有效区域*/
isMoveOut;
/**是否存在有效区域半径*/
isDieRadius;
/**是否自由变换摇杆器坐标*/
isAutoPosition;
/**方向*/
JoystickEnum_direction;
/**底盘*/
Sprite*_chassis;
/**触点*/
Sprite*_touchDot;
EventListenerTouchOneByOne*listener;
onTouchBegan(Touch*touch,Event*event);
onTouchMoved(Touch*touch,Event*event);
onTouchEnded(Touch*touch,Event*event);
/**
1、设置触点,并判断是否在无效区域内(如果在无效区域内,将重置)
2、发送角度变化(如果不在无效区域内)*/
setTouchDotPosition(Vec2vec1,Vec2vec2);
/**
1、计算摇杆器八方向
2、发送角度变化,回调弧度变化函数*/
changeAngle(Vec2position);
callDirectionFun();
/**重置(当弧度不是DEFAULT时才重置)*/
resetState();
};
#endif
|
#include"Joystick.h"
Joystick*Joystick::create(std::stringchassisPath,std::stringdotPath)
{
autojoystick=
new
Joystick();
joystick->initWithJoystick(chassisPath,dotPath);
return
joystick;
}
Joystick::initWithJoystick(std::stringchassisPath,std::stringdotPath)
{
_chassis=Sprite::create(chassisPath);
this
->addChild(_chassis,0);
_touchDot=Sprite::create(dotPath);
->addChild(_touchDot,1);
isDieRadius=
false
;
isAutoPosition=
;
isMoveOut=
;
_direction=DEFAULT;
}
Joystick::onRun()
{
listener=EventListenerTouchOneByOne::create();
listener->setSwallowTouches(
);
listener->onTouchBegan=CC_CALLBACK_2(Joystick::onTouchBegan,
);
listener->onTouchMoved=CC_CALLBACK_2(Joystick::onTouchMoved,monospace!important; font-size:1em!important; min-height:inherit!important">);
listener->onTouchEnded=CC_CALLBACK_2(Joystick::onTouchEnded,monospace!important; font-size:1em!important; min-height:inherit!important">);
->_eventDispatcher->addEventListenerWithSceneGraPHPriority(listener,monospace!important; font-size:1em!important; min-height:inherit!important">);
}
Joystick::onTouchBegan(Touch*touch,Event*event)
{
Vec2locationInNode=
->convertToNodeSpace(touch->getLocation());
if
(isAutoPosition)
{
->setPosition(touch->getLocation());
return
true
;
}
(isAutoPosition==
&&isDieRadius)
{
(locationInNode.getLength()>_radius)
{
;
}
}
_touchDot->setPosition(locationInNode);
(locationInNode.getLength()>_failradius)
{
changeAngle(locationInNode);
}
;
}
Joystick::onTouchMoved(Touch*touch,Event*event)
{
->convertToNodeSpace(touch->getLocation());
(isDieRadius)
{
(locationInNode.getLength()<_radius)
{
(isMoveOut)
{
_touchDot->setPosition(locationInNode);
;
}
setTouchDotPosition(locationInNode,_touchDot->getPosition()+touch->getDelta());
;
}
}
else
{
}
;
_touchDot->setPosition(0,0);
resetState();
}
Joystick::onTouchEnded(Touch*touch,Event*event)
{
resetState();
}
Joystick::setTouchDotPosition(Vec2vec1,Vec2vec2)
{
_touchDot->setPosition(vec2);
(_failradius>0)
{
(vec1.getLength()<_failradius)
{
resetState();
;
}
}
changeAngle(vec1);
}
Joystick::setDieRadius(
radius)
{
_radius=radius;
;
}
Joystick::setAutoPosition(
value)
{
isAutoPosition=value;
}
Joystick::setFailRadius(
radius)
{
_failradius=radius;
}
Joystick::onDisable()
{
->_eventDispatcher->removeEventListener(listener);
;
;
;
}
Joystick::changeAngle(Vec2position)
{
autoangle=CC_RADIANS_TO_DEGREES(position.getAngle());
(angle>-22.5&&angle<22.5)
{
_direction=D_RIGHT;
}
else
(angle>22.5&&angle<67.5)
{
_direction=D_RIGHT_UP;
}
(angle>67.5&&angle<112.5)
{
_direction=D_UP;
}
(angle>112.5&&angle<157.5)
{
_direction=D_LEFT_UP;
}
((angle>157.5&&angle<180)||(angle<-157.5&&angle>-180))
{
_direction=D_LEFT;
}
(angle<-112.5&&angle>-157.5)
{
_direction=D_LEFT_DOWN;
}
(angle<-67.5&&angle>-112.5)
{
_direction=D_DOWN;
}
(angle<-22.5&&angle>-67.5)
{
_direction=D_RIGHT_DOWN;
}
callDirectionFun();
}
Joystick::callDirectionFun()
{
(onDirection)
{
onDirection(_direction);
}
}
Joystick::resetState()
{
(_direction!=DEFAULT)
{
_direction=DEFAULT;
callDirectionFun();
}
}
Joystick::setVisibleJoystick(
visible)
{
_chassis->setVisible(visible);
_touchDot->setVisible(visible);
}
|
当然,如果有用到的朋友可以自己修改。这只是最简单的实现。
下面有效果图,不过加载比较慢
普通模式:
->addChild(joystick);
joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200));
//設置初始位置
joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection,0)!important">//角度变化更新(onDirection(JoystickEnumenums))
joystick->onRun();
//启动
|
存在死亡半径模式:(超出死亡半径将触点重置初始位置,移动失效)
//设置初始位置
joystick->setDieRadius(60);
//设置死亡半径(外圈)
//角度变化更新(onDirection(JoystickEnumenums))
|