cocos2dでのタッチオブジェクトの扱い方
NSSetからタッチを取り出す
前回マルチタッチの検出の仕方などを解説したので、その際に用いたNSSetというデータの扱い方を見て行きたいと思います。
ccTouchesBeganやccTouchesMovedといったマルチタッチにも対応できるメソッドはタッチをNSSetという集合データとして取得しています。タッチオブジェクトとして扱うためにはこれらからUITouchオブジェクトを取り出してやらなくてはいけません。
ccTouchBeganなどのシングルタッチ専用メソッドはNSSetの代わりにUITouchを引数に持っているので、そのままその引数を用いればタッチオブジェクトとして扱えます。
ccTouchesメソッド群の場合は以下のような方法で個々のタッチを扱います。
- forで回しながらアクセス
- NSArrayに変換
- UIEventから取り出し
おそらく他にもいろいろ方法はあると思いますが、この辺りが扱えれば十分だと思います。
1) forで回しながらアクセス
forループでNSSet内のオブジェクトに順番にアクセスする方法です。いわいる高速列挙というやつを使います。とにかく構文を見てもらいましょう。
for(UITouch *touch in touches) { /* touchの処理 */ }
touchesがNSSet型のオブジェクトでいくつかのタッチオブジェクトを持っています。UITouch*型変数touchを定義し、touchesの中のタッチを1つずつtouchに格納しているのです。
あとはforの中でタッチオブジェクトに対する処理を行います。
2) NSArrayに変換してアクセス
NSSetのメソッドを用いて、まず配列にオブジェクト集合を格納します。後はそれぞれ配列の要素としてそれらを扱います。
NSArray *touchArray = [touches allObjects]; UITouch *firstTouch = [touchArray objectAtIndex:0]; UITouch *secondTouch = [touchArray objectAtIndex:1];
1行目で”allObject”メソッドを用い、配列に変換しています。2行目、3行目はNSArrayのobjectAtIndexメソッドでインデックスの要素にアクセスしています。以下のように省略できます。
UITouch *firstTouch = [[touches allObjects] objectAtIndex:0]; UITouch *secondTouch = [[touches allObjects] objectAtIndex:1];
この方法の場合、シングルタッチだと配列の要素は1つだけになるので、secondTouchには何も入りません。というか、objectAtIndexでアクセスできるのかな?落ちる気がします。
NSSetの”count”プロパティなどで、中身の数を確定してから取り出すほうが無難です。
3) UIEventから取り出す
ccTouchesメソッド群の引数UIEventもタッチオブジェクト情報を持っています。これも結局はUIEvent型から一旦NSSet型に変換するだけの方法ですが一応書いておきます。
NSSet *touchSet = [event allTouches]; // NSSetに変換 NSArray *touchArray = [touchSet allObjects]; UITouch *firstTouch = [touchArray objectAtIndex:0]; UITouch *secondTouch = [touchArray objectAtIndex:1]; /* タッチを一つだけ取り出す場合 */ UITouch *touch = [touchSet anyObject];
1行目でNSSetに変換した後は上の1、2のどちらの方法でも扱えます。
また最後の行のように、NSSetのanyObjectメソッドを用いれば、NSSetの中からランダムで(ランダムじゃないかも)一つのオブジェクトを取得できます。
一応以下の様な形で記述例を載せておきます。
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { if(touches.count == 2) //マルチタッチの処理 { //配列に変換してからアクセス UITouch *firstTouch = [[touches allObjects] objectAtIndex:0]; UITouch *secondTouch = [[touches allObjects] objectAtIndex:1]; } else if(touches.count == 1) //シングルタッチの処理 { //UIEventからの変換 UITouch *touch = [[event allTouches] anyObject]; } else { //forで各要素にアクセス for(UITouch *touch in touches) { } } }
あとは、「タッチに反応するオブジェクトを作る」で説明したように、タッチ位置のポジションをとってcocos2d座標系に変換したり、タップやスワイプを識別したりして用いてください。タップなどの処理はまた後日。