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 AppDelegate s_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, ids, xs, ys);

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

cocos2d::CCEGLView::sharedOpenGLView()->handleTouchesCancel(i, ids, xs, 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 = new CCTouchDispatcher();

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,
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函数

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

时间: 2024-10-16 08:10:01

cocos2dx触屏事件详解的相关文章

25.Unity3D手机中Input类touch详解-Unity触屏事件解析到底(Twisted Fate)

首先贴一下Unity支持的模型文件类型,以前没有收集过. Unity支持两种类型的3D文件格式: 1.  通用的"出口型"3D文件 如.fbx..dae..3ds..dxf..obj等文件格式. 2.  3D软件专用的3D文件格式 如Max, Maya, Blender,Cinema4D, Modo, Lightwave & Cheetah3D 等软件所支持的格式,如.MAX, .MB, .MA等等. Unity3D手机中Input类touch详解: 1.Input.touch

【COCOS2D-X 备注篇】cocos2dx 获取手机截屏等意外取消触屏事件的处理方法!

最近有童鞋问我如何获取到iphone手机截屏的事件,所以本篇就简单的聊下这种问题的处理办法. 在cocos2dx引擎中,我们能在AppDelegate中获取到,用户将应用切入后台,以及重新返回应用的事件函数.那么对应的,cocos2dx也在引擎中给予我们截取屏幕等这种只能手机应有事件的处理函数. 其实大家应该都很熟悉截取用户触屏的函数,如下: 1 2 3 4 // default implements are used to call script callback if exist virtu

Cocos2d-x 3.0坐标系详解(转载)

Cocos2d-x 3.0坐标系详解Cocos2d-x坐标系和OpenGL坐标系相同,都是起源于笛卡尔坐标系.笛卡尔坐标系笛卡尔坐标系中定义右手系原点在左下角,x向右,y向上,z向外,OpenGL坐标系为笛卡尔右手系.屏幕坐标系和Cocos2d坐标系标准屏幕坐标系使用和OpenGL不同的坐标系,而Cocos2d则使用和OpenGL相同的坐标系.iOS, Android, Windows Phone等在开发应用时使用的是标准屏幕坐标系,原点为屏幕左上角,x向右,y向下.Cocos2d坐标系和Ope

C# 中的委托和事件详解

C# 中的委托和事件 文中代码在VS2005下通过,由于VS2003(.Net Framework 1.1)不支持隐式的委托变量,所以如果在一个接受委托类型的位置直接赋予方法名,在VS2003下会报错,解决办法是显式的创建一个委托类型的实例(委托变量).例如:委托类型 委托实例 = new 委托类型(方法名); 引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易

使用 jQuery Mobile 与 HTML5 开发 Web App —— jQuery Mobile 事件详解

在前文<使用 jQuery Mobile 与 HTML5 开发 Web App —— jQuery Mobile 默认配置与事件基础>中,Kayo 对 jQuery Mobile 事件的基础作出了一些说明,建议在阅读本文前首先阅读前文,这里 Kayo 再引用前文的重要内容. “jQuery Mobile 在基于本地事件上,创建了一系列的自定义事件,大部分事件是基于触摸设备的使用情况开发的,当然这些事件对于桌面环境也会有适当的处理,开发者可以使用 bind() 函数绑定到需要的页面对象中. 值得

触屏事件

iphone ipad开发: 关于触屏事件的一些操作 [cpp] view plaincopyprint? //轻击: //需要在你的ViewController里重写几个方法: //开始触摸的方法 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { messageLabel.text = @”Touches Began”; [self updateLabelsFromTouches:touches]; } //触

javascript事件详解笔记

javascript事件详解笔记: 一.事件流 1.事件流: 描述的是页面中接受事件的顺序,有事件冒泡.事件捕获两种. 2.事件冒泡: 由最具体的元素接收,然后逐级向上传播到最不具体的元素的节点(文档). 3.事件捕获: 最不具体的节点先接收事件,而最具体的节点应该是最后接收事件. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>事件</title&

Android的触屏事件

Android系统中的每个View的子类都包含的三种和touchevent有关的三种方法. ondispathTouchEvent(); 这个方法用来分发TouchEventonInterceptTouchEvent(); 这个方法用来拦截TouchEventonTouchEvent: 这个方法用来处理TouchEvent 每次触屏事件,都有最顶层的View的ondispathTouchEvent()接受,由这个方法进行分发.当方法返回true时 ,就将触屏事件传递给该View的OntouchE

SQL Server 默认跟踪 -- 捕获事件详解

SQL Server 默认跟踪 -- 捕获事件详解 哪些具体事件默认跟踪文件能够捕获到? --returns full list of events SELECT * FROM sys.trace_events --returns a full list of categories SELECT * FROM sys.trace_categories --returns a full list of subclass values SELECT * FROM sys.trace_subclass