概ねタイトル通りです。今回はタッチ操作に関する記事です。
スマホゲームだったらタッチ操作は必須ですよね(^ω^)
CCLayerクラスとCCSpriteクラスでタッチイベントを取得する方法を紹介してみます。
CCLayerでタッチイベントを取得する
まずはCCLayerでタッチイベントを取得してみます。
手順としてはとっても簡単で、
1.タッチイベントを有効にする
2.タッチイベント用のメソッドを追加する
これだけです。
タッチイベントのイベントは大きく分けて三種類あります。
メソッド名 | 内容 |
---|---|
ccTouchBegan | タッチされた(指が触れた)時に呼ばれる |
ccTouchMoved | タッチしたまま移動(スライド)した時に呼ばれる |
ccTouchEnded | タッチが終わった(指が離れた)時に呼ばれる |
-(id) init { if( (self=[super init]) ) { // ① self.isTouchEnabled = YES; } return self; } // ② -(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ CCLOG(@"CClayer touch start"); } // ③ -(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ CCLOG(@"CClayer touch start"); } // ④ -(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ CCLOG(@"CClayer touch end"); }
①...
CCLayerでタッチイベントを有効にしています。
①.②.③...
各タッチイベント用のメソッドです。
実際に動かして画面をタッチすると、ログが出力されます。
タッチした座標を受け取りたい場合は、
各メソッド内を以下のように修正します。
( ccTouchesBeganメソッドの場合 )
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *touch = [touches anyObject]; CGPoint touchPosition = [touch locationInView:touch.view]; CGPoint position = [[CCDirector sharedDirector] convertToGL:touchPosition]; CCLOG(@"CClayer move x[%f] y[%f]", position.x , position.y ); }
UIViewでタッチイベントを取得する場合と大体同じですね(^ω^)
3行目で取得した座標は左上が原点なので、
4行目で原点が左下になるように変換しています。(openGLは左下が原点)
CCSpriteでタッチイベントを取得する
今度はCCSpriteでタッチイベントを取得してみます。
CCLayerの時とは違った手順が必要になります。
[手順1]
CCSpriteを継承したクラスを作成
[手順2]
手順1で作成したクラスにCCTargetedTouchDelegateプロトコルを追加
[手順3]
手順1で作成したクラスのonEnterメソッドでCCTouchDispatcherで自分を追加
onExitメソッドでCCTouchDispatcherで自分を削除
[手順4]
タッチイベント用のメソッドを追加
こんな流れです。
Delegate?わからん!
Dispatcher?なにそれ美味しいの?
という人もとりあえずサンプル通りにやればOKです。
実装例(SampleTouchSpriteクラス)
・SampleTouchSprite.h
#import <Foundation/Foundation.h> #import "cocos2d.h" @interface SampleTouchSprite : CCSprite<CCTargetedTouchDelegate> { } @end
・SampleTouchSprite.m
#import "SampleTouchSprite.h" @implementation SampleTouchSprite -(void)onEnter{ // CCTouchDispatcherに自分を追加 [[[CCDirector sharedDirector] touchDispatcher ] addTargetedDelegate:self priority:0 swallowsTouches:YES]; [super onEnter]; } -(void)onExit{ // CCTouchDispatcherから自分を削除 [[[CCDirector sharedDirector] touchDispatcher] removeDelegate:self]; [super onExit]; } -(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{ CCLOG(@"CCSprite touch start"); return YES; } -(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event{ CCLOG(@"CCSprite touch move"); } -(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event{ CCLOG(@"CCSprite touch end"); } @end
まずはCCSpriteを継承したクラスを作成します。
今回は「SampleTouchSprite」という名前にしました。
[SampleTouchSprite.h 4行目]
作成したらヘッダファイルを編集してCCTargetedTouchDelegateプロトコルを追加します。
JAVAで言うところのインターフェースですね。
[SampleTouchSprite.m 9-11行目]
touchDispatcherに自分自身のインスタンスを登録しています。
priorityは優先度という意味で、優先度が高いものほど先にイベントが流れます。
(低い数字ほど優先度が高くなります)
[SampleTouchSprite.m 8行目]
これを忘れるとメモリがクラッシュする原因になるので重要です!
スプライトが削除される時は、touchDispatcherの登録を削除します。
[SampleTouchSprite.m 22行目]
三種類のメソッドの内、これだけは実装が必須となっています(他の2つは無くてもいい)
また、CCLayerの時と違い真偽値を戻り値として返す必要があります。
ここでtrueを返すと他の優先度の低いオブジェクトにはタッチイベントが流れなくなります。
[SampleTouchSprite.m 29,43行目]
CCLayerの時と同じです。この2つのメソッドの実装は任意です。
CCSpriteの表示領域内がタッチされたか調べる
上で書いた方法でCCSpriteにタッチイベントを実装しても
画面のどこをタッチしてもイベントが流れてしまいます。
CCSpriteの表示領域内がタッチされたか調べるには、
ccTouchBegan,ccTouchMoved,ccTouchEndedを以下のように修正します。
( ccTouchMovedメソッドの場合 )
-(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event{ // タッチされた座標を取得&変換 CGPoint touchPotision = [touch locationInView:touch.view]; CGPoint position = [[CCDirector sharedDirector] convertToGL:touchPotision]; // タッチされた座標が画像の範囲内の場合 if( CGRectContainsPoint( self.boundingBox , position) ){ // ここにタッチされた時の処理を書く CCLOG(@"CCSprite touch !!"); } }
座標の取得方法はCCLayerの時と大体同じです。
CGRectContainsPointメソッドでタッチされた座標がスプライトの
エリア内に入っているかをチェックしています。
サンプルプログラム
CCSpriteをタッチして、移動したら画像が一緒に動きます。
-GitHub
github.com/ouka-tenshi/iOS-Sample/tree/master/Cocos2dTouchSample
【実行結果】
|
|
: : :::::::,. -─´、て
::: :: :::Σco===、!,_
: : :: :::::l´i(ノリハノリ) 早くゲームが作りたいなあ…
: : :::::ルlリ⊃⊂ヽ
: : ::::(( //xxxxヽ、─────────────────
/~~~
./