2011-07-28 13 views
0

我有一個有趣的問題,處理我正在寫的一個cocos2D程序中的觸摸事件。我在CCScene中有3個CCLayer子圖層:如何在層重疊時將觸摸處理限制爲一層?

backgroundLayer - z:0 - 用於顯示背景圖像的簡單靜態圖層。

planetLayer - z:3 - 顯示層 - 數據更改的可視化顯示在此處。

gameControlsLayer - z:5 - 層用於顯示數據控制器,如滑塊和按鈕。

我分離了行星和控制層,因爲我想平移和縮放行星層而不用擔心控制受到影響。

這裏是現場初始化代碼,設置了這些層:

- (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; 
} 

我需要觸摸操作的星球以及控制層兩者。在控制層上,觸摸處理位於層次子控件對象內。我先寫了所有這些代碼,它工作正常。

之後,我爲行星層寫了全層觸摸處理,這樣我就可以觸摸滾動和縮放。我有滾動(雖然不是縮放),並且它工作正常。我的問題是這樣的:當我觸摸並操縱控制層上的控件時,它們可以正常工作,但是,例如,當我上下滑動滑塊時,控制層後面的行星層平鋪,就好像觸摸是爲了它。

它可能是多餘的,包括代碼,但在這裏是相關片段:

對於滑塊控件,控制層的子:

- (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:中,您應該找到一種方法來判斷觸摸是否位於其中一個控件的內部,並且在這種情況下返回NO而不是YES。

您有一種可能性是檢查[touch view](我有一個由UIKit對象組成的控制層,它的工作原理與此類似),否則您應該獲取觸摸的座標並檢查它們是否爲CGRectContainsPoint([control rect], location))