【iOS-Cocos2d遊戲開發之五】多觸點與觸屏事件詳解(單一監聽、事件分發)【11月28日更新】

 李華明Himi 原創,轉載務必在明顯處註明:
轉載自 【黑米GameDev街區】 原文連接:  http://www.himigame.com/iphone-cocos2d/450.html


-----------------------------------本章補充開始!---------------------------------- 
css

          本篇對於多觸點和觸屏事件已經作了一個詳細的說明,可是有一點忽略了,就是開啓多觸點的支持!步驟以下:html

         首先進入AppDelegate.m 類中, app

- (void) applicationDidFinishLaunching:(UIApplication*)application{}

  在上面這個方法中添加以下一句開啓多觸點支持的代碼:框架

 //支持多觸點 [viewController.view setMultipleTouchEnabled:YES];

其餘類設置多觸點:iphone

[[[CCDirector sharedDirector]openGLView]setMultipleTouchEnabled:YES];函數

--------------------------本章補充完畢------------------------------------------------------------------------------spa


最近幾天一直在啃cocos2d,消化了很多東西,基本能夠有些把握下手寫公司的遊戲了;那麼今天就把一些重點的拿出來分享下經驗,給新童鞋們做爲參考;.net

這篇就來詳細介紹下cocos2d對用戶觸屏的監聽事件進行下分析(cocos2d有不少詳細的文章和教程,我這裏只是出於本身的理解來講)code

進入正題:從總體cocos2d對觸屏的事件監聽能夠分爲兩種:htm

1.單一監聽,所謂單一監聽實際上是跟cocos2d引擎框架有關,由於在cocos2d中每一個遊戲界面均可以使用一個CCLayout完成,那麼當一個CCLayout在屏幕顯示出來後,想要監聽用戶的按鍵事件,通常都會使用如下形式來進行監聽:(注意:這裏是CCLayout類進行監聽的方式)

首先開啓監聽:

self.isTouchEnabled=YES;
而後重寫監聽函數便可:

//監聽首次觸發事件
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
}
//觸摸事件 - 當手指在屏幕上進行移動
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
	
}
//觸摸事件 - 當手指從屏幕擡起時調用的方法
-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
	 	
}
此種監聽狠eazy,可是要注意這裏是對CCLayout類進行的監聽方式;


2.監聽分發; 剛纔說了,遊戲的每一個界面可能都是一個CCLayout,可是若是我想讓一個CCSprite精靈主角單獨進行監聽,或者說在CCLayout有不少個精靈我想單獨監聽其中的一種的時候,這時候就須要使用監聽分發的形式了;

假設咱們自定義了一個類XX繼承CCSprite,還有一個YY類也繼承CCSprite,並且XX類型與YY類的實例都存在於一個Layout上,那麼我想對XX與YY類型分別單獨監聽的話;首先咱們先讓當前繼承的CCSprite類的XX於YY類都使用 <CCTargetedTouchDelegate>協議;

(CCSprite中沒有 self.isTouchEnabled=YES; 這個函數,別直接寫這個哦~)
 

代碼以下:

@interface XX : CCSprite <CCTargetedTouchDelegate>{

}

而後在當前實現類中重寫一個函數以下:

-(void) registerWithTouchDispatcher
{
	[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
}


或者將註冊的這句代碼,放在重寫的onEnter函數中也可;


(此函數是註冊監聽,若是裏面什麼都不寫,則當前不會相應任何觸屏事件;)

重寫觸摸的各事件函數,以下:

//監聽首次觸發事件
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{ 
	return NO;
}
//監聽移動事件
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{ 	
}
//監聽離開事件
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
	
}

你們能夠看到,此種監聽方式除了各類監聽函數與第一種相似以外,在 ccTouchBegan的函數有個返回類型-布爾值;那麼其做用下面詳細介紹;若是XX與YY類都實現了第二種監聽方式的話,那麼當用戶觸屏後,(當前用戶觸發的是XX與YY類實例所在的CCLayout)首先會進入XX或者YY的其中的ccTouchBegan函數中,這裏假設首先進入了XX類中,那麼XX類中的ccTouchBegan將會被響應,若是return true;表示再也不將用戶觸屏的消息傳遞給YY類中進行響應,也就是說再也不響應YY類中的ccTouchBegan函數,那麼若是 return false;則會將當前觸屏信息傳遞給其餘註冊過的類型中;

一句話歸納:return 的值,若是是真則代表用戶觸摸事件已經被處理,其餘不會再去進行監聽;若是爲假,則會繼續交給其餘註冊過的類型中進行處理;


那麼第二種監聽的方式比較經常使用,這樣便於處理,那麼至於註冊,通常都是放在 onEnter函數中;onEnter函數是每一個CCScene之間切換會被響應的函數,至關因而CCScene的生命週期函數,具體調用順序以下:

