在我的 cocos2d 游戏中,我需要共享一个通用的页眉和页脚,它将出现在每个游戏层上。
页眉包含现金和精灵之类的东西——而页脚包含用于在不同游戏场景之间移动的 CCMenuItem 按钮。
页眉/页脚出现在比当前场景/图层略高的 Z-index 上,因此它出现在显示的所有内容之上。
例如,标头可能如下所示:
现金:5,000 美元
例如,页脚可能看起来像带有精灵按钮的 CCMenu,如下所示:
主页 | 市场
这将被视为一个平显系统。
现在,我尝试以类似的方式将 HUD 添加到每个场景中;
HudLayer *hud = [HudLayer node]
[self addChild:hud z:1];
但是,它会导致断言错误。
* -[CCMenuItemSprite addChild:z:tag:] 中的断言失败 ...
这是因为在不同的场景中无法再次添加 HUD。这是我对 cocos2d 的真正挫败感。
到目前为止,我能够解决这个问题的唯一方法是BaseScene
拥有一个HUD
作为 CCLayer 的,然后我使用 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 并以这种方式更新标签。
IE,
BaseLayer *baseLayer = (BaseLayer *) [self.parent getChildByTag:800];
[baseLayer.hud updateCashAmount];
什么都不做。(基础层/场景和 hud 层都有一个标签)。
也不行,
HeaderHUDLayer *hud = (HeaderHUDLayer *)[base getChildByTag:kHUDTag];
[hud updateCashAmount];
我认为我不能进行强制转换的原因是因为 NSNotifications 改变了上下文。
这整件事让我对 cosos2d 感到非常沮丧。
我想要的只是很多场景中的通用页眉/页脚,我希望能够更新页眉的标签而不会大惊小怪。
鉴于此,我如何共享一个通用的页眉/页脚 CCLayer 并使页眉/页脚内的元素可更新?
有没有更简单的方法可以做到这一点,而无需到处都有大量的 NSNotifications?
感谢。