天天看點

【Cocos2dx】觸摸事件

Cocos2dx與玩家之間的互動,很大一個情況是通過處理玩家的觸摸事件來實作的。在移動應用就是觸摸,在PC應用就是點選。

下面用一個小例子說明,Cocos2dx的觸摸事件。

如下圖,每當使用者觸摸(點選)螢幕,就會生成一個觸摸精靈,結束點選之後結束生成,在精靈沒有結束生成之前,觸摸拖動能夠改變此按觸摸按鈕的位置。同時,任何一個觸摸,都會記錄目前的坐标。

【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的動作皆帶動畫效果,很耗費資源,而且視覺效果會錯位。

繼續閱讀