multiple CCSpritevFramevCache at one time - cocos2d-iphone

i am using the CCSpriteFrameCache a lot but cant understand somthing about it.
can i load many .plist to the cache at the start of my game ? or the CCSpriteFrameCache has ONLY one plist at a time ?
by now there is a sprite which is a child of a CCSpriteBatchNode ,that is been created many times during the game , with different images. so every time i create a new sprite i do this:
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:[NSString stringWithFormat:#"cand%i.plist",stage]];
candySheet = [CCSpriteBatchNode batchNodeWithFile:[NSString stringWithFormat:#"cand%i.png",stage]];
[self addChild:candySheet];
sprite1 = [CCSprite spriteWithSpriteFrameName:[NSString stringWithFormat:#"cand%i.png",1]];
is it ok ?
now lets say i have 2 spriteSheets, and 2 .plist, and i want to load both of them on my init , and add 2 sprites, each to be a child of one CCSpriteBatchNode and render images for each sprite from his own spriteSheet and Plist. but i get error then that :
CCSprite is not using the same texture id
so, i understand that each time i have to load to the cache the plist that i need at that specific time ????
thanks.

Someone asked a similar thing earlier.
You cannot make sprites children of the same CCSpriteBatchNode if they are not from the same spritesheet.
You need to create a new CCSpriteBatchNode for each spritesheet you use (by spritesheet I mean the combined image file and .plist file)
The CCSpriteFrameCache is a single cache shared across all your scenes and classes. When you call this method:
[CCSpriteFrameCache sharedSpriteFrameCache]
You are not making a new CCSpriteFrameCache object everytime, there is just ONE instance. You store all your loaded spritesheets in this single cache. So you could load 2 spritesheets into the cache like so:
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"sheet1.plist"]; [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"sheet2.plist"];
You then need to create a CCSpriteBatchNode for EACH spritesheet, you cannot have more than one sheet in a batch node:
CCSpriteBatchNode *spriteSheet1 = [CCSpriteBatchNode batchNodeWithFile:#"sheet1.pvr.ccz"];
CCSpriteBatchNode *spriteSheet2 = [CCSpriteBatchNode batchNodeWithFile:#"sheet2.pvr.ccz"];
You can then add both of these batch nodes to a layer if you wish. Sprites added to batch nodes must be from the spritesheet that batch node is using.

[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"some.plist"];
The above line takes quite a chunk of time even if the sprite frames are already loaded/cached. So make sure to avoid doing this unless you're absolutely certain that these sprite frames haven't been cached before, like at the beginning of the game or after purging the sprite frame cache.

Related

Which APIs should we use to add spritesheets and sprites to a cocos2d game?

While creating a cocos2d iOS game, there are several options to add spritesheets - CCTextureCache::addImageAsync, CCSpriteFrameCache::addSpriteFramesWithFile, etc. - what is the difference between using these different ways to add a spritesheet?
Similarly, to load a sprite, we can call CCSprite::spriteWithSpriteFrameName or CCSprite::spriteWithFile or CCSpriteBatchNode::batchNodeWithTexture, etc. What is the difference between using these techniques?
Thanks
Anand
Load sprite frames, this also loads the textures:
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"file.plist"];
Use sprite frames:
CCSprite* sprite = [CCSprite spriteWithSpriteFrameName:#"frame.png"];
Add the sprite to a batch node:
CCSpriteBatchNode* batchNode = [CCSpriteBatchNode batchNodeWithTexture:sprite.texture];
[batchNode addChild:sprite];
The batchNodeWithFile works too if you use the same image file of the sprite. If the sprite was initialized with a spriteframe, it'll be the texture atlas image (ie "file.png").
addImageAsync is only needed if you want to load your texture on another thread, usually to animate the loading screen. You'll still have to add the sprite frames afterwards.
CCSprite spriteWithFile creates a sprite from a single image file. Those can be batched too but it's better to use a texture atlas with sprite frames.

Cocos2d animations in main loop

Anyone that can give any hint of the smartest way to do a main loop animation? I don't want to use CCAnimation because I want to control the animations frame by frame.
Shall I store the sprite rect (relative to the sprite sheet) for each individual frame in an array, and then look up the suiting rect in each animation step? I tried to find out how this is done in CCAnimation, but I didn't succeed...
How to get the rect for each frame at initialization?
How to set the rect at each animation step?
Do I need to use CCSpriteBatchNode? I guess not, eh?
Cannot crealry understand, why you don't want to use CCAnimation, but anyway, to get answer for your questions you can check creation code of the CCSprite instance. Then, check creation of CCSpriteFrame instance. There you will find the answer for at least your first question.
Actually if you just want to manage animation frames differently from CCAnimate, you can just store array of CCSpriteFrames and show them as you want(in CCAnimate action these frames are just changed one by one in equal time intervals).
And if you do not want to show more than one frame of your animation, there is no difference will you use CCSpriteBatchNode or not. It saves a lot of processor time if you need to draw several parts of one texture, as it draws them in one draw call instead of send draw message to all of these sprites.
As you want animate sprite frame by frame I think using CCSpriteBatchNode would be a better option as it give you frame by frame access of animation.Making plist of sprites using any tool like "Zwoptex" will give an efficient way to animate using CCSpriteBatchNode.
Hope you know the animation using plist file with CCSpriteBatchNode.
I did the following with inspiration from Morions answer:
In the game tick function:
_animationFrames.legFrame = (_animationFrames.legFrame + 1) % _animationFrames.legFrames.count;
[_legs setDisplayFrame: [_animationFrames.legFrames objectAtIndex: _animationFrames.legFrame]];
And in the init function:
CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode
batchNodeWithFile:#"Player.png"];
[self addChild:spriteSheet];
_animationFrames.legFrames = [[NSMutableArray array] retain];
for(int i = 0; i <= 15; ++i)
{
[_animationFrames.legFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"Player_legs-%d.png", i]]];
}
_legs = [CCSprite spriteWithSpriteFrameName:#"Player_legs-0.png"];
[_sprite addChild: spriteSheet];
[spriteSheet addChild:_legs z:1];

Cocos2D - redeclaring the frame cache?

I have this declared on my main class:
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"atlas.plist"];
CCSpriteBatchNode *batchNode = [CCSpriteBatchNode batchNodeWithFile:#"atlas.png"];
now I am on another class and I want to create a new batchNode but get spriteFrames from atlas, that was declared on the main class. How do I do that? Do I need to put these same lines again on my other class? By doing so, will I have redundant images imported to the sharedSpriteFrameCache? My idea is to save memory, not wasted.
Any clues? thanks.
You don't need to call [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"atlas.plist"]; again assuming you haven't removed these sprite frames.
You will need to create another batch node to put sprites on.
If you were to try and add the sprite frames to the cache again, you wouldn't waste space, the sprite frames would only be added once, but you would waste time while cocos2D parses through the file and determines if each sprite frame has indeed already been added.

CCSpriteBatchNode children's animations

When a CCSprite child of CCSpriteBatchNode performs a CCAnimation, are the frames of that animation also batch drawn just like the main image of CCSprite? If not, is there a way to have all the frames of many animations of many batch node children all be batch drawn together?
The CCAnimation simply changes the sprite frame of the sprite. In essence it simply changes which part of the (much bigger) texture atlas the sprite is displaying. So animations are properly sprite-batched because you're just changing which part of the texture the sprite is displaying.

Adding multiple spritesheets in cocos2d

I have the following code to set up my spritesheets and batch node:
CGSize screenSize = [[CCDirector sharedDirector] winSize];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"soldier-test.plist"];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"soldier-running.plist"];
batchNode = [CCSpriteBatchNode batchNodeWithFile:#"soldier-test.png"];
self.player = [Player spriteWithSpriteFrameName:#"shooting s0000.bmp"];
[batchNode addChild:self.player];
[player setPosition:ccp(screenSize.width/2, screenSize.height/2)];
[self addChild:batchNode];
However, when I try to have player (a subclass of CCSprite) perform an action using frames from the second spritesheet, I get assertion errors related to the texture files. Do I need to combine the sheets into one, or is there a way to span one CCSprite over multiple spritesheets?
A SpriteBatchNode can only have children that all use the same texture. Your player needs to use the texture soldier-test.png if you want to add it to your batchNode.
With a TextureAtlas you can put multiple different textures into one big image.