// // Tickle2GestureRecognizer.cpp // SteveMaggieCpp // // Created by Katarzyna Kalinowska-Górska on 19.05.2017. // // #include #include "Tickle2GestureRecognizer.h" #include "AniGeometryUtils.h" #include "AniMathUtils.h" #include "AniMiscUtils.h" //constructor Tickle2GestureRecognizer::Tickle2GestureRecognizer() : AniGestureRecognizer({cocos2d::EventListener::Type::TOUCH_ONE_BY_ONE}) { this->clearTemps(); _currentDirectionX = AniGestureRecognizerDirection::NONE; _currentDirectionY = AniGestureRecognizerDirection::NONE; _onTicklingStartedCallback = [](){}; _onTicklingCallback = [](){}; _onTicklingEndedCallback = [](){}; _isTickling = false; } Tickle2GestureRecognizer::~Tickle2GestureRecognizer() { }; void Tickle2GestureRecognizer::setOnTicklingStartedCallback(std::function callback) { _onTicklingStartedCallback = callback; } void Tickle2GestureRecognizer::setOnTicklingCallback(std::function callback) { _onTicklingCallback = callback; } void Tickle2GestureRecognizer::setOnTicklingEndedCallback(std::function callback) { _onTicklingEndedCallback = callback; } // internal void Tickle2GestureRecognizer::clearTemps() { _directionChangeTimes.clear(); _lastXDeltas.clear(); _lastYDeltas.clear(); _tickleStartedTime = -1; } void Tickle2GestureRecognizer::endTickling() { _onTicklingEndedCallback(); _isTickling = false; _tickleStartedTime = -1; } // touch handlers bool Tickle2GestureRecognizer::onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event) { if(!AniGeometryUtils::getBoundingBoxToWorld(_view).containsPoint(touch->getLocation())){ return false; } this->clearTemps(); _currentDirectionX = AniGestureRecognizerDirection::NONE; _currentDirectionY = AniGestureRecognizerDirection::NONE; return true; } void Tickle2GestureRecognizer::onTouchMoved(cocos2d::Touch* touch, cocos2d::Event* event) { // if(!AniGeometryUtils::getBoundingBoxToWorld(_view).containsPoint(touch->getLocation())){ if(!AniMiscUtils::getExtendedActiveArea(_view, 20, 10).containsPoint(touch->getLocation())){ this->endTickling(); this->clearTemps(); return; } auto touchLocation = touch->getLocation(); auto prevLocation = touch->getPreviousLocation(); auto deltaX = touchLocation.x - prevLocation.x; auto deltaY = touchLocation.y - prevLocation.y; bool newTickling = false; //todo into separate function ? !!! _lastXDeltas.push_back(deltaX); if(_lastXDeltas.size() >= N_LAST_SAMPLES){ while(_lastXDeltas.size() > N_LAST_SAMPLES){ _lastXDeltas.pop_front(); } float averageDeltaX = 0; AniMathUtils::averageValue(_lastXDeltas, averageDeltaX); // log("delta: "+averageDeltaX); if(std::abs(averageDeltaX) >= MIN_DELTA_VALUE){ auto xDirection = AniGestureRecognizer::mapXToDirection(averageDeltaX); if(xDirection != _currentDirectionX && xDirection != AniGestureRecognizerDirection::NONE){ _currentDirectionX = xDirection; while(_directionChangeTimes.size() > N_DIRECTION_CHANGES_TO_DETECT_TICKLE-1){ _directionChangeTimes.pop_front(); } double now = cocos2d::utils::getTimeInMilliseconds(); _directionChangeTimes.push_back(now); if(_directionChangeTimes.size() == N_DIRECTION_CHANGES_TO_DETECT_TICKLE){ auto deltaTime = now - _directionChangeTimes[0]; // log("delta time: "+deltaTime); if(deltaTime <= MAX_DETECTION_TIME){ newTickling = true; // this->clearTemps(); } } // return; } } } _lastYDeltas.push_back(deltaY); if(!newTickling && _lastYDeltas.size() >= N_LAST_SAMPLES){ while(_lastYDeltas.size() > N_LAST_SAMPLES){ _lastYDeltas.pop_front(); } float averageDeltaY = 0; AniMathUtils::averageValue(_lastYDeltas, averageDeltaY); // cocos2d::log("average delta y: %f", averageDeltaY); if(std::abs(averageDeltaY) >= MIN_DELTA_VALUE){ auto yDirection = AniGestureRecognizer::mapYToDirection(averageDeltaY); if(yDirection != _currentDirectionY && yDirection != AniGestureRecognizerDirection::NONE){ _currentDirectionY = yDirection; // cocos2d::log("current y dir: %s",_currentDirectionY.c_str()); // cocos2d::log("dir change count: %d",_directionChangeCount); while(_directionChangeTimes.size() > N_DIRECTION_CHANGES_TO_DETECT_TICKLE-1){ _directionChangeTimes.pop_front(); } double now = cocos2d::utils::getTimeInMilliseconds(); _directionChangeTimes.push_back(now); if(_directionChangeTimes.size() == N_DIRECTION_CHANGES_TO_DETECT_TICKLE){ auto deltaTime = now - _directionChangeTimes[0]; // cocos2d::log("delta time: %f", deltaTime); if(deltaTime <= MAX_DETECTION_TIME){ newTickling = true; // this->clearTemps(); } } } } } if(newTickling == true){ if(_isTickling){ _onTicklingCallback(); } else { if(!_isTickling){ _isTickling = true; _onTicklingStartedCallback(); } _tickleStartedTime = cocos2d::utils::getTimeInMilliseconds(); } } /*else if(_isTickling) { double currentTime = cocos2d::utils::getTimeInMilliseconds(); if(currentTime - _tickleStartedTime > TIME_TO_ASSUME_TICKLE_FINISHED){ this->endTickling(); } }*/ } void Tickle2GestureRecognizer::onTouchEnded(cocos2d::Touch* touch, cocos2d::Event* event) { if(_isTickling){ this->endTickling(); } this->clearTemps(); }