Cocos2d: Change sprite's zOrder dynamically (using CCSpriteBatchNode) - cocos2d-iphone

Is there a way to change the zOrder of a sprite rendered by CCSpriteBatchNode? I've tried it like this:
[self reorderChild:mySprite z:indexOfAnArray];
I get this error: 'If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called'
I also tried with the zOrder property of the sprite but unfortunately is read-only.
I need to change the zOrder because, depending on the position where my sprite will appear, the zOrder needs to be changed.

self is probably not the parent of sprite. Remember that the parent is the CCSpriteBatchNode that holds it, and self is, from your point of view, probably the scene.

Related

Move sprite to top of all elements - Cocos2d

I know how to position a CCSprite in relation to all children nodes based on
sprite.zOrder = 5;
However, I have a CCNode that is added to the CCScene and I need a child of that CCNode to be positioned above all the elements in the CCScene. Is this possible?
You can perhaps go for manually setting the vertexZ property. Its hidden so you will have to #import CCNode_Private.h. This will break the parent children ordering the zOrder enforces but perhaps that is what you want.
You will also need to enable depth buffer CCSetupDepthFormat: #(GL_DEPTH_COMPONENT24_OES)

How to get the visible rect of the node in cocos2d or cocos2d-x?

How to get the visible rect of the node? Sometime i need to hide 50% of the sprite, if the touch point is in the hidden part, just return but not to active the callback function.
There is no default functions, maybe you need to create your own class to handle it.
You can try to create a subclass of CCNode with a changeable CCRect as touchable area, or you can try to read the Image Raw data and detect if the touch position pixel is transparent or not.

CCNode's position

This post discusses cons/pros of subclassing CCSprite or having CCSprite as member.
Suppose I have a CCNode which has a CCSprite as a member.
Then I'll add the CCNode as a child to my layer
and add CCSprite to the CCNode.
Now I want to change the position of CCSprite, should I change the position of the CCNode which contains the CCSprite or CCSprite itself?
If I change CCSprite's position, what happens to the CCNode's position?
edit
Is this considered an acceptable practice?
Am I better off setting CCNode's position and let CCSprite be positioned wherever CCNode is?
Adding a CCSprite as a child of a CCNode can be helpful when you have multiple sprites that you want to move along with the node.
Consider the example of a player sprite. Say you want to put a shadow underneath the player. Adding both the shadow sprite and the player sprite to a parent CCNode allows them both to be moved easily.
If you have a single sprite that has no other sprites you want to move along with it, then you don't need the CCNode parent.
nothing will be happened with your sprite. if you do not set content size and anchor point to your sprite's container, position of the node always will be equal to the position of node's (0.f, 0.f). so, position of your sprite will be related to it's parent (0.f, 0.f)
Basically, all Node in cocos2d-x have a parent Node (except Scene).
Changing the position of a parent Node will apply the position changes to all its child,
Changing the position of a Child Node will not affect anything unless this Child Node has its own children.
In your Example, If you change the CCSprite position, the position of CCNode will remain the same. But, if you changed the position of your CCNode, the same changes(shifting on the screen) will happen on the Sprite.
You want to set the sprite's position. The simple reason being that the node may contain other child nodes which should be able to move independently from the sprite.
Changing a node's position does not affect the parent's position at all. Likewise, changing a parent's position does not change the child node positions at all. Child node positions are an offset to their parent position, so if you move the parent they will follow along but their position property (which is relative to the parent position) remains the same.
You'd better move the CCNode's position cause the position of the CCSprite is also affected by its parent.
Although by moving the CCSprite's position you'll get the same result visually(its parent is not moved), it makes getting the position of a sprite more complicated and confusing.

How can I display the anchorpoint for a CCNode in cocos2d?

Is there a way to display a CCNode's anchor point? This would be very useful for debugging.
Not built-in, but you could draw a point or circle at the anchor point location using the anchorPointInPoints property.
-(void) draw
{
[super draw];
ccDrawCircle(self.anchorPointInPoints, 20, 0, 8, YES);
}
Of course, I always recommend not to change the anchorPoint in the first place. The alternative is to add the node to a parent node, offset it from the parent, and then the parent's position acts like the anchorpoint for the child node. The advantage is that methods like boundingBox aren't offset from the node's position (can be an issue for hit detection), and you can rotate the child node around its center point and around its parent.
You can access the anchor point of a CCNode with
- (CGPoint) anchorPointInPixels
which is a readonly method. Afterwards, you have several ways of actually marking the spot. You could use
- ccDrawCircle()
while overriding the draw method or alternatively put up a texture on that point, if you want something fancier.

How to add global CCLayer which is not affected by scene transitions in Cocos2d?

Is it possible to add global layer in Cocos2d, which is not affected by scene transitions?
As I can see, it should be above all scenes hierarchy.
There's an old and short discussion on Cocos2d forum, but there's no answer:
http://www.cocos2d-iphone.org/forum/topic/8071
UPD. 'by scene transitions' I mean 'by animated scene transitions'.
You can use the notificationNode property of CCDirector to place a CCNode (ie.CCLayer, CCLabel, etc.) that will remain above scenes, even during transitions. Something like this:
CCLayer *layer = [CCLayer node];
CCLabelTTF *label = [CCLabelTTF labelWithString:#"Test" fontName:#"Marker Felt" fontSize:32];
[layer addChild:label];
[[CCDirector sharedDirector] setNotificationNode:layer]; // Layer should be placed here
[layer onEnter]; // Schedule for updates (ie. so that CCActions will work)
It's meant for notification purposes (ads, etc.) so I wouldn't suggest trying to do anything too fancy from this node.
My gut says no, my brain says maybe.
The documentation says "It is a good practice to use and CCScene as the parent of all your nodes."
I can't test this right now, but looking at the inheritence diagram of CCNode, it looks like the logic of CCNode and CCScene differs only by anchor point. So, you might be able to create a CCLayer to use as your root layer, and add two children to it - A root CCScene, and a CCLayer for your GUI (with a higher Z order).
However, scene transitions may still be tricky, as you generally call CCDirector replaceScene, which works on the root scene you give it. If you give it the CCScene child of your root CCLayer, it may not draw the CCLayer and its GUI child. If you give it the root CCLayer, you are in the same situation as before.
I would still give it a try.
You can create a CCLayer subclass and turn it into a singleton. You add it to the scene like any other child node.
Whenever you transition from one scene to another, you can then remove the layer from the old scene and add it to the new scene as a child. This will only work if you don't use scene transition animations.
The alternative is to not use the CCDirector replaceScene method, and instead design your app to run as a single scene that never changes. To "fake" the changing of a scene you will use two layers, one global layer and another layer that contains your current scene nodes. If you want to transition you can animate the layer with CCActions to, for example, slide out of the screen while sliding in a new layer with a different node hierarchy. All you really lose is the convenience of the CCSceneTransition classes for animating scene changes.