Cocos-2d 3.x 八方向虚拟摇杆的实现

本文详细介绍如何在Cocos2d-x中实现一个八方向的虚拟摇杆,并通过角度判断来控制游戏角色移动的方向及速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值