2011-09-01 1 views
4

이것은 약간의 설명이 필요하지만 여기서는 약간의 통찰력을 고맙게 생각합니다.CCSpatch가 CCBatchNode의 하위 노드 인 터치 가능한 CCNode를 생성하는 데 문제가 있습니다.

짧은 버전 : CCSprite 이미지가 다른 클래스의 CCSpriteBatchNode의 자식 인 TouchableButton (자체 터치로 감지)을 만드는 방법은 무엇입니까? 일반적으로 CCSprite는 TouchableButton 자체의 자식입니다.

긴 버전 :

내가적인 Cocos2D를 사용하여 게임을 짓고 있어요. 이 게임은 서로 뛰고 서로 상호 작용하는 에이전트 (클래스 AgentView : CCNode)로 가득 찬 풍경 (클래스 EnvironmentView : CCLayer)에 중점을 둡니다.

EnvironmentView는 AgentView 객체 목록을 유지 관리하고 필요에 따라 (상호 작용 방식에 따라) 객체를 작성/삭제합니다.

각 AgentView에는 CCBatchNode (EnvironmentView의 @property)의 하위 뷰로 추가되는 CCSprite @property가 있으며 이는 EnvironmentView의 하위 노드로 추가됩니다.

사용자가 상담원을 만져서 가로에서 한 위치에서 다른 위치로 이동할 수있는 기능을 구현하려고합니다.

환경보기에서 주위를 돌아 다니는 많은 에이전트가 있기 때문에 터치 위치를 얻고 모든 AgentView CCSprites를 반복하는 표준 접근법을 사용하여 터치가 그들 중 하나에 도달 하는지를보고 싶지는 않습니다. 이 접근 방식을 홍보하는 답변에는 관심이 없습니다.)

대신 각 AgentView를 터치 할 수있는 노드 (터치했을 때 말한 노드가 아니라 터치 한 경우를 알고있는 노드)로 만들고 싶습니다.

기본적으로 각 AgentView의 CCSprite를 TouchableButton 객체로 대체하거나 보완하고 싶습니다.

내 게임의 UI 관련 버튼에이 방법을 사용하는 클래스 (TouchableButton이라고 부름)를 사용하고 있는데, 부모 레이어에 CCTouchesBegan 메소드를 구현하지 않고 터치 한 시점을 알고 있습니다. 하지만이 유스 케이스에 TouchableButton을 적용 할 수 없었던 이유는 다음과 같습니다.

TouchableButtons는 초기화 매개 변수로 CCSprite를 사용합니다. 이 CCSprite는 버튼의 손댈 수있는 부분으로 설정되며 버튼 자체의 자식으로 추가됩니다. 왜냐하면 나는 CCFLrite를 EnvironmentView에있는 CCSpriteBatchNode의 자식으로 추가하기 때문에 (두 개의 다른 부모 객체에 자식을 두 번 추가 할 수 없다) 오류가 발생한다. 이 갈등을 피하기 위해 어떻게 구조화 할 수 있습니까?

미리 도움을 청하십시오!

+0

+1 자세한 설명과 서식을 지정하십시오! – Kheldar

답변

0

나는 이것에 대해 많은 어려움을 겪었으며, 내 결론은 이것이 가능하지 않으며 각 버튼마다 별도의 이미지 파일을 사용해야한다는 것입니다.

이 기능이 1.0에 등장하기를 기대했지만 그럴 것이라고 생각하지 않습니다.

나는 틀렸어. :)

2

짧은 대답 : 할 수 없습니다.

긴 대답 : 동일한 효과를 얻을 수 있지만 같은 방식으로는 얻을 수 없습니다.

CCSpriteBatchNode는 일반적인 텍스처 (스프라이트 시트)를 사용하여 단일 glDrawElements 호출에서 모든 CCSprite 하위를 그려서 작동합니다. 이렇게하면 좋은 성능을 얻을 수 있습니다. 그러나 결과적으로 모든 자식은 반드시 스프라이트가되어야하며, 스프라이트에 자식을 추가하면 무시됩니다.

ButtonSprite.h :

// 
// ButtonSprite.h 
// TestButtonSprite 
// 
// Created by Karl Stenerud on 9/1/11. 
// 

#import "cocos2d.h" 

@class ButtonSprite; 

typedef void (^ButtonPressCallback)(ButtonSprite* button); 

/** 
* A sprite that can respond to touches. 
* Most of this code was taken from CCLayer. 
*/ 
@interface ButtonSprite : CCSprite <CCStandardTouchDelegate, CCTargetedTouchDelegate> 
{ 
    BOOL touchEnabled_; 
    int touchPriority_; 
    BOOL swallowTouches_; 
    BOOL registeredWithDispatcher_; 

    BOOL touchInProgress_; 
    BOOL buttonWasDown_; 

    ButtonPressCallback onButtonPressedCallback_; 
} 

/** Priority position in which this node will be handled (lower = sooner) */ 
@property(nonatomic,readwrite,assign) int touchPriority; 

/** If true, no other node will respond to touches this one responds to */ 
@property(nonatomic,readwrite,assign) BOOL swallowTouches; 

/** If true, this node responds to touches. */ 
@property(nonatomic,readwrite,assign) BOOL touchEnabled; 

/** Called whenever a full touch completes */ 
@property(nonatomic,readwrite,copy) ButtonPressCallback onButtonPressedCallback; 

/** Called when a button press is detected. */ 
- (void) onButtonPressed; 

/** Called when a button is pushed down. */ 
- (void) onButtonDown; 

/** Called when a button is released. */ 
- (void) onButtonUp; 

