私の cocos2d ゲームでは、すべてのゲーム レイヤーに表示される共通のヘッダーとフッターを共有する必要があります。
ヘッダーにはキャッシュやスプライトなどが含まれますが、フッターにはさまざまなゲーム シーン間を移動するための CCMenuItem ボタンが含まれます。
ヘッダー/フッターは、表示されているすべてのものの上に表示されるように、現在のシーン/レイヤーよりもわずかに高い Z インデックスに表示されます。
たとえば、ヘッダーは次のようになります。
現金: $5,000
フッターは、たとえば、次のように、スプライト ボタンを備えた CCMenu のように見えます。
ホーム | 市場
これは hud システムと見なされます。
今、私はこれに似た方法ですべてのシーンに HUD を追加しようとしました。
HudLayer *hud = [HudLayer node]
[self addChild:hud z:1];
ただし、アサーション エラーが発生します。
* -[CCMenuItemSprite addChild:z:tag:] でのアサーションの失敗 ...
これは、別のシーンで HUD を再度追加できないために発生します。これは、私が cocos2d に対して持っている本当のフラストレーションです。
私が今までこの問題を解決できた唯一の方法は、CCLayer として a を持つ aBaseScene
を持ち、HUD
NSNotifications を使用して後続のすべての CCLayer をロードすることです。
コードは次のとおりです。
#define HudBase 1
#define kHUDTag 9000
#import "cocos2d.h"
@interface BaseScene : CCScene
@end
@class HeaderHUDLayer;
@interface BaseLayer : CCLayer
{
CCNode *currentNode;
CCLayer *thisLayer;
HeaderHUDLayer *hud;
}
@property (nonatomic, retain) CCNode *currentNode;
@property (nonatomic, retain) CCLayer *thisLayer;
@property (nonatomic, retain) HeaderHUDLayer *hud;
-(void) changeNodeTo:(CCNode *)thisNode;
-(void) changeHUDSceneObserver:(NSNotification *)notification;
@end
@implementation BaseScene
- (id)init
{
self = [super init];
if (self) {
[self addChild:[BaseLayer node] z:0 tag:800];
}
return self;
}
@end
@implementation BaseLayer
@synthesize currentNode, thisLayer;
@synthesize hud;
-(id) init
{
if ((self =[super init]))
{
NSLog(@"HUD Scene");
self.hud = [HeaderHUDLayer node];
if (self.currentNode == nil)
{
self.currentNode = [MyDashboardScene node];
[self changeNodeTo:self.currentNode];
}
[self addChild:self.hud z:TopZLayer];
[[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(changeHUDSceneObserver:) name: @"changeHUDScene" object: nil];
} // end if
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
-(void) changeNodeTo:(CCNode *)thisNode
{
NSLog(@"changeNodeTo");
[self removeChild:self.currentNode cleanup:YES];
[self addChild:thisNode z:0];
self.currentNode = thisNode;
}
-(void) changeHUDSceneObserver:(NSNotification *)notification
{
NSLog(@"changeHUDSceneObserver = %@", notification.name);
if ([notification.name isEqualToString:@"changeHUDScene"]==YES) {
if ([notification object]!=nil) {
[self changeNodeTo:[notification object]];
}
}
}
@end
ヘッダー自体は非常に複雑ですが、簡単に言えば、次のような CCLabel があります。
NSString *txtCash = [NSString stringWithFormat:@"Cash: %d", [player.cash intValue]];
self.lblCash = [CCLabelBMFont labelWithString:txtCash fntFile:@"font_minipixi_16.fnt"];
[lblCash setTag:kCashLabelTag];
[lblCash setAnchorPoint:CGPointMake(1, 0)];
[lblCash setPosition:CGPointMake(100, 8)];
[self addChild:lblCash];
これはうまく機能し、ゲームのすべての異なる部分間を移動でき、ヘッダー/フッターはすべてのシーンで共通です。
ただし、NSNotifications を使用してノードを変更すると、本当に頭痛の種になります。つまり、HUD 内のラベル (lblCash) を変更できないようで、これを解決する方法がわかりません。
たとえば、現金を減らす CCMenuItem をクリックすると、HUD ラベルは更新されません。
この問題を回避するために、別の NSNotification を使用してこれを解決します。複数の NSNotifications (ヘッダーの変更、ページの更新など) が必要な場合を除き、再送信できないため、アサーション エラーが発生します。
ヘッダーを更新するための NSNotification がある場合があり、その直後に別の NSNotification があり、ノードを提示したい別のノードにリダイレクトします。これもアサーション エラーを引き起こします。
全体があちこちで NSNotifications の混乱に陥っているように感じ、cosos2d に非常に不満を感じています。
私が試してみました:
ベース シーンで HUD (およびそのすべての子) を削除し、再度追加します。これによりアサーション エラーが発生し、実行できないようです。私はおそらくそれを間違ってコーディングしています
タグを使用して BaseScene/Layer をキャストし、HUD を取得して、そのようにラベルを更新しようとしています。
つまり、
BaseLayer *baseLayer = (BaseLayer *) [self.parent getChildByTag:800];
[baseLayer.hud updateCashAmount];
何もしません。(基本レイヤー/シーンと hud レイヤーにはすべてタグがあります)。
どちらも、
HeaderHUDLayer *hud = (HeaderHUDLayer *)[base getChildByTag:kHUDTag];
[hud updateCashAmount];
キャストできない理由は、NSNotifications がコンテキストを変更したためだと思います。
このすべてが私をcosos2dに非常に苛立たせました。
私が欲しいのは、多くのシーンで共通のヘッダー/フッターだけです。大騒ぎせずにヘッダーのラベルを更新できるようにしたいのです。
この場合、共通のヘッダー/フッター CCLayer を共有し、ヘッダー/フッター内の要素を更新可能にするにはどうすればよいでしょうか?
大量の NSNotifications をあちこちに配置せずにこれを行う簡単な方法はありますか?
感謝を込めて。