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

原创 2015年02月02日 09:52:15

查看原文或更新请移步到我的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的核心代码

bool Joystick::init() {
    bool result = false;
    do {
        // 父类初始化
        if (!Layer::init()) {
            break;
        }
        // joystick的背景
        mJsBg = Sprite::create("joystick_bg.png");
        if (nullptr == mJsBg) {
            break;
        }
        mJsBg->setPosition(mJsPos);
        addChild(mJsBg);

        // joystick的中心点
        mJsCenter = Sprite::create("joystick_center.png");
        if (nullptr == mJsCenter) {
            break;
        }
        mJsCenter->setPosition(mJsPos);
        addChild(mJsCenter);

        // touch event监听
        auto touchListener = EventListenerTouchOneByOne::create();
        if (nullptr == touchListener) {
            break;
        }
        touchListener->setSwallowTouches(true);
        touchListener->onTouchBegan =
                CC_CALLBACK_2(Joystick::onTouchBegan, this);
        touchListener->onTouchMoved =
                CC_CALLBACK_2(Joystick::onTouchMoved, this);
        touchListener->onTouchEnded =
                CC_CALLBACK_2(Joystick::onTouchEnded, this);
        _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener,
                this);

        result = true;
    } while (0);

    return result;
}

bool Joystick::onTouchBegan(Touch *touch, Event *unused_event) {
    log("onTouchBegan");
    auto point = touch->getLocation();
    if (mJsCenter->getBoundingBox().containsPoint(point)) {
        // 若触摸点在joystick的中心点,则继续接受事件
        return true;
    }
    // 否则不接受后续事件
    return false;
}

void Joystick::onTouchMoved(Touch *touch, Event *unused_event) {
    log("onTouchMoved");

    // 1. 获得角度,
    //第一象限是0,90度
    //第二象限是90,180度
    //第三象限是-90,-180度
    //第四象限是-90,0度
    Vec2 point = touch->getLocation();
    double y = point.y - mJsPos.y;
    double x = point.x - mJsPos.x;
    double angle = atan2(y, x) * 180 / PI;
    log("------------------------------------          %f", angle);

    // 2. 更新joystick中心点位置,目的是想让中心点始终在它的背景图范围
    // joystick背景图半径
    double jsBgRadis = mJsBg->getContentSize().width * 0.5;
    //触摸点到中心点的实际距离
    double distanceOfTouchPointToCenter = sqrt(
            pow(mJsPos.x - point.x, 2) + pow(mJsPos.y - point.y, 2));
    if (distanceOfTouchPointToCenter >= jsBgRadis) {
        //利用等比关系计算delta x y
        double deltX = x * (jsBgRadis / distanceOfTouchPointToCenter);
        double deltY = y * (jsBgRadis / distanceOfTouchPointToCenter);
        mJsCenter->setPosition(Vec2(mJsPos.x + deltX, mJsPos.y + deltY));
    } else {
        mJsCenter->setPosition(point);
    }

    //   3. 分发joystick event
    JoystickEvent* jsEvent = JoystickEvent::create();
    jsEvent->mAnagle = angle;
    Director::getInstance()->getEventDispatcher()->dispatchCustomEvent(
            JoystickEvent::EVENT_JOYSTICK, jsEvent);
}

void Joystick::onTouchEnded(Touch *touch, Event *unused_event) {
    log("onTouchEnded");
    // 事件结束,还原joystick中心点位置
    mJsCenter->setPosition(mJsPos);
}

集成到项目

  • 我以proj.linx为例
  • 拷贝相关cpp .h到工程并在CMakeLists.txt中增加cpp
set(GAME_SRC
  Classes/AppDelegate.cpp
  Classes/HelloWorldScene.cpp
  Classes/Joystick.cpp        #新增
  ${PLATFORM_SPECIFIC_SRC}
)

  • 添加joystick到场景
auto joystick = Joystick::create();
scene->addChild(joystick);
  • 注册监听joystick event
