android - Cocos2d-x onTouchMoved 在没有移动发生时调用

标签 android c++ cocos2d-x cocos2d-x-3.0 cocos2d-android

我正在编写一个 cocos2d-x 3.71 跨平台应用程序(ios、android、windows10),我在实现触摸和按住检测时遇到了问题仅在 Android 上(ios 和 windows 工作正好)。我已将其原因归结为这样一个事实,即当按住触摸而不移动时,onTouchMoved() 会不断触发。我已经合并了一个解决方法,但这似乎是一个错误,我想知道是否有人有任何想法。

我在基于 cocos2d-x HelloWorld 示例的最小应用程序中重现了该问题。我只是从 cocos2d::Node (testNode) 派生了一个类并创建了它,并将其作为子级添加到 HelloWorldScene。在 testNode 中,我覆盖了更新函数并使用 onTouchBegan() 中的 scheduleUpdate() 对其进行调度。在 update() 函数中,我简单地计算时间直到达到 0.25 秒,然后使用 unscheduleUpdate() 禁用更新。我在 onTouchMoved() 中调用了另一个 unscheduleUpdate() 来停止计算保持时间,以防触摸移动。问题是,在 Android 上,onTouchMoved() 在触摸静止不动时开始不断触发。

testNode.h: 
#pragma once
#include "cocos2d.h"

class testNode : public cocos2d::Node
{
public:
    testNode() {}
    ~testNode() {}
    CREATE_FUNC(testNode);

    virtual bool init();
    virtual void update(float dt);

    bool onTouchBegan(cocos2d::Touch*, cocos2d::Event*);
    void onTouchMoved(cocos2d::Touch*, cocos2d::Event*);
    void onTouchEnded(cocos2d::Touch*, cocos2d::Event*);
    void onTouchCancelled(cocos2d::Touch*, cocos2d::Event*);

private:
    cocos2d::DrawNode* d;
    int id;
    bool touchIsDown;
    float touchTime;
    cocos2d::Label *messageLabel;
    cocos2d::Vec2 center;
};

测试节点.cpp:

#include "testNode.h"
USING_NS_CC;

bool testNode::init()
{

    if (!Node::init())
    {
        return false;
    }
    setContentSize(Size(50, 50));

    Size size = Director::getInstance()->getWinSize();
    Size visibleSize = Director::getInstance()->getVisibleSize();
    setPosition(Vec2(size.width / 2.0f, size.height / 2.0f));
    center.x = size.width / 2.0f;
    center.y = size.height / 2.0f;

    d = DrawNode::create();
    addChild(d, 10);
    d->drawCircle(Vec2(0, 0), 50, (float)M_PI * 2, 50, false, Color4F::RED);

    auto touchListener = EventListenerTouchOneByOne::create();
    touchListener->setSwallowTouches(true);
    touchListener->onTouchBegan = CC_CALLBACK_2(testNode::onTouchBegan, this);
    touchListener->onTouchEnded = CC_CALLBACK_2(testNode::onTouchEnded, this);
    touchListener->onTouchMoved = CC_CALLBACK_2(testNode::onTouchMoved, this);
    touchListener->onTouchCancelled = CC_CALLBACK_2(testNode::onTouchCancelled, this);

    _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);

    messageLabel = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 18);

    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    messageLabel->setPosition(Vec2(0,0));
    addChild(messageLabel, 1);
    return true;
}

void testNode::update(float deltaTime)
{
    // When update is scheduled with scheduleUpdate(), this will increment the touchtimer
    // used for differenciating different touch actions.
    if (touchIsDown)
    {
        touchTime += deltaTime;
        if (touchTime > 0.25)
        {
            unscheduleUpdate();
        }
    }
}

