从另一层重新启动游戏/场景

时间:2013-06-28 01:26:08

标签: ios xcode cocos2d-iphone

我现在正试图将这个问题暂时解决这个问题让我很头疼。

详细信息:
我有以下节点:

  1. GameLayer;主游戏层,也是半单身。
  2. HUDLayer;一个简单的HUD图层(用于得分和暂停按钮),当然与GameLayer一起添加到场景中。
  3. PauseLayer;一个CCLayerColor子类,它包含一个简单的菜单(恢复,重启和主菜单)。
  4. 只要按下暂停按钮,PauseLayer就会作为孩子添加到GameLayer中。


    问题:
    通过以下方式重新启动游戏/场景: [self restartGame] 来自GameLayer本身。 但是使用: [[GameLayer sharedGameLayer] restartGame] 从PauseLayer调用相同的方法并不能完全用新实例替换GameLayer场景;尽管GameLayer的dealloc被调用(仅当没有使用过渡时),旧场景仍然没有孩子,同样的旧分数等。

    代码:

    GameLayer

    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
    

    PauseLayer

    - (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方法中添加Pause图层(作为GameLayer的子图层,并且始终可见),一切都很完美..这有点奇怪。

    任何输入都非常感谢。 提前谢谢!

3 个答案:

答案 0 :(得分:0)

来自

static GameLayer *sharedGameLayer;

您需要在@implementation类行之前编写此行,以使其不是类成员变量。在sharedGameLayer方法中,您应该将其更改为

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

    return sharedGameLayer;
}

而且,当你定义游戏图层类时,你不会调用init方法,但你应该调用sharedGameLayer来使游戏图层类成为单例。

答案 1 :(得分:0)

我不建议在CCLayers上使用单例模式,但是你是否覆盖/编辑CCScene包装器,因此它不会调用init。

例如

+(id)scene
{
    CCScene* scene = [CCScene node];
    [scene addChild:[GameLayer sharedGameLayer]];
    return scene;
}

然后当你打电话

[[CCDirector sharedDirector] replaceScene:[GameLayer scene]];

请记得在

后立即重启游戏
[[GameLayer sharedInstance] restart];

或者你可以在场景包装方法中做到这一点。

希望我明白你的意思。

Atleast这将使你无法一直为游戏层重新分配空间......

答案 2 :(得分:0)

问题的罪魁祸首是在使用CCDirector的 Pause 方法暂停游戏后调用CCDirector的 ReplaceScene:方法。

我做了什么正在实现我自己的“暂停”功能主要使用: [self pauseSchedulerAndActions]; 以及我的情况: [[self.spidersBatchNode children] makeObjectsPerformSelector:@selector(pauseSchedulerAndActions)]; for spriteBatchNode里面的所有孩子。

出现了另一个问题,我将提出另一个问题。

感谢所有回复。