#include "Joystick.h"


    auto _listener = EventListenerCustom::create(JoystickEvent::EVENT_JOYSTICK, [=](EventCustom* event){
        JoystickEvent* jsevent = static_cast<JoystickEvent*>(event->getUserData());
        log("--------------got joystick event, %p,  angle=%f", jsevent, jsevent->mAnagle);

        // do you business you'd like to
    });

    _eventDispatcher->addEventListenerWithFixedPriority(_listener, 1);

效果图


参考资料


版权声明:本文为博主原创文章,未经博主允许不得转载。

cocos2dx-3.10虚拟摇杆的实现

本篇文章是在cocos2dx-2.x的基础上改编而来,基本没有什么大的改变,只是让技术小白少走一些弯路。好了。下面就直接上代码了。 首先把虚拟摇杆封装成一个类,就要建立一个.cpp文件和.文件,这个...
  • hj3601947
  • hj3601947
  • 2017年03月14日 16:22
  • 569

做一个cocos2d-html5的虚拟摇杆

留坑
  • u013340539
  • u013340539
  • 2014年02月03日 16:07
  • 2194

Cocos2d-js3.3 虚拟摇杆的实现

虚拟摇杆是在手机格斗游戏中经常看到的一个东西,今天就来了解一下如何在cocos2d-js实现一个虚拟摇杆... 首先,先来看一下这个虚拟摇杆的效果,其中分为默认类型(Default)和跟随类型(Fol...
  • u013455818
  • u013455818
  • 2015年04月03日 09:51
  • 931

cocos2d-x 3.x学习之虚拟摇杆

摇杆类 #ifndef Joystick_hpp #define Joystick_hpp #include #include "cocos2d.h" USING_NS_CC; enum Tag...
  • wandersm
  • wandersm
  • 2016年10月21日 16:10
  • 802

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

查看原文或更新请移步到我的wiki: https://github.com/cheyiliu/All-in-One/wiki/cocos2d-x-3.3-018-joystick4cocos3.3...
  • cheyiliu
  • cheyiliu
  • 2015年02月02日 09:52
  • 2714

15款Cocos2d-x游戏源码

http://blog.okbase.net/iphone/archive/4619.html (1)用cocos2d-x开发的中国象棋游戏源码 使用Cocos2d-X2.2.3开发的一款中国象...
  • kenkao
  • kenkao
  • 2016年07月01日 22:23
  • 10027

Arduino使用游戏摇杆joystick

这是我买的37款传感器套件中的一款,下面是截图:  根据参考文献1,了解到游戏摇杆的五个引脚的意义,除了电源正极和负极之外: VRx表示X轴方向的输出 VRy表示Y轴方向的输出 SW输出0表示按下摇杆...
  • gc_2299
  • gc_2299
  • 2017年11月12日 19:59
  • 186

使用joystick控制arduino调试电机

一般电调在刚上电时需要使用航模遥控器设置油门行程,或者是设置电调参数时,也需要使用航模遥控器来控制选项 当然也可以直接使用mega板直接设置电调的高低行程,但我手头现在有一个摇杆所以就试着使用JOYS...
  • danti
  • danti
  • 2015年08月22日 21:34
  • 602

Cocos2D 3.x 横版动作游戏教程 Part1

  • 2015年01月22日 14:05
  • 12MB
  • 下载

cocos2d-X 手机游戏《雷电游戏》完整源码下载

源码介绍 雷电游戏--cocos2d-x手机游戏源码下载 本demo是在雷电游戏基本功能完成的基础上,又增加了摇杆模式和精灵关卡。游戏主要功能包括选择关卡,游戏控制模式设置,分数存储,游戏介绍,各...
  • donghong2008
  • donghong2008
  • 2015年06月17日 20:23
  • 4836
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:cocos2d-x-3.3-018-游戏摇杆joystick源码分享
举报原因:
原因补充:

(最多只允许输入30个字)