currently I am adding my background via the method below. how can I modify the background so that it auto scrolls along with the tilemap.
- (void)setupParallax {
NSString *backgroundName = [self.tilemap propertyNamed:#"BackgroundImage"];
CCSprite *background = [CCSprite spriteWithFile:[AssetHelper
getDeviceSpecificFileNameFor:[NSString stringWithFormat:#"background-%#.png",backgroundName]]];
background.anchorPoint = ccp(0,0);
background.position = CGPointMake(0, 0);
[self addChild:background z:0];
}
You may use a CCParallaxNode. Your background and map would be children of the parallaxNode, and when you move it, its children will automatically move accordingly. Assuming the background should be behind your map, the code will look something like this.-
CCParallaxNode *voidNode = [CCParallaxNode node];
[voidNode addChild:background z:10 parallaxRatio:ccp(0.8f, 0.8f) positionOffset:ccp(0, 0)];
[voidNode addChild:map z:20 parallaxRatio:ccp(1.0f, 1.0f) positionOffset:ccp(0, 0)];
[self addChild:voidNode];
ParallaxRatio will set the speed of each layer based on ParallaxNode movement:
(1.0, 1.0) means that the map will move at the same speed that the voidNode among x and y.
(0.8, 0.8) means that the background will move 80% slower than the ParallaxNode
I created a simple, 2 frame sprite animation based off a few tutorials that I found across the web. I took my 2 images, created a sprite sheet with plist and png file, and incorporated them into my code as seen below. This setup worked fine in Cocos2d V 1.0.1. I just upgraded my project to 2.0rc0a and now my app crashes with the following error at the point where it should switch from the first frame to the second: 'CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteBatchNode'
I looked at this SO question, but I'm not sure if it's the same thing that I'm doing wrong, and because I'm still very new to Cocos2d, am unsure how to correctly adjust my code. Is this something that was changed in 2.0 that I didn't see in the notes, a bug that I should report, or just incorrect coding on my part? I still have a copy of the 1.0.1 project with identical code and the animation works correctly.
//CHAMELEON
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"front page/mainchameleon.plist"];
mainChameleon = [CCSpriteBatchNode batchNodeWithFile:#"front page/mainchameleon.png"];
[self addChild:mainChameleon z:7];
NSMutableArray *chameleonFrames = [NSMutableArray array];
for (int i = 1; i <= 2; ++i)
{
[chameleonFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"chameleon%d.png", i]]];
}
CCAnimation *mouthAnim = [CCAnimation animationWithSpriteFrames:chameleonFrames delay:0.3f];
chameleon = [CCSprite spriteWithSpriteFrameName:#"chameleon1.png"];
CCAnimate *chameleonAction = [CCAnimate actionWithAnimation:mouthAnim];
CCDelayTime *chameleonDelay = [CCDelayTime actionWithDuration:10];
CCRepeatForever *chameleonRepeat = [CCRepeatForever actionWithAction:[CCSequence actions:chameleonDelay, chameleonAction, chameleonDelay, nil]];
[chameleon runAction:chameleonRepeat];
[mainChameleon addChild:chameleon];
If I comment out chameleon = [CCSprite spriteWithSpriteFrameName:#"chameleon1.png"]; then the app doesn't crash, but the chameleon doesn't appear at all, as would be expected with how the code is currently written.
Or, if I comment out [chameleon runAction:chameleonRepeat]; then the chameleon appears showing the frame, chameleon1.png, but obviously doesn't go through the animation.
OK, so to make me even more confused because I'm definitely missing something, I tried changing the bottom portion of the code to this and the animation goes from frame 1, to frame 2, then stays on 2 indefinitely. However, if I make the delay anything longer than 1.0, I receive the same error I was getting before. If I re-include chameleonDelay prior to the action without the repeat forever statement, I also get the same crash. It appears that the app crashes if it has to wait longer than 1 second to perform the switch. What I need is for frame 1 to sit for a while (10 seconds) then switch to frame 2 for 0.3 seconds, then switch back to frame 1 and sit for a while again.
Attempted code #2:
CCAnimation *mouthAnim = [CCAnimation animationWithSpriteFrames:chameleonFrames delay:0.3f]; //<--- maxes out at 1.0. Anything more causes crash
chameleon = [CCSprite spriteWithSpriteFrameName:#"chameleon1.png"];
CCAnimate *chameleonAction = [CCAnimate actionWithAnimation:mouthAnim];
[chameleon runAction:chameleonAction];
[mainChameleon addChild:chameleon];
YvesLeBorg suggested using the restoreOriginalFrame statement, but that is deprecated in ver 2.0. I tried using
CCAnimation *mouthAnim = [CCAnimation animationWithAnimationFrames:chameleonFrames delayPerUnit:0.3f loops:5];
and get the error '-[CCSpriteFrame delayUnits]: unrecognized selector sent to instance'. I'm not sure why that isn't working or what else to try from here.
EDIT: So Now It's Working...But not as efficiently coded as I'd like:
New Code:
//CHAMELEON
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"front page/mainchameleon.plist"];
mainChameleon = [CCSpriteBatchNode batchNodeWithFile:#"front page/mainchameleon.png"];
[self addChild:mainChameleon z:7];
NSMutableArray *chameleonFrames = [NSMutableArray array];
//Frame 1 - closed mouth
[chameleonFrames addObject:[CCSpriteFrame frameWithTexture:mainChameleon.texture rect:CGRectMake(0, 124, 149, 122)]];
//Frame 2 - Open Mouth
[chameleonFrames addObject:[CCSpriteFrame frameWithTexture:mainChameleon.texture rect:CGRectMake(0, 0, 149, 122)]];
//Frame 1 - closed mouth
[chameleonFrames addObject:[CCSpriteFrame frameWithTexture:mainChameleon.texture rect:CGRectMake(0, 124, 149, 122)]];
CCAnimation *mouthAnim = [CCAnimation animationWithSpriteFrames:chameleonFrames delay:0.9f];
chameleon = [CCSprite spriteWithTexture:mainChameleon.texture rect:CGRectMake(0,124,149,122)];
CCAnimate *chameleonAction = [CCAnimate actionWithAnimation:mouthAnim];
CCDelayTime *chameleonDelay = [CCDelayTime actionWithDuration:10];
CCRepeatForever *chameleonRepeat = [CCRepeatForever actionWithAction:[CCSequence actions:chameleonDelay, chameleonAction, nil]];
[chameleon runAction:chameleonRepeat];
[mainChameleon addChild:chameleon];
I really liked the way that I was doing it in 1.0.1 because if I had 2 frames or 100 frames, I only had to make a small adjustment to the if statement. This way requires coding each individual frame which seems counter-intuitive to using a plist. If no one is able to provide a better solution, or "real" answer in the next few days, I will post this as an answer and accept it to close out the question.
Here's the code I ended up with that works correctly. Not sure why I had to make these changes, but there it is. (Some of the names have changed as I started a new project to fix this on, but the differences between my original code and this are apparent). To anyone else finding this thread, my original code was based on Ray Wenderlich's sprite sheet tutorial.
CCSpriteBatchNode *chameleonBN = [CCSpriteBatchNode batchNodeWithFile:#"chameleonimages.png"];
[self addChild:chameleonBN];
//ADDED the texture part to resolve: 'CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteBatchNode'
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"chameleonplist.plist" texture:chameleonBN.texture];
NSMutableArray *chameleonframes = [NSMutableArray array];
for (int i = 1; i <= 2 ; i++)
{
[chameleonframes addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:#"chameleon%d.png", i]]];
}
CCAnimation *mouthAnim = [CCAnimation animationWithSpriteFrames:chameleonframes delay:0.9f];
//ADDED this sprite frame to resolve texture id assert error
CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:chameleonBN.texture rect:CGRectMake(0, 0, 149, 122)];
CCSprite *chameleon = [CCSprite spriteWithSpriteFrame:frame];
chameleon.position = ccp(512,384);
CCAnimate *chameleonAnimate = [CCAnimate actionWithAnimation:mouthAnim];
CCDelayTime *chameleonDelay = [CCDelayTime actionWithDuration:10];
CCDelayTime *chameleonDelay2 = [CCDelayTime actionWithDuration:0.1];//Had to use this to ge tthe mouth to close. Using restore original frame doesn't work for me.
CCRepeatForever *chameleonRepeat = [CCRepeatForever actionWithAction:[CCSequence actions:chameleonDelay, chameleonAnimate, chameleonDelay2, nil]];
[chameleon runAction:chameleonRepeat];
[chameleonBN addChild:chameleon];
Not certain whether this is a 2.0 issue or not, but i notice you are using twice the chameleonDelay object in the same sequence. Is this really what you were trying to accomplish ie
delay,action,delay,delay,action,delay,delay,action .... etc.
try this to see if it works :
CCRepeatForever *chameleonRepeat = [CCRepeatForever actionWithAction:[CCSequence actions:chameleonDelay, chameleonAction, nil]];
This is how I create a sprite with texture form a sprite-sheet. But how do I change the sprites texture later on?
I have tried using setTexture but I can't get i working.
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"gameSpriteSheet.plist"];
CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"gameSpriteSheet.png"];
[self addChild:spriteSheet];
// Add hangman graphic sprite to Scene
playerSprite = [CCSprite spriteWithSpriteFrameName:#"playerX"];
playerSprite.position = ccp(580, 400);
[self addChild:playerSprite];
You can't.
A CCSpriteBatchNode uses a single texture. All of the sprites added to the CCSpriteBatchNode must use the same texture - that of the CCSpriteBatchNode.
I'm sure there's a different solution to the problem you're facing, give it some thought from a different angle. For example you could achieve the same effect by simply creating a new sprite.
If you're looking to change just the CCSpriteFrame of the sprite, use setDisplayedFrame.
I am making application which is crashing giving the above warning in console.
There are two sprites.
Train=[CCSprite spriteWithFile:#"train.png"];
[self addChild:train z:0 tag:1];
AlphaImage=[CCSprite node];
AlphaImage.position=ccp(245,155);
[Train addChild:AlphaImage z:1 tag:2];
In other method I am initializing AlphaImage using animation.
CCSpriteFrameCache *frameCache1 =[CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache1 addSpriteFramesWithFile:plist1];
CCSpriteBatchNode *danceSheet1 = [CCSpriteBatchNode batchNodeWithFile:png1];
[self addChild:danceSheet1];
NSMutableArray *animFrames1 = [NSMutableArray arrayWithCapacity:frame[x]];
for(int i = 1; i < frame[x]+1; i++) {
NSString *namef1=[NSString stringWithFormat:#"%#%i.png",alpha1,i];
CCSpriteFrame *frame1 = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:namef1];
[animFrames1 addObject:frame1];
}
CCAnimation *anim1 = [CCAnimation animationWithFrames:animFrames1 delay:0.3f];
CCAnimate *animN1 = [CCAnimate actionWithAnimation:anim1];
CCRepeatForever *repeat1 = [CCRepeatForever actionWithAction:animN1];
[AlphaImage runAction:repeat1];
I have used zwoptex to create plist and Texture atlas.
As train goes and comes back the plist and Texture atlas for animation changes. But after 4 or 5 times application is crashing. I have also deallcated all frames and texture before new animation comes to AlphaImage.i have used this:
[CCSpriteFrameCache purgeSharedSpriteFrameCache];
[CCTextureCache purgeSharedTextureCache];
I am using hd images for the application.I have gone through many documents, they have suggested these:
[[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFrames];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
But in console it is not showing anything about removal of frames using these lines.
Is there something that I am doing wrong?
Where are you running [[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames]; this statement run it background thread using performSelectorInBackground method of NSObject.
Try to release an array after animation ends.
//This may be the reason.
[animFrames1 release];
animFrames1 = nil;
In cocos2d, there used to be a TextureMgr method (Async) that let you load images for later use. Now when I use TextureMgr, it says it's undeclared. Is it deprecated? I'm on .99.5. If it's no longer usable, what replaces it? Is there anything that can do the same as this line?
[[TextureMgr sharedTextureMgr] addImageAsync:...NSString goes here... target:self selector:#selector(method:)];
take a look at CCTextureCache
http://www.cocos2d-iphone.org/api-ref/0.99.5/interface_c_c_texture_cache.html
maybe it is you are looking for.
This cache is used when your are creating any object weith a texture: sprite for example. And you can use it for precaching your images.
EDIT:
The CCTextureCache is used when your creating ang object with a texture, as i said - and so if the texture is already in cache the element creation is much more faster then if you would loading the texture first and then creating an object.
For example if you are writing the code like this:
id sprite = [CCSprite spriteWithFile: #"my-file.png"]
and the #"my-file.png" texture is not in cache it will be loaded first and it will take some time (much more then just creating an object).
If you are writing code like this:
id sprite1 = [CCSprite spriteWithFile: #"my-file.png"];
id sprite2 = [CCSprite spriteWithFile: #"my-file.png"];
Then sprite1 will be created slow and sprite2 much more faster because the texture is already in cache.
You can manuale add texture to cache
[[CCTextureCache sharedTextureCache] addImage: #"my-file.png"];
and the creating of all objects with this texture will be fast.
The common place in code when you have to precache textures is game loading or level package loading or level loading.
Also You can precache sounds if you need using them SimpleAudioEngine singleton
Andrew pretty much answered your question, I just want to give you a code segment about how to use CCTextureCache and CCSpriteFrameCache. Texture Cache load real textures/images and sprite frame cache loads the information regarding textures (if you are loading a Sprite sheet.)
Okay here's the sample code.
Here latestBurp1-1.pvr.ccz and burpParticles1-1.png are my sprite sheets and their information is in (same name).plist files.
In the below function I am loading textures and also spriteFrames (the info about textures).
Also take a look at pvr files and pvr.ccz file they load much faster than png.
-(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];
}
I just gave you a lot of information so you might need to google some terms.
I think you are looking for [CCSpriteFrameCache sharedSpriteFrameCache]
http://www.cocos2d-iphone.org/api-ref/0.99.5/interface_c_c_sprite_frame_cache.html