【cocos2dx 3.2】自己写的虚拟摇杆,可换皮肤

在项目中写了个虚拟摇杆控件,在这里分享给大家,可以根据自己的需要换贴图皮肤

代码中会用到3个贴图,这3个贴图可以替换,在这里先介绍下3个贴图的作用,他们分别是摇杆控件背景,摇杆移动范围背景,以及摇杆本身

摇杆控件背景定义了虚拟摇杆空间的大小,以及触摸大小,在该范围内的触摸都会触发摇杆的移动
摇杆移动范围背景,这一层定义了摇杆可运动的范围。 移动范围是一个圆,该圆的半径是移动范围背景贴图宽的一半,见黑色大圆圈
摇杆本身贴图,这一层中有个黑色小圆,这个小圆定义了摇杆和移动范围碰触的边缘。

下面是代码,在INIT函数里修改3个贴图文件,就可以实现自己的摇杆了

#define WIDTH(obj) (obj)->getContentSize().width
#define HEIGHT(obj) (obj)->getContentSize().height
class Joystick : public Sprite
{
public:
 CREATE_FUNC(Joystick);
 virtual bool init();


 typedef std::function JoystickHandler;
 void setJoystickPositionChangeHandler(JoystickHandler);


 CC_SYNTHESIZE(float, _controlDiameter, ControlDiameter);


private:
 Sprite* _stick;
 Sprite* _frame;
 Vec2 _lastPos;
 JoystickHandler _handler;
 EventListenerTouchOneByOne* _touchEventListener;


 bool onTouchBegan(Touch*, Event*);
 void onTouchMoved(Touch*, Event*);
 void onTouchEnded(Touch*, Event*);
 void onTouchCancelled(Touch*, Event*);


 void handleTouchChange(Touch*);
};

bool Joystick::init()
{
    if (!Sprite::initWithSpriteFrameName(“joystickbackground.png”))
        return false;

    _lastPos = Vec2::ZERO;

    _frame = Sprite::createWithSpriteFrameName("joystickframebackground.png");
    _frame->setPosition(WIDTH(this) / 2, HEIGHT(this) / 2);
    addChild(_frame);

    _stick = Sprite::createWithSpriteFrameName("joystick.png");
    _stick->setPosition(WIDTH(_frame) / 2, HEIGHT(_frame) / 2);
    _frame->addChild(_stick);

    _controlDiameter = WIDTH(_frame) - WIDTH(_stick);

    _touchEventListener = EventListenerTouchOneByOne::create();
    _touchEventListener->onTouchBegan = CC_CALLBACK_2(Joystick::onTouchBegan, this);
    _touchEventListener->onTouchMoved = CC_CALLBACK_2(Joystick::onTouchMoved, this);
    _touchEventListener->onTouchEnded = CC_CALLBACK_2(Joystick::onTouchEnded, this);
    _touchEventListener->onTouchCancelled = CC_CALLBACK_2(Joystick::onTouchCancelled, this);
    _touchEventListener->setSwallowTouches(true);

    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(_touchEventListener, this);

    return true;
}

void Joystick::setJoystickPositionChangeHandler(JoystickHandler handler)
{
    _handler = handler;
}

bool Joystick::onTouchBegan(Touch* touch, Event* event)
{
    if (this->getBoundingBox().containsPoint(touch->getLocation()))
    {
        handleTouchChange(touch);
        return true;
    }

    return false;
}

void Joystick::onTouchMoved(Touch* touch, Event* event)
{
    if (this->getBoundingBox().containsPoint(touch->getLocation()))
        handleTouchChange(touch);
}

void Joystick::onTouchEnded(Touch* touch, Event* event)
{
    static Vec2 origin = Vec2(WIDTH(_frame) / 2, HEIGHT(_frame) / 2);

    _stick->setPosition(origin);

    if (!_handler._Empty())
        _handler(Vec2::ZERO, Vec2::ZERO);

    _lastPos = Vec2::ZERO;
}

void Joystick::onTouchCancelled(Touch* touch, Event* event)
{
    onTouchEnded(touch, event);
}

void Joystick::handleTouchChange(Touch* touch)
{
    static Vec2 origin = Vec2(WIDTH(_frame) / 2, HEIGHT(_frame) / 2);
    static float bigR = WIDTH(_frame) / 2;
    static float smallR = WIDTH(_stick) / 2;
         
    Vec2 hit = this->_frame->convertToNodeSpaceAR(touch->getLocation());

    if (hit.getDistance(Vec2::ZERO) + smallR > bigR)
    {
        float x = (bigR - smallR) / sqrt(1 + hit.y * hit.y / hit.x / hit.x);
        float y = abs(hit.y / hit.x * x);

        if (hit.x > 0)
        {
            if (hit.y > 0)
            {
                hit.x = x;
                hit.y = y;
            }
            else
            {
                hit.x = x;
                hit.y = -y;
            }
        }
        else
        {
            if (hit.y > 0)
            {
                hit.x = -x;
                hit.y = y;
            }
            else
            {
                hit.x = -x;
                hit.y = -y;
            }
        }
    }

    _stick->setPosition(hit + origin);

    if (!_handler._Empty())
        _handler(hit, _lastPos);

    _lastPos = hit;
}

```


因为是自己项目内部用的,所以没把3个贴图参数化

顶一个!帖子已加精,楼主可以考虑把代码解释一下,然后贴一张最后的效果图,这样就更好了!:2::2::2:

恩,我稍后自己贴图做好了会放一个上来
代码解释也会一并放上

顶!:2::2::2::2::2:

LZ想问一下,你是如何解决在触摸摇杆进行移动的时候需要同时点击攻击按钮的情况?多点触控?

lz,能说下怎么调用么?

:2: :2: :2: :2: :2: :2:

肯定多点触摸啊

有谁知道,如何用lua中调用这个么

你把他逻辑看清楚用lua代码写一下都好了