问题
EDIT: I am using ARC
In my code (based on the ShootEmUp example in this book, which I highly reccomend, source code in chapter 8 available here) I often use the trick of accessing the GameScene via:
+(GameScene*) sharedGameScene;
which returns a reference to the static instance of GameScene and is used by all children of GameScene (e.g. ShipEntity, InputLayer.. etc..) to dialog with GameScene (EDIT: aka singleton instance of GameScene).
To create multiple levels I thought of implementing a method calledsceneWithId:(int) method where I load different level data each time.
EDIT: Code snippet of init method:
-(id) initWithId:(int)sceneId
{
CCLOG(@"scene With id");
if ((self = [super init]))
{
//All common initialization happens here..
switch (sceneId) {
case 1:
[self loadFirstLevelData];
break;
case 2:
[self loadSecondLevelData];
break;
default:
[self loadSecondLevelData];
break;
}
//Other common stuff..
[self setUpCounters];
[self setUpWeaponsMenu];
[self scheduleUpdate];
[self schedule:@selector(timerUpdate:) interval:1];
InputLayerButtons* inputLayer = [InputLayerButtons node];
[self addChild:inputLayer z:1 tag:GameSceneLayerTagInput];
}
EDIT: Is that init method ok? I have found this post which uses dispatch_once. Should I do the same?
Or should I pheraps create a GameScene class and then sublcass it?
E.g. FirstGameScene : GameScene
EDIT: I have followed the advice of @LearnCocos2D and used the cleanup method, and I used it to stop a singleton object music layer to play (the MusicLayer object is initialized in AppDelegate and I meant to use it to "manage" the music across all scenes - the problem was that without stopping it in dealloc it would have kept playing the music that was loaded at init time).
-(void) loadFirstLevelData{
//HERE WILL LOAD ALL SPECIFIC ELEMENTS: ENEMIES, BONUSES etc..
//AS WELL AS THE MUSIC FOR THE LEVEL
[[MusicLayer sharedMusicLayer] _loadMusic:@"1.mp3"];
[[MusicLayer sharedMusicLayer] playBackgroundMusicFile: @"1.mp3"];
}
-(void) cleanup
{
//Should I remove all child loaded in LoadLevelData??
CCLOG(@"cleanup GameScene");
[[MusicLayer sharedMusicLayer] stopAllMusic];
//MusicLayer is not a child of GameScene but of AppDelegate - the idea is to keep loading and unloading music files - sometimes I need to keep playing the file between scenes and hence I used the singleton pattern for this as well..
[super cleanup];
}
But I still have some doubts:
Is it ok to have several loadLevelData methods in GameScene class? Each method can be 200 lines long! I tried to sublcass GameScene but is a bit messy. I explain better. I imported "GameScene.h" in the header file of the subclass and by doing so I expected that if I had ovverriden only certain methods (e.g. init) I would have been able to see the various classes imported in GameScene (e.g. InputLayerButtons). It is not the case. So I probably don't understand how imports work in Objective-C
Is it ok to remove specifc children in the cleanup method? I thought that I would remove all child that are added in the LoadLevelXXXData method to reduce the memory usage.
I have set a bounty for this question but I will probably need to test the answer and re-edit as I don't have a clear enough understanding of the subject to be super precise in the question. Hope is ok.
PS: Would be great if someone would feel like sharing a UML style diagram of a Cocos2D Shooter Game where with various levels and GameScene using singleton pattern :).
回答1:
I'll focus on the questions on the bottom:
- Is it ok to have several loadLevelData methods in GameScene class? Each method can be 200 lines long! I tried to sublcass GameScene but is a bit messy. I explain better. I imported "GameScene.h" in the header file of the subclass and by doing so I expected that if I had ovverriden only certain methods (e.g. init) I would have been able to see the various classes imported in GameScene (e.g. InputLayerButtons). It is not the case. So I probably don't understand how imports work in Objective-C
There's nothing wrong with having long methods. However I suspect your loading methods perform very similar routines, so you should check if you can generalize these into subroutines. A good indicator is if several lines of code are absolutely identical except for the parameters or variable names. The best practice is to write identical code only once, and execute it many times with varying parameters.
The #import
statement is used to allow the compiler to "see" other classes. Without importing other header files, you couldn't use that class' methods and properties without the compiler complaining.
2 . Is it ok to remove specifc children in the cleanup method? I thought that I would remove all child that are added in the LoadLevelXXXData method to reduce the memory usage.
It makes no sense to remove children during cleanup. Cocos2D removes all children during cleanup automatically.
If that does not seem to be the case for you, you have a retain cycle somewhere that prevents child nodes from deallocating.
回答2:
sorry for answering this but I have been experimenting and decided to:
- not use the singleton pattern for GameScene
- use, insteada a singleton object to keep all shared data
My implementation draft for the GameScene (now called ShooterScene) is the following (I followed some advices in a cocos2d-iphone forum post as well as this other one ):
#import "ShooterScene.h"
#import "LevelData.h"
#import "HudLayer.h"
@interface ShooterScene (PrivateMethods)
-(void) loadGameArtFile;
@end
@implementation ShooterScene
+ (id) sceneWithId:(int)sceneId
{
CCScene *scene = [CCScene node];
ShooterScene * shooterLayer = [ShooterScene node];
[scene addChild:shooterLayer];
[shooterLayer loadGameArtFile];
LevelData * levelData = [LevelData node];
[shooterLayer addChild:levelData];
switch (sceneId) {
case 1:
[levelData loadLevelDataOne];
break;
case 2:
[levelData loadLevelDataOne];
break;
default:
break;
}
HudLayer * hud = [HudLayer node];
[hud setUpPauseMenu];
[shooterLayer addChild:hud];
return scene;
}
I am using the update method of ShooterScene to manage the all the game events (E.g. spawning, checking collisions, moving the background layer). I haven't put the full implementation here as is still work in progress, but is just to have an idea of the type of answer I am finding useful.
来源:https://stackoverflow.com/questions/12396352/cocos2d-with-arc-what-is-the-best-implementation-of-singleton-pattern-for-games