1. 八方向虚拟摇杆的实现
准备工作: 我们需要两张图片,一张是摇杆的,一张是摇杆背景的图片
将这两张图片拷贝到工程的Resouce目录下, 接下来我们开始编码了.
打开我们的工程
创建一个摇杆类继承自Layer
JoyStick.hpp
#ifndef JoyStick_hpp
#define JoyStick_hpp
#include "cocos2d.h"
class JoyStick : public cocos2d::Layer
{
public:
virtual bool init() override;
CREATE_FUNC(JoyStick);
};
#endif
JoyStick.cpp
#include "JoyStick.hpp"
USING_NS_CC;
bool JoyStick::init()
{
if (!Layer::init()) {
return false;
}
/*1. 创建摇杆的背景*/
Sprite* rocker_bg = Sprite::create("joystickBg.png");
rocker_bg->setPosition(Vec2(150,150));
addChild(rocker_bg);
/*2. 创建摇杆*/
Sprite* rocker = Sprite::create("joystick.png");
rocker->setPosition(Vec2(150,150));
addChild(rocker);
return true;
}
然后在HelloWorld.cpp中将我们的摇杆层添加到场景中
先引入头文件 #include "JoyStick.hpp"
在HelloWorld::init() 函数中添加以下代码
JoyStick* rocker = JoyStick::create();
rocker->setPosition(Vec2::ZERO);
addChild(rocker);
之后开始运行吧, 是不是已经看到有摇杆的雏形了? 我们继续
摇杆摇杆, 那我们怎么能让它动起来呢? 我们为该方法添加触摸事件, 接下来修改我们的源码。
JoyStick.hpp
#ifndef JoyStick_hpp
#define JoyStick_hpp
#include "cocos2d.h"
class JoyStick : public cocos2d::Layer
{
public:
virtual bool init() override;
CREATE_FUNC(JoyStick);
virtual void onEnter() override;
virtual void onExit() override;
virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event) override;
virtual void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event) override;
virtual void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event) override;
private:
cocos2d::EventListenerTouchOneByOne* listener; /*定义为成员变量,方便移除监听*/
cocos2d::Sprite* rocker; /*方便获取*/
cocos2d::Sprite* rocker_bg; /*方便获取*/
};
#endif
JoyStick.cpp
#include "JoyStick.hpp"
USING_NS_CC;
bool JoyStick::init()
{
if (!Layer::init()) {
return false;
}
/*1. 创建摇杆的背景*/
rocker_bg = Sprite::create("joystickBg.png");
rocker_bg->setPosition(Vec2(150,150));
addChild(rocker_bg);
/*2. 创建摇杆*/
rocker = Sprite::create("joystick.png");
rocker->setPosition(Vec2(150,150));
addChild(rocker);
return true;
}
/*当前对象被加入到父类节点上会调用该方法*/
void JoyStick::onEnter()
{
/*首先调用父类的onEnter方法*/
Layer::onEnter();
/*开启单点触摸的监听, 可以用auto*/
listener = EventListenerTouchOneByOne::create();
/*可以使用lambda表达式来创建,但那样看起来太乱, 这里我们还是使用回调函数*/
listener->onTouchBegan = CC_CALLBACK_2(JoyStick::onTouchBegan, this);
listener->onTouchMoved = CC_CALLBACK_2(JoyStick::onTouchMoved, this);
listener->onTouchEnded = CC_CALLBACK_2(JoyStick::onTouchEnded, this);
/*注册监听*/
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
}
/*当前对象从父类上移除时会调用该方法*/
void JoyStick::onExit()
{
/*从分发中心移除注册的监听*/
Director::getInstance()->getEventDispatcher()->removeEventListener(listener);
/*最后调用父类的onExit()方法*/
Layer::onExit();
}
bool JoyStick::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event)
{
/*当触摸开始的时候, 如果触摸点的位置和我们中心点位置的距离 < 圆的半径 我们才能Move*/
/*获取圆心点和半径*/
float radius = rocker_bg->getContentSize().width / 2;
Vec2 center = rocker_bg->getPosition();
if (touch->getLocation().distance(center) > radius ) {
return false;
} else {
rocker->setPosition(Vec2(touch->getLocation()));
return true;
}
}
void JoyStick::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event)
{
/*当触摸移动的时候, 如果触摸点的位置和我们中心点位置的距离 < 圆的半径 */
/*获取圆心点和半径*/
float radius = rocker_bg->getContentSize().width/2;
Vec2 center = rocker_bg->getPosition();
/*获取触摸点位置*/
Vec2 touch_pos = touch->getLocation();
float dis = touch_pos.distance(center);
float angle = acos ( (touch_pos.x - center.x)/dis );
if ( dis <= radius ) {
rocker->setPosition( Vec2(touch_pos) );
} else {
/*如果在上半圆*/
if ( touch_pos.y > center.y ) {
rocker->setPosition(Vec2( center.x + radius*cos(angle), center.y + radius*sin(angle) ));
} else {
rocker->setPosition(Vec2 (center.x + radius*cos(angle), center.y - radius*sin(angle)) );
}
}
}
void JoyStick::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event)
{
/*在结束触摸时,将摇杆归为圆点位置*/
rocker->setPosition(rocker_bg->getPosition());
}
哈哈, 现在我们的摇杆顺利的动起来了!!
接下来我们要判定一下摇杆运动的方向
这是八方向摇杆的角度判定, 弄清楚这个之后, 我们来编码吧
我们先准备一张帧动画的文件, 来测试我们摇杆的判定是否能让它动起来,或者一张图片也行。
我们要让精灵移动的距离和我们的摇杆力度相同
首先定义一个枚举
/*定义摇杆方向的枚举*/
typedef enum direction
{
STAY = 0,
UP,
DOWN,
LEFT,
RIGHT,
R_UP, //右上
R_DOWN,
L_UP,
L_DOWN
}RDIRECTION;
判定当前角度的方向
void JoyStick::checkDirection(float angle)
{
/*右方向*/
if (angle >= -M_PI/8.0 && angle <= M_PI/8.0) {
dir = RIGHT;
}
/*右边走 -八分之派 到 八分之派*/
if (angle >= -(M_PI/8.0) && angle <= M_PI/8.0) {
dir = RIGHT;
}
/*右上方向 八分之派 到 八分之三派*/
else if( angle >= M_PI/8.0 && angle < 3*M_PI/8.0) {
dir = R_UP;
}
/*上方向 八分之三派 到 八分之五派*/
else if( angle >= 3*M_PI/8.0 && angle <= 5*M_PI/8.0) {
dir = UP;
}
/*左上方向 八分之5派 到 八分之七派*/
else if( angle > 5*M_PI/8.0 && angle < 7*M_PI/8.0) {
dir = L_UP;
}
/*左方向*/
else if( (angle >= 7*M_PI/8.0 && angle <= M_PI) || (angle <= -7*M_PI/8.0 && angle >= -M_PI)){
dir = LEFT;
}
/*左下方向*/
else if( angle > -7*M_PI/8.0 && angle < -5*M_PI/8.0) {
dir = L_DOWN;
}
/*下方向*/
else if( angle >= -5*M_PI/8.0 && angle <= -3*M_PI/8.0) {
dir = DOWN;
}
/*右下方向*/
else if( angle > -3*M_PI/8.0 && angle < -M_PI/8.0 ) {
dir = R_DOWN;
}
}
在onTouchMoved方法中我们调用该方法, 但是注意了,反余弦值没有负数,所以我们要判定,如果触摸点在圆点下方的时候传-angle过去判定方向
/*获取圆心点和半径*/
float radius = rocker_bg->getContentSize().width/2;
Vec2 center = rocker_bg->getPosition();
/*获取触摸点位置*/
Vec2 touch_pos = touch->getLocation();
float dis = touch_pos.distance(center);
angle = acos ( (touch_pos.x - center.x)/dis );
if (touch_pos.y > center.y) {
checkDirection(angle);
} else {
checkDirection(-angle);
}
然后在主场景中就可以使用我们这个摇杆啦, 可以看到我们的精灵是按照摇杆的力度移动距离的
源码下载地址: https://github.com/Kevin20166/JoyStick
---------------------
作者:JKevin2016
来源:CSDN
原文:https://blog.csdn.net/JKevin2016/article/details/52885137
版权声明:本文为博主原创文章,转载请附上博文链接!