Reusing CCSpriteFrame objects with different textures

Forums Programming cocos2d support (graphics engine) Reusing CCSpriteFrame objects with different textures

This topic contains 5 replies, has 3 voices, and was last updated by  pvlasie 3 years, 2 months ago.

Viewing 6 posts - 1 through 6 (of 6 total)
Author Posts
Author Posts
February 16, 2011 at 7:53 pm #228568

pvlasie
@pvlasie

Hello,

I would appreciate some insight into this from people with more experience using cocos2d.

Basically I want to have multiple sprite sheets that use the same frames.

As an example, imagine you have an enemy sprite sheet that contains several frames: “head”, “torso”, “arms”, “legs”, etc. It should be possible to have different enemies that share the same texture layout (basically a different skin for enemies, but one that has the same physical layout).

The idea is that you could add enemies in a data-driven way, without updating the code, because you know each enemy has “head”, “torso”, “arms” and “legs” frames and the coordinates for these are always the same.

However, the current cocos2d architecture seems to prevent this, as each CCSpriteFrame is associated with a texture, so you cannot reuse a CCSpriteFrame object with another texture.

Has anyone done something like this in their projects? Is there something obvious I’m missing here?

Thank you,

Paul

February 16, 2011 at 8:28 pm #315920

Lam
Moderator
@lam

Yeah it’s really the issue of performance. For this scenario you’ll have to either have to see if you can get away with standard sprites without batching or try to handle it with more than one SpriteBatchNode.

A CCSpite that’s allocated with a CCSpriteFrame doesn’t have to be in a CCSpriteBatch. So you can lose a bit of performance but still use spriteSheets.

February 16, 2011 at 9:13 pm #315921

pvlasie
@pvlasie

Hi Lam,

The only reason I am using CCSpriteBatchNode is to draw each enemy in a single GL draw call. Am I correct in assuming that your suggestion would basically issue a draw call for each frame? If so, that is not really an option for us…

The other alternative is to create each spritesheet .plist with different frame names, for instance:

enemy1.plist

- “enemy1_head”

- “enemy1_torso”

enemy2.plist

- “enemy2_head”

- “enemy2_torso”

Then, when loading an arbitrary enemy spritesheet, we could concatenate the name of the .plist file with the previously established frame names. I don’t really like this, but it sounds feasible.

Here’s a question for the cocos2d experts:

Is there no way currently to use a local CCSpriteFrameCache for each spritesheet, instead of using the singleton sharedSpriteFrameCache?

Something like:

[myCustomFrameCache addSpriteFramesWithFile:@"enemy1.plist"];

where myCustomFrameCache would be an instance of CCSpriteFrameCache that I allocate myself for each enemy spritesheet I want to load?

Thanks,

Paul

February 16, 2011 at 11:31 pm #315922

Lam
Moderator
@lam

Yeah both ways are valid. If you want to use CCSpriteFrameCache then you just have to extend all spritesheet plists to have really specific names so you won’t have any collisions.

enemy1.plist
- "enemy1_head"
- "enemy1_torso"

enemy2.plist
- "enemy2_head"
- "enemy2_torso"

If you want a local CCSpriteFrameCache, it’s actually not that hard to write one since it really is just a dictionary storage of CCSpriteFrames.

It’s probably only a few minutes of work actually to strip out all the singleton logic and have a cache that can be instantiated.

February 17, 2011 at 3:23 am #315923

Benihana
Participant
@benihana

The only reason I am using CCSpriteBatchNode is to draw each enemy in a single GL draw call. Am I correct in assuming that your suggestion would basically issue a draw call for each frame? If so, that is not really an option for us…

As far as I know, you’re kind of asking for two things which are not compatible. Making one OpenGL call means that all the quads you want to draw are from the texture that’s currently loaded, and as far as I know you can’t load more than one texture into OpenGL at the same time, so that is the limitation, not cocos2d’s architecture (which is as a result of OpenGL’s setup).

The only way around that would be to stitch together a new texture which contains multiple textures, and pass that to OpenGL instead. I’m not sure how large you’re expecting your enemy spritesheets to be.

February 18, 2011 at 3:14 pm #315924

pvlasie
@pvlasie

Benihana: I am not trying to have a single draw call for multiple textures atlases, I only want to use the same CCSpriteFrames with different CCSpriteBatches.

Something like this:

“enemy1.plist” -> “enemy1.png” texture atlas

CCSpriteFrame “head” 0, 0, 32, 32 coordinates

CCSpriteFrame “torso” 32, 0, 32, 32 coordinates

“enemy2.plist” -> “enemy2.png” texture atlas

CCSpriteFrame “head” 0, 0, 32, 32 coordinates

CCSpriteFrame “torso” 32, 0, 32, 32 coordinates

I want to reuse the sprite frames for both enemies, seeing as the coordinates are the same. So basically 2 draw calls but without duplicating the “head” and “torso” frames.

So far I have prefixed each of my frame names to avoid collisions, however I am going to try Lam’s solution (making my own CCSpriteFrameCache by stripping out the singleton logic and supporting local, not shared frame names).

Thanks everyone!

Viewing 6 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic.