Cocos2dx與玩家之間的互動,很大一個情況是通過處理玩家的觸摸事件來實作的。在移動應用就是觸摸,在PC應用就是點選。
下面用一個小例子說明,Cocos2dx的觸摸事件。
如下圖,每當使用者觸摸(點選)螢幕,就會生成一個觸摸精靈,結束點選之後結束生成,在精靈沒有結束生成之前,觸摸拖動能夠改變此按觸摸按鈕的位置。同時,任何一個觸摸,都會記錄目前的坐标。
制作過程還是老樣子,首先利用(cocos2d-x-2.2.6安裝目錄)\tools\project-creator下的create_project.py,建立一個用cpp語言寫的名為moveAction的Cocos2dx工程,打開裡面proj.win32的HelloCpp.sln開始程式編寫,在AppDelegate.cpp關掉調試資訊,此步驟已經在此前文章多次提及,不會的可以參看《【Cocos2dx】Windows平台下Cocos2dx 2.x的下載下傳、安裝、配置,打造自己的Helloworld》(點選打開連結)。
1、之後,現改寫HelloWorldScene.h,删除原來關閉按鈕的回調函數,聲明四個觸摸事件的函數,如下所示:
#include "cocos2d.h"
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 recommend returning the class instance pointer
static cocos2d::CCScene* scene();
// implement the "static node()" method manually
CREATE_FUNC(HelloWorld);
//觸摸事件的函數聲明
void ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);//開始觸摸
void ccTouchesMoved(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);//觸摸并移動
void ccTouchesEnded(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);//結束觸摸
void ccTouchesCancelled(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);//觸摸被強行打斷
};
雖然最後一個函數void ccTouchesCancelled(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);在此例子中沒有展示與實作,但這也是觸摸事件的一個重要函數。用于,觸摸被強行打斷的情況。例如,玩家在進行Cocos2dx的遊戲并正在觸摸,突然來了個電話,此apps被打斷,此時void ccTouchesCancelled(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);函數就生效了,一些釋放、回收資源的語句可以寫了此函數裡面。
2、最後,改寫HelloWorldScene.cpp如下:
#include "HelloWorldScene.h"
USING_NS_CC;
#define LABEL_TARGET 65535//設定文字的LABEL
int sprite_num=0;//用于判斷添加按鈕的個數
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()
{
//擷取螢幕的尺寸、位置資訊等
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
//聲明這個場景是存在觸摸事件的
this->setTouchEnabled(true);
//聲明文字部分
CCLabelTTF *label = CCLabelTTF::create("","arial",36);//聲明一個沒有内容文字
label->setPosition(ccp(visibleSize.width/2,visibleSize.height-visibleSize.height/2));//按鈕的中心點位于螢幕的中央
this->addChild(label,0,LABEL_TARGET);//添加此文字到場景中,與普通的this->addChild(label)不同,第3個參數可以了解為此檔案的Tag,也就是類似其他程式設計語言中id的東西,其餘函數可以通過this->getChildByTag(65535);并通過強制類型轉換擷取這個文字
return true;
}
//開始觸摸
void HelloWorld::ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent){
sprite_num++;//觸摸螢幕生成一個按鈕精靈
CCSprite *sprite=CCSprite::create("CloseSelected.png");
CCTouch *touch=(CCTouch *)pTouches->anyObject();//擷取觸摸
CCLabelTTF *label=(CCLabelTTF*)this->getChildByTag(LABEL_TARGET);//擷取文字
label->setString(CCString::createWithFormat("Touch Begin\nsprite %d:%.2f,%.2f",sprite_num,touch->getLocation().x,touch->getLocation().y)->getCString());
//顯示目前點選位置,點選位置的坐标通過touch->getLocation().x/y來擷取
sprite->setPosition(ccp(touch->getLocation().x,touch->getLocation().y));//按鈕精靈的位置放置在觸摸的位置
this->addChild(sprite,0,sprite_num);//生成精靈的Tag為目前按鈕精靈的數量。
};
//觸摸并移動
void HelloWorld::ccTouchesMoved(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent){
CCTouch *touch=(CCTouch *)pTouches->anyObject();//擷取觸摸
CCLabelTTF *label=(CCLabelTTF*)this->getChildByTag(LABEL_TARGET);//擷取文字
label->setString(CCString::createWithFormat("Touch Move\nsprite %d:%.2f,%.2f",sprite_num,touch->getLocation().x,touch->getLocation().y)->getCString());
//顯示目前點選位置,點選位置的坐标通過touch->getLocation().x/y來擷取
CCSprite *sprite=(CCSprite*)this->getChildByTag(sprite_num);//擷取精靈
sprite->setPosition(ccp(touch->getLocation().x,touch->getLocation().y));//設定精靈的位置
};
//結束觸摸,同上
void HelloWorld::ccTouchesEnded(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent){
CCTouch *touch=(CCTouch *)pTouches->anyObject();
CCLabelTTF *label=(CCLabelTTF*)this->getChildByTag(LABEL_TARGET);
label->setString(CCString::createWithFormat("Touch End\nsprite %d:%.2f,%.2f",sprite_num,touch->getLocation().x,touch->getLocation().y)->getCString());
CCSprite *sprite=(CCSprite*)this->getChildByTag(sprite_num);
sprite->setPosition(ccp(touch->getLocation().x,touch->getLocation().y)) ;
};
//觸摸被強行打斷
void HelloWorld::ccTouchesCancelled(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent){
};
此程式的關鍵地方如下:
(1)在此場景的初始化過程中,先初始化一個沒有内容的文字,通過宏,定義其TARGET為65535,用于顯示觸摸坐标,之是以定義一個這麼大的TARGET,是因為沒觸摸螢幕一次,則在螢幕上生成一個帶TARGET的精靈。精靈1的TARGET就為1,精靈2的TARGET就為2,以此類推,避免精靈的TARGET與文字的TARGET重複。
(2)隻要在bool HelloWorld::init(){}存在語句this->setTouchEnabled(true);,所有觸摸處理函數皆與場景HelloWorld中生效。程式猿隻要實作這四個函數即可。
(3)改變精靈位置,直接通過setPosition方法實作即可,無須把此精靈删除又添加,也不要通過《【Cocos2dx】基本動作、動作序列與動作合并》(點選打開連結)中的MoveTo動作,設定一個0.0f的時間間隔實作,Cocos2dx的動作皆帶動畫效果,很耗費資源,而且視覺效果會錯位。