【Cocos2D-X 学习笔记】为精灵添加单点触控
由于Cocos2d-x处于新学的阶段,因此最近也无法进行系统地更新,只会选择一些典型的Demo贴上来,一来是与大家分享,而来也可以作为以后回顾时的参考。
今天介绍一下Cocos2d-x的触摸事件处理,了解Android开发的朋友们知道,Android里会用一个OnClickListener()进行事件监听,而在J2SE中也会有Event类实现专门的监听处理。在Cocos2d-x中,因为是游戏引擎,用户在玩游戏时总是要通过屏幕与游戏进行交互,可想而知触摸事件是主要处理的事件。这里主要讲一下如何为精灵添加触控事件,最终的效果是做一个可以拖动的小球,内容很简单。
cocos2d-x提供的CCSprite (或者Sprite)类并没有添加触控监听接口,这就要求我们需要自己创建一个类继承CCSprite并且添加单点触控接口CCTargetedTouchDelegate (多点触控同理),并且实现三个虚方法bool ccTouchBegan() ccTouchMoved() ccTouchEnded() , 然后需要响应触摸事件还需要把该对象添加进CCTouchDispatcher中。
下面是具体的代码:
首先是Ball类的声明:
ball.h
#include "cocos2d.h" USING_NS_CC; //using namespace cocos2d class Ball: public CCSprite,public CCTargetedTouchDelegate{ public: virtual void onEnter(); //新创建一个Ball对象并显示时就会调用onEnter方法,在onEnter中把该对象添加进CCTouchDispatcher(触摸事件管理器)中 virtual void onExit(); //该对象终结时会调用onExit方法,在该方法中,把该对象从CCTouchDispatcher中删除 static Ball* create(char *imageName); //重写了父类的create()方法,使得可以喝CCSprite一样通过create方法创建一个Ball精灵 public: virtual bool isPointInside(CCPoint point); //判断当前触摸到的点是否刚好在精灵上 //触摸事件必须要实现的三个接口 public: virtual bool ccTouchBegan(CCTouch *touch,CCEvent *pevent); virtual void ccTouchMoved(CCTouch *touch,CCEvent *pevent); virtual void ccTouchEnded(CCTouch *touch,CCEvent *pevent); };
然后是各个虚函数的具体实现部分
ball.cpp
#include "cocos2d.h" #include "ball.h" USING_NS_CC; //在类声明里面出现的静态成员必须在定义的时候进行外部引用声明!! void Ball::onEnter(){ CCDirector *director=CCDirector::sharedDirector(); director->getTouchDispatcher()->addTargetedDelegate(this,0,true); //将该对象添加进事件处理序列 CCSprite::onEnter(); //调用其父类的构造方法保证精灵能够正常初始化 CCLog("On Enter!"); } void Ball::onExit(){ CCDirector *director=CCDirector::sharedDirector(); director->getTouchDispatcher()->removeDelegate(this); //将该对象从事件处理序列中移除 CCSprite::onExit(); CCLog("On Exit!"); } Ball* Ball::create(char *imageName){ Ball *ball=new Ball(); //采用new方法创建一个对象,并设置自动释放 ball->autorelease(); ball->initWithTexture(CCTextureCache::sharedTextureCache()->addImage(imageName));
//CCTextureCache是一个单例模式,同CCDirector类似,addImage()方法回返回一个Texture2D对象供精灵初始化使用 //addIamge方法回返回一个设定图像的Texture2D对象 return ball; } bool Ball::ccTouchBegan(CCTouch *touch,CCEvent *pEvent){ CCPoint point=touch->getLocation(); if(!isPointInside(point)) return false; //ccTouchBegan返回false时表示不再执行ccTouchMoved 和ccTouchEnded函数,否则返回true时会执行上述两个方法 return true; } void Ball::ccTouchMoved(CCTouch *touch,CCEvent *pEvent){ CCPoint point=touch->getLocation(); this->setPosition(point); } void Ball::ccTouchEnded(CCTouch *touch,CCEvent *pEvent){ } //因为使用了new 方法,所以必须把所有的虚函数都实现,这是C++自身的语法 bool Ball::isPointInside(CCPoint point){ CCPoint nodePoint=this->convertToNodeSpace(point); CCSize size=this->getContentSize(); if(nodePoint.x>size.width ||nodePoint.x<0 ||nodePoint.y>size.height ||nodePoint.y<0 ) return false; else return true; }
然后在CCLayer中像添加一个普通精灵一个添加即可,create()创建对象,设置位置,通过addChild()添加进图层即可:
#include "HelloWorldScene.h" #include "ball.h" using namespace cocos2d; CCScene* HelloWorld::scene() { CCScene * scene = NULL; do { // 'scene' is an autorelease object scene = CCScene::create(); CC_BREAK_IF(! scene); // 'layer' is an autorelease object HelloWorld *layer = HelloWorld::create(); CC_BREAK_IF(! layer); // add layer as a child to scene scene->addChild(layer); } while (0); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { bool bRet = false; do { ////////////////////////////////////////////////////////////////////////// // super init first ////////////////////////////////////////////////////////////////////////// CC_BREAK_IF(! CCLayer::init()); ////////////////////////////////////////////////////////////////////////// // add your codes below... ////////////////////////////////////////////////////////////////////////// // 1. Add a menu item with "X" image, which is clicked to quit the program. // Create a "close" menu item with close icon, it's an auto release object. CCMenuItemImage *pCloseItem = CCMenuItemImage::create( "CloseNormal.png", "CloseSelected.png", this, menu_selector(HelloWorld::menuCloseCallback)); CC_BREAK_IF(! pCloseItem); // Place the menu item bottom-right conner. pCloseItem->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20)); // Create a menu with the "close" menu item, it's an auto release object. CCMenu* pMenu = CCMenu::create(pCloseItem, NULL); pMenu->setPosition(CCPointZero); CC_BREAK_IF(! pMenu); // Add the menu to HelloWorld layer as a child layer. this->addChild(pMenu, 1); Ball *ball=Ball::create("ball.png"); ball->setPosition(ccp(100,100)); this->addChild(ball); bRet = true; } while (0); return bRet; } void HelloWorld::menuCloseCallback(CCObject* pSender) { // "close" menu item clicked CCDirector::sharedDirector()->end(); }
关于资源文件配置,cocos2d-x引擎生命周期等不再详述。