用到相似三角形,和两点间的距离公式。
具体实现如下。
头文件
#ifndef _MYROCKER_H_
#define _MYROCKER_H_
#include"cocos2d.h"
//摇杆状态枚举
enum ROCKER_STATE
{
ROCKER_STAT,
ROCKER_UP,
ROCKER_DOWN,
ROCKER_LEFT,
ROCKER_RIGHT
};
class MyRocker:public cocos2d::Layer
{
private:
//摇杆状态
ROCKER_STATE state;
//摇杆背景
cocos2d::Sprite*m_spRockerbg;
//摇杆
cocos2d::Sprite*m_spRocker;
//单点触摸事件
cocos2d::EventListenerTouchOneByOne*_listenertouch;
//是否触碰摇杆
bool m_isTouchRocker;
//动态获取坐标
cocos2d::Vec2 getRockerPos(cocos2d::Vec2 touchPos);
public:
//获取摇杆
cocos2d::Vec2 getDirection();
//获取摇杆状态
ROCKER_STATE getState();
virtual void setPosition(const cocos2d::Vec2& pos) override//重写,有继承关系,在子类中
{
m_spRockerbg->setPosition(pos);
m_spRocker->setPosition(pos);
}
static MyRocker*create(const std::string& rockerbgfilename,const std::string& rockerfilename,const cocos2d::Vec2& pos);
virtual bool init(const std::string& rockerbgfilename, const std::string& rockerfilename, const cocos2d::Vec2& pos);
};
#endif
源文件
#include"MyRocker.h"
USING_NS_CC;
Vec2 MyRocker::getRockerPos(Vec2 touchPos)
{
//大三角
float R = touchPos.distance(m_spRockerbg->getPosition());
float X = touchPos.x - m_spRockerbg->getPositionX();
float Y = touchPos.y - m_spRockerbg->getPositionY();
//小三角
float r = m_spRockerbg->getContentSize().width / 2;
float x = r / R*X;
float y = r / R*Y;
x += m_spRockerbg->getPositionX();
y += m_spRockerbg->getPositionY();
return Vec2(x, y);
}
//获取摇杆状态
ROCKER_STATE MyRocker::getState()
{
return state;
}
Vec2 MyRocker::getDirection()
{
float x = m_spRocker->getPositionX() - m_spRockerbg->getPositionX();
float y = m_spRocker->getPositionY() - m_spRockerbg->getPositionY();
Vec2 vec2(x, y);
vec2.normalize();
return vec2;
}
MyRocker*MyRocker::create(const std::string& rockerbgfilename, const std::string& rockerfilename, const Vec2& pos)
{
MyRocker*myrocker = new MyRocker;
if (myrocker&&myrocker->init(rockerbgfilename, rockerfilename, pos))
{
myrocker->autorelease();
}
else
{
delete myrocker;
myrocker = nullptr;
}
return myrocker;
}
bool MyRocker::init(const std::string& rockerbgfilename, const std::string& rockerfilename, const Vec2& pos)
{
if (!Layer::init())
{
return false;
}
m_isTouchRocker = false;
state = ROCKER_STAT;
//摇杆背景
m_spRockerbg = Sprite::create(rockerbgfilename);
m_spRockerbg->setLocalZOrder(5);
this->addChild(m_spRockerbg);
m_spRockerbg->setPosition(pos);
//摇杆
m_spRocker = Sprite::create(rockerfilename);
m_spRocker->setLocalZOrder(5);
this->addChild(m_spRocker);
m_spRocker->setPosition(pos);
//初始化单点触摸事件
_listenertouch = EventListenerTouchOneByOne::create();
_listenertouch->onTouchBegan = [&](Touch*touch, Event*event){
//1获取触摸点坐标
Vec2 touchPos = touch->getLocation();
//2.获取摇杆的包围盒
Rect boundingbox = m_spRocker->getBoundingBox();
//3,判断包围盒是否包含触摸点坐标
if (boundingbox.containsPoint(touchPos))
{
m_isTouchRocker = true;
m_spRocker->setOpacity(127);
m_spRockerbg->setOpacity(127);
}
return true;
};
_listenertouch->onTouchMoved = [&](Touch*touch, Event*event){
//有触摸到摇杆
if (m_isTouchRocker)
{
//1获取触摸点坐标
Vec2 pos = touch->getLocation();
// 2.判断触摸点是否在摇杆背景范围内
// 触摸点到圆心的距离
float dis = pos.distance(m_spRockerbg->getPosition());
//圆的半径
float r = m_spRockerbg->getContentSize().width / 2;
if (dis < r)
{//跟随手指移动
m_spRocker->setPosition(pos);
}
else
{//不在,动态获取坐标设置给摇杆
m_spRocker->setPosition(getRockerPos(pos));
}
// // 根据手指的位置来确定摇杆的状态
pos -= m_spRockerbg->getPosition();
if (pos.y / pos.x >= 1 || pos.y / pos.x <= -1)
{
if (pos.y > 0)
{
state = ROCKER_UP;
}
else
{
state = ROCKER_DOWN;
}
}
else if (pos.y / pos.x<1 && pos.y / pos.x>-1)
{
if (pos.x > 0)
{
state = ROCKER_RIGHT;
}
else
{
state = ROCKER_LEFT;
}
}
}
};
_listenertouch->onTouchEnded = [&](Touch*touch, Event*event){
// 1.是否触碰到摇杆还原
m_isTouchRocker = false;
// 2.摇杆位置还原
m_spRocker->setPosition(m_spRockerbg->getPosition());
//m_spRocker->runAction(MoveTo::create(0.1, m_spRockerBG->getPosition()));
// 3.还原摇杆状态
state = ROCKER_STAT;
m_spRocker->setOpacity(255);
m_spRockerbg->setOpacity(255);
};
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(_listenertouch, this);
return true;
}