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,);
_touchDot = Sprite::create(dotPath);
this->addChild(_touchDot,); 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(,);
resetState();
}
void Joystick::onTouchEnded(Touch* touch,Event* event)
{
_touchDot->setPosition(,);
isMoveOut = false;
resetState();
} void Joystick::setTouchDotPosition(Vec2 vec1,Vec2 vec2)
{
_touchDot->setPosition(vec2);
if( _failradius> )
{
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 < )||(angle < -157.5 && angle > -))
{
_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(,));//設置初始位置
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(,));//設置初始位置
joystick->setDieRadius();//設置死亡半徑(外圈)
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(,));//設置初始位置
joystick->setDieRadius();//設置死亡半徑(外圈)
joystick->setFailRadius();//設置失效半徑(內圈)
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(,));//設置初始位置
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(,));//設置初始位置
joystick->setAutoPosition(true);//是否自由改變座標
joystick->setVisibleJoystick(false);//是否顯示
joystick->onDirection=CC_CALLBACK_1(SceneMain::onDirection,this);//角度變化更新
joystick->onRun();//啟動

Cocos2d-x 3.2 学习笔记(十)Joystick 搖杆控件的更多相关文章
- Android学习笔记(七)——常见控件
//此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! Android 给我们提供了大量的 UI控件,下面我们简单试试几种常用的控件. 一.TextView 在布局文 ...
- Java学习笔记——可视化Swing中JTable控件绑定SQL数据源的两种方法
在 MyEclipse 的可视化 Swing 中,有 JTable 控件. JTable 用来显示和编辑常规二维单元表. 那么,如何将 数据库SQL中的数据绑定至JTable中呢? 在这里,提供两种方 ...
- Unity3D学习笔记(一)GUI控件的调用
GUI控件:1.在Start中初始化,在OnGUI中调整.2.公有变量才会出现在Inspector面板.3.GUI控件的初始化和处理在OnGUI内完成.4.JavaScript的中文为UTF-8编码可 ...
- C# 学习笔记 三层架构系列(控件一)
下面是我两周的学习总结:这是我写给自己的,如果哪位朋友有幸看到这篇文章就是缘分.如果所说的内容不对,就请纠正.勿喷!!! 想要将两周的学习知识通过文字.通过代码.通过图片储备起来,以防自己那天思维短路 ...
- COCOS学习笔记--Button类及其相关控件属性
一.Button介绍 Button就是button.Cocos中提供了Button类对button进行相关的操作.我们看一下Button类继承关系图: 能够看到.Button是继承自Widget类,W ...
- .net core 学习笔记(1)-分页控件的使用
最近有个小项目,用.net core开发练练手,碰到的第一个问题就是分页控件的问题,自己写太费时间,上网查了下,发现有人已经封装好了的,就拿过来用了,分页控件github:https://github ...
- Android学习笔记50:使用WebView控件浏览网页
在Android中,可以使用Webview控件来浏览网页.通过使用该控件,我们可以自制一个简单的浏览器,运行效果如图1所示. 图1 运行效果 1.WebView 在使用WebView控件时,首先需要在 ...
- 【jQuery UI 1.8 The User Interface Library for jQuery】.学习笔记.10.Button 和 Autocomplete控件
Button ,可以使用 <button> <input> <a>. <input> 中的不同类型,submit , radio , checkbox ...
- [Android学习笔记]继承自ViewGroup的控件的过程学习
ViewGroup文档 http://developer.android.com/training/index.html 继承自ViewGroup需要重写onLayout方法用来为子View设定位置信 ...
随机推荐
- 新装ubuntu12.04需要敲的命令集合
1.sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup sudo gedit /etc/apt/sources.list copy: ...
- Linux内核--网络栈实现分析(八)--应用层发送数据(下)
本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7547826 更多请查看专栏,地 ...
- 快速学习C语言四: 造轮子,ArrayList
高级语言里的列表是最常用的数据结构,在C里造个轮子玩玩,C没有泛型,先用int练习. Collection的ADT一般有hasnext,next,add, remove操作,List一般还加了remo ...
- [Asp.net 开发系列之SignalR篇]专题六:使用SignalR实现消息提醒
一.引言 前面一篇文章我介绍了如何使用SignalR实现图片的传输,然后对于即时通讯应用来说,消息提醒是必不可少的.现在很多网站的都有新消息的提醒功能.自然对于SignalR系列也少不了这个功能的实现 ...
- objective-c(代码块)
objective-c代码块(block)对写惯C语言的人非常熟悉,就类似一个函数指针,指向一个代码段的首地址: 给出简单例子如下: int main(int argc, const char * a ...
- 谈谈javascript语法里一些难点问题(二)
3) 作用域链相关的问题 作用域链是javascript语言里非常红的概念,很多学习和使用javascript语言的程序员都知道作用域链是理解javascript里很重要的一些概念的关键,这些概 ...
- 用1、2、2、3、4、5这六个数字,用java写一个main函数,打印出所有不同的排列,如:512234、412345等,要求:"4"不能在第三位,"3"与"5"不能相连。
最近在看算法,看到这个题,觉得挺经典的,收起. 分析: 1 .把问题归结为图结构的遍历问题.实际上6个数字就是六个结点,把六个结点连接成无向连通图,对于每一个结点求这个图形的遍历路径,所有结点的遍历路 ...
- 自动备份文件到GITHUB的方法
由于一个制作着玩的项目需要制作上传文件的功能,自己又不是搞网站的,也不想去维护一个服务器. 于是开发了一个上传服务器,可以自动把我上传到服务器的数据同步到Github服务器 而github服务器又提供 ...
- [Unity3D入门]入门级游戏项目"坦克狙击手"更新
[Unity3D入门]入门级游戏项目"坦克狙击手"更新 在上一篇中我分享了一个尚未完全写好的入门级unity3d项目"坦克狙击手". 本文介绍最新版的" ...
- Google 新推出Background sync API
Background sync是Google新推出的Web API,可延迟用户行为,直到用户网络连接稳定.这样有助于保证用户想要发送的数据就是实际发送的数据. 目前存在的问题 网络是消磨用户时间最多的 ...