Cocos2d-x 触摸响应事件CCTouchDelegate
2014-07-03 11:52
295 查看
刚开始接触Cocos2d-x,一边看书,一边看官方Demo的代码,在SpriteTest中,有个函数ccTouchesEnded(...)功能类似VC里面LeftButtonUp(...),刚开始以为这是自定义的函数实现,后来打开demo在屏幕上操作,发现这是个响应事件,然后去找基类,看有没有这个函数,然后就发现了这么个玩意。class CC_DLL CCLayer : public
CCNode, public CCTouchDelegate, public CCAccelerometerDelegate, public CCKeypadDelegate{...};
后面发现这个跟VC里面鼠标响应事件一个原理,就查询资料,继续加强对这个触摸类的理解和使用。
1.要想使得该布景层有这种触摸响应,要进行游戏交互,就得先在构造函数中 setTouchEnabled( true );
2.了解一下相关的几个类
CCTouch:它封装了触摸点,可以通过locationInView函数返回一个CCPoint。
CCTouchDelegate:它是触摸事件委托,就是系统捕捉到触摸事件后交由它或者它的子类处理,所以我们在处理触屏事件时,必须得继承它。它封装了下面这些处理触屏事件的函数:
ccTouchesCancelled和ccTouchCancelled函数很少用,在接到系统中断通知,需要取消触摸事件的时候才会调用此方法。如:应用长时间无响应、当前view从window上移除、触摸的时候来电话了等。
CCTargetedTouchDelegate和CCStandardTouchDelegate是CCTouchDelegate的子类,类结构图如下:
![](http://codingnow.cn/wp-content/uploads/2012/10/20121029205431-e1352125993651.png)
CCStandardTouchDelegate用于处理多点触摸;CCTargetedTouchDelegate用于处理单点触摸。
CCTouchDispatcher:实现触摸事件分发,它封装了下面这两个函数,可以把CCStandardTouchDelegate和CCTargetedTouchDelegate添加到分发列表中:
(2.)registerWithTouchDispatcher函数实现
(3.)在init或者OnEnter中调用
(4.)追踪解析
appdelegate.cpp
跟进getFrameSize()函数,发现了:
这下就明白了,其实最终接受处理跟VC一样,只不过cocos2d-x封装了以下,以下是WindowProc(...)的实现代码:
(5.)所以使用基本和VC中鼠标响应事件一样。
第一步.
第二步.【注意】
第三步.
【注意】:第二步中的setTouchEnabled( true );如果要放在init()里面的话,尽量放到结尾,放在开头不会响应事件。
【吞噬触屏问题解决办法】:/article/2670030.html
CCNode, public CCTouchDelegate, public CCAccelerometerDelegate, public CCKeypadDelegate{...};
void Sprite1::ccTouchesEnded(CCSet* touches, CCEvent* event) { CCSetIterator it; CCTouch* touch; for( it = touches->begin(); it != touches->end(); it++) { touch = (CCTouch*)(*it); if(!touch) break; CCPoint location = touch->getLocation(); addNewSpriteWithCoords( location ); } }
后面发现这个跟VC里面鼠标响应事件一个原理,就查询资料,继续加强对这个触摸类的理解和使用。
1.要想使得该布景层有这种触摸响应,要进行游戏交互,就得先在构造函数中 setTouchEnabled( true );
2.了解一下相关的几个类
CCTouch:它封装了触摸点,可以通过locationInView函数返回一个CCPoint。
CCTouchDelegate:它是触摸事件委托,就是系统捕捉到触摸事件后交由它或者它的子类处理,所以我们在处理触屏事件时,必须得继承它。它封装了下面这些处理触屏事件的函数:
virtualboolcc<span style="color:#ff0000;">Touch</span>Began(CCTouch *pTouch, CCEvent *pEvent); virtualvoidccTouchMoved(CCTouch *pTouch, CCEvent *pEvent); virtualvoidccTouchEnded(CCTouch *pTouch, CCEvent *pEvent); virtualvoidccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
virtualvoidcc<span style="color:#ff0000;">Touches</span>Began(CCSet *pTouches, CCEvent *pEvent); virtualvoidccTouchesMoved(CCSet *pTouches, CCEvent *pEvent); virtualvoidccTouchesEnded(CCSet *pTouches, CCEvent *pEvent); virtualvoidccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent);
ccTouchesCancelled和ccTouchCancelled函数很少用,在接到系统中断通知,需要取消触摸事件的时候才会调用此方法。如:应用长时间无响应、当前view从window上移除、触摸的时候来电话了等。
CCTargetedTouchDelegate和CCStandardTouchDelegate是CCTouchDelegate的子类,类结构图如下:
![](http://codingnow.cn/wp-content/uploads/2012/10/20121029205431-e1352125993651.png)
CCStandardTouchDelegate用于处理多点触摸;CCTargetedTouchDelegate用于处理单点触摸。
CCTouchDispatcher:实现触摸事件分发,它封装了下面这两个函数,可以把CCStandardTouchDelegate和CCTargetedTouchDelegate添加到分发列表中:
void addStandardDelegate(CCTouchDelegate *pDelegate, intnPriority); void addTargetedDelegate(CCTouchDelegate *pDelegate, intnPriority,boolbSwallowsTouches);
CCTouchHandler:封装了CCTouchDelegate和其对应的优先级,优先级越高,分发的时候越容易获得事件处理权,CCStandardTouchHandler和CCTargetedTouchHandler是它的子类。
3.处理触屏事件时操作和执行的流程
用户自定义类继承CCTouchDelegate,重写触屏事件处理函数和registerWithTouchDispatcher函数,在init或者onEnter函数中调用registerWithTouchDispatcher函数,如:
(1.)定义类
class CCGameLayer : public CCNode, public CCTouchDelegate, public CCAccelerometerDelegate, public CCKeypadDelegate { public: CCGameLayer(); virtual ~CCGameLayer(); bool init(); CC_DEPRECATED_ATTRIBUTE static CCGameLayer *node(void); static CCGameLayer *create(void); virtual void onEnter(); virtual void onExit(); virtual void onEnterTransitionDidFinish(); // default implements are used to call script callback if exist virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent); virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent); virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent); // default implements are used to call script callback if exist virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent); virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent); virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent); virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent); virtual void didAccelerate(CCAcceleration* pAccelerationValue); virtual void registerWithTouchDispatcher(void); };
(2.)registerWithTouchDispatcher函数实现
void CCGameLayer::registerWithTouchDispatcher() { cocos2d::CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, true); }
(3.)在init或者OnEnter中调用
void CCGameLayer::onEnter() { CCDirector* pDirector = CCDirector::sharedDirector(); if (m_bIsTouchEnabled) { <span style="color:#ff0000;">this->registerWithTouchDispatcher(); </span> } CCNode::onEnter(); if (m_bIsAccelerometerEnabled) { pDirector->getAccelerometer()->setDelegate(this); } if (m_bIsKeypadEnabled) { pDirector->getKeypadDispatcher()->addDelegate(this); } }
(4.)追踪解析
appdelegate.cpp
CCDirector *pDirector = CCDirector::sharedDirector(); pDirector->setOpenGLView(CCEGLView::sharedOpenGLView()); CCSize screenSize = CCEGLView::sharedOpenGLView()->getFrameSize();
跟进getFrameSize()函数,发现了:
LRESULT CCEGLView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
这下就明白了,其实最终接受处理跟VC一样,只不过cocos2d-x封装了以下,以下是WindowProc(...)的实现代码:
LRESULT CCEGLView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { BOOL bProcessed = FALSE; switch (message) { case <span style="color:#ff0000;">WM_LBUTTONDOWN</span>: #if(_MSC_VER >= 1600) // Don't process message generated by Windows Touch if (m_bSupportTouch && (s_pfGetMessageExtraInfoFunction() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) break; #endif /* #if(_MSC_VER >= 1600) */ if (m_pDelegate && MK_LBUTTON == wParam) { POINT point = {(short)LOWORD(lParam), (short)HIWORD(lParam)}; CCPoint pt(point.x, point.y); pt.x /= m_fFrameZoomFactor; pt.y /= m_fFrameZoomFactor; CCPoint tmp = ccp(pt.x, m_obScreenSize.height - pt.y); if (m_obViewPortRect.equals(CCRectZero) || m_obViewPortRect.containsPoint(tmp)) { m_bCaptured = true; SetCapture(m_hWnd); int id = 0; handleTouchesBegin(1, &id, &pt.x, &pt.y); } } break; case WM_MOUSEMOVE: #if(_MSC_VER >= 1600) // Don't process message generated by Windows Touch if (m_bSupportTouch && (s_pfGetMessageExtraInfoFunction() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) break; #endif /* #if(_MSC_VER >= 1600) */ if (MK_LBUTTON == wParam && m_bCaptured) { POINT point = {(short)LOWORD(lParam), (short)HIWORD(lParam)}; CCPoint pt(point.x, point.y); int id = 0; pt.x /= m_fFrameZoomFactor; pt.y /= m_fFrameZoomFactor; handleTouchesMove(1, &id, &pt.x, &pt.y); } break; case WM_LBUTTONUP: #if(_MSC_VER >= 1600) // Don't process message generated by Windows Touch if (m_bSupportTouch && (s_pfGetMessageExtraInfoFunction() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) break; #endif /* #if(_MSC_VER >= 1600) */ if (m_bCaptured) { POINT point = {(short)LOWORD(lParam), (short)HIWORD(lParam)}; CCPoint pt(point.x, point.y); int id = 0; pt.x /= m_fFrameZoomFactor; pt.y /= m_fFrameZoomFactor; handleTouchesEnd(1, &id, &pt.x, &pt.y); ReleaseCapture(); m_bCaptured = false; } break; #if(_MSC_VER >= 1600) case <span style="color:#ff0000;">WM_TOUCH</span>: { BOOL bHandled = FALSE; UINT cInputs = LOWORD(wParam); PTOUCHINPUT pInputs = new TOUCHINPUT[cInputs]; if (pInputs) { if (s_pfGetTouchInputInfoFunction((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT))) { for (UINT i=0; i < cInputs; i++) { TOUCHINPUT ti = pInputs[i]; POINT input; input.x = TOUCH_COORD_TO_PIXEL(ti.x); input.y = TOUCH_COORD_TO_PIXEL(ti.y); ScreenToClient(m_hWnd, &input); CCPoint pt(input.x, input.y); CCPoint tmp = ccp(pt.x, m_obScreenSize.height - pt.y); if (m_obViewPortRect.equals(CCRectZero) || m_obViewPortRect.containsPoint(tmp)) { pt.x /= m_fFrameZoomFactor; pt.y /= m_fFrameZoomFactor; if (ti.dwFlags & TOUCHEVENTF_DOWN) handleTouchesBegin(1, reinterpret_cast<int*>(&ti.dwID), &pt.x, &pt.y); else if (ti.dwFlags & TOUCHEVENTF_MOVE) handleTouchesMove(1, reinterpret_cast<int*>(&ti.dwID), &pt.x, &pt.y); else if (ti.dwFlags & TOUCHEVENTF_UP) handleTouchesEnd(1, reinterpret_cast<int*>(&ti.dwID), &pt.x, &pt.y); } } bHandled = TRUE; } delete [] pInputs; } if (bHandled) { s_pfCloseTouchInputHandleFunction((HTOUCHINPUT)lParam); } } break; #endif /* #if(_MSC_VER >= 1600) */ case WM_SIZE: switch (wParam) { case SIZE_RESTORED: CCApplication::sharedApplication()->applicationWillEnterForeground(); break; case SIZE_MINIMIZED: CCApplication::sharedApplication()->applicationDidEnterBackground(); break; } break; case WM_KEYDOWN: if (wParam == VK_F1 || wParam == VK_F2) { CCDirector* pDirector = CCDirector::sharedDirector(); if (GetKeyState(VK_LSHIFT) < 0 || GetKeyState(VK_RSHIFT) < 0 || GetKeyState(VK_SHIFT) < 0) pDirector->getKeypadDispatcher()->dispatchKeypadMSG(wParam == VK_F1 ? kTypeBackClicked : kTypeMenuClicked); } if ( m_lpfnAccelerometerKeyHook!=NULL ) { (*m_lpfnAccelerometerKeyHook)( message,wParam,lParam ); } break; case WM_KEYUP: if ( m_lpfnAccelerometerKeyHook!=NULL ) { (*m_lpfnAccelerometerKeyHook)( message,wParam,lParam ); } break; case WM_CHAR: { if (wParam < 0x20) { if (VK_BACK == wParam) { CCIMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(); } else if (VK_RETURN == wParam) { CCIMEDispatcher::sharedDispatcher()->dispatchInsertText("\n", 1); } else if (VK_TAB == wParam) { // tab input } else if (VK_ESCAPE == wParam) { // ESC input //CCDirector::sharedDirector()->end(); } } else if (wParam < 128) { // ascii char CCIMEDispatcher::sharedDispatcher()->dispatchInsertText((const char *)&wParam, 1); } else { char szUtf8[8] = {0}; int nLen = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)&wParam, 1, szUtf8, sizeof(szUtf8), NULL, NULL); CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(szUtf8, nLen); } if ( m_lpfnAccelerometerKeyHook!=NULL ) { (*m_lpfnAccelerometerKeyHook)( message,wParam,lParam ); } } break; case <span style="color:#ff0000;">WM_PAINT</span>: PAINTSTRUCT ps; BeginPaint(m_hWnd, &ps); EndPaint(m_hWnd, &ps); break; case <span style="color:#ff0000;">WM_CLOSE</span>: CCDirector::sharedDirector()->end(); break; case <span style="color:#ff0000;">WM_DESTROY</span>: destroyGL(); PostQuitMessage(0); break; default: if (m_wndproc) { m_wndproc(message, wParam, lParam, &bProcessed); if (bProcessed) break; } return DefWindowProc(m_hWnd, message, wParam, lParam); } if (m_wndproc && !bProcessed) { m_wndproc(message, wParam, lParam, &bProcessed); } return 0; }
(5.)所以使用基本和VC中鼠标响应事件一样。
第一步.
class Sprite1 : public SpriteTestDemo { public: Sprite1(); virtual std::string title(); void addNewSpriteWithCoords(CCPoint p); <span style="color:#ff0000;">void ccTouchesEnded(CCSet* touches, CCEvent* event); </span>};
第二步.【注意】
Sprite1::Sprite1() { <span style="color:#ff0000;">setTouchEnabled( true ); </span> CCSize s = CCDirector::sharedDirector()->getWinSize(); addNewSpriteWithCoords( ccp(s.width/2, s.height/2) ); }
第三步.
void Sprite1::ccTouchesEnded(CCSet* touches, CCEvent* event) { CCSetIterator it; CCTouch* touch; for( it = touches->begin(); it != touches->end(); it++) { touch = (CCTouch*)(*it); if(!touch) break; CCPoint location = touch->getLocation(); addNewSpriteWithCoords( location ); } }
【注意】:第二步中的setTouchEnabled( true );如果要放在init()里面的话,尽量放到结尾,放在开头不会响应事件。
【吞噬触屏问题解决办法】:/article/2670030.html
相关文章推荐
- cocos2d ccLayer响应触摸事件方法:CCStandardTouchDelegate 与 CCTargetedTouchDelegate
- cocos2d ccLayer响应触摸事件方法:CCStandardTouchDelegate 与 CCTargetedTouchDelegate
- cocos2d ccLayer响应触摸事件方法
- COCOS2d中添加UIButton不响应触摸事件---iOS开发之最灵异事件之2
- cocos2d ccLayer响应触摸事件方法:CCStandardTouchDelegate 与 CCTargetedTouchDelegate
- Cocos2d-x游戏开发之2.x后弹出键盘后无法响应除键盘外的触摸事件解决
- cocos2d屏幕部分区域无法响应触摸事件
- 游戏开发随手记:cocos2d ccLayer响应触摸事件方法
- cocos2d JS 监听键盘触摸响应事件(cc.EventListener.KEYBOARD)
- Cocos2d-x:触摸事件优先级的探究与实践
- Cocos2d-x中触摸事件
- cocos2d-x 界面编程二(cocostudio GUI的控件事件响应)
- cocos2d 触摸事件中 触摸点在目标范围内 怎么判断触摸到了目标
- 让UIScrollView的子view响应触摸事件
- cocos2d-x中关于touch事件的响应
- cocos2dx 弹出键盘无法响应键盘外的触摸事件
- cocos2d-x 事件分发机制 ——触摸事件监听
- cocos2d-x游戏引擎核心之五——触摸事件和触摸分发器机制
- cocos2d ccLayer响应触摸事件方法:CCStandardTouchDelegate 与 CCTargetedTouchDelegate
- cocos2d-x jsb 防止触摸事件传递