Cocos2dx(1)_CCLayer触屏事件研究
对于CCLayer子类,想响应触屏事件比较简单,init的时候调用setTouchEnable(true)并重载下列函数:
virtual void registerWithTouchDispatcher(void); 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);
典型的registerWithTouchDispatcher实现是:
void XXLayer::registerWithTouchDispatcher() { CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,true); }
做的事情就是注册触屏事件。
addTargetedDelegate的第一个参数是delegate,就是回调函数执行的对象;第二个参数priority和第三个参数bSwallowsTouches决定多个对象同时注册触屏事件时的行为。具体的意义是:
priority值越小,回调越早被调用。
bSwallowsTouches为true,则ccTouchBegan返回ture以后,其他的回调将不再被调用,就好像触屏事件被吃掉了一样。
ccTouchxx系列函数就是触屏事件的响应函数。
CCLayer提供了一个registerWithTouchDispatcher的默认实现,主要功能相当于
CCDirector::sharedDirector()->getTouchDispatcher()->addStandardDelegate(this,0)
也是注册触屏事件。但是addStandardDelegate和前面我们使用的addTargetedDelegate有诸多不同。
1.不支持bSwallowsTouches参数,在触屏动作发生时,所有注册了触屏事件的对象的回调函数都会被调用。
2.回调函数定义不同,它的回调函数定义是:
virtualvoid ccTouchesBegan(CCSet *pTouches,CCEvent *pEvent);
virtualvoid ccTouchesMoved(CCSet *pTouches,CCEvent *pEvent);
virtualvoid ccTouchesEnded(CCSet *pTouches,CCEvent *pEvent);
virtualvoid ccTouchesCancelled(CCSet *pTouches,CCEvent *pEvent);
回调函数的第一个参数是CCSet*,另外ccTouchesBegan也不像ccTouchBegan那样有一个bool型的返回值。
网上有人提到支持多点触摸时需要使用addStandardDelegate,暂时还没有研究过。
前面只说了注册事件,没有提注销。CCLayer是在onExit中帮我们做了这件事,子类就不用再处理了。
下面提供一个CCLayer子类响应触屏事件的实例,用cocos2dx template生成Hello world工程后,替换HelloWorldScene.h和HelloWorldScene.cpp即可测试这个例子,这个例子的重点在onEnter函数中,值得仔细思考下。
HelloWorldScene.h:
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" #include "cocos-ext.h" USING_NS_CC; USING_NS_CC_EXT; class HelloWorld : public cocos2d::CCLayer { public: // Here\'s a difference. Method \'init\' in cocos2d-x returns bool, instead of returning \'id\' in cocos2d-iphone virtual bool init(); // there\'s no \'id\' in cpp, so we recommand to return the exactly class pointer static cocos2d::CCScene* scene(); // a selector callback void menuCloseCallback(CCObject* pSender); // implement the "static node()" method manually CREATE_FUNC(HelloWorld); public: virtual void onEnter(); virtual void registerWithTouchDispatcher(); 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); private: // 菜单回调 void menu1Callback(CCNode *pSender); void menu2Callback(CCNode *pSender); private: CCMenu *menu; CCScrollView *scrollView; }; #endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp
#include "HelloWorldScene.h" #include "SimpleAudioEngine.h" using namespace cocos2d; using namespace CocosDenshion; USING_NS_CC_EXT; CCScene* HelloWorld::scene() { // \'scene\' is an autorelease object CCScene *scene = CCScene::create(); // \'layer\' is an autorelease object HelloWorld *layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !CCLayer::init() ) { return false; } setTouchEnabled(true); ///////////////////////////// // 3. add your codes below... // ask director the window size CCSize size = CCDirector::sharedDirector()->getWinSize(); // CCScrollView scrollView = CCScrollView::create(); CCLayer *layer = CCLayer::create(); CCSprite *sprite1 = CCSprite::create("HelloWorld.png"); CCSprite *sprite2 = CCSprite::create("HelloWorld.png"); layer->setAnchorPoint(ccp(0, 0)); layer->setPosition(ccp(0, 0)); // Menu CCMenuItemSprite *menuItem1 = CCMenuItemSprite::create(sprite1, sprite1, this, menu_selector(HelloWorld::menu1Callback)); float scale = 0.5; CCSize itemSize(sprite1->getTextureRect().size); menuItem1->setPosition(ccpAdd(CCPointZero, ccp(itemSize.width*scale / 2, itemSize.height*scale / 2))); menuItem1->setScale(scale); CCMenuItemSprite *menuItem2 = CCMenuItemSprite::create(sprite2, sprite2, this, menu_selector(HelloWorld::menu2Callback)); // menuItem2->setPosition(ccpAdd(ccp(480, 0), ccp(size.width / 2, size.height / 2))); menuItem2->setPosition(ccp(itemSize.width*scale*3/2, itemSize.height*scale / 2)); menuItem2->setScale(scale); menu = CCMenu::create(menuItem1, menuItem2, NULL); menu->setPosition(CCPointZero); layer->addChild(menu); layer->setContentSize(CCSizeMake(itemSize.width*2*scale, 320)); scrollView->setPosition(ccp(0,0)); scrollView->setContentOffset(CCPointZero); scrollView->setContentSize(CCSizeMake(640, 320)); scrollView->setContainer(layer); scrollView->setDirection(kCCScrollViewDirectionHorizontal); this->addChild(scrollView); return true; } void HelloWorld::onEnter() { CCLayer::onEnter(); //这里是重点,尝试注释掉它然后再执行程序,看左右拖动图片时行为有什么变化。 menu->setHandlerPriority(1); } void HelloWorld::menuCloseCallback(CCObject* pSender) { CCDirector::sharedDirector()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif } void HelloWorld::registerWithTouchDispatcher() { CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, false); } bool HelloWorld::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) { return true; } void HelloWorld::ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) { CCLOG("move"); } void HelloWorld::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) { } void HelloWorld::ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) { } void HelloWorld::menu1Callback(cocos2d::CCNode *pSender) { CCLOG("menu1Callback"); } void HelloWorld::menu2Callback(cocos2d::CCNode *pSender) { CCLOG("menu2Callback"); }
转自:http://blog.csdn.net/herain_cs/article/details/8627995
附: