Search code examples
cocos2d-iphoneisometric

Best way for z-ordering sprites on isometric map with cocos2d


after few headaches i figured out that using CCSpriteBatchNode with cocos2d olny allows to z-order sprites added to it as child (which is obvious, now i see..)

    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"token_default.plist"];
    CCSpriteBatchNode *tokenSpriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"token_default.png"];
    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"objects_default.plist"];
    CCSpriteBatchNode *objectsSpriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"objects_default.png"];

    CCSprite *token = [[[CCSprite alloc] initWithSpriteFrameName:@"token_SE.png"] autorelease];
    [token setPosition:tokenSpawnPoint];
    CCSprite *enemy = [[[CCSprite alloc] initWithSpriteFrameName:@"token_blak_SE.png"] autorelease];
    [enemy setPosition:enemySpawnPoint];
    CCSprite *houseA = [[[CCSprite alloc] initWithSpriteFrameName:@"house_small.png"] autorelease];
    [houseA setPosition:[self randomHousePosition]];
    CCSprite *houseB = [[[CCSprite alloc] initWithSpriteFrameName:@"house_big.png"] autorelease];
    [houseB setPosition:[self randomHousePosition]];

    [tokenSpriteSheet addChild:token];
    [tokenSpriteSheet addChild:enemy];
    [objectsSpriteSheet addChild:houseA];
    [objectsSpriteSheet addChild:houseB];

and since i have to add them to the display list as follows..

    [_isoMap addChild:objectsSpriteSheet];
    [_isoMap addChild:tokenSpriteSheet];

there is no way i can change the z-order of single tokens between other houses...
they will be always rendered over the house until i change the order of these batch nodes

btw, i can "merge" all sprites' arts in one big single batch node... doing so it became possible to order sprites using sprite's coordinates

    [fullSpriteSheet reorderChild:token z:token.position.y];

i'm a little stuck with it...... is there a way to achieve that, having different sprite bacth nodes? or is possible to programmatically merge two batchnodes? (or something like that)

i found KnightFight, a really interesting open project on github by LozArcher.. he used CCSpriteFrame and CCSprite's setDisplayFrame method, instead of batch nodes... but i can't run it since it seems to be an older version of cocos2d (apparently not working with xcode 4)


Solution

  • i found out that changing the vertexZ property of a CCNode (like a CCSprite) it actually changes its Z position (so it will be slightly bigger/smaller, and also translated)

    so, in order to arrange on z-index CCSprites with different spriteSheet i had to use reorderChild method (to just change the rendering order) and mostly i need NOT TO USE CCSpriteBatchNode..

    after a little refactoring of the above example, i should have:

    CCSprite *token = [CCSprite spriteWithSpriteFrameName:@"token_SE.png"];
    [token setPosition:tokenSpawnPoint];
    CCSprite *enemy = [CCSprite spriteWithSpriteFrameName:@"token_blak_SE.png"];
    [enemy setPosition:enemySpawnPoint];
    
    CCSprite *houseA = [CCSprite spriteWithSpriteFrameName:@"house_small.png"];
    [houseA setPosition:[self randomHousePosition]];
    CCSprite *houseB = [CCSprite spriteWithSpriteFrameName:@"house_big.png"];
    [houseB setPosition:[self randomHousePosition]];
    
    [_isoMap addChild:token];
    [_isoMap addChild:enemy];
    [_isoMap addChild:houseA];
    [_isoMap addChild:houseB];
    

    i also added each sprite to a NSMutableArray and then in a for loop (inside the update scheduled method):

    CCSprite *sprite = [mySpritesArray objectAtIndex:i];
    [_isoMap reorderChild:sprite z:(_isoMap.mapSize.height - sprite.y)];
    

    hope this could help someone :)