溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

3.2 Joystick 搖桿控件

發(fā)布時間:2020-06-12 21:34:07 來源:網(wǎng)絡(luò) 閱讀:375 作者:libinqi456 欄目:開發(fā)技術(shù)
******************************** Joystick.h **************************** 
#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();
    /** 清除數(shù)據(jù) */
    void onDisable();
    /** 設(shè)置死亡半徑,即超出半徑將搖桿器失效 */
    void setDieRadius(float radius);
    /** 設(shè)置無效區(qū)域半徑(如果在無效區(qū)域內(nèi),將重置) */
    void setFailRadius(float radius);
    /** 是否顯示底盤和觸點(diǎn) */
    void setVisibleJoystick(bool visible);
    /** 是否自由變換搖桿器的位置,即在屏幕上每一次按下鼠標(biāo)時的座標(biāo)將是搖桿器的座標(biāo),移動時將不改變搖桿器座標(biāo),直到下次按下鼠標(biāo) */
    void setAutoPosition(bool value);
    /** 回調(diào)函數(shù)指針 */
    std::function<void(JoystickEnum)> onDirection;
    /** 靜態(tài)創(chuàng)建函數(shù)(需要傳入底盤和觸點(diǎn)圖片路徑) */
    static Joystick* create(std::string chassisPath,std::string dotPath);
    /** 初始化搖桿器(需要傳入底盤和觸點(diǎn)圖片路徑) */
    void initWithJoystick(std::string chassisPath,std::string dotPath);
protected:
    /** 有效區(qū)域半徑 */
    float _radius;
    /** 失效區(qū)域半徑 */
    float _failradius;
    /** 是否移出有效區(qū)域 */
    bool isMoveOut;
    /** 是否存在有效區(qū)域半徑 */
    bool isDieRadius;
    /** 是否自由變換搖桿器座標(biāo) */
    bool isAutoPosition;
    /** 方向 */
    JoystickEnum _direction;
    /** 底盤 */
    Sprite* _chassis;
    /** 觸點(diǎn) */
    Sprite* _touchDot;
    //*定義一個監(jiān)聽對象*/
    EventListenerTouchOneByOne* listener;
    
    bool onTouchBegan(Touch* touch,Event* event);
    void onTouchMoved(Touch* touch,Event* event);
    void onTouchEnded(Touch* touch,Event* event);
    /** 
    1、設(shè)置觸點(diǎn),并判斷是否在無效區(qū)域內(nèi)(如果在無效區(qū)域內(nèi),將重置)
    2、發(fā)送角度變化(如果不在無效區(qū)域內(nèi)) */
    void setTouchDotPosition(Vec2 vec1,Vec2 vec2);
    /** 
    1、計算搖桿器八方向
    2、發(fā)送角度變化,回調(diào)弧度變化函數(shù) */
    void changeAngle( Vec2 position );
    /** 回調(diào)註冊的監(jiān)聽函數(shù) */
    void callDirectionFun();
    /** 重置(當(dāng)弧度不是 DEFAULT時才重置) */
    void resetState();
    
};

#endif
***********************   Joystick.cpp   ******************************
#include "Joystick.h"
/** 靜態(tài)創(chuàng)建函數(shù)(需要傳入底盤和觸點(diǎn)圖片路徑) */
Joystick* Joystick::create(std::string chassisPath,std::string dotPath)
{
    auto joystick = new Joystick();/*創(chuàng)建一個對象*/
    joystick->initWithJoystick(chassisPath,dotPath);/*調(diào)用初始化函數(shù)*/
    return joystick;/*返回對象*/
}
/** 初始化搖桿器(需要傳入底盤和觸點(diǎn)圖片路徑) */
void Joystick::initWithJoystick(std::string chassisPath,std::string dotPath)
{
    _chassis = Sprite::create(chassisPath);/** 底盤 */
    this->addChild(_chassis,0);
    _touchDot = Sprite::create(dotPath);/** 觸點(diǎn) */
    this->addChild(_touchDot,1);

    isDieRadius = false;/** 是否存在有效區(qū)域半徑 */
    isAutoPosition = false;/** 是否自由變換搖桿器座標(biāo) */
    isMoveOut = false;/** 是否移出有效區(qū)域 */
    _direction = DEFAULT;/*方向默認(rèn)不動*/
}
/** 啟動搖桿器 */
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)
{     /*將觸摸點(diǎn)轉(zhuǎn)換為本地坐標(biāo)  左下角為原點(diǎn)*/
    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);
}
 /** 設(shè)置死亡半徑,即超出半徑將搖桿器失效 */
