Я пишу кроссплатформенное приложение cocos2d-x 3.71 (ios, android, windows10) и испытываю проблемы с реализацией обнаружения касания и удержания только на Android (IOS и Windows работают нормально). Я проследил причину этого до того факта, что, удерживая прикосновение вниз и не двигаясь, onTouchMoved() постоянно срабатывает. Я включил обходной путь, но это похоже на ошибку, и мне интересно, есть ли у кого-нибудь идеи.
Я воссоздал проблему в минимальном приложении, основанном на примере cocos2d-x HelloWorld. Я просто получил класс от cocos2d :: Node (testNode) и создал его и добавил как дочерний элемент в HelloWorldScene. В testNode я перезаписываю функцию обновления и планирую ее scheduleUpdate() от onTouchBegan(). В функции update () я просто считаю время до достижения 0,25 с, а затем отключаю обновление с помощью unscheduleUpdate(). У меня был другой unscheduleUpdate() вызывать 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-x (32508):
startDistFromCenter: 33.753014 09-23 23: 42: 39.902: отладка D / cocos2d-x
информация (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 / cocos2d-x (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-x (32508): время удержания: 0,042597
Как видите, позиция не на самом деле движется …. что дает?
Для справки я занимаюсь разработкой для Windows 10, Visual Studio 2015, cocos2d-x 3.71 и тестирую на Android 5.1.1 (телефон OnePlusOne)
Я проверил ваш код, и проблема связана с Android Lollipop. На киткат все работает (тестирование устройства 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, но я не помню точно модель), и это, как вы сказали. Спам касания переместился с той же позиции.
В качестве обходного пути вы можете сделать так, как сказал Алекс Г., или вспомнить последнюю позицию (помните, что она началась при прикосновении) и игнорировать события с точно такой же позицией.
Кстати, я использую Mac OS X Yosemite и Cocos2d-x 3.8.
Вы должны начать выпуск на странице cocos2d-x github.
Других решений пока нет …