/* * LsTouch.h */ #ifndef LSTOUCH_H_ #define LSTOUCH_H_ #include "cocos2d.h" USING_NS_CC; class LsTouchEvent; /** * 定義可觸摸元素,用於統一管理 */ class LsTouch : public CCNode { public: LsTouch(); ~LsTouch(); CREATE_FUNC(LsTouch); virtual bool init(); // 設置顯示項 void setDisplay(CCSprite* dis); void setEventId(int eventId); int getEventId(); /// 常規判斷 bool selfCheck(CCTouch* ccTouch, LsTouchEvent* lsTe); private: // 判斷當前的元素是否被點擊 bool containsCCTouchPoint(CCTouch* ccTouch); bool isParentAllVisible(LsTouchEvent* lsTe); // 用戶保存顯示精靈的 tag static const int TAG_DISPLAY = 100; int m_iEventId; }; class LsTouchEvent { public: LsTouchEvent(); ~LsTouchEvent(); void addLsTouch(LsTouch* touch, int eventId); void removeLsTouch(LsTouch* touch); bool sendTouchMessage(CCTouch* ccTouch); // 返回優先級較高的可觸摸對象 LsTouch* getPriorityTouch(LsTouch* a, LsTouch* b); virtual void touchEventAction(LsTouch* touch) = 0; private: CCArray* m_pLsTouches; }; #endif /* LSTOUCH_H_ */
/* * LsTouch.cpp * */ #include "LsTouch.h" LsTouch::LsTouch() { CCLog("LsTouch()"); m_iEventId = 0; } LsTouch::~LsTouch() { CCLog("LsTouch().~()"); } bool LsTouch::init() { if ( !Node::init() ) { return false; } return true; } void LsTouch::setDisplay(CCSprite* dis) { // 設置以前先清除,沒有也無所謂 removeChildByTag(TAG_DISPLAY, true); addChild(dis, 0, TAG_DISPLAY); } void LsTouch::setEventId(int eventId) { m_iEventId = eventId; } int LsTouch::getEventId() { return m_iEventId; } bool LsTouch::selfCheck(CCTouch* ccTouch, LsTouchEvent* lsTe) { bool bRef = false; // 可點擊項的檢測,可擴展 do { // 是否經過點擊位置檢測 CC_BREAK_IF(!containsCCTouchPoint(ccTouch)); // 是否正在運行,排除可能存在已經從界面移除,可是並無釋放的可能 CC_BREAK_IF(!isRunning()); // 判斷是否隱藏 CC_BREAK_IF(!isVisible()); // 這裏可能還須要判斷內部顯示項目是否隱藏 ///// 暫留 // 不只判斷當前元素是否隱藏,還須要判斷在它之上的元素直到事件處理層,是否存在隱藏 CC_BREAK_IF(!isParentAllVisible(lsTe)); bRef = true; } while (0); return bRef; } bool LsTouch::containsCCTouchPoint(CCTouch* ccTouch) { // 得到顯示內容 CCNode* dis = getChildByTag(TAG_DISPLAY); CCSprite* sprite = dynamic_cast<CCSprite*>(dis); CCPoint point = sprite->convertTouchToNodeSpaceAR(ccTouch); CCSize s = sprite->getTexture()->getContentSize(); CCRect rect = CCRectMake(-s.width / 2, -s.height / 2, s.width, s.height); return rect.containsPoint(point); } bool LsTouch::isParentAllVisible(LsTouchEvent* lsTe) { bool bRef = true; // 向父類轉型,以便獲取地址比較對象,LsTouchEvent 的對象必須同時直接或者簡介繼承 CCNode CCNode* nLsTe = dynamic_cast<CCNode*>(lsTe); CCNode* parent = getParent(); do { // 若是遍歷完畢,說明 LsTouch 再也不 LsTouchEvent 以內 if (!parent) { bRef = false; break; } // 若是 LsTouch 在 LsTouchEvent 以內,返回 true // 注意:若是想讓LsTouchEvent 處理 不在其 CCNode 結構以內的元素,則取消此處判斷 if (nLsTe == parent) { break; } if (!parent->isVisible()) { bRef = false; break; } parent = parent->getParent(); } while (1); return bRef; } LsTouchEvent::LsTouchEvent() { CCLog("LsTouchEvent()"); m_pLsTouches = CCArray::create(); m_pLsTouches->retain(); } LsTouchEvent::~LsTouchEvent() { CCLog("LsTouchEvent().~()"); m_pLsTouches->release(); } void LsTouchEvent::addLsTouch(LsTouch* touch, int eventId) { touch->setEventId(eventId); m_pLsTouches->addObject(touch); } void LsTouchEvent::removeLsTouch(LsTouch* touch) { m_pLsTouches->removeObject(touch, true); } bool LsTouchEvent::sendTouchMessage(CCTouch* ccTouch) { // 編寫判斷,集合中的哪一個元素級別高,就觸發哪個 LsTouch* lsTouch = NULL; // 得到點擊的點 CCObject* pObj = NULL; LsTouch* lt = NULL; CCARRAY_FOREACH(m_pLsTouches, pObj) { lt = dynamic_cast<LsTouch*>(pObj); if (lt) { if (lt->selfCheck(ccTouch, this)) { if (lsTouch == NULL) lsTouch = lt; else // 若是已存在符合條件元素,比較優先級 lsTouch = getPriorityTouch(lsTouch, lt); } } } // 比對最終只有一個元素觸發 if (lsTouch){ touchEventAction(lsTouch); return true; } return false; } LsTouch* LsTouchEvent::getPriorityTouch(LsTouch* a, LsTouch* b) { // 觸摸優先級經過 CCNode 樹判斷,也既是顯示層次級別等因素 // 以當前元素爲「根」向父類轉型,以便獲取地址比較對象,LsTouchEvent 的對象必須同時直接或者簡介繼承 CCNode CCNode* nLsTe = dynamic_cast<CCNode*>(this); // 共同的分枝 CCNode* allParent = NULL; // 尋找 a 與 b 共同的分枝 CCNode* nAParent = a; CCNode* nBParent = b; CCNode* nAChild = NULL; CCNode* nBChild = NULL; do { nAChild = nAParent; nAParent = nAParent->getParent(); if (!nAParent) break; nBParent = b; do { nBChild = nBParent; nBParent = nBParent->getParent(); if (!nBParent) break; if (nAParent == nBParent) { allParent = nAParent; break; } if (nBParent == nLsTe) { break; } } while (1); if (allParent) break; if (nAParent == nLsTe) { break; } } while (1); // 此處只須要判斷 nAChild 和 nBChild 的優先級便可,默認返回 a if (!nAChild || !nBChild) return a; // 根據 ZOrder 判斷,若是 ZOrder同樣,根據索引位置判斷 if ( nAChild->getZOrder() == nBChild->getZOrder() ) { return (allParent->getChildren().getIndex(nAChild)) > (allParent->getChildren().getIndex(nBChild)) ? a : b; } else { return nAChild->getZOrder() > nBChild->getZOrder() ? a : b; } }
調用例子:html
1. 繼承
this
class HelloWorld : public cocos2d::Layer, public LsTouchEvent
2. 重寫 touchEventAction:spa
void HelloWorld::touchEventAction(LsTouch* touch) { //touch->getEventId() 事件ID CCLog("touch event action id: %d", touch->getEventId()); }
3.調用code
//建立精靈 auto sprint1 = Sprite::create("CloseNormal.png"); //建立可觸控對象 LsTouch* lt = LsTouch::create(); //設置可觸控對象的位置 lt->setPosition(origin.x, origin.y); //把精靈綁定到可操控對象上,把精靈加入帶可操控對象表 lt->setDisplay(sprint1); //把可觸控對象加入到場景中 this->addChild(lt); //把可觸控對象加入事件處理,當觸屏綁定精靈時調用touchEventAction //並傳達事件ID,根據區分ID 處理對應的事情 this->addLsTouch(lt, 120); //建立佈景的 觸摸監聽 auto listener1 = EventListenerTouchOneByOne::create();//建立一個觸摸監聽 listener1->setSwallowTouches(true);//設置是否想下傳遞觸摸 listener1->onTouchBegan = [ = ](Touch* touch, Event* event){ // 給事件類 發送消息 sendTouchMessage(touch); return true; }; _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);
本文引用:http://blog.leafsoar.com/archives/2013/05-25.htmlorm