6

I'm trying to control the order in which CCSprites are being layered one on top of the other. I'd use zOrder, but I'm animating characters made up of articulated sprites (some sprites parented on others with addChild) and zOrder is only honored among sibling sprites.

Basically, I want to parent my sprites so they can inherit each others' transforms, but I want to determine the draw order.

Looking around, it sounds like using a CCSprite's vertexZ property is the way to go. I've tried that. I set the draw method of my custom CCSprite like so:

- (void)draw
{
    glEnable(GL_BLEND);
    CHECK_GL_ERROR_DEBUG();
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);
    CHECK_GL_ERROR_DEBUG();
    [super draw];
    glDisable(GL_BLEND);
}

Each of my sprites now has a zOrder of 0 and a unique vertexZ to layer them as I'd like, but it's not working: any sprite that has a parent is not displayed!

Trying some things, I find if I don't set vertexZ, all sprites are displayed. And if I keep the vertexZs and don't parent, they're all displayed. But with vertexZs set, any child sprite won't display.

What's going on here and how can I get it to work?

Update: More clues. I can comment out the GL functions around my call to [super draw] entirely and the results are the same. Also, it turns out child sprites with a vertexZ do display, but wherever they overlap any other sprite they go invisible. The purple paper sprite is a child of the creature's left forearm sprite (on screen right) yet should go on top of it.

There are bites taken out of the purple sprite wherever it's over or under other sprites.

For the picture above, I'm basically doing this in my CCLayer. I want the parenting, but I want hand and paper to be on the top.

[self addChild:lUpperarm];
[self addChild:lForearm];
[self addChild:face];
[self addChild:rUpperarm];
[self addChild:rForearm];
[lForearm addChild:handAndPaper];

lUpperarm.vertexZ = -100;
lForearm.vertexZ = -99;
face.vertexZ = -98;
rUpperarm.vertexZ = -97;
rForearm.vertexZ = -96;
handAndPaper.vertexZ = -95;

This is how I want it to look. (I changed the last line to [self addChild:handAndPaper] which loses lForearm's transformations, not what I want.)

The purple paper covering the other sprites.

Update 2: Some have suggested I add all children with zOrder set to -1: e.g. [lForearm addChild:handAndPaper z:-1]. This changed things a little, but still didn't fix it, alas. Seems either vertexZ is not determining draw order and/or the blending is wrong.

The effects of zOrder -1.

Community
  • 1
  • 1
Dylan
  • 2,315
  • 2
  • 20
  • 33

4 Answers4

1

I dealt with this issue when writing an RPG with Cocos2d. The problem is the alpha blending. As you are seeing, the paper is being covered up by the left arm sprite, even though it is transparent. For some reason, when Cocos2d's vertexZ technique is used, this problem can sometimes occur. To fix it, you can try changing your alpha blending level. Try 0.0, 0.5 and 1.0:

-(void) draw
{
    glEnable(GL_ALPHA_TEST);
    glAlphaFunc(GL_GREATER, 0.0f);
    [super draw];
    glDisable(GL_ALPHA_TEST);
}

If that doesn't work, then I recommend a complete workaround solution. Keep all your sprites as part of the same parent node and use regular z ordering. It's not an ideal solution, but if you use a "meta" parent node then you can still transform all the children easily.

Nathanael Weiss
  • 737
  • 1
  • 10
  • 23
0

While adding only u can control z-order?

[self addChild:lUpperarm z:1];
[self addChild:lForearm z:2];
[self addChild:face z:3];
[self addChild:rUpperarm z:4];
[self addChild:rForearm z:5];
[lForearm addChild:handAndPaper z:6];
Guru
  • 21,652
  • 10
  • 63
  • 102
  • I've tried that -- just did again -- and z-order has no effect. I've even read it's best to give them all the same `zOrder` and let `vertexZ` resolve ordering. I'd wager the problem is in the drawing somehow. – Dylan Aug 29 '12 at 16:31
0

I can't be sure that this is your problem but I've had issues in the past when playing with draw() and it turned out to be that I wasn't resetting the blendfunc at the end of the call.

Here's a draw function I use that does some basic drawing with some transparency. Again, no guarantees.

- (void) draw {
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    ccDrawSolidPoly(vertices, 4, fillColor);

    // This is the important bit.  Must do this last.
    //
    glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
}
PKCLsoft
  • 1,359
  • 2
  • 26
  • 35
-3

set higher z value to set object on top. and lower z value to set in back..

Ayaz
  • 1,398
  • 15
  • 29
  • That works fine among siblings, sprites that share the same parent. But that's not what I'm asking. I want to make a child (and potentially some of its children) be above its own parent while inheriting the parent's transforms. – Dylan Aug 30 '12 at 12:51