0

编辑:我正在使用 ARC

在我的代码中(基于本书中的 ShootEmUp 示例,我强烈推荐,第 8 章的源代码可在此处获得)我经常使用通过以下方式访问 GameScene 的技巧:

+(GameScene*) sharedGameScene;

它返回对 GameScene 静态实例的引用,并被 GameScene 的所有子项(例如 ShipEntity、InputLayer.. 等)用于与 GameScene 对话(编辑:又名GameScene 的单例实例)。

为了创建多个关卡,我想到了实现一个名为sceneWithId:(int) 的方法,在该方法中我每次加载不同的关卡数据。

编辑: init 方法的代码片段:

-(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];
}

编辑:那个 init 方法可以吗?我发现这篇使用 dispatch_once 的帖子。我应该这样做吗?

或者我应该创建一个 GameScene 类,然后将其子类化?

E.g. FirstGameScene : GameScene 

编辑:我遵循了@LearnCocos2D 的建议并使用了清理方法,我用它来停止播放单例对象音乐层(MusicLayer 对象在 AppDelegate 中初始化,我打算用它来“管理”整个音乐所有场景 - 问题是如果不在 dealloc 中停止它,它将继续播放在初始化时加载的音乐)。

-(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];     
}

但我还是有一些疑问:

  1. 在 GameScene 类中有几个 loadLevelData 方法可以吗?每个方法可以长达 200 行!我试图 sublcass GameScene 但有点乱。我解释得更好。我在子类的头文件中导入了“GameScene.h”,通过这样做,我希望如果我只使用某些方法(例如 init),我将能够看到在 GameScene 中导入的各种类(例如 InputLayerButtons)。事实并非如此。所以我可能不明白 Objective-C 中的导入是如何工作的

  2. 可以在清理方法中删除特定的孩子吗?我以为我会删除 LoadLevelXXXData 方法中添加的所有子项以减少内存使用量。

我已经为这个问题设置了赏金,但我可能需要测试答案并重新编辑,因为我对该主题没有足够清晰的理解,无法在问题中非常精确。希望没事。

PS:如果有人愿意分享一个Cocos2D 射击游戏的UML 样式图,其中有不同的关卡和使用单例模式的 GameScene,那就太好了:)。

4

2 回答 2

1

我将专注于底部的问题:

  1. 在 GameScene 类中有几个 loadLevelData 方法可以吗?每个方法可以长达 200 行!我试图 sublcass GameScene 但有点乱。我解释得更好。我在子类的头文件中导入了“GameScene.h”,通过这样做,我希望如果我只使用某些方法(例如 init),我将能够看到在 GameScene 中导入的各种类(例如 InputLayerButtons)。事实并非如此。所以我可能不明白 Objective-C 中的导入是如何工作的

使用长方法并没有错。但是我怀疑您的加载方法执行非常相似的例程,因此您应该检查是否可以将它们概括为子例程。一个很好的指标是,除了参数或变量名之外,几行代码是否完全相同。最佳实践是只编写一次相同的代码,并使用不同的参数多次执行。

#import语句用于允许编译器“看到”其他类。如果不导入其他头文件,您将无法使用该类的方法和属性而编译器会抱怨。

2. 可以在清理方法中删除特定的孩子吗?我以为我会删除 LoadLevelXXXData 方法中添加的所有子项以减少内存使用量。

在清理过程中移除孩子是没有意义的。Cocos2D 会在清理过程中自动移除所有子节点。

如果您的情况似乎并非如此,那么您在某处有一个保留周期,可以防止子节点解除分配。

于 2012-09-18T22:53:32.517 回答
0

很抱歉回答这个问题,但我一直在尝试并决定:

  • 不要对 GameScene 使用单例模式
  • 使用,而不是一个单例对象来保留所有共享数据

我的 GameScene(现在称为 ShooterScene)的实现草案如下(我遵循了 cocos2d-iphone 论坛帖子中的一些建议以及另一个):

#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 的更新方法来管理所有的游戏事件(例如生成、检查碰撞、移动背景层)。我还没有把完整的实现放在这里,因为它仍在进行中,只是为了了解我发现有用的答案类型。

于 2012-09-17T09:01:07.360 回答