Запуск действия на подклассе CCSprite - PullRequest
0 голосов
/ 15 января 2011

Пожалуйста, потерпите меня, я собираюсь опубликовать длинный код. Я делаю подклассы CCSprite:

@interface Character : CCSprite {
    }
    -(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect;
    @end

    @implementation Character
    -(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
    {
        NSLog(@"in initWithTexture");
        if( (self=[super initWithTexture:texture rect:rect]))
        {
        }
        return self;
    }
    -(void) dealloc
    {
        NSLog(@"character dealloced");
        [super dealloc];
    }
    @end

Вопрос № 1: это правильно?

У меня есть слой, содержащий этот спрайт как переменную класса, а также еще один CCSprite.

Character *characterSprite;
CCSprite *burpSprite;

Этот слой также имеет два объекта CCAnimation:

CCAnimation *burpAnim;
CCAnimation *burpParticlesAnim;

В этом классе у меня есть два метода: - (void) loadBurpAnimation; - (void) unloadBurpAnimation;

-(void) loadBurpAnimation {
        NSString* burpFile;
        NSString* burpFilePVR;

        NSString* burpParticlesFile;
        NSString* burpParticlesFilePVR;

        burpFile = @"latestBurp1-1.plist";
        burpFilePVR = @"latestBurp1-1.pvr.ccz";
        burpParticlesFile = @"burpParticles1-1.plist";
        burpParticlesFilePVR = @"burpParticles1-1.png";

        [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:burpFile texture:[[CCTextureCache sharedTextureCache] addImage:burpFilePVR]];
        [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:burpParticlesFile texture:[[CCTextureCache sharedTextureCache] addImage:burpParticlesFilePVR]];

        NSMutableArray *burpFrames = [NSMutableArray array];
        for(int i = 231; i <= 268; ++i) {
            [burpFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"burp.%d.png", i]]];
        }
        burpAnim = [[CCAnimation alloc] initWithFrames:burpFrames delay:0.04f];
        [burpFrames removeAllObjects];

        //Burp Particles
        [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:burpParticlesFile];
        NSMutableArray *burpParticlesFrames = [NSMutableArray array];
        for(int i = 3; i <= 37; ++i) {
            [burpParticlesFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"Burp_%05d.png", i]]];
        }

        burpParticlesAnim = [[CCAnimation alloc] initWithFrames:burpParticlesFrames delay:0.04f];
        [burpParticlesFrames removeAllObjects];
}

-(void) unloadBurpAnimation {

    [burpAnim release];
    [burpParticlesAnim release];
}

Я должен загрузить анимацию отрыжки в потоке и вызвать метод в главном потоке, чтобы воспроизвести его, который выглядит следующим образом:

-(void) loadAnimation {
    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];

    [dictLock lock];

    if( [EAGLContext setCurrentContext:auxEAGLcontext] ) {
        [self loadBurpAnimation];
                [self performSelectorOnMainThread:@selector(burpAnimation) withObject:nil waitUntilDone:NO];
        } else {
        CCLOG(@"cocos2d: TetureCache: EAGLContext error");
    }
    [dictLock unlock];
    [autoreleasepool drain];
}

Я знаю, что есть метод для загрузки анимации отдельно "asynchAddImage", но здесь это не проблема.

-(void) burpAnimation {

    CCAction *burpAction = [CCSequence actions:
                            [CCAnimate actionWithAnimation:burpAnim restoreOriginalFrame:NO],
                            [CCCallFunc actionWithTarget:self selector:@selector(animationDone)],nil];
    CGSize winSize = [CCDirector sharedDirector].winSize;
    characterSprite = [[Character alloc] initWithSpriteFrameName:@"burp.231.png"];
    characterSprite.position = ccp(winSize.width/2, winSize.height/2);
    [characterSprite setScale:1.5];

    CCAction *particlesAction = [CCSequence actions:
                            [CCAnimate actionWithAnimation:burpParticlesAnim restoreOriginalFrame:NO],
                            nil];
    burpSprite = [[CCSprite alloc] initWithSpriteFrameName:@"Burp_00003.png"];
    burpSprite.position = ccp(winSize.width/2-50, winSize.height/2-80);

    [self addChild:characterSprite];
    [characterSprite release];

    [self addChild:burpSprite];
    [burpSprite release];

    [characterSprite runAction:burpAction];
    [burpSprite runAction:particlesAction];
}

