title: What is the proper way to implement animation in a CCSprite subclass?
body: <p>in my game I made a subclass of CCSprite (cocos2d) for my enemies.
  Because I want control over animation, from within every instance of this subclass, I had to translate my animation code in my main class, which loads
  the enemies, to this subclass. </p>
  
  <p>I found this rather hard but.... after some time it magically started to work. </p>
  
  <p>Unfortunately after creating and setting properties in this subclass I started to have weird crashes. Because they are in cocosDenshion and other places which have nothing to do with my
  enemy class and after a research in depth in my code and on the net, I'm convinced its some kind of data corruption and I'm almost completely certain its because I did my enemie class with his animation code completely the wrong way.</p>
  
  <p>To be honest, I cannot even wrap my mind around what is going on here anymore and how this actually works :S...I'm completely stuck. any help is much appreciated! </p>
  
  <p><strong>So my main questions would be: What is the proper way to implement animation in a CCSprite subclass ? / what am I doing wrong here?</strong></p>
  
  <p>simplified my code here: (it triggers the animation every 2 seconds to show how I want
  to use it)</p>
  
  <pre><code>#import "cocos2d.h"
  
  @interface Npc : CCSprite 
  {
      CCAction *_runAnimation;
      NSString* name;
      int strength;
  }
  
  @property (nonatomic, retain) CCAction *runAnimation;
  @property int strength;
  @property (nonatomic, retain) NSString* name;
  
  - (Npc*)loadAnimation;
  - (void)animate;
  @end
  </code></pre>
  
  <hr>
  
  <pre><code>#import "Npc.h"
  
  @implementation Npc
  
  @synthesize runAnimation = _runAnimation;
  @synthesize name;
  @synthesize strength;
  
  -(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
  {
      if( (self=[super initWithTexture:texture rect:rect]))
      {
      }
      return self;
  }
  
  - (Npc*)loadAnimation
  {
  
      int lastFrame = 11;
      NSString *creatureFile = @"vis 1";
  
      [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:
       [NSString stringWithFormat:@"%@.plist", creatureFile]];
      CCSpriteBatchNode* sheet = [CCSpriteBatchNode batchNodeWithFile:
                                  [NSString stringWithFormat:@"%@.png", creatureFile]];
  
      self = [Npc spriteWithTexture:sheet.texture];
      NSMutableArray* animFrames = [[NSMutableArray alloc] init];     
  
      for (int x = 0; x &lt; lastFrame; x++) 
      {
          [animFrames addObject:
           [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
            [NSString stringWithFormat:@"%@ %d.png", creatureFile, x]]];              
      }
  
      CCAnimation* anim = [CCAnimation animationWithFrames: animFrames delay: 0.1];
  
      self.runAnimation = [CCAnimate actionWithAnimation:anim restoreOriginalFrame:NO];
  
      [self runAction:_runAnimation];
  
      return self;
  }
  
  - (void)animate
  {
      [self runAction:self.runAnimation]; 
  }
  
  - (void)dealloc 
  {
      [super dealloc];
  
      [name release];
  }
  
  @end
  </code></pre>
  
  <hr>
  
  <pre><code>#import "HelloWorldLayer.h"
  #import "Npc.h"
  
  @implementation HelloWorldLayer
  
  +(CCScene *) scene
  {
      CCScene *scene = [CCScene node];
      HelloWorldLayer *layer = [HelloWorldLayer node];
      [scene addChild: layer];
      return scene;
  }
  
  
  -(id) init
  {
  
  if( (self=[super init])) 
  {
      timer = 0; 
  
      creatureTemp = [Npc spriteWithFile:@"Icon.png"];
      creature = [creatureTemp loadAnimation];
      creature.position = ccp(100,100);
      [self addChild:creature];
  
      [self schedule:@selector(nextFrame:)];
  
  }
  return self;
  }
  
  
  - (void)nextFrame:(ccTime)dt
  {
      timer += dt;
      if (timer &gt; 2.)
      {
          [creature animate];
          timer = 0.;
      }
  }
  
  - (void) dealloc
  {
      [super dealloc];
  }
  @end
  </code></pre>
  
  <p><strong>-------------------EDIT--------------------</strong></p>
  
  <p>I changed my code with help of a tutorial by Ray Wenderlich: <a href="http://www.raywenderlich.com/3888/how-to-create-a-game-like-tiny-wings-part-1" rel="nofollow">http://www.raywenderlich.com/3888/how-to-create-a-game-like-tiny-wings-part-1</a></p>
  
  <p>this is I think much closer to what it should be. Unfortunately it still crashes on my iphone (not the simulator) on SimpleAudioEngine (which I implement right) so I still do something wrong.</p>
  
  <p>on top of the Npc class:</p>
  
  <pre><code>@synthesize batchNode = _batchNode;
  </code></pre>
  
  <p>the init of the Npc class:</p>
  
  <pre><code>-(id) initNpc
  {
      if( (self=[super initWithSpriteFrameName:@"vis 1 0.png"]))
      {
          _normalAnim = [[CCAnimation alloc] init];
  
          NSMutableArray* animFrames = [[NSMutableArray alloc] init]; 
  
          int lastFrame = 11;
  
          for (int x = 0; x &lt; lastFrame; x++) 
          {
              [animFrames addObject:
               [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
                [NSString stringWithFormat:@"vis 1 %d.png", x]]]; 
          }
  
          _normalAnim = [CCAnimation animationWithFrames: animFrames delay: 0.1];
          self.runAnimation = [CCAnimate actionWithAnimation:_normalAnim restoreOriginalFrame:NO];
  
  
      }
      return self;
  }
  </code></pre>
  
  <p>and the init of the HelloWorldLayer</p>
  
  <pre><code>-(id) init
  {
  
      if( (self=[super init])) 
      {
          timer = 0; 
  
  
          _batchNode = [CCSpriteBatchNode batchNodeWithFile:@"vis 1.png"];
          [self addChild:_batchNode];
          [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"vis 1.plist"];
  
          creature = [[[Npc alloc] initNpc] autorelease];
          creature.position = ccp(200,200);
  
          [_batchNode addChild:creature];
  
          [self schedule:@selector(nextFrame:)];
  
          [[SimpleAudioEngine sharedEngine] preloadEffect:@"super1.mp3"];
  
      }
      return self;
  }
  </code></pre>