2011-07-28 4 views
0

私が書いているcocos2Dプログラムのタッチイベントを扱うのに面白い問題があります。 CCSceneに3つのCCLayerサブレイヤレイヤーがあります。レイヤーが重なっている場合、どのように1つのレイヤーにタッチ操作を制限できますか?

backgroundLayer - z:0 - 背景画像を表示するための単純な静的レイヤーです。

planetLayer - z:3 - 表示レイヤー - データ変更の視覚化がここに表示されます。

gameControlsLayer - z:スライダーやボタンなどのデータコントローラーを表示するために使用されるレイヤー。

惑星層と雲母層を分けたのは、影響を受けるコントロールを心配することなく惑星層をパンしてズームしたいからです。

- (id) init 
{ 
    self = [super init]; 
    if (self != nil) 
    { 
     // background layer 
     BackgroundLayer *backgroundLayer = [BackgroundLayer node]; 
     [self addChild:backgroundLayer z:0]; 

     // planet layer 
     PlanetLayer *planetLayer = [PlanetLayer node]; 
     [self addChild:planetLayer z:3]; 

     // gameplay layer 
     GameControlsLayer *gameControlsLayer = [GameControlsLayer node]; 
     [self addChild:gameControlsLayer z:5]; 
    } 
    return self; 
} 

私は両方の惑星と制御層の上に取り扱う触れる必要があります。ここでは

は、これらの層を設定したシーンのinitコードです。コントロールレイヤーでは、タッチハンドリングは、レイヤーの子であるコントロールオブジェクト内にあります。私はこのコードをすべて最初に書きました。

その後、惑星層のレイヤー全体のタッチ操作を記述して、タッチのスクロールとズームを行うことができました。私はスクロールしているが(まだズームはしていないが)、うまく動作する。私の問題はこれです:コントロールレイヤーのコントロールをタッチして操作するとうまく動作しますが、スライダーの親指を上下に動かすと、コントロールレイヤーの後ろの惑星レイヤーがあたかもそれ。

コードを含むように冗長であるが、ここでは関連するスニペットある可能性がありますスライダコントロールのために

、制御層の子:ここ

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

- (void) onExit 
{ 
    [[CCTouchDispatcher sharedDispatcher] removeDelegate:self]; 
} 

#pragma mark Touch Delegate 

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    CGPoint location = [[CCDirector sharedDirector] 
       convertToGL:[touch locationInView:[touch view]]]; 



    float distance = [self distanceBetweenPointOne:thumbPosition 
             andPointTwo:location]; 
    if (distance > thumbRadius*2) 
    { 
     return NO; 
    } 

    // touch is on the thumb. store the location so we 
    // can calculate changes on ccTouchMoved events 
    touched = YES; 
    return YES; 
} 

- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    if (!touched) 
    { 
     return; 
    } 

    CGPoint location = [[CCDirector sharedDirector] 
       convertToGL:[touch locationInView:[touch view]]]; 
    location = [self convertToNodeSpace:location]; 

    // if we're too far off the thumb, abandon it 
    float distance = [self distanceBetweenPointOne:thumbPosition 
             andPointTwo:location]; 
    if (distance > thumbRadius*3) 
    { 
     //touched = NO; 
     return; 
    } 

    // this call adjusts some ivars – not relevant 
    [self updateValueAndPosition:location]; 
} 

- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    if (touched) 
    { 
     touched = NO; 
    } 
} 

- (void)ccTouchCancelled:(UITouch *)touch 
       withEvent:(UIEvent *)event 
{ 
    [self ccTouchEnded:touch withEvent:event]; 
} 

はから関連するコードです惑星層:

// Yes, we want touch notifications please 
// 
- (void) onEnterTransitionDidFinish 
{ 
    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self 
     priority:0 swallowsTouches:NO]; 
} 

#pragma mark Touch Delegate 

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    CGPoint touchLocation = [touch locationInView:[touch view]]; 
    touchLocation = [[CCDirector sharedDirector] 
         convertToGL:touchLocation]; 

    // ****NOTE – the following is a kludge I used it to break 
    // ********** the behavior; the controls are all grouped 
    // ********** at the bottom of the screen. But this is not 
    // ********** an acceptable fix. I shouldn’t need to mask 
    // ********** off certain areas of the screen. This strategy 
    // ********** will not hold once I add other controls to the 
    // ********** control layer. 
    // 
    if (touchLocation.y > 250.0f) 
    { 
     self.touched = YES; 
     touchHash = [touch hash]; 
     return YES; 
    } 
    return YES; 
} 

- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    if (!touched) 
    { 
     return; 
    } 

    if ([touch hash] == touchHash) 
    { 
     CGSize screenSize = [[CCDirector sharedDirector] winSize]; 

     CGPoint touchLocation = 
       [touch locationInView:[touch view]]; 
     CGPoint prevLocation = 
       [touch previousLocationInView:[touch view]]; 

     touchLocation = [[CCDirector sharedDirector] 
          convertToGL:touchLocation]; 
     prevLocation = [[CCDirector sharedDirector] 
          convertToGL:prevLocation]; 

     CGPoint diff = ccpSub(touchLocation, prevLocation); 

     CGPoint currentPosition = [self position]; 
     CGPoint newPosition = ccpAdd(currentPosition, diff); 

     if (newPosition.x < lowestX) 
      newPosition.x = lowestX; 
     else if (newPosition.x > highestX-screenSize.width) 
      newPosition.x = highestX-screenSize.width; 

     if (newPosition.y < lowestY) 
      newPosition.y = lowestY; 
     else if (newPosition.y > highestY-screenSize.height) 
      newPosition.y = highestY-screenSize.height; 

     [self setPosition:newPosition]; 
    } 
} 

- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    if ([touch hash] == touchHash) 
    { 
     if (touched) 
     { 
      touched = NO; 
     } 
    } 
} 

- (void)ccTouchCancelled:(UITouch *)touch 
       withEvent:(UIEvent *)event 
{ 
    [self ccTouchEnded:touch withEvent:event]; 
} 

私はピンチズーム機能を追加したいと思いますが、私はこの問題を解決する必要があります。誰か答えがありますか?私は何かが明らかに欠けているように感じる...

ありがとう!

答えて

0

planetLayerccTouchBegan:には、タッチがコントロールの1つに含まれているかどうかを確認する方法があります。そうした場合、YESではなくNOを返します。

あなたが持っている可能性は、[touch view]です(私はUIKitオブジェクトで作られたコントロールレイヤーを持っています。そのように動作します)。そうでなければ、タッチの座標を取得し、CGRectContainsPoint([control rect], location))かどうかを確認する必要があります。

関連する問題