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 行です。GameScene をサブクラス化しようとしましたが、少し面倒です。私はよりよく説明します。サブクラスのヘッダー ファイルに "GameScene.h" をインポートしました。そうすることで、特定のメソッド (init など) のみをオーバーライドした場合、GameScene にインポートされたさまざまなクラス (InputLayerButtons など) を確認できると期待していました。そうではありません。したがって、Objective-C でインポートがどのように機能するかはおそらく理解できません

  2. クリーンアップ メソッドで特定の子を削除しても問題ありませんか? LoadLevelXXXData メソッドに追加されたすべての子を削除して、メモリ使用量を削減しようと考えました。

この質問に報奨金を設定しましたが、質問を非常に正確にするために主題を十分に明確に理解していないため、おそらく回答をテストして再編集する必要があります。希望は大丈夫です。

PS: Cocos2D Shooter Game のUML スタイルの図を誰かが共有したいと思うなら、それは素晴らしいことです:)

4

2 に答える 2

1

一番下の質問に焦点を当てます。

  1. GameScene クラスに複数の loadLevelData メソッドがあっても問題ありませんか? 各メソッドの長さは 200 行です。GameScene をサブクラス化しようとしましたが、少し面倒です。私はよりよく説明します。サブクラスのヘッダー ファイルに "GameScene.h" をインポートしました。そうすることで、特定のメソッド (init など) のみをオーバーライドした場合、GameScene にインポートされたさまざまなクラス (InputLayerButtons など) を確認できると期待していました。そうではありません。したがって、Objective-C でインポートがどのように機能するかはおそらく理解できません

長いメソッドを使用しても問題はありません。ただし、ロード メソッドは非常によく似たルーチンを実行すると思われるため、これらをサブルーチンに一般化できるかどうかを確認する必要があります。パラメータまたは変数名を除いて、いくつかのコード行が完全に同一であるかどうかは、良い指標です。ベスト プラクティスは、同一のコードを 1 回だけ記述し、さまざまなパラメーターを使用して何度も実行することです。

この#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 に答える