0

しばらくの間、この問題を静かに診断しようとして、本当に頭が痛いです。

詳細:
次のノードがあります。

  1. ゲームレイヤー; ゲームのメインレイヤーであり、セミシングルトンでもあります。
  2. HUDLayer; シンプルな HUD レイヤー (スコアと一時停止ボタン用) はもちろん、GameLayer と共にシーンに追加されます。
  3. 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 の子として、常に表示される) 一時停止レイヤーを追加すると、すべてが完全に機能します..これは少し奇妙です。

どんな入力でも大歓迎です。前もって感謝します!

4

3 に答える 3

0

ラインから

static GameLayer *sharedGameLayer;

@implementation class 行の前にこの行を記述して、クラス メンバー変数にならないようにする必要がありました。そして sharedGameLayer メソッドで、それを次のように変更する必要があります

+ (GameLayer *)sharedGameLayer {
    @synchronized(self) {
        if (sharedGameLayer == nil) {
            sharedGameLayer = [[self alloc] init];
        }
    }

    return sharedGameLayer;
}

また、ゲーム レイヤ クラスを定義するときに init メソッドを呼び出すのではなく、sharedGameLayer を呼び出してゲーム レイヤ クラスをシングルトンにする必要があります。

于 2013-06-28T02:54:27.617 に答える
0

この問題の原因は、CCDirector のPauseメソッドを使用してゲームを一時停止した後で、CCDirector のReplaceScene:メソッドを呼び出すことでした。私がしたことは、主に[self pauseSchedulerAndActions];を使用して独自の「一時停止」機能を実装することでした。また、私の場合: [[self.spidersBatchNode children] makeObjectsPerformSelector:@selector(pauseSchedulerAndActions)]; spriteBatchNode 内のすべての子に対して。別の問題が発生したので、別の質問をします。すべての返信に感謝します。





于 2013-06-30T22:52:46.177 に答える