bool testNode::onTouchBegan(Touch* touch, Event* event)
{
    Vec2 touchPoint = touch->getLocation();
    float startDistFromCenter = center.getDistance(touchPoint);
    touchTime = 0.0f;

    // Handle touch only if inside the radius of the circle
    if (startDistFromCenter <= 50)
    {
        // Track how long the touch is held without moving or releasing
        touchIsDown = true;
        scheduleUpdate();
        return true;
    }
    else
        return false;
}
void testNode::onTouchMoved(Touch* touch, Event* event)
{
    Vec2 pos = touch->getLocation();
    log("moving...pos = %f , %f", pos.x, pos.y);
    touchIsDown = false;
    unscheduleUpdate();
}
void testNode::onTouchEnded(Touch* touch, Event* event)
{
    touchIsDown = false;
    unscheduleUpdate();

    log("Hold Time: %f", touchTime);
}

void testNode::onTouchCancelled(Touch* touch, Event* event)
{
}

触摸/按住事件的典型输出:

09-23 23:42:39.852: D/cocos2d-x debug info(32508): startDistFromCenter: 33.753014 09-23 23:42:39.902: D/cocos2d-x debug info(32508): moving...pos = 246.732849 , 126.925316 09-23 23:42:39.902: D/cocos2d-x debug info(32508): moving...pos = 246.732849 , 126.925316 09-23 23:42:39.920: D/cocos2d-x debug info(32508): moving...pos = 246.732849 , 126.925316 09-23 23:42:39.935: D/cocos2d-x debug info(32508): moving...pos = 246.732849 , 126.925316 09-23 23:42:39.969: D/cocos2d-x debug info(32508): moving...pos = 246.732849 , 126.925316 09-23 23:42:39.969: D/cocos2d-x debug info(32508): moving...pos = 246.732849 , 126.925316 09-23 23:42:39.989: D/cocos2d-x debug info(32508): moving...pos = 246.732849 , 126.925316 09-23 23:42:39.999: D/cocos2d-x debug info(32508): moving...pos = 246.732849 , 126.925316 09-23 23:42:40.027: D/cocos2d-x debug info(32508): moving...pos = 246.732849 , 126.925316 09-23 23:42:40.043: D/cocos2d-x debug info(32508): moving...pos = 246.732849 , 126.925316 09-23 23:42:40.043: D/cocos2d-x debug info(32508): Hold Time: 0.042597

如您所见,该位置实际上没有在移动....这是怎么回事?

作为引用,我在 Windows 10、Visual Studio 2015、cocos2d-x 3.71 上开发,并在 Android 5.1.1(OnePlusOne 手机)上进行测试

最佳答案

我测试了你的代码,这个问题与 android lollipop 有关。在 kitkat 上一切正常(测试设备 Huawei Ascend P7 android 4.4.2):

09-24 11:51:25.351: D/cocos2d-x debug info(1058): Hold Time: 0.252129
09-24 11:51:27.361: D/cocos2d-x debug info(1058): Hold Time: 0.251298
09-24 11:51:28.711: D/cocos2d-x debug info(1058): Hold Time: 0.252115
09-24 11:51:30.101: D/cocos2d-x debug info(1058): Hold Time: 0.251961

我也在 Lollipop 设备(LG,但我不记得具体型号)上试过了,就像你说的那样。 spam of touch 以相同的位置移动。

作为一种变通方法,您可以像 Alex G 所说的那样做,或者记住最后一个位置(在触摸开始时记住它)并忽略具有完全相同位置的事件。

顺便说一句,我正在使用 Mac OS X Yosemite 和 Cocos2d-x 3.8。

你应该在 cocos2d-x github 页面上发起一个问题。

关于android - Cocos2d-x onTouchMoved 在没有移动发生时调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32753149/

相关文章:

android - 如何下载Android应用程序的sqlite数据库?

C++ 平方根函数错误

c++ - 将菜单项位置引用到同一菜单中的另一个菜单项

java - 如何使用 jsoup post 请求提交没有按钮名称的表单

android - android屏幕坐标如何工作?

Android 屏幕方向因设备而异

c++ - 在Linux ubuntu中用c++调用具有两个输出的函数时出错

c++ - 析构函数是唯一在 move 构造函数/赋值的 RHS 上调用过的东西吗?

c++ - 确定距离直线一定距离的点

c++ - 打印 Vec2 x 值