How to change the image of a CCSprite in cocos2d v3.x - cocos2d-iphone

In cocos2d 2.x we change the image of a CCSprite using CCTexture. But in cocos2d 3.x CCTextureCache seems to be deprecated as Xcode warns me : "undeclared identifier 'CCTextureCache'". Or may be am I miss something as I'm new to cocos.
So how can we change the image of a CCSprite in v3 ??
Thank you.

I think I know how to do.
We have to use a spriteSheet built with TexturePacker [note : may be it's wrong to speak about external resources like it on SO] for example (let's say we have 2 images : monster_01.png and monster_02.png).
We add the .plist and the .png into xCode
We put the spritesheet in cache
and then we can create a CCSprite with a frame using a item of the spritesheet.
This image can be changed.
Some code :
3) We put in cache
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"monsterSpriteSheet.plist"];
4) We create the sprite
CCSprite * mySprite = [CCSprite initWithSpriteFrame: [CCSpriteFrame frameWithImageNamed: #"monster_01.png"]];
5) To change image :
[mySprite setSpriteFrame:[CCSpriteFrame frameWithImageNamed: #"monster_02.png"]];
This works perfectly with cocos2d v3.
I spent 6 hours to have this process. Sometimes I feel stupid.

You can do it by using this
CCSpriteFrameCache and after that you can change you sprite by using function setSpriteFrame of ccsprite.

Related

Strange artefacts appear on CCSprite

I have a CCLayer class imported onto a game layer
strangely all the the sprites have "artefacts" that seem to appear from nowhere since I have checked and re-exported all of the files
Is some setting or something else that could cause this to happen?
I'm new at this
but I have checked so far:
set to PixelFormat_RGBA8888
PVRImagesHavePremultipliedAlpha:YES
png's are clear from artefact (28bit with transparency)
Textures are made with texture packer with "pre-multiplied"
The Background is a CCLayer
The Mine is a CCLayer
both are added to the game layer (cclayer also) as "addChild"
backgroundManager = [[BackGround alloc] init];
[self addChild:backgroundManager z:0];
myShip = [[Ship alloc]init];
[self addChild:myShip z:5];
Yes it was the settings in texture packer
after a few changes in the settings they now seem to load fine.
with no artifacts
use pre multiple
trim not crop
and give a little more inner padding
hope it helps someone else (since it was driving me a little crazy)

Updating a CCTexture2D from a BatchNode

After I completed my testing, I have moved my images over to a spritesheet.
I loaded up the batchnode with the appropriate files and my images load just fine.
But I am running into an issue of swapping the textures out. When the images were individual files, there was no problem. Now it seems the CCTexture2d doesn’t like my sprite sheet.
I have the objects stored in a multidimensional array, so I can run through them quickly and update their image.
Here is what I did when it worked:
CCTexture2D* tex = [[CCTextureCache sharedTextureCache] addImage:#"alt-image.png"];
[((MyFunObject*)[[myFunObject2DArr objectAtIndex:j]objectAtIndex:i])->img setTexture: tex];
Here is what I am doing now:
CCTexture2D* tex = [[CCTextureCache sharedTextureCache] addImage:[CCSprite spriteWithSpriteFrameName:#"alt-image.png"]];
[((MyFunObject*)[[myFunObject2DArr objectAtIndex:j]objectAtIndex:i])->img setTexture: tex];
MyFunObject is a subclass of CCSprite and has an CCSprite img property that get set. I run through the array and find like objects and replace their image with a new image “alt-image.png”.
Seems simple, but outside of a sprite sheet this worked flawlessly.
Can someone tell me what I am doing wrong?
UPDATE:
HERE IS THE SOLUTION FOR ANYONE IN THE FUTURE WHO HAS THIS ISSUE
You can't change the sprites 'texture' when the texture in question is spritesheet. (Slapped my head on that one)
You can only change the rectangle that is viewed.
Here is how you do it:
[((MyFunObject*)[[myFunObject2DArr objectAtIndex:j]objectAtIndex:i])->img setTextureRect:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: #"alt-image.png" ].rect];
Notice I changed setTexture to setTextureRect, then I called the SpriteFrame's rectangle as an argument.
Enjoy.

Error adding sprites using addchild method: argument must to be non-nil

I've a problem using the method addchild adding sprites
previously I've never had this problem and I could add png files without problems,now sometimes if I try to add some sprites to the scene using the addchild method I receive these errors:
[2126:15503] cocos2d: CCTexture2D. Can't create Texture. cgImage is nil
[2126:15503] cocos2d: Couldn't add image:image_1.png in CCTextureCache
[2126:15503] * Assertion failure in -[HelloWorldLayer addChild:]
I think that the problem isn't in the code because if I try to add sprites using the images included in the default Cocos2d project it works... I receive this error only from some images...also if I've added it by the same way to the project and to the scene, what could be the cause?
I receive this error also using the default helloWorldLayer class, without changing anything, only adding
CCSprite * sprite = [CCSprite SpriteWithFile: #"image_1.png"];
[self addChild:sprite];
the rest of the code is exactly the same of the default HelloWorldLayer class
there could be something that might cause this error in some png files?
Add image_1.png to your Xcode project. Make sure you use the exact same filename, for example Image_1.PNG won't load on devices due to uppercasing.

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.

reveal the contents of a layer through a rectangle "cut-out" with cocos2d?

I am looking for a way to mask out a layer and reveal the contents of the layer through a rectangle (actually I want multiple rectangles to reveal the underlying layer's content).
I came across this similar question:
Cocos2d iPhone - Sprite cliping/mask/frame
Which had a solution:
http://www.learn-cocos2d.com/2011/01/cocos2d-gem-clippingnode/
However, when trying to use this class, I get the warning: "implicit declaration of function 'glPushMatrix' is invalid in C99"... I also get the error: "Property 'deviceOrientation' not found on object of type 'CCDirector *'"
What do I need to do to get this to work with the latest version of cocos2d?
... In any event, I commented out the deviceOrientation stuff, just to test if it will even work, and it doesn't seem to be.
I've got a CCBatchNode:
sheet = [CCSpriteBatchNode batchNodeWithFile:#"bg.png" capacity:500];
Then I add many sprites to that
[sheet addChild:sprite1];
[sheet addChild:sprite2];
[sheet addChild:sprite3];
Then I make the clipping node layer
ClippingNode *clipNode = [ClippingNode node];
clipNode.clippingRegion = CGRectMake(50, 50, 200, 200);
Then I add the sprite sheet and the clipNode:
[layer addChild:sheet];
[layer addChild:clipNode];
Then I add that to the CCSprite object
[self addChild:layer];
...
The result is, I see my many sprites from the sheet, but there is no clipping mask.. And my console shows a million: "OpenGL error 0x0502 in -[CCTextureAtlas drawNumberOfQuads:fromIndex:] 556"
so..... I am not sure what I am doing wrong-- or if this all has to do with the openGL warnings and device orientation errors... ?
UPDATE: I added #include <OpenGLES/ES1/gl.h> to the ClippingNode.m, and it got rid of the glpush/pop warnings.. But still results in the same OpenGL error once I add the clipNode child to the layer...
You can do it with shaders in cocos2d 2.0. Have a look at this tutorial.
http://www.raywenderlich.com/4428/how-to-mask-a-sprite-with-cocos2d-2-0