3.2 Joystick 摇杆控件
******************************** Joystick.h ****************************
#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 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
*********************** Joystick.cpp ******************************
#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);
}
在 HelloWord.h中 加个 void update(float dt);
在 HelloWord.cpp中
void HelloWorld::update(float dt)
{/* D_UP,
D_DOWN,
D_LEFT,
D_RIGHT,
D_LEFT_UP,
D_LEFT_DOWN,
D_RIGHT_UP,
D_RIGHT_DOWN*/
switch (j->getDirection())
{
case 1:
log("D_UP");
break;
case 2:
log("D_DOWN");
break;
case 3:
log("D_LEFT");
break;
case 4:
log("D_RIGHT");
break;
case 5:
log("D_LEFT_UP");
break;
case 6:
log("D_LEFT_DOWN");
break;
case 7:
log("D_RIGHT_UP");
break;
case 8:
log("D_RIGHT_DOWN");
break;
default:
log("stop");
break;
}
}
之后调用检检摇杆**********************************
在 HelloWord中调用Joystick
*******************************************************************
普通模式
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();//启动
****************************************************************
存在死亡半径模式:(超出死亡半径将触点重置初始位置,移动失效)
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();//启动
*******************************************************************
设置失效半径:(在失效半径内将不会触发角度改变事件)
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();//启动
*-****************************************************************
设置自由变换位置:以鼠标按下的座标为初始位置
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();//启动
*********************************************************************
设置隐藏摇杆:(不显示摇杆底盘和触点,一般会设置成自由改变位置)
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();//启动
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.