Cocos2d with ARC: what is the best implementation of singleton pattern for GameScene when having multiple levels?
编辑:我正在使用ARC
在我的代码中(基于本书中的ShootemUp示例,我高度推荐,这里提供第8章中的源代码),我经常使用通过以下方式访问游戏场景的技巧:
+(游戏场景*)sharedgamesecene;
它返回对gamesecene静态实例的引用,并由gamesecene的所有子代(例如shipEntity、inputlier..等)与游戏场景对话(编辑:即游戏场景的单例实例)。
为了创建多个级别,我考虑实现一个名为dscenewithid:(int)方法的方法,每次加载不同级别的数据。
编辑:init方法的代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | -(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]; } |
编辑:初始化方法可以吗?我找到了这篇文章,它使用了一次分派。我也应该这样做吗?
或者我应该先创建一个游戏场景类,然后再将其子类化?
1 | E.g. FirstGameScene : GameScene |
编辑:我按照@learncocos2d的建议使用了清理方法,并使用它来停止要播放的单件对象音乐层(Musiclayer对象在AppDelegate中初始化,我打算使用它来"管理"所有场景中的音乐-问题是,如果不在DealLoc中停止它,它将继续播放t是在初始化时加载的)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | -(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]; } |
但我仍然有一些疑问:
游戏场景类中有几个loadLevelData方法可以吗?每个方法可以有200行长!我试图放弃游戏场景,但有点混乱。我解释得更好。我在子类的头文件中导入了"gamesecene.h",通过这样做,我期望如果我只有ovverriden,那么只有某些方法(例如init),我就能够看到在gamesecene中导入的各种类(例如inputlayerbuttons)。事实并非如此。所以我可能不明白进口是如何在目标C中起作用的。
是否可以在清理方法中删除特定的子项?我想我会删除loadlevelxxxdata方法中添加的所有子级,以减少内存使用。
我已经为这个问题设置了一个赏金,但我可能需要测试答案并重新编辑,因为我对这个问题没有足够清晰的理解,无法在这个问题上做到非常精确。希望没问题。
PS:如果有人想共享一个Cocos2d射击游戏的UML样式图,在该图中,各个级别和游戏场景都使用单例模式:),那就太好了。
我将集中讨论下面的问题:
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
长方法没什么错。不过,我怀疑您的加载方法执行非常相似的例程,所以您应该检查是否可以将这些例程归纳为子例程。一个好的指标是,如果有几行代码完全相同,除了参数或变量名。最佳实践是只写一次相同的代码,并用不同的参数多次执行它。
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.
在清理过程中移除孩子是没有意义的。cocos2d在清理过程中自动删除所有子项。
如果您不这么认为,那么您在某个地方有一个保留循环,可以防止子节点解除分配。
很抱歉回答这个问题,但我一直在尝试并决定:
- 在游戏场景中不使用单件模式
- 使用,代替singleton对象保留所有共享数据
我的游戏场景(现在称为shooterscene)的实施草案如下(我在一篇Cocos2d iPhone论坛帖子以及另一篇文章中听取了一些建议):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #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; } |
我使用shooterscene的更新方法来管理所有游戏事件(例如,生成、检查碰撞、移动背景层)。我还没有将完整的实现放在这里,因为仍在进行中,但只是想知道我发现有用的答案类型。