しばらくの間、この問題を静かに診断しようとして、本当に頭が痛いです。
詳細:
次のノードがあります。
- ゲームレイヤー; ゲームのメインレイヤーであり、セミシングルトンでもあります。
- HUDLayer; シンプルな HUD レイヤー (スコアと一時停止ボタン用) はもちろん、GameLayer と共にシーンに追加されます。
- PauseLayer; シンプルなメニュー (再開、再起動、およびメイン メニュー) を保持する CCLayerColor サブクラス。
一時停止ボタンが押されるたびに、PauseLayer が子として GameLayer に追加されます。
問題: GameLayer 自体から[self restartGame]
を実行
すると、ゲーム/シーンの再起動が正常に機能します。ただし、 [[GameLayer sharedGameLayer] restartGame]を使用して PauseLayer から同じメソッドを呼び出しても、GameLayer シーンが新しいインスタンスに完全に置き換えられるわけではありません。GameLayer の dealloc が呼び出されていますが (トランジションが使用されていない場合のみ)、古いシーンにはまだ子がなく、同じ古いスコアなどがあります。
コード:
ゲームレイヤー
static GameLayer *sharedGameLayer;
@implementation GameLayer
- (id)init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super's" return value
if(self = [super initWithColor:ccc4(255, 255, 255, 255) width:[CCDirector sharedDirector].winSize.width height:[CCDirector sharedDirector].winSize.height])
{
NSLog(@"%s", __PRETTY_FUNCTION__);
sharedGameLayer = self;
.
.
}
+ (GameLayer *)sharedGameLayer {
@synchronized(self) {
if (sharedGameLayer == nil) {
sharedGameLayer = [[self alloc] init];
}
}
return sharedGameLayer;
}
- (void)pauseGame
{
NSLog(@"%s", __PRETTY_FUNCTION__);
if (![[CCDirector sharedDirector] isPaused])
{
// Disable the top menu.
self.hud.topMenu.enabled = NO;
// Pause game.
[[CCDirector sharedDirector] pause];
// Pause the background music.
[[SimpleAudioEngine sharedEngine] pauseBackgroundMusic];
// Disable touch detection.
[[CCDirector sharedDirector].touchDispatcher removeDelegate:self];
// Add the Pause Layer.
PauseLayer *pauseLayer = [[PauseLayer alloc] init];
pauseLayer.tag = 2;
pauseLayer.zOrder = 10;
[self addChild:pauseLayer z:10 tag:2];
}
}
- (void)restartGame
{
NSLog(@"%s", __PRETTY_FUNCTION__);
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[CCDirector sharedDirector].touchDispatcher removeAllDelegates];
[self stopAllActions];
[self unscheduleAllSelectors];
[self unscheduleUpdate];
[self removeAllChildrenWithCleanup:YES];
[[CCDirector sharedDirector] replaceScene:[GameLayer scene]];
//[[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1.0 scene:[GameLayer scene]]];
}
- (void)dealloc
{
NSLog(@"%s", __PRETTY_FUNCTION__);
sharedGameLayer = nil;
}
@end
一時停止レイヤー
- (id)init
{
if (self = [super initWithColor:ccc4(0, 0, 0, 128) width:[CCDirector sharedDirector].winSize.width height:[CCDirector sharedDirector].winSize.height])
{
// Create a menu.
// Resume button.
CCLabelTTF *resumeLabel = [CCLabelTTF labelWithString:@"Resume" fontName:@"Marker Felt" fontSize:32];
resumeLabel.color = ccc3(240, 240, 240);
CCMenuItemLabel *resumeButton = [CCMenuItemLabel itemWithLabel:resumeLabel block:^(id sender) {
[[GameLayer sharedGameLayer] resumeGame];
}];
// Restart Game button.
CCLabelTTF *restartLabel = [CCLabelTTF labelWithString:@"Restart" fontName:@"Marker Felt" fontSize:32];
restartLabel.color = ccc3(240, 240, 240);
CCMenuItemLabel *restartButton = [CCMenuItemLabel itemWithLabel:restartLabel block:^(id sender) {
[[GameLayer sharedGameLayer] restartGame];
}];
// Main Menu button.
CCLabelTTF *mainMenuLabel = [CCLabelTTF labelWithString:@"Main Menu" fontName:@"Marker Felt" fontSize:32];
mainMenuLabel.color = ccc3(240, 240, 240);
CCMenuItemLabel *mainMenuButton = [CCMenuItemLabel itemWithLabel:mainMenuLabel block:^(id sender) {
[[GameLayer sharedGameLayer] gotoMainMenu];
}];
CCMenu *menu = [CCMenu menuWithItems:resumeButton, restartButton, mainMenuButton, nil];
[menu alignItemsVerticallyWithPadding:10.0];
menu.position = ccp([CCDirector sharedDirector].winSize.width / 2, [CCDirector sharedDirector].winSize.height / 2);
[self addChild:menu];
}
return self;
}
編集: GameLayer の init メソッドで (GameLayer の子として、常に表示される) 一時停止レイヤーを追加すると、すべてが完全に機能します..これは少し奇妙です。
どんな入力でも大歓迎です。前もって感謝します!