void Joystick::setDieRadius(float radius)
{
    _radius = radius;
    isDieRadius = true;
}

void Joystick::setAutoPosition(bool value)
{
    isAutoPosition = value;
}
 /** 設(shè)置無效區(qū)域半徑(如果在無效區(qū)域內(nèi),將重置) */
void Joystick::setFailRadius(float radius)
{
    _failradius = radius;
}
/** 清除數(shù)據(jù) */
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();
    }
}
/** 是否顯示底盤和觸點(diǎn) */
void Joystick::setVisibleJoystick(bool visible)
{
    _chassis->setVisible(visible);
    _touchDot->setVisible(visible);
}

在  HelloWord.h中   加個 void update(float dt);
在  HelloWord.cpp中
void HelloWorld::update(float dt)
{/* D_UP,
 D_DOWN,
 D_LEFT,
 D_RIGHT,
 D_LEFT_UP,
 D_LEFT_DOWN,
 D_RIGHT_UP,
 D_RIGHT_DOWN*/
    switch (j->getDirection())
    {
    case 1:
        log("D_UP");
        break;
    case 2:
        log("D_DOWN");

        break;
    case 3:
        log("D_LEFT");
        break;
    case 4:
        log("D_RIGHT");
        break;
    case 5:
        log("D_LEFT_UP");
        break;
    case 6:
        log("D_LEFT_DOWN");
        break;
    case 7:
        log("D_RIGHT_UP");
        break;
    case 8:
        log("D_RIGHT_DOWN");
        break;
    default:
        log("stop");
        break;
    }
}
之后調(diào)用檢檢搖桿**********************************

在  HelloWord中調(diào)用Joystick
*******************************************************************
普通模式
auto joystick = Joystick::create("rocker.png","rocker_joy.png");//通過兩張圖片初始化控件
    this->addChild(joystick);
    joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200));//設(shè)置初始位置  joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection,this);//角度變化更新(onDirection(JoystickEnum enums))
    joystick->onRun();//啟動
****************************************************************
存在死亡半徑模式:(超出死亡半徑將觸點(diǎn)重置初始位置,移動失效)
auto joystick = Joystick::create("rocker.png","rocker_joy.png");//通過兩張圖片初始化控件this->addChild(joystick);
joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200));//設(shè)置初始位置
joystick->setDieRadius(60);//設(shè)置死亡半徑(外圈)
joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection,this);//角度變化更新(onDirection(JoystickEnum enums))
joystick->onRun();//啟動
*******************************************************************
設(shè)置失效半徑:(在失效半徑內(nèi)將不會觸發(fā)角度改變事件)
auto joystick = Joystick::create("rocker.png","rocker_joy.png");//通過兩張圖片初始化控件
this->addChild(joystick);
joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200));//設(shè)置初始位置
joystick->setDieRadius(60);//設(shè)置死亡半徑(外圈)
joystick->setFailRadius(30);//設(shè)置失效半徑(內(nèi)圈) 
joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection,this);//角度變化更新(onDirection(JoystickEnum enums))
joystick->onRun();//啟動
*-****************************************************************
設(shè)置自由變換位置:以鼠標(biāo)按下的座標(biāo)為初始位置
auto joystick = Joystick::create("rocker.png","rocker_joy.png");//通過兩張圖片初始化控件
this->addChild(joystick);
joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200));//設(shè)置初始位置
joystick->setAutoPosition(true);//是否自由改變座標(biāo)
joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection,this);//角度變化更新
joystick->onRun();//啟動
*********************************************************************
設(shè)置隱藏?fù)u桿:(不顯示搖桿底盤和觸點(diǎn),一般會設(shè)置成自由改變位置)
auto joystick = Joystick::create("rocker.png","rocker_joy.png");//通過兩張圖片初始化控件
this->addChild(joystick);
joystick->setPosition(VisibleRect::leftBottom()+Vec2(200,200));//設(shè)置初始位置
joystick->setAutoPosition(true);//是否自由改變座標(biāo)
joystick->setVisibleJoystick(false);//是否顯示
joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection,this);//角度變化更新
joystick->onRun();//啟動
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI