在CCSprite的子类上运行操作

时间:2011-01-15 12:28:33

标签: animation cocos2d-iphone

请耐心等待我发布长码。 我是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];
}

我必须在线程中加载burp动画并在主线程上调用一个方法来播放它,如下所示:

-(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,但我的保留计数等于1。 虽然我已经发布了burpAnim但我的保留计数等于1,因为这个CCSpriteFrameCache无法删除spriteFrames,因此纹理也不会被删除。

这两个问题是否相互关联? 谢谢你们阅读本文,非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

  

两个问题:虽然我已经删除了   我保留了characterSprite   数等于一。虽然我有   发布了burpAnim我得到了它的保留   由于这个原因,计数等于1   CCSpriteFrameCache无法删除   spriteFrames,因此纹理是   也没有删除。

您的第一个问题是您正在呼叫retainCount并认为返回的号码是有意义的。

对象的保留计数应始终视为delta。如果你通过保留某些东西来增加它,你必须通过释放或自动释放其他地方来减少它。哪里完全取决于你“拥有”对象的引用多长时间。

还有其他一些可疑的内容:

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

为什么在之前的for()循环中设置burpFrames的内容,然后将其传递给CCAnimation,然后立即removeAllObjects?如果CCAnimation没有复制数组,那么你只需从动画中清空它。由于数组是自动释放的,因此无需清空它。

同样适用于burpParticleFrames

在一个线程上锁定(dictLock)然后调用主线程似乎很可疑;像一个生成死锁的好方法。如果主线程不应该锁定该线程,你是否有多个后台线程在运行?你的并发模型是什么?

请注意,[self removeChild:characterSprite cleanup:YES];可能会释放characterSprite,因为希望self上的方法遵循正常的Cocoa约定。

这听起来像你有一些基本的保留/释放问题。 Read the guide然后使用Build and Analyze来解决任何问题。如果您的应用仍然崩溃,请使用Zombie检测来确定解除分配后的消息。