我正在使用半单身方法进行我的cocos2d游戏的主要游戏层/场景,如后面的代码所示。
目标是通过调用: [[GameLayer sharedGameLayer] restart] 方法,使用暂停或游戏结构层中的按钮正确重启/重新创建此单例场景。< / p>
问题是指我使用CCTransition效果,并使用 sharedGameLayer = nil; 行覆盖GameLayer的 dealloc 方法(至确保重置静态变量),sharedGameLayer变量在第一次重启后保持为nil(也就是在第一次dealloc之后),因此调用 restart 方法什么都不做。
怀疑有用的根本不会覆盖 dealloc 方法,但在使用 replaceScene:重新启动场景之前,我设置了sharedGameLayer为nil。
问题:这是重启/重新创建这个半单身类的正确方法吗?
提前致谢。
代码:
GameLayer.m:
static GameLayer *sharedGameLayer;
@implementation GameLayer
- (id)init
{
NSLog(@"%s", __PRETTY_FUNCTION__);
// 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])
{
// Set the sharedGameLayer instance to self.
sharedGameLayer = self;
// Set the initial game state.
self.gameState = kGameStateRunning;
// Register with the notification center in order to pause the game when game resigns the active state.
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(pauseGame) name:UIApplicationWillResignActiveNotification object:nil];
// Enable touches and multi-touch.
CCDirector *director = [CCDirector sharedDirector];
[director.touchDispatcher addTargetedDelegate:self priority:0 swallowsTouches:YES];
director.view.multipleTouchEnabled = YES;
// Set the initial score.
self.score = 5;
// Create the spiders batch node.
[self createSpidersBatchNode];
// Load the game assets.
[self loadAssets];
// Play Background music.
if (![SimpleAudioEngine sharedEngine].isBackgroundMusicPlaying)
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"backgroundmusic.mp3" loop:YES];
// Preload sound effects.
[[SimpleAudioEngine sharedEngine] preloadEffect:@"inbucket.mp3"];
[[SimpleAudioEngine sharedEngine] preloadEffect:@"outbucket.mp3"];
[[SimpleAudioEngine sharedEngine] preloadEffect:@"gameover.mp3"];
// Schdule updates.
[self scheduleUpdate];
[self schedule:@selector(releaseSpiders) interval:0.7];
}
return self;
}
- (void)createSpidersBatchNode
{
NSLog(@"%s", __PRETTY_FUNCTION__);
// BatchNode. (For Animation Optimization)
self.spidersBatchNode = [CCSpriteBatchNode batchNodeWithFile:@"spiderAtlas.png"];
// Spider sprite + BatchNode + animation action.
for (int i = 0; i < 50; i++) {
Spider *spider = [[Spider alloc] init];
spider.spiderSprite.visible = NO;
}
[self addChild:self.spidersBatchNode];
}
- (void)restartGame
{
// Play button pressed sound effect.
[[SimpleAudioEngine sharedEngine] playEffect:@"button.mp3"];
// Nil'ing the static variable.
sharedGameLayer = nil;
// Restart game.
[[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1.0 scene:[GameLayer scene]]];
}
+ (CCScene *)scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// Game Layer.
// 'gameLayer' is an autorelease object.
GameLayer *gameLayer = [GameLayer node];
// add gameLayer as a child to scene
[scene addChild: gameLayer];
// HUD Layer.
HUDLayer *hudLayer = [HUDLayer node];
[scene addChild:hudLayer];
gameLayer.hud = hudLayer;
// return the scene
return scene;
}
+ (GameLayer *)sharedGameLayer
{
return sharedGameLayer;
}
- (void)cleanup
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[CCDirector sharedDirector].touchDispatcher removeDelegate:self];
[self stopAllActions];
[self unscheduleAllSelectors];
[self unscheduleUpdate];
[self removeAllChildrenWithCleanup:YES];
self.hud = nil;
[super cleanup];
}
//- (void)dealloc
//{
// sharedGameLayer = nil;
//}
@end
答案 0 :(得分:0)
我敢打赌你的新游戏层是在第一个游戏层解除分配之前创建的,因此它将静态var设置为nil。在dealloc中检查sharedGameLayer是否等于self。
答案 1 :(得分:0)
不要使用dealloc将静态变量设置为nil。 对象停止使用后,Dealloc发生。切勿使用它来控制应用的行为。
众所周知,将sharedGameLayer
设置为nil
和调用dealloc
方法之间可能已经过了30分钟。或者dealloc
永远不会被调用。
您的代码看起来不错,只需删除注释掉的“dealloc”代码。
此外,此代码:
[[NSNotificationCenter defaultCenter] removeObserver:self];
除了您的自定义-dealloc
方法之外,还应该使用-cleanup
方法。移除一个观察者两次是完全没问题的,如果它已被移除,则不会发生任何事情。
另一个注意事项,+sharedGameLayer
应该返回instancetype
类型的变量,它应该负责设置sharedGameLayer
变量。如果您在sharedGameLayer
内-init
,则会遇到错误。
例如:
+ (instancetype)sharedGameLayer
{
if (sharedGameLayer)
return sharedGameLayer;
sharedGameLayer = [[[self class] alloc] init];
return sharedGameLayer;
}
- (id)init
{
if (!(self = [super init]))
return nil;
.
.
.
return self;
}