- (BOOL) touchHitsSelf:(UITouch*) touch; 

- (BOOL) touch:(UITouch*) touch hitsNode:(CCNode*) node; 

@end 

ButtonSprite.m :

그래서,이 시점에서 당신의 유일한 수단은과 같이, 버튼으로 CCSprite를 서브 클래스와 많은 기능을 복제하는 것입니다 그래서 같은
// 
// ButtonSprite.m 
// TestButtonSprite 
// 
// Created by Karl Stenerud on 9/1/11. 
// 

#import "ButtonSprite.h" 


@interface ButtonSprite() 

- (void) registerWithTouchDispatcher; 
- (void) unregisterWithTouchDispatcher; 

@end 

@implementation ButtonSprite 

@synthesize touchEnabled = touchEnabled_; 
@synthesize touchPriority = touchPriority_; 
@synthesize swallowTouches = swallowTouches_; 
@synthesize onButtonPressedCallback = onButtonPressedCallback_; 

- (id) init 
{ 
    if(nil != (self = [super init])) 
    { 
     touchPriority_ = 0; 
     swallowTouches_ = YES; 
     touchEnabled_ = YES; 

     self.isRelativeAnchorPoint = YES; 
     self.anchorPoint = ccp(0.5, 0.5); 
    } 
    return self; 
} 

- (void) dealloc 
{ 
    [self unregisterWithTouchDispatcher]; 
    [onButtonPressedCallback_ release]; 

    [super dealloc]; 
} 

- (void) registerWithTouchDispatcher 
{ 
    [self unregisterWithTouchDispatcher]; 

    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:self.touchPriority swallowsTouches:self.swallowTouches]; 
    registeredWithDispatcher_ = YES; 
} 

- (void) unregisterWithTouchDispatcher 
{ 
    if(registeredWithDispatcher_) 
    { 
     [[CCTouchDispatcher sharedDispatcher] removeDelegate:self]; 
     registeredWithDispatcher_ = NO; 
    } 
} 

- (void) setSwallowTouches:(BOOL) value 
{ 
    if(swallowTouches_ != value) 
    { 
     swallowTouches_ = value; 

     if(isRunning_ && touchEnabled_) 
     { 
      [self registerWithTouchDispatcher]; 
     } 
    } 
} 

- (void) setTouchPriority:(int) value 
{ 
    if(touchPriority_ != value) 
    { 
     touchPriority_ = value; 
     if(isRunning_ && touchEnabled_) 
     { 
      [self registerWithTouchDispatcher]; 
     } 
    } 
} 

-(void) setTouchEnabled:(BOOL)enabled 
{ 
    if(touchEnabled_ != enabled) 
    { 
     touchEnabled_ = enabled; 
     if(isRunning_) 
     { 
      if(touchEnabled_) 
      { 
       [self registerWithTouchDispatcher]; 
      } 
      else 
      { 
       [self unregisterWithTouchDispatcher]; 
      } 
     } 
    } 
} 

- (void)cleanup 
{ 
    self.touchEnabled = NO; 
} 

#pragma mark TouchableNode - Callbacks 
-(void) onEnter 
{ 
    // register 'parent' nodes first 
    // since events are propagated in reverse order 
    if (self.touchEnabled) 
    { 
     [self registerWithTouchDispatcher]; 
    } 

    // then iterate over all the children 
    [super onEnter]; 
} 

-(void) onExit 
{ 
    if(self.touchEnabled) 
    { 
     [self unregisterWithTouchDispatcher]; 
    } 

    [super onExit]; 
} 

-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    if([self touchHitsSelf:touch]) 
    { 
     touchInProgress_ = YES; 
     buttonWasDown_ = YES; 
     [self onButtonDown]; 
     return YES; 
    } 
    return NO; 
} 

-(void) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    if(touchInProgress_) 
    { 
     if([self touchHitsSelf:touch]) 
     { 
      if(!buttonWasDown_) 
      { 
       [self onButtonDown]; 
      } 
     } 
     else 
     { 
      if(buttonWasDown_) 
      { 
       [self onButtonUp]; 
      } 
     } 
    } 
} 

-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    if(buttonWasDown_) 
    { 
     [self onButtonUp]; 
    } 
    if(touchInProgress_ && [self touchHitsSelf:touch]) 
    { 
     touchInProgress_ = NO; 
     [self onButtonPressed]; 
    } 
} 

-(void) ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    if(buttonWasDown_) 
    { 
     [self onButtonUp]; 
    } 
    touchInProgress_ = NO; 
} 

- (void) onButtonDown 
{ 
    buttonWasDown_ = YES; 
} 

- (void) onButtonUp 
{ 
    buttonWasDown_ = NO; 
} 

- (void) onButtonPressed 
{ 
    self.onButtonPressedCallback(self); 
} 


- (BOOL) touchHitsSelf:(UITouch*) touch 
{ 
    return [self touch:touch hitsNode:self]; 
} 

- (BOOL) touch:(UITouch*) touch hitsNode:(CCNode*) node 
{ 
    CGRect r = CGRectMake(0, 0, node.contentSize.width, node.contentSize.height); 
    CGPoint local = [node convertTouchToNodeSpace:touch]; 

    return CGRectContainsPoint(r, local); 
} 

@end 

사용을 :

ButtonSprite* myButton = [ButtonSprite spriteWithFile:@"button_image.png"]; 
    myButton.onButtonPressedCallback = ^(ButtonSprite* button) 
    { 
     NSLog(@"Pressed!"); 
    }; 
    [self addChild: myButton]; 

배치 노드에서이 클래스를 사용하는 경우 자체 클래스의 자식을 가질 수 없습니다.

관련 문제