0

I am trying to create a CCSprite subclass called Enemy

#import "Enemy.h"


@implementation Enemy
{
    CCSprite* ant;
    CCAnimation *walkAnim ;
}

-(id)init
{
    self = [super init];
    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"char.plist"];
    CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"char.png"];
    [self addChild:spriteSheet];

    NSMutableArray *walkAnimFrames = [NSMutableArray array];
    for (int i=1; i<=3; i++) {
        [walkAnimFrames addObject:
         [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
          [NSString stringWithFormat:@"antNormal_%d.png",i]]];
    }

    walkAnim = [CCAnimation animationWithSpriteFrames:walkAnimFrames delay:0.1f];
    self = [CCSprite spriteWithSpriteFrameName:@"antNormal_1.png"];
    CCAction* walkAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim]];
    [self runAction:walkAction];

    return self;
}
@end

and then in my gamelayer I have the enemies added like this

    enemies=[[CCArray alloc] initWithCapacity:100];
    for (int i=0; i<10; i++) {
        Enemy* ant=[[Enemy alloc] init];
        [ant setPosition:ccp(100*i,100)];
        [enemies addObject:ant];
    }

But this is causing the program to crash on start with the error

'NSInternalInconsistencyException', reason: 'Animate: argument Animation must be non-nil'

If I comment out the CCAction though, the enemies display correctly, just without animation(obviously). Not sure how to solve this at the moment.

4

1 回答 1

1

While I can't speak to Cocos2d specifically, there's several things wrong in your init method from an ObjC standpoint that probably contribute to the problem.

  1. self is set self twice. The second one creates a new instance of the class and clobbers the old one. You should only set self to the result of an init method, not a class factory method
  2. self is not checked for nil. You should always check self for nil before setting any ivars. If the init method you call fails, if will be nil and your app will crash.
  3. walkAnim is not retained, it will be released at a later time and your app will crash when you try to use it. It must be retained.
  4. Do not call methods on self in your custom init methods. By definition, your object is not in a fully initialized state inside init methods. Strange things can occur if you call methods on self. Other init methods are an exception.

While I cannot guarantee this is free of bugs, as I am not personally familiar with Cocoas2d, this should get you closer to what you want:

-(id)init
{
    self = [CCSprite initWithSpriteFrameName:@"antNormal_1.png"];

    if (self)
    {
        [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"char.plist"];
        CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"char.png"];
        [self addChild:spriteSheet];

        NSMutableArray *walkAnimFrames = [NSMutableArray array];
        for (int i=1; i<=3; i++) {
            [walkAnimFrames addObject:
             [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
              [NSString stringWithFormat:@"antNormal_%d.png",i]]];
        }

        walkAnim = [[CCAnimation animationWithSpriteFrames:walkAnimFrames delay:0.1f] retain];
    }
    return self;
}

-(void)startWalkAction
{
        CCAction* walkAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim]];
        [self runAction:walkAction];
}

And then add enemies like this:

enemies=[[CCArray alloc] initWithCapacity:100];
for (int i=0; i<10; i++) {
    Enemy* ant=[[Enemy alloc] init];
    [ant setPosition:ccp(100*i,100)];
    [ant startWalkAction];
    [enemies addObject:ant];
}
于 2013-07-28T19:48:35.563 回答