2013-06-28 3 views
0

나는 잠시 조용하게이 문제를 진단하려고 진짜 두통을 느낀다.다른 레이어에서 게임/장면 다시 시작

세부 사항 :
I 다음 노드가 있습니다

  1. GameLayer를; 메인 게임 층, 또한 세미 싱글 톤.
  2. HUDLayer; 물론 GameLayer와 함께 장면에 추가 된 간단한 HUD 레이어 (점수 및 일시 중지 버튼 용).
  3. PauseLayer; 간단한 메뉴 (resume, restart, main menu)를 가지고있는 CCLayerColor 서브 클래스.

일시 중지 버튼을 누를 때마다 PauseLayer가 자식으로 GameLayer에 추가됩니다.


문제 : GameLayer 자체 내에서 [자기 restartGame] : 게임/장면을 다시 시작
에 의해 잘 작동합니다. 그러나 다음과 같이 PauseLayer에서 같은 메서드를 호출합니다. [[GameLayer sharedGameLayer] restartGame]은 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; 
} 



EDIT : GameLayer의 init 메소드에서 Pause 레이어 (GameLayer의 자식으로, 항상 표시됨)를 추가하면 모든 것이 완벽하게 작동합니다 .. 조금 이상합니다.

모든 입력 사항을 높이 평가합니다. 미리 감사드립니다. 당신은 그것을 클래스 멤버 변수 있지 않은지 확인하기 위해 @implementation 클래스 줄 앞에 줄을 쓰기 위해 필요한 라인

static GameLayer *sharedGameLayer; 

에서

답변

0

당신을 저장합니다 방법.

내가 한 일은 주로 "일시 중지"기능을 구현하는 것입니다. [self pauseSchedulerAndActions]; 또한 내 경우에는 [[self.spidersBatchNode children] makeObjectsPerformSelector : @selector (pauseSchedulerAndActions)];은 spriteBatchNode 내부의 모든 자식에 적용됩니다.

또 다른 질문이 생길 수있는 또 다른 문제가 발생했습니다.

모든 답장을 보내 주셔서 감사합니다.

+0

새 질문의 URL은 다음과 같습니다. [link] (http://stackoverflow.com/questions/17395827/properly-restarting-re-initializing-a-semi-singleton) – MHany

0

. 및 sharedGameLayer 방법에 당신은

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

    return sharedGameLayer; 
} 

로 변경해야합니다, 당신은 당신이 init 메소드를 호출하지 않는 게임 층 클래스를 정의 할 때하지만 당신은 게임 층 클래스는 싱글이 될 수 있도록 sharedGameLayer를 호출해야합니다.

+0

_static GameLayer * sharedGameLayer; _는 이미 @Implementation 지시어를 벗어났습니다. 코드에서이를 수정했습니다. 제안한대로 _ + (GameLayer *) sharedGameLayer_ 메서드도 수정했지만 불행히도 동작은 동일합니다. – MHany

+0

EDIT : GameLayer의 init 메소드에서 Pause 레이어를 추가하면 (게임 레이어에 자식으로, 항상 표시됨) 모든 것이 완벽하게 작동합니다 .. 조금 이상합니다. – MHany

0

CCLayers에 싱글 톤 패턴을 사용할 것을 제안하지 않았지만 CCLene 래퍼를 덮어 쓰거나 편집하여 init을 호출하지 않았습니까?

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

예를

를 들어

은 그럼 당신은

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

[[GameLayer sharedInstance] restart]; 

후 게임을 다시 시작하는 것을 잊지 호출 할 때 또는 장면 래퍼 방법으로 그렇게 할 수 있습니다.

희망이 있습니다. CCDirector의 일시 정지를 사용하여 게임을 일시 정지 한 후 방법 :

이어야이 문제의 원인은 CCDirector의 ReplaceScene를 호출했다 .. 게임 층을 위해 모든 시간 도니는 다르게이 공간을 재 할당에서

+0

_ [scene addChild : [GameLayer sharedGameLayer]]; _ 어설 션 오류가 발생합니다. 또한 _restart_ 메서드는 장면을 실제로 대체하는 메서드입니다.
어쨌든 문제가 발생하면 문제가 거의 해결되었으므로 먼저 질문을 수정하겠습니다. – MHany