0

私は現在、cocos2dを使用してiPhone用のゲームを構築していますが、次の問題があります。

現在のレベルのシーンの前にHUDを表示するGameHUDというシングルトンクラスがあります。たまにHUDを再描画したいので、現在のゲームの状態に応じて変化します。問題は、HUDを再描画する頻度が高いほど、フレームレートが低下することです。

一部のリソースをリリースできなかったと思いますが、どのリソースをリリースする必要があるのか​​わかりません。(私はメモリ管理にかなり慣れていません。「new」、「alloc」、「copy」、「retain」のいずれかのキーワードで作成されたオブジェクトをリリースする必要があることを理解しています。ただし、cocos2dは主に自動リリースオブジェクトを生成します。 、そのため、手動でリリースしてはいけません。間違っている場合は修正してください;))

//static, so it can be called from other classes
+(void)redrawGameHUD{

CGSize winSize = [CCDirector sharedDirector].winSize;

//get reference to background-sprite
CCSprite *background = [[[GameHUD class] sharedHUD] towerBackground];

//remove the child from the HUD, if it exists
[[[GameHUD class] sharedHUD] removeChild:background cleanup:YES];

//create sprite containing the background-image
background = [CCSprite spriteWithFile:@"background.png"];

//add background image to HUD
[[[GameHUD class] sharedHUD] addChild:background];

//load images that should be displayed into an array
NSArray *images = [NSArray arrayWithObjects:@"image1.png", @"image2.png", @"image3.png", @"image4.png", nil];

//remove sprites from HUD before drawing them again.
//the "buildable" array contains all those already drawn sprites
for (CCSprite *entity in [[[GameHUD class] sharedHUD] buildable]) {
    [[[GameHUD class] sharedHUD] removeChild:entity cleanup:YES];
}
[[[[GameHUD class] sharedHUD] buildable] removeAllObjects];

//loop over sprites, initialize them and add them to the HUD
for(int i = 0; i < images.count; ++i) {

    NSString *image = [images objectAtIndex:i];
    CCSprite *sprite = [CCSprite spriteWithFile:image];

    //add sprite to HUD and memorize them in the "buildable" array
    [[[GameHUD class] sharedHUD] addChild:sprite];
    [[[[GameHUD class] sharedHUD] buildable] addObject:sprite];
}   

}

したがって、このメソッドが呼び出されるたびに、フレームレートが少し低下し、低下したままになります。誰かが私に何を間違っているのか教えてもらえますか?ありがとう。

4

2 に答える 2

2

実行時にスプライトを作成したり削除したりしないようにしてください。つまり、これを頻繁に行わないようにしてください。

[CCSprite spriteWithFile:@"background.png"];

これにより、スプライトに新しいメモリが割り当てられ、新しいスプライトを作成するときに、舞台裏でかなりのことが行われます。そしてもちろん、既存のスプライトを解放しています。それはすべて不要です。

redrawGameHUD メソッドには、実際にスプライトを新たに作成する理由がわかりません。スプライトは毎回同じ画像を使用しています。では、なぜ古いものを保管しないのでしょうか。質問に投稿する前にコードを編集しない限り、HUD スプライトを削除して再作成する必要はありません。

また、すべての HUD スプライト イメージのテクスチャ アトラスを作成することもできます。1 つには、CCSpriteBatchNode を使用して、1 回の描画呼び出しですべての HUD スプライトをレンダリングできます。次に、新しいテクスチャを既存のスプライトに割り当てたい場合は、スプライトを破棄して再作成するのではなく、そのスプライトの CCSpriteFrame を変更するだけです。

私を悩ませている他の何か、あなたはこれを書き続けています:

[[[GameHUD class] sharedHUD] addChild:sprite];

まず、これは次のように書くのと同じです。クラスへのメッセージはまったく不要です (どこで拾ったのだろうか?)。

[[GameHUD sharedHUD] addChild:sprite];

これを何度も行うため、GameHUD の一時的なローカル コピーを保持する必要があります。これにより、不要な Objective-C メッセージがいくつか削除されます。

GameHUD* gameHUD = [GameHUD sharedHUD];
// from now on use gameHUD instead of [GameHUD sharedHUD]
[gameHUD addChild:sprite];

これはループに対して特に良いアドバイスです。

for (CCSprite *entity in [[[GameHUD class] sharedHUD] buildable])

は、ビルド可能な配列内のすべてのエンティティに対して 2 つの追加メッセージ (クラスと sharedHUD) を送信します。これらの余分な呼び出しはすぐに加算されますが、発生しているフレームレートの低下には十分ではありません.

また、すべての HUD スプライトを不必要に「ビルド可能な」配列に保持します。cocos2d が使用する既存の children 配列を使用しないのはなぜですか? 「ビルド可能」な各 HUD スプライトを同じタグ (123 など) で追加するだけです。

[gameHUD addChild:sprite z:0 tag:123];

すべての「構築可能な」スプライトで何かをする必要がある場合は、次のように子を反復処理できます。

CCNode* node;
CCARRAY_FOREACH([gameHUD children], node)
{
   if (node.tag == 123)
   {
      CCSprite* buildable = (CCSprite*)node;
      // do stuff with buildable sprite ...
   }
}

繰り返しになりますが、これにより、構築可能な配列内のオブジェクトの不要な追加、保持、削除、および解放が回避されます。また、誤ってノード階層からスプライトを削除してビルド可能な配列から削除したり、その逆を行ったりすることはありません。

私は仮定で締めくくりたいと思います:あなたのコードでは、あなたが不必要に多くの余分なことをしているという一般的な傾向を見ました。だから私はこれがプロジェクト全体に当てはまると推測しています。戻って自問したいかもしれません (より良い: 見つけてください) デバイスに実行させているもので、むしろ不必要なものが他にあるでしょうか。

于 2011-10-31T22:05:54.133 に答える