1

しばらくの間、iOS 向けのタワー ディフェンス ゲームに取り組んでいます。Cocos2d を使用しています (v0.99.5 は不明)。最近、スプライトの削除を開始したときに、いくつかの問題が発生し始めました。

楽器とゾンビを使用してプロファイルを作成すると、次のようになります。

ゾンビの痕跡 スプライトを更新する (および削除する) ためのコードは update にあります。

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

GameSprite.m の remove メソッド:

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

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

したがって、私の問題は、発射体がクリープに衝突し、発射体(およびそのクリープを発射する他のすべての発射体)が削除されると、ランダムにクラッシュすることです。クリープの参照カウントは 0 になりましたが、まだ子配列にあるようです。エラーの原因は次のとおりです。

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

(**) でマークした行に

問題は、Cocos2d の removeFromParentAndCleanUP: を理解することであるか、または発射物とクリープの関係を処理するための私の「解決策」がメモリの観点から悪いことです。これを解決する方法やさらにデバッグする方法についてのアイデアはありますか?

4

1 に答える 1

3

配列を調べるための高速な列挙手法では、その配列内のすべてのスプライトをCCSpriteのカスタムサブクラスとしてキャストし、代わりにTowerなどの別のカスタムサブクラスであるかどうかを確認します。これは正常ではないと思います。プログラミングの練習。一方のクラスのメソッドがもう一方のクラスにない場合があるため、それでもキャストしています。

それはあなたの問題に貢献しているかもしれないし、貢献していないかもしれませんが、より賢明なアプローチはassign特定のクラスの子供のためにiVarCCArrayを維持することです。つまり、作成時にすべての発射体を1つの配列に入れてバッチノードに追加すると、それらの個々の配列を通過することで、すべての発射体、タワーなどを反復処理できます。ここで、それらがすでにどのようなクラスであるかがわかります。次に、必要に応じて、それらをアレイおよび親から削除します。これは、バッチノードにあるすべてのゲームのスプライト全体を調べるよりもかなり安全だと思います。これには、おそらく使用されていないスプライトが含まれ、それらをキャストして別のクラスとしてテストする場合があります。

于 2012-03-07T02:00:48.143 に答える