首页 > 代码库 > 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();//啟動
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。