知識
不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側(cè)重于功能的便捷,營銷的便利,運(yùn)營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏壧峁┍憬莸闹С郑?
cocos2dx觸屏事件詳解
發(fā)表時間:2020-10-19
發(fā)布人:葵宇科技
瀏覽次數(shù):85
版本:2.x
平臺iso
先看mian.m文件
//創(chuàng)建一個iso應(yīng)用
int retVal = UIApplicationMain(argc, argv, nil, @"AppController");
iOS體系會調(diào)用AppController 的 didFinishLaunchingWithOptions函數(shù),瑯綾擎做了一些創(chuàng)建界面的器械
該函數(shù)內(nèi)部有如下代碼;
cocos2d::CCApplication::sharedApplication()->run();
注:*.mm文件為object C與C++混編文件定名
AppController.mm文件膳綾擎對 AppDelegate創(chuàng)建一個對象,AppDelegate持續(xù)于CCApplication, cocos2d::CCApplication::sharedApplication()取得的就是該對象
static AppDelegate s_sharedApplication;
進(jìn)入 CCApplication::run()函數(shù)
int CCApplication::run()
{
if (applicationDidFinishLaunching())
{
[[CCDirectorCaller sharedDirectorCaller] startMainLoop];
}
return 0;
}
進(jìn)入AppDelegate::applicationDidFinishLaunching 函數(shù),省略部分代碼
bool AppDelegate::applicationDidFinishLaunching()
{
// initialize director
CCDirector *pDirector = CCDirector::sharedDirector();
pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());
進(jìn)入setOpenGLView函數(shù),
void CCDirector::setOpenGLView(CCEGLView *pobOpenGLView)
{
。
。
。
m_pobOpenGLView->setTouchDelegate(m_pTouchDispatcher);//設(shè)置觸摸代勞 只是對CCEGLViewProtocol中 EGLTouchDelegate* m_pDelegate; 變量初始化
m_pTouchDispatcher->setDispatchEvents(true);//設(shè)置接收派發(fā)事宜
}
}
CCDirector::init() 已經(jīng)對cocos2dx引擎用到的變量進(jìn)行了一些初始化
m_pTouchDispatcher = new CCTouchDispatcher();
m_pTouchDispatcher->init();
我們先回頭看一下cocosdx是怎么大年夜ios體系中取得觸摸事宜:
為了便于針對openGL ES的編程,蘋不雅公司供給了派生于類UIView的類EAGLView來實(shí)現(xiàn)OpenGL的輸出支撐。
如許EAGLView.mm中得
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
就會接收到ios體系發(fā)送過來的觸屏事宜
瑯綾擎分別調(diào)用了
cocos2d::CCEGLView::sharedOpenGLView()->handleTouchesBegin(i, ids, xs, ys);
cocos2d::CCEGLView::sharedOpenGLView()->handleTouchesMove(i, ids, xs, ys);
cocos2d::CCEGLView::sharedOpenGLView()->handleTouchesEnd(i, ids, xs, ys);
cocos2d::CCEGLView::sharedOpenGLView()->handleTouchesCancel(i, ids, xs, ys);
進(jìn)入CCEGLViewProtocol 的┞封幾個函數(shù),瑯綾擎分別調(diào)用了
m_pDelegate->touchesBegan(&set, NULL);
m_pDelegate->touchesMoved(&set, NULL);
m_pDelegate->touchesEnded(&set, NULL);
m_pDelegate->touchesCancelled(&set, NULL);
膳綾擎已經(jīng)對m_pDelegate 進(jìn)行了賦值
m_pTouchDispatcher = new CCTouchDispatcher();
m_pobOpenGLView->setTouchDelegate(m_pTouchDispatcher);
如許CCTouchDispatcher 就能接收到ios體系發(fā)送過來的觸屏事宜了。
看一下 這幾個函數(shù) m_bDispatchEvents 膳綾擎已經(jīng)對其設(shè)置為 true 然后這幾個函數(shù)都邑調(diào)用該類的touches函數(shù)
void CCTouchDispatcher::touchesBegan(CCSet *touches, CCEvent *pEvent)
{
if (m_bDispatchEvents)
{
this->touches(touches, pEvent, CCTOUCHBEGAN);
}
}
void CCTouchDispatcher::touchesMoved(CCSet *touches, CCEvent *pEvent)
{
if (m_bDispatchEvents)
{
this->touches(touches, pEvent, CCTOUCHMOVED);
}
}
void CCTouchDispatcher::touchesEnded(CCSet *touches, CCEvent *pEvent)
{
if (m_bDispatchEvents)
{
this->touches(touches, pEvent, CCTOUCHENDED);
}
}
void CCTouchDispatcher::touchesCancelled(CCSet *touches, CCEvent *pEvent)
{
if (m_bDispatchEvents)
{
this->touches(touches, pEvent, CCTOUCHCANCELLED);
}
}
我們來看下touches函數(shù)
void CCTouchDispatcher::touches(CCSet *pTouches, CCEvent *pEvent, unsigned int uIndex)
{
CCAssert(uIndex >= 0 && uIndex < 4, "");
CCSet *pMutableTouches;
m_bLocked = true;
// optimization to prevent a mutable copy when it is not necessary
unsigned int uTargetedHandlersCount = m_pTargetedHandlers->count();
unsigned int uStandardHandlersCount = m_pStandardHandlers->count();
bool bNeedsMutableSet = (uTargetedHandlersCount && uStandardHandlersCount);
pMutableTouches = (bNeedsMutableSet ? pTouches->mutableCopy() : pTouches);
struct ccTouchHandlerHelperData sHelper = m_sHandlerHelperData[uIndex];
//
// process the target handlers 1st
//單點(diǎn)觸摸
if (uTargetedHandlersCount > 0)
{
CCTouch *pTouch;
CCSetIterator setIter;
for (setIter = pTouches->begin(); setIter != pTouches->end(); ++setIter)
{
pTouch = (CCTouch *)(*setIter);
CCTargetedTouchHandler *pHandler = NULL;
CCObject* pObj = NULL;
//大年夜CCTargetedTouchHandler的數(shù)組中掏出單個CCTargetedTouchHandler對象
CCARRAY_FOREACH(m_pTargetedHandlers, pObj)
{
pHandler = (CCTargetedTouchHandler *)(pObj);
if (! pHandler)
{
break;
}
bool bClaimed = false;
if (uIndex == CCTOUCHBEGAN)
{
//這里調(diào)用CCTargetedTouchHandler對象的ccTouchBegin辦法,我們知道cocos2dx中l(wèi)ayer為cocos2dx中接收觸屏事宜的最小單位
bClaimed = pHandler->getDelegate()->ccTouchBegan(pTouch, pEvent);
//如不雅ccTouchBegin 辦法返回true 會把這個CCTargetedTouchHandler對象 參加到 處理 move end canceled 的數(shù)組中
//意思就是 如不雅ccTouchBegin 辦法返回true 該CCTargetedTouchHandler對象 才會持續(xù)接收到 move end canceled 這三個事宜
if (bClaimed)
{
pHandler->getClaimedTouches()->addObject(pTouch);
}
} else
if (pHandler->getClaimedTouches()->containsObject(pTouch))
{
// moved ended canceled
bClaimed = true;
switch (sHelper.m_type)
{
case CCTOUCHMOVED:
pHandler->getDelegate()->ccTouchMoved(pTouch, pEvent);
break;
case CCTOUCHENDED:
pHandler->getDelegate()->ccTouchEnded(pTouch, pEvent);
pHandler->getClaimedTouches()->removeObject(pTouch);
break;
case CCTOUCHCANCELLED:
pHandler->getDelegate()->ccTouchCancelled(pTouch, pEvent);
pHandler->getClaimedTouches()->removeObject(pTouch);
break;
}
}
//如不雅有CCTargetedTouchHandler對象 接收到這個觸摸事宜了 如不雅設(shè)置為兼并事宜 不向下傳遞了 這里就會把 觸屏事宜刪除
if (bClaimed && pHandler->isSwallowsTouches())
{
if (bNeedsMutableSet)
{
pMutableTouches->removeObject(pTouch);
}
break;
}
}
}
}
//
// process standard handlers 2nd
//這里是多點(diǎn)觸摸
if (uStandardHandlersCount > 0 && pMutableTouches->count() > 0)
{
CCStandardTouchHandler *pHandler = NULL;
CCObject* pObj = NULL;
CCARRAY_FOREACH(m_pStandardHandlers, pObj)
{
pHandler = (CCStandardTouchHandler*)(pObj);
if (! pHandler)
{
break;
}
switch (sHelper.m_type)
{
case CCTOUCHBEGAN:
pHandler->getDelegate()->ccTouchesBegan(pMutableTouches, pEvent);
break;
case CCTOUCHMOVED:
pHandler->getDelegate()->ccTouchesMoved(pMutableTouches, pEvent);
break;
case CCTOUCHENDED:
pHandler->getDelegate()->ccTouchesEnded(pMutableTouches, pEvent);
break;
case CCTOUCHCANCELLED:
pHandler->getDelegate()->ccTouchesCancelled(pMutableTouches, pEvent);
break;
}
}
}
//多點(diǎn)觸摸是否釋放
if (bNeedsMutableSet)
{
pMutableTouches->release();
}
//
// Optimization. To prevent a [handlers copy] which is expensive
// the add/removes/quit is done after the iterations
//這以下沒研究到底是干什么的 感興趣可以本身看下
m_bLocked = false;
if (m_bToRemove)
{
m_bToRemove = false;
for (unsigned int i = 0; i < m_pHandlersToRemove->num; ++i)
{
forceRemoveDelegate((CCTouchDelegate*)m_pHandlersToRemove->arr[i]);
}
ccCArrayRemoveAllValues(m_pHandlersToRemove);
}
if (m_bToAdd)
{
m_bToAdd = false;
CCTouchHandler* pHandler = NULL;
CCObject* pObj = NULL;
CCARRAY_FOREACH(m_pHandlersToAdd, pObj)
{
pHandler = (CCTouchHandler*)pObj;
if (! pHandler)
{
break;
}
if (dynamic_cast<CCTargetedTouchHandler*>(pHandler) != NULL)
{
forceAddHandler(pHandler, m_pTargetedHandlers);
}
else
{
forceAddHandler(pHandler, m_pStandardHandlers);
}
}
m_pHandlersToAdd->removeAllObjects();
}
if (m_bToQuit)
{
m_bToQuit = false;
forceRemoveAllDelegates();
}
}
如今我們已經(jīng)懂得了 觸屏事宜的調(diào)用流程,我們來看一下 膳綾擎的 m_pTargetedHandlers 變量是怎么添加對象的
先來看一下 CCLayer函數(shù)中得 setTouchEnabled函數(shù) 有如下代碼
void CCLayer::setTouchEnabled(bool enabled)
if (enabled)
{//ture 注冊
this->registerWithTouchDispatcher();
}
else
{
// 傳進(jìn)來的是false刪除
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
}
看下這個函數(shù)
void CCLayer::registerWithTouchDispatcher()
{
CCTouchDispatcher* pDispatcher = CCDirector::sharedDirector()->getTouchDispatcher();
// Using LuaBindings 用于lua的
if (m_pScriptTouchHandlerEntry)
{
if (m_pScriptTouchHandlerEntry->isMultiTouches())
{
pDispatcher->addStandardDelegate(this, 0);
LUALOG("[LUA] Add multi-touches event handler: %d", m_pScriptTouchHandlerEntry->getHandler());
}
else
{
pDispatcher->addTargetedDelegate(this,
m_pScriptTouchHandlerEntry->getPriority(),
m_pScriptTouchHandlerEntry->getSwallowsTouches());
LUALOG("[LUA] Add touch event handler: %d", m_pScriptTouchHandlerEntry->getHandler());
}
}
else
{
if( m_eTouchMode == kCCTouchesAllAtOnce ) {
pDispatcher->addStandardDelegate(this, 0);
} else {
pDispatcher->addTargetedDelegate(this, m_nTouchPriority, true);//把當(dāng)前l(fā)ayer或layer的子類參加 //觸摸優(yōu)先級 //接收到觸摸事宜是否兼并 不向該優(yōu)先級以下 傳遞
}
}
}
看下addTargetedDelegate函數(shù) m_pTargetedHandlers 就是我們上文中 touchs函數(shù)中CCTouchHandler * 的數(shù)組
void CCTouchDispatcher::addTargetedDelegate(CCTouchDelegate *pDelegate, int nPriority, bool bSwallowsTouches)
{
CCTouchHandler *pHandler = CCTargetedTouchHandler::handlerWithDelegate(pDelegate, nPriority, bSwallowsTouches);
if (! m_bLocked)
{
forceAddHandler(pHandler, m_pTargetedHandlers);
}
然后再看下forceAddHandler函數(shù),該函數(shù)添加之前須要遍歷一遍數(shù)組,把當(dāng)前參加的CCTouchHandler* 按竽暌古先級參加到已有的CCTouchHandler* 數(shù)組中
大年夜下面的代碼中 我們知道 數(shù)組的排序是按 優(yōu)先級 大年夜小到大年夜分列的 也就是說 設(shè)置的優(yōu)先級 越小,就會最優(yōu)先接收到觸屏事宜
void CCTouchDispatcher::forceAddHandler(CCTouchHandler *pHandler, CCArray *pArray)
{
unsigned int u = 0;
CCObject* pObj = NULL;
//遍歷數(shù)組
CCARRAY_FOREACH(pArray, pObj)
{
CCTouchHandler *h = (CCTouchHandler *)pObj;
if (h)
{//比較優(yōu)先級 設(shè)置插入的地位
if (h->getPriority() < pHandler->getPriority())
{
++u;
}
if (h->getDelegate() == pHandler->getDelegate())
{
CCAssert(0, "");
return;
}
}
}
//向該數(shù)組中 參加該CCTouchHandler *pHandler
pArray->insertObject(pHandler, u);
}
如今觸摸事宜的流程,我們已經(jīng)知道了,如今來實(shí)現(xiàn)我們本身的觸摸函數(shù)
起首我們要持續(xù)CCLayer函數(shù),重寫接收觸摸事宜的個函數(shù)
class UILayer : public CCLayer
{
public:
UILayer();
~UILayer();
public:
virtual bool init();
virtual void onEnter();
virtual void onExit();
virtual void registerWithTouchDispatcher();
virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
virtual void ccTouchEnded(CCTouch* touch, CCEvent* event);
virtual void ccTouchCancelled(CCTouch* touch, CCEvent* event);
virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);
CREATE_FUNC(UILayer);
};
UILayer::UILayer()
{
}
UILayer::~UILayer()
{
}
bool UILayer::init()
{
if ( !CCLayer::init() )
{
return false;
}
return true;
}
void UILayer::onEnter()
{
CCLayer::onEnter();
setTouchEnabled(true);
}
void UILayer::onExit()
{
CCLayer::onExit();
}
void UILayer::registerWithTouchDispatcher()
{
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, ROR::TOUCH_UI_PRIORITY, true);//默認(rèn)吞噬觸摸事宜
}
bool UILayer::ccTouchBegan(CCTouch* touch, CCEvent* event)
{
CCLOG("ccTouchBegan");
return true;
}
void UILayer::ccTouchEnded(CCTouch* touch, CCEvent* event)
{
CCLOG("ccTouchEnded");
}
void UILayer::ccTouchCancelled(CCTouch* touch, CCEvent* event)
{
CCLOG("ccTouchCancelled");
}
void UILayer::ccTouchMoved(CCTouch* touch, CCEvent* event)
{
CCLOG("ccTouchMoved");
}
OK,觸摸事宜已經(jīng)實(shí)現(xiàn)了,可以根據(jù)本身的須要,寫一些邏輯了。
相關(guān)案例查看更多
相關(guān)閱讀
- 微分銷
- 云南小程序開發(fā)費(fèi)用
- 正規(guī)網(wǎng)站建設(shè)公司
- 昆明小程序開發(fā)
- 報廢車拆解軟件
- 云南網(wǎng)站建設(shè)高手
- 小程序分銷商城
- 網(wǎng)站建設(shè)首選公司
- 云南網(wǎng)站建設(shè)服務(wù)公司
- 云南網(wǎng)站建設(shè)公司排名
- 網(wǎng)站開發(fā)
- 云南網(wǎng)站建設(shè)公司地址
- 云南小程序設(shè)計
- 網(wǎng)站建設(shè)電話
- 前端技術(shù)
- 昆明小程序設(shè)計
- 百度自然排名
- 昆明網(wǎng)絡(luò)公司
- 小程序密鑰
- 百度快速排名
- 汽車報廢拆解管理系統(tǒng)
- 支付寶小程序被騙
- 網(wǎng)站建設(shè)需要多少錢
- 云南網(wǎng)站建設(shè)百度
- 開通微信小程序被騙
- 網(wǎng)絡(luò)公司
- 云南小程序開發(fā)哪家好
- 網(wǎng)站上首頁
- web開發(fā)技術(shù)
- 云南手機(jī)網(wǎng)站建設(shè)