博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Cocos2d-x 3.2 学习笔记(十)Joystick 搖杆控件
阅读量:4314 次
发布时间:2019-06-06

本文共 7765 字,大约阅读时间需要 25 分钟。

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

話不多說,看代碼:

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

转载于:https://www.cnblogs.com/Richard-Core/p/3915898.html

你可能感兴趣的文章
一周学会Mootools 1.4中文教程:(6)动画
查看>>
优秀的第二外语学习网站:Lang-8
查看>>
oracle存储过程杂记
查看>>
JPA @Id 和 @GeneratedValue 注解详解
查看>>
自定义Template
查看>>
su 和 su -
查看>>
MapReduce:共同好友详解
查看>>
python函数:匿名函数、函数递归与二分法、面向过程编程
查看>>
final、static、代码块、静态代码块、内部类、代码执行顺序
查看>>
LeetCode-Burst Balloons
查看>>
LeetCode-Bitwise AND of Numbers Range
查看>>
Windows Server 2012和2008中使用计划任务定时执行BAT批处理文件 定时备份mysql数据...
查看>>
费马小定理与GCD&LCM
查看>>
P1077 摆花
查看>>
zynq修改ramdisk文件系统
查看>>
C#测量程序运行时间及cpu使用时间
查看>>
并发编程
查看>>
我自己曾经经历的CMMI3认证通过关于软件测试的访谈【转载】
查看>>
C# 操作Excel ——Excel获取数据、时间、图片
查看>>
【Express系列】第3篇——接入mysql
查看>>