Реальная проблема, с которой я сталкиваюсь, заключается в том, что селектор CCCallFunc вызывается после анимации:

- (void)animationDone {
    //Here characterSprite retain count is 2
        NSLog(@"B4 stop char rc %d", [characterSprite retainCount]);

        [characterSprite stopAllActions];

        //Here characterSprite retain count is still 2
        NSLog(@"B4 stop char rc %d", [characterSprite retainCount]);

    [self removeChild:characterSprite cleanup:YES];

>>>     //Here characterSprite retain count is 1 WHY?
>>>     NSLog(@"char rc %d", [characterSprite retainCount]);

        //Here burpSprite retain count is 2
        NSLog(@"particles rc %d", [burpSprite retainCount]);

    [burpSprite stopAllActions];

        //Here burp retain count is 1
        NSLog(@"particles rc %d", [burpSprite retainCount]);
    [self removeChild:burpSprite cleanup:YES];

        // releases the animation objects
    [self unloadBurpAnimation];

        //Here burpAnim retainCount = 1
        NSLog(@"BURP ANIM rc = %d", [burpAnim retainCount]);

        //Here burpParticlesAnim retainCount = 0 , crashes if print here obviously.
        //NSLog(@"Particles ANIM rc = %d", [burpParticlesAnim retainCount]);

        [[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
    [[CCTextureCache sharedTextureCache] removeUnusedTextures];
}

Две проблемы: Несмотря на то, что я удалил characterSprite, я сохранил его количество, равное единице. Несмотря на то, что я выпустил burpAnim, количество его сохранений равно единице, из-за этого CCSpriteFrameCache не может удалить spriteFrames и, следовательно, текстура также не удаляется.

Обе эти проблемы взаимосвязаны? Спасибо, ребята, что прочитали это, любая помощь очень ценится.

1 Ответ

0 голосов
/ 15 января 2011

Две проблемы: хотя я удалил ХарактерSprite Я получаю свое сохранение считать равным единице. Хотя у меня есть выпустил отрыжку считать равным единице, благодаря этому CCSpriteFrameCache не может удалить spriteFrames и, следовательно, текстура не удаляется тоже.

Ваша первая проблема в том, что вы звоните retainCount и думаете, что возвращенный номер имеет смысл.

Счет сохранения объекта всегда должен рассматриваться как дельта. Если вы увеличиваете его, сохраняя что-то, вы должны уменьшить его, выпуская или выпуская его в другое место. Где полностью зависит от того, как долго вы «владеете» ссылкой на объект.

Есть еще несколько сомнительных битов:

    burpAnim = [[CCAnimation alloc] initWithFrames:burpFrames delay:0.04f];
    [burpFrames removeAllObjects];

Почему вы устанавливаете содержимое burpFrames в цикле for () непосредственно перед этим, затем передаете его в CCAnimation, а затем быстро removeAllObjects? Если CCAnimation не копирует массив, вы просто удалили его из-под анимации. Поскольку массив автоматически освобождается, его не нужно очищать.

То же самое относится к burpParticleFrames.

Получение блокировки (dictLock) для потока, а затем вызов основного потока кажется сомнительным; как отличный способ создать мертвый замок. Если основной поток не должен блокировать этот поток, есть ли у вас более одного фонового потока? Какая у вас модель параллелизма?

Обратите внимание, что [self removeChild:characterSprite cleanup:YES];, вероятно, выпускает characterSprite, так как, надеюсь, метод на self будет следовать обычным соглашениям Какао.

Все это звучит так, как будто у вас есть некоторые основные проблемы с сохранением / освобождением. Прочтите руководство , а затем используйте Build and Analyze, чтобы исправить любые проблемы. Если ваше приложение все еще не работает, используйте функцию обнаружения зомби, чтобы выяснить, что сообщается после освобождения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...