2012-03-06 14 views
1

しばらくの間、iOSのタワーディフェンスゲームで作業していました。私はCocos2dを使用しています(v0.99.5はわかりません)。最近、スプライトの削除を開始したときにいくつかの問題が発生し始めました。スプライトメモリの問題をCocos2dで取り除く方法をデバッグする方法

は楽器やゾンビを使用してプロファイルを持っているし、ここで私が得るものです:

Zombie trace コードを(してもそれらを削除)更新に位置してスプライトを更新するために:

-(void) update:(ccTime)deltaTime { 
if (paused) 
    return; 

CCArray *childs = [textureAtlas children]; 

//Update all objects 
for (GameSprite *tempChar in childs) { 
    if ([tempChar respondsToSelector:@selector(updateStateWithDeltaTime:andListOfGameObjects:andAtlas:)]) { 
     [(GameSprite*)tempChar updateStateWithDeltaTime:deltaTime andListOfGameObjects:[textureAtlas children] andAtlas:textureAtlas]; 
    } 
} 

//Remove dead projectiles 
for (GameSprite *tempChar in childs) {   
    if ([tempChar isKindOfClass:Projectile.class]) { //(**) 
     if (![tempChar alive]) { 
      [tempChar remove]; 
     } 
    } 
} 

//Remove dead towers 
for (GameSprite *tempChar in childs) { 
    if ([tempChar isKindOfClass:Tower.class]) { 
     if (![tempChar alive]) { 
      [tempChar remove]; 
     } 
    } 
} 
//Remove dead creeps 
for (GameSprite *tempChar in childs) { 
    if ([tempChar isKindOfClass:Creep.class]) { 
     if (![tempChar alive]) { 
      [tempChar remove]; 
     } 
    } 
} 
} 

removeメソッドでGameSprite.m:

-(void)remove { 
    CCLOG(@"remove"); 
    [self removeFromParentAndCleanup:YES]; 
} 

最初のブロックはSpriteBatchNode/textureAtlasにスプライトを更新します。 3つの残りのブロックは、削除すべきオブジェクトがあるかどうかをチェックします。 (それらのalive-variableはNO?に設定されています)。私が異なるタイプのブロックを3つ持っている理由は、発射体が(弱い)射撃を参照しているため、射撃の前に削除する必要があるからです。

私の問題は、発射物がクリープに当たってプロジェクタイル(およびそのクリープで射撃する他のすべての発射体)を取り除くときにランダムにクラッシュすることです。クリープ参照カウントは0になりますが、まだチャイルド配列内にあるようです。原因私が手にエラーがある:私は(**)

でマークされた行の

*** -[NormalProjectile isKindOfClass:]: message sent to deallocated instance 0xff33e30 

どちらの問題は私がCocos2dのremoveFromParentAndCleanUPを理解することである:またはその弾丸クリープを処理するための私の「ソリューション」 - 記憶の観点から、関係は悪いです。どのようにこれを解決するか、それをさらにデバッグするためのアイデア?

答えて

3

アレイを通過するための高速列挙手法では、その配列内のすべてのスプライトがCCSpriteのカスタムサブクラスとしてキャストされているので、Towerなどの別のカスタムサブクラスであるかどうかを確認します。 1つのクラスのメソッドが他のクラスにない可能性があるため、これを健全なプログラミングの練習と見なします。それでも、あなたはそれらをキャストしています。

あなたの問題に貢献しているかもしれませんが、特定のクラスの子どものためにassign iVar CCArrayを保つことが賢明な方法です。つまり、すべての発射体を1つの配列に入れて、バッチノードに追加すると、それらの個々の配列を通過することで、すべての発射体、塔などを反復することができます。その後、必要に応じてアレイからも親からも削除します。私はこれがあなたのbatchnodeにあるすべてのゲームのスプライトを通過するよりもかなり安全だと思うでしょう。おそらく使用されていない麻薬を含んでいて、それらをキャストして別のクラスとしてテストしているかもしれません。

+0

ありがとうございました。 3つの新しい配列を作成し、それらを列挙して解決しました。これをスキップすることを望んでいましたが、textureAtlasの子を反復処理するのは安全な方法ではありません。 – Sunkas

+0

安全なテクニックを使って解決したことは素晴らしいことです。それは本当に正しいアプローチです。 – johnbakers

関連する問題