首页 > 代码库 > Cocos2d-x 3.2 学习笔记(十)Joystick 搖杆控件

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();//啟動