2013-08-31 27 views
0

我試圖讓玩家將我遊戲中的物體從屏幕的一部分拖動到另一部分。問題是,要拖動的對象在它們下面還需要接受觸摸的圖層。通常情況下,我只是忍住觸摸,但據我所知,只能在ccTouchBegan期間完成。我不知道用戶是否試圖拖動對象直到調用ccTouchMoved之後,所以我需要一種方法來明確吞下(或以其他方式防止較低層)在確定它是觸摸之後接收觸摸對此感興趣(在ccTouchMoved之內)。在ccTouchMoved上吞食ccTouch

回答

1

我得到了幾乎相同的問題,但我不知道我的解決方案是否適合在這裏。主要想法是應該拖動的對象是同一CCNode層次結構中的子項下面的子項。解決方案包括父母禁用兒童觸摸事件,然後攔截這些事件。如果某個對象被拖動,則父項將所有事件發送給它,而在另一種情況下,父項將處理事件本身。

讓我試着展示我的意思。對於能夠吞下觸摸項目創建協議ccTouchMoved:

@protocol SwallowingOnTouchMovedNode 
{ 
    -(BOOL) ccTouchMoved:(UITouch*)touch; // not full signature for simpleness (UIEvent should be also here) 
} 

然後創建層,這將手動處理其子的亮點:

@interface TouchHandler : CCLayer 
{ 
    NSMutableArray *draggableChildren_, nonDraggableChildren_, *claimedChildren_; 
    BOOL isDragging_; 
} 

@implementation TouchHandler 

-(id) init 
{ 
    ... 
    self.isTouchEnabled = YES; 
    draggableChildren_ = [[NSMutableArray alloc] init]; 
    nonDraggableChildren_ = [[NSMutableArray alloc] init]; 
    claimedChildren = [[NSMutableArray alloc] init]; 
    ... 
} 

創建兩個方法TouchHandler添加兩種類型的孩子 - 可拖動的和其他的。該方法將禁用對兒童的觸摸,因此父母將手動處理它們。

-(void) addChild:(CCNode*)child shouldBeDragged:(BOOL)shouldBeDragged 
{ 
    NSMutableArray *arrayToAddChild = shouldBeDragged ? draggableChildren_ : nonDraggableChildren_; 
    [arrayToAddChild addObject:child]; 
    // note, that if the child has its own children, you will need to 
    // set isTouchEnabled on all of them, as adding all children to array recursively 
    if ([child respondsToSelector:@selector(setIsTouchEnabled:)]) ((CCLayer*)child).isTouchEnabled = NO; 
    [self addChild:child]; // maybe you need to call -addChild:zOrder:tag: here 
} 

然後覆蓋觸摸處理這樣的:

-(BOOL) ccTouchBegan:(UITouch*)touch 
{ 
    for (CCNode *child in draggableChildren) 
    { 
     if ([child ccTouchBegin:touch]) 
     { 
      // this behavior looks like the one in CCTouchDispatcher - 
      // we claim children which return YES for touchBegin 
      [claimedChildren addObject:child]; 
     } 
    } 
} 

-(void) ccTouchMoved:(UITouch*)touch 
{ 
    for (CCNode *child in claimedChildren) 
    { 
     if ([(id<SwallowingOnTouchMovedNode>)child ccTouchMoved:touch]) 
     { 
      isDragging_ = YES; 
     } 
    } 

    // if no one swallowed touches 
    if (!isDragging_) 
    { 
     for (CCNode *child in nonDraggableChildren) 
     { 
      // we did not called ccTouchBegan earlier for these items, 
      // so for consistency we need to call it now 
      if ([child ccTouchBegin:touch]) 
      { 
       [child ccTouchMoved:touch]; 
       [claimedChildren addObject:child]; 
      } 
     } 
    } 
} 

-(void) ccTouchEnded:(UITouch*)touch 
{ 
    isDragging_ = NO; 
    for (CCNode *child in claimedChildren) 
    { 
     [child ccTouchEnded]; 
    } 
} 

不要忘記實現-ccTouchCancelled。這段代碼非常具體,所以你可能需要做一些修改,但是我希望我已經解釋了我的想法。一般來說,TouchHandler甚至可能不是CCLayer這樣工作,只需將其添加爲接收觸摸的目標代表即可。

還有另外一種方法,從OOP的角度來看,它似乎更加一致和正確,但我不確定。 ccTouchBegin,ccTouchMovedccTouchEnded中的行爲幾乎與CCTouchDispatcher中的行爲重複。您可以繼承它並覆蓋一些接收觸摸事件的方法,並像我一樣完成-(BOOL)ccTouchMoved。另外,我不知道我們是否可以替換默認的CCTouchDispatcher。希望這會有所幫助!