【麦可网】Cocos2d-X跨平台游戏开发---学习笔记
第十五课:Cocos2D-X事件处理1-7
=======================================================================================================================================================================
课程目标:
-Cocos2D-X事件处理机制
-Cocos2D-X输入框使用
课程重点:
-Cocos2D-X事件处理机制
-Cocos2D-X输入框使用
-为节点添加触摸事件
考核目标:
-掌握Cocos2D-X但多点触摸
-掌握Cocos2D-X重力感应事件
-掌握Cocos2D-X输入框使用
-理解为节点添加触摸事件
=======================================================================================================================================================================
一、单点/多点触摸事件接口
事件队列 CCTouchDispather //存需要处理事件节点的类 CCTouchDelegate CCTargetedTouchDelegate //单点触摸的事件 CCStandardTouchDelegate //多点触摸的事件 参考代码:tests->touch_dispatcher -------------触摸事件接口------------- class CC_DLL CCTouchDelegate { public: CCTouchDelegate() {} virtual ~CCTouchDelegate() { } //返回值bool来判读是否继续往下执行,true不执行后面的事件,反之则执行 virtual bool ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent); return false;}; // optional virtual void ccTouchMoved(CCTouch *pTouch,CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent);} virtual void ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent);} virtual void ccTouchCancelled(CCTouch *pTouch,CCEvent *pEvent) {CC_UNUSED_PARAM(pTouch); CC_UNUSED_PARAM(pEvent);} // optional virtual void ccTouchesBegan(CCSet *pTouches,CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);} virtual void ccTouchesMoved(CCSet *pTouches,CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);} virtual void ccTouchesEnded(CCSet *pTouches,CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);} virtual void ccTouchesCancelled(CCSet *pTouches,CCEvent *pEvent) {CC_UNUSED_PARAM(pTouches); CC_UNUSED_PARAM(pEvent);} };
二、单点/多点触摸事件处理
CCTargetedTouchDelegate virtual bool ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent); virtual bool ccTouchMoved(CCTouch *pTouch,CCEvent *pEvent); virtual bool ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent); virtual bool ccTouchCancelled(CCTouch *pTouch,CCEvent *pEvent); CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this,true); setTouchEnabled(true); <span style="white-space:pre"> </span> //开启触摸使能 ----------------触摸使能----------------- void CCLayer::setTouchEnabled(bool enabled) { if (m_bTouchEnabled != enabled) { m_bTouchEnabled = enabled; if (m_bRunning) { if (enabled) { this->registerWithTouchDispatcher(); //添加节点到管理器 } else { // have problems? //节点移除管理器 CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this); } } } } ----------------触摸开始----------------- void LayerTest1::ccTouchesBegan(CCSet *pTouches,CCEvent *pEvent) { ccTouchesMoved(pTouches,pEvent); } ----------------触摸移动----------------- void LayerTest1::ccTouchesMoved(CCSet *pTouches,CCEvent *pEvent) { CCTouch *touch = (CCTouch*)pTouches->anyObject(); CCPoint touchLocation = touch->getLocation(); //获得单点 updateSize(touchLocation); //更新尺寸 } ----------------更新尺寸----------------- void LayerTest1::updateSize(CCPoint &touchLocation) { CCSize s = CCDirector::sharedDirector()->getWinSize(); CCSize newSize = CCSizeMake( fabs(touchLocation.x - s.width/2)*2,fabs(touchLocation.y - s.height/2)*2); //重新计算大小 CCLayerColor* l = (CCLayerColor*) getChildByTag(kTagLayer); l->setContentSize( newSize ); //重新绘制大写 } 默认情况下,节点是实现多点触控,要想节点实现单点触控,则复写以下虚函数,并把多点触摸函数改成单点触摸函数。 void LayerTest1::registerWithTouchDispatcher() { CCTouchDispather::sharedDispatcher()->addTargetedDelegate(this,true); }
三、重力感应事件处理
CCAccelerometerDelegate virtual void didAccelerate(CCAcceleration *pAccelerationValue); setAccelerometerEnabled(ture); 参考代码:tests->Accelerometer Test setAccelerometerEnabled(true); //启用重力感应
四、按键事件处理
class CC_DLL CCKeypadDelegate { public: // 返回键 virtual void keyBackClicked() {} // 菜单键,安卓手机可用 virtual void keyMenuClicked() {}; }; 参考代码:tests->KeypadTest
五、为精灵添加事件
步骤1:继承触摸 class Paddle : public CCSprite,public CCTargetedTouchDelegate { …… }; 步骤2:实现接口 bool Paddle::ccTouchBegan(CCTouch* touch,CCEvent* event) { if (m_state != kPaddleStateUngrabbed) return false; //判断触摸点是否在矩形区域内 if ( !containsTouchLocation(touch) ) return false; m_state = kPaddleStateGrabbed; return true; } 其中: bool Paddle::containsTouchLocation(CCTouch* touch) { //坐标转换,坐标原点设置在精灵的锚点 return rect().containsPoint(convertTouchToNodeSpaceAR(touch)); } CCRect Paddle::rect() { CCSize s = getTexture()->getContentSize(); return CCRectMake(-s.width / 2,-s.height / 2,s.width,s.height); } #define CCRectMake(x,y,width,height) CCRect((float)(x),(float)(y),(float)(width),(float)(height)) --------------------------------------------------------- void Paddle::ccTouchMoved(CCTouch* touch,CCEvent* event) { // If it weren't for the TouchDispatcher,you would need to keep a reference // to the touch from touchBegan and check that the current touch is the same // as that one. // Actually,it would be even more complicated since in the Cocos dispatcher // you get CCSets instead of 1 UITouch,so you'd need to loop through the set // in each touchXXX method. CCAssert(m_state == kPaddleStateGrabbed,"Paddle - Unexpected state!"); CCPoint touchPoint = touch->getLocation(); setPosition( ccp(touchPoint.x,getPosition().y) ); } void Paddle::ccTouchEnded(CCTouch* touch,CCEvent* event) { CCAssert(m_state == kPaddleStateGrabbed,"Paddle - Unexpected state!"); m_state = kPaddleStateUngrabbed; } 步骤3:注册,添加到事件管理器 void Paddle::onEnter() { CCDirector* pDirector = CCDirector::sharedDirector(); pDirector->getTouchDispatcher()->addTargetedDelegate(this,true); CCSprite::onEnter(); } 步骤4:从事件管理器中删除 void Paddle::onExit() { CCDirector* pDirector = CCDirector::sharedDirector(); pDirector->getTouchDispatcher()->removeDelegate(this); CCSprite::onExit(); }
六、通知中心
//添加监听消息 CCNotificationCenter::sharedNotificationCenter()->addObserver(this,callfuncO_selector(GameManager::onClickTest),CLICK_TEST_MSG,NULL); //发送消息 CCNotificationCenter::sharedNotificationCenter()->postNotification(CLICK_TEST_MSG,(CCObject*)data); //取消监听消息 CCNotificationCenter::sharedNotificationCenter()->removerObserver(this,CLICK_TEST_MSG); //收到消息后的执行动作 void GameManager::onClickTest(CCObject *obj) { }
七、输入框使用
CCTextFieldTTF //创建输入框 CCIMEDelegate //输入法,弹出键盘 CCTextFieldDelegate <span style="white-space:pre"> </span>//添加输入效果的接口 ----------------------------------------------------- class CC_DLL CCIMEDelegate { public: virtual ~CCIMEDelegate(); virtual bool attachWithIME(); //打开键盘 virtual bool detachWithIME(); //关闭键盘 …… }; --------------------------触摸按下-------------------------- bool KeyboardNotificationLayer::ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent) { CCLOG("++++++++++++++++++++++++++++++++++++++++++++"); m_beginPos = pTouch->getLocation(); return true; } --------------------------触摸结束-------------------------- void KeyboardNotificationLayer::ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent) { if (! m_pTrackNode) { return; } CCPoint endPos = pTouch->getLocation(); float delta = 5.0f; if (::abs(endPos.x - m_beginPos.x) > delta //排除滑动操作 || ::abs(endPos.y - m_beginPos.y) > delta) { // not click m_beginPos.x = m_beginPos.y = -1; return; } // decide the trackNode is clicked. CCRect rect; CCPoint point = convertTouchToNodeSpaceAR(pTouch); CCLOG("KeyboardNotificationLayer:clickedAt(%f,%f)",point.x,point.y); rect = getRect(m_pTrackNode); CCLOG("KeyboardNotificationLayer:TrackNode at(origin:%f,%f,size:%f,rect.origin.x,rect.origin.y,rect.size.width,rect.size.height); this->onClickTrackNode(rect.containsPoint(point)); //判断在输入框内点击 CCLOG("----------------------------------"); } --------------------------判断是否打开键盘-------------------------- void TextFieldTTFDefaultTest::onClickTrackNode(bool bClicked) { CCTextFieldTTF * pTextField = (CCTextFieldTTF*)m_pTrackNode; if (bClicked) { // TextFieldTTFTest be clicked CCLOG("TextFieldTTFDefaultTest:CCTextFieldTTF attachWithIME"); pTextField->attachWithIME(); } else { // TextFieldTTFTest not be clicked CCLOG("TextFieldTTFDefaultTest:CCTextFieldTTF detachWithIME"); pTextField->detachWithIME(); } } --------------------------键盘打开前的动作-------------------------- 比如键盘把输入框遮住了,输入框要整体往上移动,代码则放在这里面 void KeyboardNotificationLayer::keyboardWillShow(CCIMEKeyboardNotificationInfo& info) //包含键盘信息,如尺寸 { CCLOG("TextInputTest:keyboardWillShowAt(origin:%f,info.end.origin.x,info.end.origin.y,info.end.size.width,info.end.size.height); if (! m_pTrackNode) { return; } CCRect rectTracked = getRect(m_pTrackNode); CCLOG("TextInputTest:trackingNodeAt(origin:%f,rectTracked.origin.x,rectTracked.origin.y,rectTracked.size.width,rectTracked.size.height); // 如果键盘没有覆盖输入框,则直接返回 if (! rectTracked.intersectsRect(info.end)) { return; } // assume keyboard at the bottom of screen,calculate the vertical adjustment. float adjustVert = info.end.getMaxY() - rectTracked.getMinY(); CCLOG("TextInputTest:needAdjustVerticalPosition(%f)",adjustVert); // 所有的子节点都向上移动 CCArray * children = getChildren(); CCNode * node = 0; int count = children->count(); CCPoint pos; for (int i = 0; i < count; ++i) { node = (CCNode*)children->objectAtIndex(i); pos = node->getPosition(); pos.y += adjustVert; node->setPosition(pos); } } --------------------------为输入和删除文字添加动画-------------------------- 继承于CCTextFieldDelegate virtual bool onTextFieldAttachWithIME(CCTextFieldTTF * pSender); virtual bool onTextFieldDetachWithIME(CCTextFieldTTF * pSender); virtual bool onTextFieldInsertText(CCTextFieldTTF * pSender,const char * text,int nLen); virtual bool onTextFieldDeleteBackward(CCTextFieldTTF * pSender,const char * delText,int nLen); virtual bool onDraw(CCTextFieldTTF * pSender);
===================================================================
总结:
理解了这几个步骤就差不多了
步骤1:创建文本框 CCTextFieldTTF
步骤2:启用触摸事件处理 KeyboardNotificationLayer
步骤3:注册事件 registerWithTouchDispatcher
步骤4:实现键盘的弹出 attachWithIME
步骤5:判读键盘是否挡住其它节点 keyboardWillShow
步骤6:设置输入动画 CCTextFieldDelegate
开心一刻:
小明上课迟到了。
老师怒:小明,今天来这么晚?
小明:睡过了!
老师:怎么会睡过呢?
小明:做梦梦见老师讲课,就想多听一会…
老师:滚!
【麦可网】Cocos2d-X跨平台游戏开发---教程下载:http://pan.baidu.com/s/1kTio1Av
【麦可网】Cocos2d-X跨平台游戏开发---笔记系列:http://blog.csdn.net/qiulanzhu