Cocos2d show only a part of a CCSprite - cocos2d-iphone

Is there any possibility to show only a part of an CCSprite?
It seams that contentSize property doesn't have a good result.

I think you might have to create a new sprite for this. The general pseudo code is this.
CCTexture2D *origTexture = originalSprite->getTexture();
CGRect rect = {0, 0, 20, 20};
CCSprite *destSprite = CCSprite::spriteWithTexture(origTexture, CGRect);

Both doc_180's and James' answers work by creating new CCSprite using a portion of the texture, but if you are using clipping method, you will get CCSprite that uses the full texture but have the ability to only draw a portion of it on screen. One advantage of this method is you are able to modify how big or small the portion that you want shown or hidden on the fly rather than having to re-create the CCSprite again and again (or replacing the texture again and again).
So, to use the clipping method, simply download the ClippingNode class from here, and add the CCSprite you want clipped to that ClippingNode. Then you call one of its methods to specify which region to limit the drawing to. I'm currently using it to create a progress bar so I know for sure it works great.

Get the [sprite displayedFrame], change the frame of that, and create a new sprite with that spriteframe: CCSprite *sprite2 = [CCSprite spriteWithSpriteFrame:frame]

Related

Exchanging sprite content in cocos2d-x 3

I exchange sprite content with this code:
mySprite->setTexture(Director::getInstance()->getTextureCache()->addImage("newImage.png"));
The problem is that newImage.png is much smaller than the old content image of the sprite. But cocos2d-x scales newImage.png to have the same size as oldImage.png. How I can prevent this scaling. I need newImage.png to be its natural size, but to appear in the coordinates of oldImage.png (I want to retain the same sprite object, as far as I have a pointer on it and also the same position and same anchor point. That's why I use setTexture just to change the image.)
Well, this may not be the cleanest way, but it seems the most straigthforward to me :
Sprite *newSprite = Sprite::create("newImage.png");
newSprite->setAnchorPoint(mySprite->getAnchorPoint());
newSprite->setPosition(mySprite->getPosition());
mySprite->removeFormParentAndCleanup(true);
mySprite = newSprite; // <-- magic happens here
So basically you create a new sprite, place it based in old sprites position/anchor and then after removing the old one, you assigne the mySprite variable to point to the same place as newSprite.
mySprite->setTexture("newImage.png");
This sets the content Rect too.

ccSpriteBatchNode child bounding box transformation

I'm using cocos2d 1.0.1.
I've created a CCSpriteBatchNode, it includes a CCSprite (let's name it parentLayer) which includes some X number of childs(CCSprites).
The problem is - when I rotate parentLayer all sprites (childs) correctly displayed, however bounding boxes are at the same place (where they've been before rotation), so world coordinates of those sprites won't be changed.
Off course, all of the above works great without CCSpriteBatchNode. But, I would like to use batch node due to amount of sprites involved.
The question is, is there any way to update bounding boxes & child positions correspondingly?
How many sprites are we talking about? I would just go with a fast enumeration call to rotate each one individually. I nave never noticed a performance hit when doing this, have you?
CCArray *listOfChildren = [parentLayer children];
for (CCSprite *sprite in listOfChildren) {
[sprite setRotation:someValue];
}

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

Cocos2d tiled map add sprites

In the isometric tiled map z-ordering example for cocos2d-iphone, they use an object that is already in the tilemap as the player sprite, which is rendered as moving through the trees.
Is there a way to use a random CCNode, created though code (not in the tmx file, and not part of the sprite sheet), and have it z-ordered correctly with the tilemap? addChild is not supported on a CCTMXLayer, and the gives an error when using that reads:'addChild: is not supported on CCTMXLayer. Instead use setTileGID:at:/tileAt:'.
There's got to be a way to have a CCNode (let's say a simple CCSprite) z-order correctly with a tilemap, either using cocos2d's API, or some z-buffer technique. Any pointers?
The CCTMXLayer doesn't support adding tiles at runtime because it's implemented with all sprites on a single spritesheet. Because of this implementation detail you also can't call setTexture on an individual tile.
The easiest solution would be to have the sprite you want to use on the spritesheet at the beginning. If you can't do this because it's generated at runtime or something, the next best thing (without touching cocos2d code) would be to modify the spritesheet.
Put a dummy tile in the spritesheet you're using for the TMXLayer and then, once you have the image you want to use, write it to the spritesheet using CCRenderTexture or something and use the newly generated Texture as your TMXLayer's texture.
You could also modify the CCTMXLayer to allow for your functionality but it sounds like you want to avoid that.
If you want to add a tile to say tile (x,y) ( (x,y) in Tiled Map editor coordinates ) then use the following code -
myTileMap is the reference to the CCTMXTiledMap object.
CCTMXLayer *layer=[myTileMap layerNamed:#"yourlayer"];
NSAssert(floorLayer !=nil, #"Ground layer not found!");
CGPoint tileAddPosition = [layer positionAt: CGPointMake(x,y)];
//Create your CCNode or CCSprite or whatever...say object name is **tileToBeAdded**
tileToBeAdded.anchorPoint = CGPointZero;
tileToBeAdded.position = tileAddPosition;
[myTileMap addChild:addedTile z:1];

create a texture from a spritesheet cocos2d

Hey all
Basically all i want is to create CCTexture2D objects from a spritesheet. I can make individual sprites from
charSpriteCur = [CCSprite spriteWithTexture:charSheet.texture rect:CGRectMake(136, 0, 136, 223)];
but i want to get individual textures from a spritesheet so that i can use
[mySprite setTexture:tex];
to change the sprite as required. I dont need it to be an animated sprite i just want to be able to change its texture when i want using a spritesheet.
any ideas with this or what is the best approach?
thanks
g
I don't think this is possible. When I need to do this I instead remove the CCSprite node (which I have setup as a property in my class) and then make a new one. Here is an example:
[self removeChild:[self mySprite] cleanup:YES];
[self setMySprite:[CCSprite spriteWithSpriteFrameName:#"image.png"]];
[mySprite setAnchorPoint:ccp(0,1)];
[mySprite setPosition:ccp(623,872)];
[self addChild:mySprite z:5];