cocos2dx触屏事件详解

前端之家收集整理的这篇文章主要介绍了cocos2dx触屏事件详解前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

版本:2.x

平台iso

先看mian.m文件

//创建一个iso应用

int retVal = UIApplicationMain(argc,argv,nil,@"AppController");

iOS系统会调用AppController 的didFinishLaunchingWithOptions函数,里面做了一些创建界面的东西

函数内部有如下代码

cocos2d::CCApplication::sharedApplication()->run();

注:*.mm文件为object C与C++混编文件命名

AppController.mm文件上面对AppDelegate创建一个对象,AppDelegate继承于CCApplication,cocos2d::CCApplication::sharedApplication()取得的就是该对象

static AppDelegates_sharedApplication;

进入CCApplication::run()函数

int CCApplication::run()

{

if (applicationDidFinishLaunching())

{

[[CCDirectorCaller sharedDirectorCaller] startMainLoop];

}

return 0;

}

进入 AppDelegate::applicationDidFinishLaunching 函数,省略部分代码

bool AppDelegate::applicationDidFinishLaunching()

{

// initialize director

CCDirector *pDirector = CCDirector::sharedDirector();

pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());

进入setOpenGLView函数

void CCDirector::setOpenGLView(CCEGLView *pobOpenGLView)

{

m_pobOpenGLView->setTouchDelegate(m_pTouchDispatcher);//设置触摸代理 只是对CCEGLViewProtocol中EGLTouchDelegate* m_pDelegate; 变量初始化

m_pTouchDispatcher->setDispatchEvents(true);//设置接受派发事件

}

}

CCDirector::init() 已经对cocos2dx引擎用到的变量进行了一些初始化

m_pTouchDispatcher = new CCTouchDispatcher();

m_pTouchDispatcher->init();


我们先回头看一下cocosdx是怎么从ios系统中取得触摸事件:

为了便于针对openGL ES的编程,苹果公司提供了派生于类UIView的类EAGLView来实现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系统发送过来的触屏事件

里面分别调用

cocos2d::CCEGLView::sharedOpenGLView()->handleTouchesBegin(i,ids,xs,ys);

cocos2d::CCEGLView::sharedOpenGLView()->handleTouchesMove(i,ys);

cocos2d::CCEGLView::sharedOpenGLView()->handleTouchesEnd(i,ys);

cocos2d::CCEGLView::sharedOpenGLView()->handleTouchesCancel(i,ys);

进入CCEGLViewProtocol 的这几个函数,里面分别调用

m_pDelegate->touchesBegan(&set,NULL);

m_pDelegate->touchesMoved(&set,NULL);

m_pDelegate->touchesEnded(&set,NULL);

m_pDelegate->touchesCancelled(&set,NULL);

上面已经对m_pDelegate 进行了赋值

m_pTouchDispatcher=newCCTouchDispatcher();

m_pobOpenGLView->setTouchDelegate(m_pTouchDispatcher);


这样CCTouchDispatcher 就能接受到ios系统发送过来的触屏事件了。

看一下 这几个函数m_bDispatchEvents 上面已经对其设置为 true 然后这几个函数都会调用该类的touches函数

void CCTouchDispatcher::touchesBegan(CCSet *touches,CCEvent *pEvent)

{

if (m_bDispatchEvents)

{

this->touches(touches,pEvent,CCTOUCHBEGAN);

}

}


void CCTouchDispatcher::touchesMoved(CCSet *touches,CCTOUCHMOVED);

}

}


void CCTouchDispatcher::touchesEnded(CCSet *touches,CCTOUCHENDED);

}

}


void CCTouchDispatcher::touchesCancelled(CCSet *touches,CCTOUCHCANCELLED);

}

}

我们来看下touches函数

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

//单点触摸

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的数组中取出单个CCTargetedTouchHandler对象

CCARRAY_FOREACH(m_pTargetedHandlers,pObj)

{

pHandler = (CCTargetedTouchHandler *)(pObj);


if (! pHandler)

{

break;

}


bool bClaimed = false;

if (uIndex == CCTOUCHBEGAN)

{

//这里调用CCTargetedTouchHandler对象的ccTouchBegin方法,我们知道cocos2dx中layer为cocos2dx中接受触屏事件的最小单位

bClaimed = pHandler->getDelegate()->ccTouchBegan(pTouch,pEvent);

//如果ccTouchBegin 方法返回true 会把这个CCTargetedTouchHandler对象 加入到 处理 move end canceled 的数组中

//意思就是 如果ccTouchBegin 方法返回true 该CCTargetedTouchHandler对象 才会继续接受到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对象 接受到这个触摸事件了 如果设置为吞并事件 不向下传递了 这里就会把 触屏事件删除

if (bClaimed && pHandler->isSwallowsTouches())

{

if (bNeedsMutableSet)

{

pMutableTouches->removeObject(pTouch);

}


break;

}

}

}

}


//

// process standard handlers 2nd

//这里是多点触摸

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;

}

}

}

//多点触摸是否释放

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();

}

}

现在我们已经了解了 触屏事件的调用流程,我们来看一下 上面的m_pTargetedHandlers 变量是怎么添加对象的

先来看一下 CCLayer函数中得 setTouchEnabled函数 有如下代码

void CCLayer::setTouchEnabled(bool enabled)

if (enabled)

{//ture 注册

this->registerWithTouchDispatcher();

}

else

{

// 传进来的是false删除

CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);

}

看下这个函数

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);//把当前layer或layer的子类加入//触摸优先级//接受到触摸事件是否吞并 不向该优先级以下 传递

}

}

}

看下addTargetedDelegate函数m_pTargetedHandlers 就是我们上文中 touchs函数CCTouchHandler* 的数组

void CCTouchDispatcher::addTargetedDelegate(CCTouchDelegate *pDelegate,int nPriority,bool bSwallowsTouches)

{

CCTouchHandler *pHandler = CCTargetedTouchHandler::handlerWithDelegate(pDelegate,nPriority,bSwallowsTouches);

if (! m_bLocked)

{

forceAddHandler(pHandler,m_pTargetedHandlers);

}

然后再看下forceAddHandler函数,该函数添加之前需要遍历一遍数组,把当前加入的CCTouchHandler* 按优先级加入到已有的CCTouchHandler*数组中

从下面的代码中 我们知道 数组的排序是按 优先级 从小到大排列的 也就是说 设置的优先级 越小,就会最优先接受到触屏事件

void CCTouchDispatcher::forceAddHandler(CCTouchHandler *pHandler,CCArray *pArray)

{

unsigned int u = 0;

CCObject* pObj = NULL;

//遍历数组

CCARRAY_FOREACH(pArray,pObj)

{

CCTouchHandler *h = (CCTouchHandler *)pObj;

if (h)

{//比较优先级 设置插入的位置

if (h->getPriority() < pHandler->getPriority())

{

++u;

}

if (h->getDelegate() == pHandler->getDelegate())

{

CCAssert(0, "");

return;

}

}

}

//向该数组中 加入该CCTouchHandler*pHandler

pArray->insertObject(pHandler,u);

}


现在触摸事件的流程,我们已经知道了,现在来实现我们自己的触摸函数

首先我们要继承CCLayer函数,重写接受触摸事件的个函数

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);//默认吞噬触摸事件

}

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,触摸事件已经实现了,可以根据自己的需要,写一些逻辑了。

原文链接:https://www.f2er.com/cocos2dx/345119.html

猜你在找的Cocos2d-x相关文章