Cocos2d-x 3.2 学习笔记(十)Joystick 搖杆控件

  最近想做格鬥遊戲,那麼就要有搖杆控件,不想去看別人的代碼就自己寫了個搖杆控件,實現起來很簡單。

話不多說,看代碼:

#ifndef __Joystick__

#define __Joystick__



#include "cocos2d.h"

USING_NS_CC;



enum JoystickEnum

{

    DEFAULT,

    D_UP,

    D_DOWN,

    D_LEFT,

    D_RIGHT,

    D_LEFT_UP,

    D_LEFT_DOWN,

    D_RIGHT_UP,

    D_RIGHT_DOWN

};



class Joystick : public Layer

{

public:

    /** 啟動搖杆器 */

    void onRun();

    /** 清除數據 */

    void onDisable();

    /** 設置死亡半徑,即超出半徑將摇杆器失效 */

    void setDieRadius(float radius);

    /** 設置無效區域半徑(如果在無效區域內,將重置) */

    void setFailRadius(float radius);

    /** 是否顯示底盤和觸點 */

    void setVisibleJoystick(bool visible);

    /** 是否自由變換搖杆器的位置,即在屏幕上每一次按下鼠標時的座標將是搖杆器的座標,移動時將不改變搖杆器座標,直到下次按下鼠標 */

    void setAutoPosition(bool value);

    /** 回調函數指針 */

    std::function<void(JoystickEnum)> onDirection;

    /** 靜態創建函數(需要傳入底盤和觸點圖片路徑) */

    static Joystick* create(std::string chassisPath,std::string dotPath);

    /** 初始化搖杆器(需要傳入底盤和觸點圖片路徑) */

    void initWithJoystick(std::string chassisPath,std::string dotPath);

protected:

    /** 有效區域半徑 */

    float _radius;

    /** 失效區域半徑 */

    float _failradius;

    /** 是否移出有效區域 */

    bool isMoveOut;

    /** 是否存在有效區域半徑 */

    bool isDieRadius;

    /** 是否自由變換搖杆器座標 */

    bool isAutoPosition;

    /** 方向 */

    JoystickEnum _direction;

    /** 底盤 */

    Sprite* _chassis;

    /** 觸點 */

    Sprite* _touchDot;

    EventListenerTouchOneByOne* listener;

    

    bool onTouchBegan(Touch* touch,Event* event);

    void onTouchMoved(Touch* touch,Event* event);

    void onTouchEnded(Touch* touch,Event* event);

    /** 

    1、設置觸點,并判斷是否在無效區域內(如果在無效區域內,將重置)

    2、發送角度變化(如果不在無效區域內) */

    void setTouchDotPosition(Vec2 vec1,Vec2 vec2);

    /** 

    1、計算搖杆器八方向

    2、發送角度變化,回調弧度變化函數 */

    void changeAngle( Vec2 position );

    /** 回調註冊的監聽函數 */

    void callDirectionFun();

    /** 重置(當弧度不是 DEFAULT時才重置) */

    void resetState();

    

};



#endif
#include "Joystick.h"



Joystick* Joystick::create(std::string chassisPath,std::string dotPath)

{

    auto joystick = new Joystick();

    joystick->initWithJoystick(chassisPath,dotPath);

    return joystick;

}



void Joystick::initWithJoystick(std::string chassisPath,std::string dotPath)

{

    _chassis = Sprite::create(chassisPath);

    this->addChild(_chassis,0);

    _touchDot = Sprite::create(dotPath);

    this->addChild(_touchDot,1);



    isDieRadius = false;

    isAutoPosition = false;

    isMoveOut = false;

    _direction = DEFAULT;

}



void Joystick::onRun()

{

    listener = EventListenerTouchOneByOne::create();

    listener->setSwallowTouches(false);

    listener->onTouchBegan = CC_CALLBACK_2(Joystick::onTouchBegan,this);

    listener->onTouchMoved = CC_CALLBACK_2(Joystick::onTouchMoved,this);

    listener->onTouchEnded = CC_CALLBACK_2(Joystick::onTouchEnded,this);

    this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);

}



bool Joystick::onTouchBegan(Touch* touch,Event* event)

{

    Vec2 locationInNode = this->convertToNodeSpace(touch->getLocation());

    if( isAutoPosition )

    {

        this->setPosition(touch->getLocation());

        return true;

    }

    if( isAutoPosition==false && isDieRadius )

    {

        if( locationInNode.getLength() > _radius )

        {

            return false;

        }

    }

    _touchDot->setPosition(locationInNode);

    if( locationInNode.getLength() > _failradius )

    {

        changeAngle(locationInNode);

    }

    return true;

}

void Joystick::onTouchMoved(Touch* touch,Event* event)

