写这篇博客的目的主要是记录一下 虚拟摇杆的实现过程。虚拟摇杆一般分文四方向和八方向,也主要根据项目需求来决定。直接进入主题吧。
先上效果图:
- 方向的思路分析
看图,说先我们可以将8个方向在坐标系中画出来,这里涉及到余弦定理,高中数学可能经常看到这样的图,从图中可以很明确的看出每45°一个方向。这里我们只需要根据a的度数来判别方向。(例如:022.5°和337.5°360° 是右方向,67.5112.5是上方向,等等)。那么问题来了,怎么去算出a的角度呢,根据反余弦定义,我们一般只能算出0180°,那如何才能得到0~360°呢?这里隐约记得当a大于180度时候,a的余弦值等于(360-a)的余弦(如果不熟悉的话记得补一补高中数学了)。这样就解决了方向问题啦。
上代码:
/**
* 获取以p1为圆心,p2p1与x轴的弧度值
*/
float GameRocker::getRad(cocos2d::Point p1, cocos2d::Point p2)
{
float xx = p2.x - p1.x;
float yy = p2.y - p1.y;
// 斜边
float xie = sqrt(pow(xx, 2) + pow(yy, 2));
// yy >= 0 弧度在于 0 到 π 之间。(0~180°)
// yy < 0 弧度在于 π 到 2π 之间。(180°~360°)
float rad = yy >= 0 ? (acos(xx / xie)) : (PI * 2 - acos(xx / xie));
return rad;
}
- 虚拟摇杆类的实现
有一个问题需要思考,这个遥感类应该继承Node呢还是Layer,为什么我会考虑这个,因为我看到一些遥感类都是继承Layer,而我一般喜欢继承Node。而且我觉得继承Node要比继承Layer更加灵活(这个问题希望大牛过来指点)。
无论继承Node还是Layer还是其他,我们都需要添加触摸监听事件。
很多游戏中,我们发现虚拟摇杆会有个额外状态,常见的就是加速,玩儿过手机版的2K的应该熟悉。我也考虑做类似的功能,还有许多游戏中摇杆可能不是固定的。这里我就直接上代码了。
GameRocker.h
/**
* 摇杆状态类
*/
class GameRockerState
{
public:
/**
* 摇杆方向枚举
*/
enum class DirectionType
{
StayType,
LeftType,
LeftUpType,
UpType,
RightUpType,
RightType,
RightDownType,
DownType,
LeftDownType,
};
/**
* 速度状态
*/
enum class SpeedState
{
StayState,
NormalState,
QuickState,
};
public:
GameRockerState():_direction(GameRockerState::DirectionType::StayType),_speedState(GameRockerState::SpeedState::StayState) {
};
GameRockerState(const GameRockerState& state){
_direction = state.getDirection();
_speedState = state.getSpeedState();
};
~GameRockerState(){
};
GameRockerState operator = (const GameRockerState& state)
{
if(this == &state) return *this;
_direction = state.getDirection();
_speedState = state.getSpeedState();
return *this;
};
bool operator == (const GameRockerState& state)
{
return (_direction == state.getDirection() && _speedState == state.getSpeedState());
}
bool operator != (const GameRockerState& state)
{
return !(*this==state);
}
protected:
CC_SYNTHESIZE_PASS_BY_REF(GameRockerState::DirectionType,_direction,Direction);
CC_SYNTHESIZE_PASS_BY_REF(GameRockerState::SpeedState,_speedState,SpeedState);
};
/**
* 摇杆类
*/
class GameRocker:public cocos2d::Node
{
public:
typedef std::function<void(const GameRockerState&)> StateChangeCallback;
/**
* 速度状态
*/
enum class KeysType
{
Key_4,