2011-09-01 7 views
4

これは少し説明するかもしれませんが、ここではすべての洞察を本当に感謝します。CCBritNodeのCCSpriteが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は、initパラメータとしてCCSpriteを使用します。このCCSpriteは、ボタンのタッチ可能な部分に設定され、ボタン自体の子として追加されます。私はCCFLriteをEnvironmentViewのCCSpriteBatchNodeの子として追加しているので、エラーが発生します(2つの異なる親オブジェクトに子として何かを追加することはできません)。この葛藤を避けるために、私は物事を構造化することができます

ありがとうございました!

+0

+1詳細な説明と書式設定が必要です。 – Kheldar

答えて

0

私は、これで自分自身をたくさん苦闘しました、そして、私の結論は、これは不可能であり、あなたはボタンごとに別々の画像ファイルを使用する必要があることです。

私はこの機能が1.0に表示されます期待していたが、私はそれがなかったとは思いません。

しかし、私が間違っている期待して! :)

2

短い答え:あなたがすることはできません。

長い答え:あなたはなく、同じように、同じ効果を得ることができます。

CCSpriteBatchNodeは、その共通のテクスチャ(スプライトシート)を持つ単一のglDrawElements呼び出しですべてのCCSprite子を描画することによって動作します。しかし結果として、すべての子はスプライトでなければならず、子をスプライトに追加すると無視されます。

ので、この時点で、あなたの唯一の頼みの綱は、ボタンとして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:

ButtonSprite* myButton = [ButtonSprite spriteWithFile:@"button_image.png"]; 
    myButton.onButtonPressedCallback = ^(ButtonSprite* button) 
    { 
     NSLog(@"Pressed!"); 
    }; 
    [self addChild: myButton]; 
// 
// 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 

はそうのようにそれを使用します

このクラスをバッチ・ノードで使用する場合は、それ自身の子を持つことはできません(MUST NOT)。

関連する問題