cocos2d-x-3.3-018-游戏摇杆joystick源码分享

前端之家收集整理的这篇文章主要介绍了cocos2d-x-3.3-018-游戏摇杆joystick源码分享前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

查看原文或更新请移步到我的wiki: https://github.com/cheyiliu/All-in-One/wiki/cocos2d-x-3.3-018-joystick4cocos3.3



joystick

核心思想

  • 解耦,采用事件机制将joystick的事件和目标对象之间的关联进行解耦

实现思路

  • 1.继承自layer并注册监听touch event
  • 2.若touch事件在joystick的中心点触发的,则继续下面的逻辑
  • 3.更新joystick中心点的位置
  • 4.计算touch点joystick中心点的角度(角度范围,第一象限[0,90],第二象限[90,180], 第三象限[-180,-90], 第四象限[-90,0])
  • 5.发布自定义的joystick event,目前事件仅包含上面计算的角度值,可根据需要进行增改
  • 6.注册joystick event的事件监听器,并在回调函数里实现你的业务逻辑
  • 7.joystick event中的userdata的内存释放,交给auto-release-pool了, 具体见JoystickEvent的实现

核心代码

  • JoystickEvent主要是规范内存管理,严格按照cocos的'风俗'进行: 两段构造方式create+Ref+pool,使create出的对象像个栈上的局部变量。(mainLoop下次清理pool时自动删除)。
  • Joystick的核心代码
  1. bool Joystick::init() {
  2. bool result = false;
  3. do {
  4. // 父类初始化
  5. if (!Layer::init()) {
  6. break;
  7. }
  8. // joystick的背景
  9. mJsBg = Sprite::create("joystick_bg.png");
  10. if (nullptr == mJsBg) {
  11. break;
  12. }
  13. mJsBg->setPosition(mJsPos);
  14. addChild(mJsBg);
  15.  
  16. // joystick的中心点
  17. mJsCenter = Sprite::create("joystick_center.png");
  18. if (nullptr == mJsCenter) {
  19. break;
  20. }
  21. mJsCenter->setPosition(mJsPos);
  22. addChild(mJsCenter);
  23.  
  24. // touch event监听
  25. auto touchListener = EventListenerTouchOneByOne::create();
  26. if (nullptr == touchListener) {
  27. break;
  28. }
  29. touchListener->setSwallowTouches(true);
  30. touchListener->onTouchBegan =
  31. CC_CALLBACK_2(Joystick::onTouchBegan,this);
  32. touchListener->onTouchMoved =
  33. CC_CALLBACK_2(Joystick::onTouchMoved,this);
  34. touchListener->onTouchEnded =
  35. CC_CALLBACK_2(Joystick::onTouchEnded,this);
  36. _eventDispatcher->addEventListenerWithSceneGraPHPriority(touchListener,this);
  37.  
  38. result = true;
  39. } while (0);
  40.  
  41. return result;
  42. }
  43.  
  44. bool Joystick::onTouchBegan(Touch *touch,Event *unused_event) {
  45. log("onTouchBegan");
  46. auto point = touch->getLocation();
  47. if (mJsCenter->getBoundingBox().containsPoint(point)) {
  48. // 若触摸点在joystick的中心点,则继续接受事件
  49. return true;
  50. }
  51. // 否则不接受后续事件
  52. return false;
  53. }
  54.  
  55. void Joystick::onTouchMoved(Touch *touch,Event *unused_event) {
  56. log("onTouchMoved");
  57.  
  58. // 1. 获得角度,
  59. //第一象限是0,90度
  60. //第二象限是90,180度
  61. //第三象限是-90,-180度
  62. //第四象限是-90,0度
  63. Vec2 point = touch->getLocation();
  64. double y = point.y - mJsPos.y;
  65. double x = point.x - mJsPos.x;
  66. double angle = atan2(y,x) * 180 / PI;
  67. log("------------------------------------ %f",angle);
  68.  
  69. // 2. 更新joystick中心点位置,目的是想让中心点始终在它的背景图范围
  70. // joystick背景图半径
  71. double jsBgRadis = mJsBg->getContentSize().width * 0.5;
  72. //触摸点到中心点的实际距离
  73. double distanceOfTouchPointToCenter = sqrt(
  74. pow(mJsPos.x - point.x,2) + pow(mJsPos.y - point.y,2));
  75. if (distanceOfTouchPointToCenter >= jsBgRadis) {
  76. //利用等比关系计算delta x y
  77. double deltX = x * (jsBgRadis / distanceOfTouchPointToCenter);
  78. double deltY = y * (jsBgRadis / distanceOfTouchPointToCenter);
  79. mJsCenter->setPosition(Vec2(mJsPos.x + deltX,mJsPos.y + deltY));
  80. } else {
  81. mJsCenter->setPosition(point);
  82. }
  83.  
  84. // 3. 分发joystick event
  85. JoystickEvent* jsEvent = JoystickEvent::create();
  86. jsEvent->mAnagle = angle;
  87. Director::getInstance()->getEventDispatcher()->dispatchCustomEvent(
  88. JoystickEvent::EVENT_JOYSTICK,jsEvent);
  89. }
  90.  
  91. void Joystick::onTouchEnded(Touch *touch,Event *unused_event) {
  92. log("onTouchEnded");
  93. // 事件结束,还原joystick中心点位置
  94. mJsCenter->setPosition(mJsPos);
  95. }

集成到项目

  • 我以proj.linx为例
  • 拷贝相关cpp .h到工程并在CMakeLists.txt中增加cpp
  1. set(GAME_SRC
  2. Classes/AppDelegate.cpp
  3. Classes/HelloWorldScene.cpp
  4. Classes/Joystick.cpp #新增
  5. ${PLATFORM_SPECIFIC_SRC}
  6. )
  1. auto joystick = Joystick::create();
  2. scene->addChild(joystick);
  1. #include "Joystick.h"
  2.  
  3.  
  4. auto _listener = EventListenerCustom::create(JoystickEvent::EVENT_JOYSTICK,[=](EventCustom* event){
  5. JoystickEvent* jsevent = static_cast<JoystickEvent*>(event->getUserData());
  6. log("--------------got joystick event,%p,angle=%f",jsevent,jsevent->mAnagle);
  7.  
  8. // do you business you'd like to
  9. });
  10.  
  11. _eventDispatcher->addEventListenerWithFixedPriority(_listener,1);

效果


参考资料

猜你在找的Cocos2d-x相关文章