cocos2dの基礎 タッチでオブジェクトを動かす.
前回、タッチに反応するオブジェクトを作りました。
今回は、ドラッグでこのオブジェクトを動かせるようにしましょう。
タッチメソッドの制御
タッチポイントが動いた時に呼び出されるメソッドはccTouchMoved、またはccTouchesMovedでした。まずはこのメソッドが「オブジェクト上でタッチが始まった時」のみ処理されるようにする必要があります。
この機能を実現するために、ccTouchBeganのreturnを利用します。
このreturnはこれ以降のタッチ処理をブロックするかどうか決定するのに用いることができます。YESが返ればタッチ処理を続け、NOが返ればこれ以降のccTouchMovedやccTouchEndedは呼ばれません。
したがって、オブジェクトを動かす際の流れは以下のようになります。
前回のタッチ開始メソッドを以下のように変更します。
-(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { CGPoint touchPos = [[CCDirector sharedDirector] convertToGL:[touch locationInView:[touch view]]]; CCSprite* circle = (CCSprite*)[self getChildByTag:tagCircle]; BOOL unblock = NO; if(CGRectContainsPoint(circle.boundingBox, touchPos)) { unblock = YES; NSLog(@"Touch Started"); } return unblock; }
前回と同じよう、まずタッチポイントのcocos2d上での座標値を3行目で取得しています。そして5行目ではイニシャライザで読み込んでいるスプライトをタグを使って呼び出しています。
タッチがオブジェクト上で起こったかどうかの判定はBOOL型のunblock変数を定義して行なっています。スプライトのバウンディングボックス内にタッチポジションが含まれている場合はunblockにYESを代入ています。
こうすることで、オブジェクト上でタッチが起こった時のみ、その後のタッチメソッドが呼び出されるようになります。
返り値は、結局CGRectContaintsPointの値が返ればいいので、以下のように書くこともできます。
-(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { CGPoint touchPos = [[CCDirector sharedDirector] convertToGL:[touch locationInView:[touch view]]]; CCSprite* circle = (CCSprite*)[self getChildByTag:tagCircle]; return CGRectContainsPoint(circle.boundingBox, touchPos); }
ccTouchMovedの処理
タッチメソッドの制御はできるようになったので、次はタッチが動いている時の処理を書いていきます。
オブジェクトを動かす処理は様々な方法があると思いますが、基本的には以下の様な考え方で行われます。
現在のタッチ位置と、1フレーム前のタッチ位置を取得し、どれだけ移動したかを算出します。
この動いた分だけ、オブジェクトのポジションも動かしてやればOKです。
UITouchのクラスには1フレーム前のポジションを取得するメソッドが用意されています。
上の図をそのままプログラムにすると以下のようになります。
-(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event { CCSprite* circle = (CCSprite*)[self getChildByTag:tagCircle]; CGPoint currentPos = [[CCDirector sharedDirector] convertToGL:[touch locationInView:[touch view]]]; CGPoint previousPos = [[CCDirector sharedDirector] convertToGL:[touch previousLocationInView:[touch view]]]; CGPoint difference = ccpSub(currentPos, previousPos); circle.position = ccpAdd(circle.position, difference); }
7行目が移動前のタッチ位置を取得している部分です。touchオブジェクトに’previousLocationInView’メッセージを送ることで位置を取得しています。
CGPoint型の演算には9行目や11行目のようなccpから始まる関数を用います。ccpSubで移動距離を出し、ccpAddでオブジェクトの位置を更新しています。
実行してみましょう。オブジェクト上でタッチを開始し、移動に合わせて、オブジェクトも移動したら成功です。