{

    Vec2 locationInNode = this->convertToNodeSpace(touch->getLocation());

    if( isDieRadius )

    {

        if( locationInNode.getLength() < _radius )

        {

            if( isMoveOut )

            {

                _touchDot->setPosition(locationInNode);

                isMoveOut = false;

            }

            setTouchDotPosition(locationInNode,_touchDot->getPosition() + touch->getDelta());

            return;

        }

    }

    else

    {

        setTouchDotPosition(locationInNode,_touchDot->getPosition() + touch->getDelta());

        return;

    }

    

    isMoveOut = true;

    _touchDot->setPosition(0,0);

    resetState();

}

void Joystick::onTouchEnded(Touch* touch,Event* event)

{

    _touchDot->setPosition(0,0);

    isMoveOut = false;

    resetState();

}



void Joystick::setTouchDotPosition(Vec2 vec1,Vec2 vec2)

{

    _touchDot->setPosition(vec2);

    if( _failradius>0 )

    {

        if( vec1.getLength() < _failradius )

        {

            resetState();

            return;

        }

    }

    changeAngle(vec1);

}



void Joystick::setDieRadius(float radius)

{

    _radius = radius;

    isDieRadius = true;

}



void Joystick::setAutoPosition(bool value)

{

    isAutoPosition = value;

}



void Joystick::setFailRadius(float radius)

{

    _failradius = radius;

}



void Joystick::onDisable()

{

    this->_eventDispatcher->removeEventListener(listener);

    isDieRadius = false;

    isAutoPosition = false;

    isMoveOut = false;

}



void Joystick::changeAngle( Vec2 position )

{

    auto angle = CC_RADIANS_TO_DEGREES(position.getAngle());

    if(angle > -22.5 && angle < 22.5)

    {

        _direction=D_RIGHT;

    }

    else if(angle > 22.5 && angle < 67.5)

    {

        _direction=D_RIGHT_UP;

    }

    else if(angle > 67.5 && angle < 112.5)

    {

        _direction=D_UP;

    }

    else if(angle > 112.5 && angle < 157.5)

    {

        _direction=D_LEFT_UP;

    }

    else if((angle > 157.5 && angle < 180)||(angle < -157.5 && angle > -180))

    {

        _direction=D_LEFT;

    }

    else if(angle < -112.5 && angle > -157.5)

    {

        _direction=D_LEFT_DOWN;

    }

    else if(angle < -67.5 && angle > -112.5)

    {

        _direction=D_DOWN;

    }

    else if(angle < -22.5 && angle > -67.5)

    {

        _direction=D_RIGHT_DOWN;

    }

    callDirectionFun();

}



void Joystick::callDirectionFun()

{

    if( onDirection )

    {

        onDirection(_direction);

    }

}



void Joystick::resetState()

{

    if(_direction != DEFAULT)

    {

        _direction = DEFAULT;

        callDirectionFun();

    }

}



void Joystick::setVisibleJoystick(bool visible)

{

    _chassis->setVisible(visible);

    _touchDot->setVisible(visible);

}

當然,如果有用到的朋友可以自己修改。這隻是最簡單的實現。

下面有效果圖,不過加載比較慢:

普通模式

  auto joystick = Joystick::create("rocker.png","rocker_joy.png");//通過兩張圖片初始化控件

    this->addChild(joystick);

    joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200));//設置初始位置

  joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection,this);//角度變化更新(onDirection(JoystickEnum enums))

    joystick->onRun();//啟動

 

存在死亡半徑模式:(超出死亡半徑將觸點重置初始位置,移動失效)

auto joystick = Joystick::create("rocker.png","rocker_joy.png");//通過兩張圖片初始化控件

this->addChild(joystick);

joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200));//設置初始位置

joystick->setDieRadius(60);//設置死亡半徑(外圈)

joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection,this);//角度變化更新(onDirection(JoystickEnum enums))

joystick->onRun();//啟動

 

 

 

設置失效半徑:(在失效半徑內將不會觸發角度改變事件)

auto joystick = Joystick::create("rocker.png","rocker_joy.png");//通過兩張圖片初始化控件

this->addChild(joystick);

joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200));//設置初始位置

joystick->setDieRadius(60);//設置死亡半徑(外圈)

joystick->setFailRadius(30);//設置失效半徑(內圈) 

joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection,this);//角度變化更新(onDirection(JoystickEnum enums))

joystick->onRun();//啟動

 

 

設置自由變換位置:以鼠標按下的座標為初始位置

auto joystick = Joystick::create("rocker.png","rocker_joy.png");//通過兩張圖片初始化控件

this->addChild(joystick);

joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200));//設置初始位置

joystick->setAutoPosition(true);//是否自由改變座標

joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection,this);//角度變化更新

joystick->onRun();//啟動

 

設置隱藏搖杆:(不顯示搖杆底盤和觸點,一般會設置成自由改變位置)

auto joystick = Joystick::create("rocker.png","rocker_joy.png");//通過兩張圖片初始化控件

this->addChild(joystick);

joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200));//設置初始位置

joystick->setAutoPosition(true);//是否自由改變座標

joystick->setVisibleJoystick(false);//是否顯示

joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection,this);//角度變化更新

joystick->onRun();//啟動

你可能感兴趣的:(cocos2d-x)