-1

I have to run several sprite sheet animations with each sheet having hundreds of frames. I have tried SpriteKit as well as Cocos2D, each having memory and CPU load time issues. Can anyone please recommend the best way to about it using Cocos2D, SpriteKit or any other method, so as to minimize cpu usage and prevent the app crashing due to memory overload.

Simulator
  • 156
  • 1
  • 11

1 Answers1

1

you can do it by using your own custom class by extending spriteNode here is example in objective c

create a new coca touch class where you .h file contain

#import <SpriteKit/SpriteKit.h>

@interface multiSpriteAnimation : SKSpriteNode
{

}
//variables
//starting frame of animation
@property (nonatomic,strong) SKTexture *startingFrame;
//sprite which hold all animtion
@property (nonatomic,strong) SKSpriteNode *animatedSprite;


@property (nonatomic,strong) NSMutableDictionary *allAnimation;
@property (nonatomic,strong) NSMutableDictionary *allAnimationFrameRates;
@property (nonatomic,strong) NSMutableDictionary *animationList;
//function
@property (nonatomic,strong) SKAction *currentAction;



-(id) copyWithZone: (NSZone *) zone;
- (instancetype)initSpritesAnimation:(SKTexture*)startingFrame;
//add animation
-(void)addAnimation:(NSMutableArray*)frames frameRate:(float)time withKey:(NSString*)Key;
-(void)playAnimation:(NSString*)label withType:(NSString*)type;

//play animation with sound
-(void)playAnimation:(NSString*)label withType:(NSString*)type withSound:(NSString*)soundname loopRequired:(BOOL)loop;

//clear all sounds
-(void)clearAllsounds;

@end

and .m file contain

#import "multiSpriteAnimation.h"
@implementation multiSpriteAnimation
{
    SKTexture *__startingFrame;
}
- (instancetype)initSpritesAnimation:(SKTexture*)startingFrame
{
    self = [super init];
    if (self) {
        //init all animation dictionary
        _animationList=[[NSMutableDictionary alloc] init];
        _allAnimation=[[NSMutableDictionary alloc] init];
        _allAnimationFrameRates=[[NSMutableDictionary alloc] init];
        //draw first frame for the animation
        __startingFrame=startingFrame;
        _animatedSprite=[SKSpriteNode spriteNodeWithTexture:startingFrame];
        _animatedSprite.anchorPoint=CGPointMake(0.5, 0.5);
        [self addChild:_animatedSprite];

    }
    return self;
}
-(void)addAnimation:(NSMutableArray*)frames frameRate:(float)time withKey:(NSString*)Key
{

    //add all animation only once for stable framerate
    [_allAnimation setObject:frames forKey:Key];
    [_allAnimationFrameRates setObject:[NSNumber numberWithFloat:1/time] forKey:Key];

}

-(void)playAnimation:(NSString*)label withType:(NSString*)type
{
    //total frame to play animation
    NSMutableArray *frames=[_allAnimation objectForKey:label];
    //frame rate of a animation
    float time=[[_allAnimationFrameRates objectForKey:label] floatValue];
    SKAction *Animation = [SKAction animateWithTextures:frames timePerFrame:time resize:TRUE restore:TRUE];
    //play in a loop
    if([type isEqualToString:@"loop"])
    {
        _currentAction = [SKAction repeatActionForever:Animation ];
    }
    //play once with complete handler
    else if([type isEqualToString:@"playonce"])
    {
        _currentAction=Animation;
    }
    [_animatedSprite runAction:_currentAction];
    //only one hero have cap
}
//clear all sounds
-(void)clearAllsounds
{
    [self removeActionForKey:@"sound"];
}

-(id) copyWithZone: (NSZone *) zone
{

    multiSpriteAnimation *copy = [[[self class] allocWithZone:zone] initSpritesAnimation:__startingFrame];
    return copy;
}
-(void)playSound:(NSString *)path withLoop:(BOOL)loop
{
    SKAction *sound;
    if(loop)
    {
        sound = [SKAction playSoundFileNamed:path waitForCompletion:YES];
        [self runAction:[SKAction repeatActionForever:sound] withKey:@"sound"];
    }
    else
    {
        sound = [SKAction playSoundFileNamed:path waitForCompletion:NO];
        [self runAction:sound withKey:@"sound"];
    }
}

//play animation with sound
-(void)playAnimation:(NSString*)label withType:(NSString*)type withSound:(NSString*)soundname loopRequired:(BOOL)loop
{
    //total frame to play animation
    NSMutableArray *frames=[_allAnimation objectForKey:label];
    //frame rate of a animation
    float time=[[_allAnimationFrameRates objectForKey:label] floatValue];
    SKAction *Animation = [SKAction animateWithTextures:frames timePerFrame:time resize:TRUE restore:TRUE];
    //play in a loop
    if([type isEqualToString:@"loop"])
    {
        _currentAction = [SKAction repeatActionForever:Animation ];
        [self playSound:soundname withLoop:loop];
    }
    //play once with complete handler
    else if([type isEqualToString:@"playonce"])
    {
        _currentAction=Animation;
        [self playSound:soundname withLoop:loop];
    }
    [_animatedSprite runAction:_currentAction];
    //only one hero have cap
}



@end

now import this class in any of your scene and add all your animation one by one

multiSpriteAnimation *player=[[multiSpriteAnimation alloc] initSpritesAnimation:A1[0]];
//where A1[0] is first frame of your animation

    //and A1 as a array of frames or textures with a key 

    [player addAnimation:A1 frameRate:30.0f withKey:@"run"];

    player.position=CGPointMake(200.0f, 400.0f);
    [self addChild:player];
//play animation by key
    [player playAnimation:@"run" withType:@"loop"];

this way you can handle multiple animation remember save all animation frames or textures as a singleton for further use 
dragoneye
  • 703
  • 6
  • 14
  • it still does not resolve cpu peaking for 10-15 seconds initially, I am adding 19 nodes and each node has about 40 frames. – Simulator Sep 02 '15 at 05:20
  • are you preloading textures for animation please fetch textures from atlas and preload them for further use for e.g. load texture from atlas and save them in a data class or singleton class ...so are you loading texture atlas in memory for further use – dragoneye Sep 02 '15 at 10:20
  • You can download the code from [Here](http://www.filedropper.com/spritekittestmodbobjt) – Simulator Sep 03 '15 at 04:59