//使用[CCDirector replaceScene:XX],替換場景時,會調用如下3個方法
//調用順序依次爲:
//1.othterScene的+(id)Scene——>
//2.otherScene的init——>
//3.otherScene的onEnter——>
//4.運行過渡效果
//5.當前Scene的onExit函數——>
//6.otherLayout的onEnterTransitionDidFinish()
//7.當前Scene的dealoc函數
-(void) onEnter{
	//調用其餘Scene的init方法之後會調用此方法
	//若是使用了CCTransitionScene,本方法將在過渡效果開始後調用
	//(若是不調用super onEnter新場景可能對觸摸和加速計無發應)
	[super onEnter];
}
-(void) onEnterTransitionDidFinish{
	//調用onEnter後會調用此函數
	//若是使用了CCTransitionScene,將會在過渡效果完成時調用此方法
	[super onEnterTransitionDidFinish];
}
-(void)onExit{ 
	//在調用dealloc以前會調用此函數;
	//若是使用了CCTransitionScene,將會在過渡效果結束之後調用此方法
	//(若是不調用super onExit,當前場景可能不會從內存中釋放)
	[super onExit];
}

那麼大概介紹了監聽事件後,那麼觸屏中最關心的就應該是多觸點啦;

//-----獲取多點觸摸
	NSSet *allTouches = [event allTouches];
	UITouch *touchOne = [[allTouches allObjects]objectAtIndex:0];
	UITouch *touchTwo = [[allTouches allObjects]objectAtIndex:1];
	//...類推

獲取多點狠簡單,那麼下面再將基本經常使用到的幾個判斷寫下:

1-判斷用戶單擊仍是雙擊(針對一個觸點)

 
 

if([allTouches count]==1) { 
	UITouch *touchOne = [[allTouches allObjects]objectAtIndex:0];
	switch ([touchOne tapCount]) {
		case 1:
			 //單擊
			CCLOG(@"%@",@"單擊");
			break;
		case 2:
			//雙擊
			CCLOG(@"%@",@"雙擊");
			break;
	}
}

1-判斷用戶兩個觸點之間是合攏仍是分開(針對兩個觸點)

 
 

if([allTouches count]==2) { 
	//適當修改處理,不能同時取,不然確定同樣的啦(能夠一個在began 一個在end)
	UITouch *touchOne = [[allTouches allObjects]objectAtIndex:0];
	UITouch *touchTwo = [[allTouches allObjects]objectAtIndex:1];
	CGFloat *disFirst  =[self distance:[touchOne locationInView:[self view]] 
							todistance:[touchTwo locationInView:[self view]]];
	
	UITouch *touchOne = [[allTouches allObjects]objectAtIndex:0];
	UITouch *touchTwo = [[allTouches allObjects]objectAtIndex:1];
	CGFloat *disFinal  =[self distance:[touchOne locationInView:[self view]]
							todistance:[touchTwo locationInView:[self view]]];
	if (disFirst>disFinal) {
		CCLOG(@"%@",@"合攏");
	}else{
		CCLOG(@"%@",@"分開");
	}
}


 


 

這裏我就粗略的寫在一塊兒,斷定兩個觸點是否合攏其實就是用戶剛觸屏時記錄兩點之間的距離記作disFirst,而後在兩個觸點離開屏幕(或者移動事件中)的時候計算

當前的兩個觸點的距離disFinal,那麼最後根據disFirst與disFinal距離關係就能知道是合攏仍是分開;

(CCLOG 是cocos2d封裝的打印方法,此種打印在編譯發佈正式遊戲程序的時候是不會編譯到程序中的,可是NSLOG會一直存在!要注意!)

最後給出兩個函數,用於計算不一樣方式監聽的函數中獲取(轉換)座標的,由於cocos2d是openGL進行搭建的框架,因此須要座標轉換;

+(CGPoint) locationFromTouches:(NSSet*)touches
{
	return [self locationFromTouch:[touches anyObject]];
}
+(CGPoint) locationFromTouch:(UITouch*)touch
{
	CGPoint touchLocation = [touch locationInView: [touch view]];
	return [[CCDirector sharedDirector] convertToGL:touchLocation];
}

兩個方法一看就能看出區別,一個是UITouch的,一個是NSSet,一個是單一監聽,一個是分發監聽;

ok,本章就到這裏~~~(下週進入封閉開發了,吃睡都在公司了,咳咳,帶上個人多啦a夢的小褲衩,娃哈哈~)








 

 

原文連接: http://blog.csdn.net/xiaominghimi/article/details/6665887
相關文章
相關標籤/搜索