2015-09-24 4 views
1

Я пишу кросс-платформенное приложение cocos2d-x 3.71 (ios, android, windows10), и у меня возникают проблемы с моей реализацией обнаружения касания и удержания только для Android (ios и windows работают отлично). Я проследил причину этого в том, что, удерживая прикосновение и не двигаясь, onTouchMoved() постоянно стреляет. Я включил обход, но это похоже на ошибку, и мне интересно, есть ли у кого-нибудь идеи.Cocos2d-x onTouchMoved вызывается, когда не происходит движение

Я воссоздал проблему в минимальном приложении, основанном на примере HelloWorld cocos2d-x. Я просто получил класс из cocos2d :: Node (testNode) и создал его и добавил его в качестве дочернего элемента HelloWorldScene. В testNode я переопределяю функцию обновления и планирую ее с scheduleUpdate() от onTouchBegan(). В функции update() я просто подсчитываю время до достижения 0,25 с, а затем отключает обновление с помощью unscheduleUpdate(). У меня было еще uncheduleUpdate() звонок в onTouchMoved(), чтобы прекратить отсчет времени удержания в случае перемещения касания. Проблема в том, что на 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; 
}; 

testNode.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-х отладочная информация (32508): startDistFromCenter: 33.753014 09-23 23: 42: 39.902: D/cocos2d-x debug info (32508): перемещение ... pos = 246.732849, 126.925316 09-23 23: 42: 39.902: информация об отладке D/cocos2d-x (32508): перемещение ... pos = 246.732849 , 126.925316 09-23 23: 42: 39.920: D/cocos2d-x информация об отладке (32508): перемещение ... pos = 246.732849, 126.925316 09-23 23: 42: 39.935: D/cocos2d-x информация об отладке (32508): перемещение ... pos = 246,732849, 126,925316 09-23 23: 42: 39,969: D/(32508): перемещение ... pos = 246.732849 , 126.925316 09-23 23: 42: 39.969: D/cocos2d-x информация об отладке (32508): перемещение ... pos = 246.732849, 126.925316 09 -23 23: 42: 39.989: D/cocos2d-x информация об отладке (32508): перемещение ... pos = 246.732849, 126.925316 09-23 23: 42: 39.999: D/cocos2d-x отладочная информация (32508): перемещение ... pos = 246.732849 , 126.925316 09-23 23: 42: 40.027: D/cocos2d-x информация об отладке (32508): перемещение ... pos = 246.732849, 126.925316 09-23 23: 42: 40.043: D/cocos2d-x информация об отладке (32508): перемещение ... pos = 246,732849, 126,925316 09-23 23: 42: 40.043: D/cocos2d-х отладочная информация (32508): Время удержания: 0,042597

Как вы можете видеть, позиция не на самом деле движется .... что дает?

Для справки, я разрабатываю на Windows 10, Visual Studio 2015, cocos2d-х 3.71, а также тестирование на Android 5.1.1 (OnePlusOne телефона)

+0

Звучит как ошибка. Вы можете запустить проблему в github: https://github.com/cocos2d/cocos2d-x. Обходной путь можно рассчитать Dx и Dy и только сделать что-то, если Dx> 0 && Dy> 0. –

+0

Спасибо за предложение. Я уже реализовал аналогичное исправление, связанное с проверкой фактического движения. Вопрос был отправлен. – Polaris

ответ

1

Я проверил ваш код и вопрос связан с андроида леденец , На 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 

Я попробовал также на леденец устройства (LG, но я не помню точно модель), и это, как вы сказали. Спам касания двигался с той же позицией.

В качестве обходного пути вы можете сделать, как Алекс G сказал или запомнил последнюю позицию (вспомните ее при касании) и проигнорируйте события с точно такой же позицией.

Btw Я использую Mac OS X Yosemite и Cocos2d-x 3.8.

Вы должны начать выпуск на странице cocos2d-x github.

+0

Спасибо за проверку этого и подтверждение на Lollipop vs KitKat (также подтверждение того, что ошибка все еще существует в 3.8). Выпуск № 14021 представлен на GitHub. – Polaris