Recent Posts
Recent Comments
- Mose 在 FMDB:我的SQLite救星
- welsonla 在 FMDB:我的SQLite救星
- liter0827 在 FMDB:我的SQLite救星
- liter0827 在 FMDB:我的SQLite救星
- bonjouryentinglai 在 FMDB:我的SQLite救星
- henry 在 FMDB:我的SQLite救星
~我的iPhone程式筆記~
最近網友的回應讓我想到,教學寫了那麼多,好像還沒教過怎麼處理觸控事件。實在是天大的疏忽,這個教學應該在早早之前就寫了說。iPhone唯一能讓使用者輸入的介面就是那一大片的觸控螢幕,如果一個iPhone app沒有觸控功能,那還搞屁啊?今天我們就來看看如何在程式裡處理觸控事件。
如果你已經看過其他iPone SDK的相關書籍,大概會知道,iPhone的觸控主要由三個函式方法負責:
﹣(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
﹣(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
﹣(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
基本上看到函式的名稱就可以知道它所對應的功能。當使用者第一次按下螢幕時,touchesBegan的方法就會被觸發。如果使用者開啟移動,touchesMoved裡的程式便會被執行。最後一個touchesEnded就是當手指離開螢幕時要會觸發的函式。
這三個函式並沒有順序性的關係,也不需要三個函式的內容都寫,完全取決於這個app遇到對應的觸控事件時該怎麼處理對應的動作。
重點來了,如果你在cocos2d的CCLayer裡寫入這三個函式方法,是一點用處也沒有的,因為cocos2d有自己的觸控事件函式。但是也不用太擔心,基本上沒有什麼困難的地方,只不過就是在上述三個函式的名稱前加入cc兩個字而已:
﹣(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
﹣(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
﹣(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
至於為什麼要改名字,A兜。。。這個老實說我也不是很清楚,只能告訴你因為cocos2d並沒有直接繼承UIKit的類別,所以很多protocol都得重新稍微定義一下才行,大概是這個樣子。
好了,廢話不多說,來寫程式。這一次的程式目的是建立一個CCSprite物件,使用者可以觸碰這個物件並移動它,當使用者的手指離開螢幕後,物件會回到螢幕中心的位置。
前置作業就不再重覆了,開啟一個cocos2d專案,在HelloWorldScene.h裡的大括內加入
CCSprite *touchIcon;
接著到HelloWorldScene.m裡,把- (init)的部份改為下列程式碼:
-(id) init {
// always call “super” init
// Apple recommends to re-assign “self” with the “super” return value
if( (self=[super init] )) {self.isTouchEnabled = YES;
touchIcon = [CCSprite spriteWithFile:@"Icon.png"];
[touchIcon setPosition:ccp(240,160)];
[touchIcon setOpacity:100];
[self addChild:touchIcon];
}
return self;
}
這裡比較重要的大概就是self.isTouchEnabled = YES這行,主要功能就是把接收觸控事件的功能打開,這樣等等加入的觸控函式才能發揮功用。剩下就只是touchIcon這個物件的一些相關設定,這次比較偷懶,連圖檔都不附了,反正cocos2d模版裡就有圖檔,我們就直接拿來用,省去大家還要下載的麻煩。
接著就是今天的重頭戲了,我們要加入負責接收觸控事件的三個函式。將下列程式碼加到HelloWorldScene.m裡:
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];CGRect rect = CGRectMake(touchIcon.position.x -
touchIcon.contentSize.width/2, touchIcon.position.y -
touchIcon.contentSize.height/2,
touchIcon.contentSize.width, touchIcon.contentSize.height);if (CGRectContainsPoint(rect, location)) {
[touchIcon setOpacity:255];
}
}- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];CGRect rect = CGRectMake(touchIcon.position.x -
touchIcon.contentSize.width/2, touchIcon.position.y -
touchIcon.contentSize.height/2,
touchIcon.contentSize.width, touchIcon.contentSize.height);if (CGRectContainsPoint(rect, location)) {
[touchIcon setPosition:location];
}
}- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];CGRect rect = CGRectMake(touchIcon.position.x -
touchIcon.contentSize.width/2, touchIcon.position.y -
touchIcon.contentSize.height/2,
touchIcon.contentSize.width, touchIcon.contentSize.height);if (CGRectContainsPoint(rect, location)) {
[touchIcon runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(240,160)]];
[touchIcon setOpacity:100];
}
}
這三個函式的結構大同小異,所以這裡就將相同的部份統一說明。
首先看到的是
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
我們先建立一個UITouch物件myTouch,它的內容來自於touches。接著我們用locationInView這個方法從myTouch中取出觸碰的位置。最後一行相當重要,因為myTouch傳回的位置所用的座標原點是在螢幕左上角,但在cocos2d中所使用的座標原點則是在螢幕左下角,所以cocos2d提供了這個簡便的方法讓我們轉換兩者間的關係。這一步一定要記得做,不然到時觸控起來會很奇怪。
接著程式建立了一個CGrect,
CGRect rect = CGRectMake(touchIcon.position.x – touchIcon.contentSize.width/2, touchIcon.position.y – touchIcon.contentSize.height/2, touchIcon.contentSize.width, touchIcon.contentSize.height);
這是由Core Graphic所定義的矩形結構,我們用CGRectMake這個C語言函式來建立它。參數依序是矩形左下角的x和y值,以及矩形的寬和高。我們建立的這個大小就是touchIcon的範圍,有了這個範圍,我們再利用CGRectContainsPoint這個函式來判斷這個矩形是否有包函觸碰的位置。如果有,代表使用者按到這個圖形了,我們再依觸碰事件的種類來執行對應的動作,包括:
ccTouchesBegan:使用者第一次按到touchIcon,把圖檔的透明度調成255(即不再半透明)。
ccTouchesMoved:使用者開始移動手指,設定touchIcon的位置為手指移到的位置點。
ccTouchesEnded:使用者手指離開螢幕,此時令touchIcon執行回到中心點的動作,並將圖檔調回半透明。
趕快run一下你的程式,操作起來應該會下面的影片一樣。基本的觸控事件處理大概就是這麼一回事,是不是很簡單呢?
哇~~太讚了,我一直在讀你的教學,每個我都有成功,真是太謝謝你了
要加油喔~~~~今天你一貼上,我就試成功了~~~
能不能再寫一篇三軸加速度計,如何讀取呀???
謝謝了
呵呵,是忠實觀眾耶~應該要表揚一下~哈哈~
加速度計的部份有空我會寫的,不過最近還滿忙的,又要寫程式又要寫部落格實在有點忙不太過來,還請您耐心等候^^
對了~~我們有三個人在寫iphone程式,有一個是美工,我想寫一個大一點的game,但是我們都是新手,不知你有沒有興趣參與~~~
呵~~我們也都是工作之餘的~~~
只要有遊戲寫我都還滿感興趣的,不過最近有件急事要處理,大概要四月底才會結束,可能要那時才有空(好像有點太久了XD)。如果您不介意,是否方便在”About”的頁面留下您的聯絡方式,如果到時還缺人手或需要幫忙,我們可以再詳談^^
我現在也都在寫iPhone程式,學寫iPhone也有一段時間了,一直對寫遊戲非常有興趣,不知道是不是可以參與你們?我的MSN是
yuh_hung@yahoo.co.uk
如果怕人多手雜,不介意的話還是可以加我一起討論或分享經驗也好:)
已經加您MSN囉~
err…我沒收到通知說 囧
請問一下~~假設我今天畫面中有兩個可以被touch移動的sprite
我要怎麼判斷這次是按到誰
謝謝
通常的作法是,把畫面中所有的sprite放到一個array裡,然後用迴圈一個個去判斷這個sprite的rect有沒有包含touch的位置,有的話再對該sprite進行動作。
請問一下~~~如果我想用touchevent 傳送socket到PC要怎麼做?
謝謝
呵呵~~socket以解決了~~~
期待版主發新文哩
期待有加速度計的教學
謝謝
我是剛進入cocos2d的新手,十分期待看板主的教學文,清楚易懂!!
期待有新教學可以學習!!
最近剛好想學Cocos2D
感謝您的教學,我終於抓到一點訣竅了
謝謝
板大你好
照著你的方法練習到這
都還很順利也學到很多
但是TOUCH這邊
照著練習玩卻還是還無動靜
也有嘗試 其他人的範例
但依舊沒有動靜只好求助板大
有一些小小問題想要先提問
﹣(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
﹣(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
﹣(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
此三個方法 並非寫在INIT裡面是麼?
就是要寫在外面吧!!
此外 全部寫玩後編譯完
會出現警告
initialization from distinct Objective-C type
此時 Simulator 中間出現圖片 但對TOUCH毫無反應
SO
我在HwlloWorldScene.h
@end 前 把方法宣告上去
警告消失了
但simulator ㄧ樣是出現圖片 但對 touch還是無反應
還是找不出問題在哪
請板大OR其他高手 幫幫忙謝謝
那三行需要做一點變動
原本是
[quote]
﹣(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
﹣(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
﹣(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
[/quote]
實際在寫的時候應該是
[quote]
﹣(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
}
﹣(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
}
﹣(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
}
[/quote]
寫在@implementation裡面,它們是message/method
謝謝樓上
你指的變更是
加上 大括號
在裡面寫入實做 這樣麼?
如果是
那我應該沒打錯
我是照版大的寫法 打上去的
嘗試的做了一個小範例
在init裡面加入
self.isTouchEnabled=YES;
NSString*str1=@”asd”;
NSLog(@”qwe%@”,str1);
NSLog(@”mikeqwe”);
並加入
-(BOOL)ccTouchBegan:(NSSet*)touches withEvent:(UIEvent*)event{
NSLog(@”bettyissobuty”);
return YES;
}
執行結果
2010-07-31 13:18:28.620 touchtest3[18030:20b] qweasd
2010-07-31 13:18:28.621 touchtest3[18030:20b] mikeqwe
2010-07-31 13:18:28.632 touchtest3[18030:20b] cocos2d: surface size: 320×480
touch後 還是無反應
thx
你要不要把整個code 貼上來看看??
XCode右下角有沒有出現黃色的三角形Warning圖示?
終於發現原因了
不好意思 勞煩兩位
由於習慣在打到一半時
直接按ESC 選擇方法
反而導致盲點
事實上應該是才對…
-(BOOL)ccTouchesBegan:…..event
但是用ESC 選擇的方法 卻是
-(BOOL)ccTouchBegan:…..event
差別在ccTouch”es”Bgan
不知原因何在
另外
而一開始打錯時
會出現警告
initialization from distinct Objective-C type
此時要去h黨宣告方法
而
-(BOOL)ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
是cocos2d自己的觸控事件函式
所以不需再h檔宣告
不知道 這樣推論是否正確
另外謝謝版大的所有文章
真的受益良多
HI,你的教學很棒,但是我想問如果我有一張圖片,想把拉到螢幕下方,然後圖就會住下消息應該怎樣做?
我的MSN:supercat5@hotmail.com
希望大家能交流一下
抱歉我想請問一下,“住下消息“是什麼意思@@“
對不去,是往下消失@@
板主可以請教一下題外話嗎
COCOS2D做出來的APP一開始一定要跑出她們的官方圖片嗎
有沒有辦法拿掉呢
在Xcode resource裡把Default.png換掉就好囉~
我想請教一下~只有文字也是用這個觸發嗎??
我想他點某段字就跳出東西來~
也是用這個觸發寫嗎?還是不用用到這個~~
不好意思我是IPHONE超級新手~XD~
cocos2d的资料还真不多,能找到楼主的文章真令我兴奋不已,我看了你几乎所有的文章,希望有空能向你讨教,请加我MSN : happy10086@gmail.com
已經加入囉~
在Objective-C裡,不管是文字還是圖片,都是一個物件。只要把文字當作是圖片,剩下的作法都一樣喔。
如果是在cocos2d裡,文字會用CCLabel實作。
樓主教學太棒了~
還有很多希望數主可以教一下~
例如:
virtual joystick 加按鈕怎樣做….用touch event 嗎?還是用menu button?
1些橫向action遊戲的原理又怎樣做…背景怎樣跑….?
萬分感謝:)
virtual joystick好像google搜尋一下就有現成的模組可以使用了。
橫向遊戲的背景要怎麼跑喔?
就。。。。方向鍵按右的時候,令背景向左移,您是要問這個嗎??
對喔~但圖檔好像有限width??
那背景要換很多圖嚕..?
是啊,就換吧~
覺得你的教學寫的很淺顯易懂…非常不容易…
方便的話…
想加您的msn…
我的是zhihmeng@hotmail.com…
謝謝囉…
已經加囉~
看了一些教學 真的很厲害
如果方便的話想加您的msn
我的是kite129@yahoo.com.tw
感謝啦!!
已經加囉~~
這裡快變成加好友專區了….
你好~
你寫的文章真棒,且淺顯易懂,我們專題剛好有要做這方面的事
方便的話可以加你msn嗎,想跟你討論一些事情…>”<
giwawamsl@hotmail.com
感謝你~
已經加囉