Questions about loading lots of spritesheets

Hey, I’m thinking about something that seems pretty daunting right now, wanted to get your thoughts.

In my football game, I load a single spritesheet for each team at the start of a game (one wears white jerseys, the other wears color jerseys). As a result, every player on the field has the same jersey number. The mod creators and I still have the psd files which use lots of layers for editing, and we can remove the jersey numbers and put those in separate files (a separate spritesheet for each possibly number, 0-99).

We’ve been batting around the idea of using real numbers on jerseys. Here’s my initial thought on how, and I’m not sure it’s feasible for performance and memory.

• we modify the sprite sheets not include jersey numbers
• the mod guys create 100 sprite sheets of jersey numbers (0-99) matching every player frame, preferably with two colors that I can hopefully swap on the fly (one for the jersey number and one for the outline). These are probably black (outline) and white (number), and I’d swap the colors on the fly.
• before animating a play, I load 11 sprite sheets for the offense and 11 for the defense, based on who’s on the field.
• for each frame, for every player, I load his current image from his team’s sprite sheet and also load the corresponding jersey number sprite from the sprite sheet. I then color the number and outline of that jersey number sprite based on his team and lay that sprite on top of the player sprite. So, for example, I might color the number navy blue and the outline black or white.

I’m afraid this might not be feasible because of memory and perhaps because of performance, and maybe there’s a better way to do this?

My question is, will this kill memory, since I’m loading 22 spritesheets into memory. Since I set the GL context to 24 bits at the start, my concern is that every spritesheet may load as 24 bits. Well, now that I think about it, I guess I do need to allow that jersey number to be at least 8 bits, maybe 16.

My spritesheets are pretty large, with each sheet 3840x2640 in size. That’s 10MB each (for one-bit) before I even consider the depth.

Also, would I use
SpriteFrameCache::getInstance()->addSpriteFramesWithFile();
for all 22 jersey numbers?

I load all 22 jersey numbers, because the teams will vary depending on who’s on offense, rather this is a punt, whether some subs are in the game, etc.

Now, I might be able to scale these images down to maybe 60% if that’ll help.

Any ideas on this?

thanks!

At the beginning of each round of play, or whenever players have selected their team etc, load up the required graphic files, and use a RenderTexture to blend the jersey numbers on each unique frame you need with the correct colors.

For each of those new textures/sprites you have created, get their width and height, and pass those values to a rectangle packing algorithm that will find the optimal way to fit them onto a texture size of your choosing. For instance, if you pass 4049x4096 to it, it will attempt to fit all the frames into that texture size. You get a list of coordinates for each frame in that 4096x4096 space, so use those coordinates to set the position of each one of the sprite frames you previously created, and add them to a 4096x4096 RenderTexture.

The final result is that you have now created a new sprite sheet in memory. The one thing left to do is to create a PLIST file that references all the frames in that new texture. You can use the data from the texture packer to create this PLIST file. The format of that file can be seen here, and you can also look at existing PLIST files as reference, or look up the code in Cocos2d-x that reads the PLIST to figure out what you need.

Once this is all done you can pass that dynamically created PLIST and associated texture to the sprite frame cache, and go from there. You can unload all the original sprite sheets you loaded with jerseys and numbers etc., since you no longer require them.

Assuming the resulting dynamically generated sprite sheet is only a single large texture, then it’ll be only 1 draw call, along with using a lot less RAM in the process.

There are other implementations of the texture packer, such as this.

You can save that new sprite sheet you created to disk along with the associated PLIST file, if you need to use it later, or only keep it in memory only for the duration of that round of play etc.

I hope that helps.

Thanks, I’ll have to think about that, since I have to reload them every frame, but I’ll start with this.

You did make me think of something with the Texture Packer. I’ve used Texture Packer Pro for years and will look at the other one you mentioned. Maybe I can make the jersey number spritesheet very small and figure out its anchor points per frame. That may help a lot. Thanks!

The one you sent looks very interesting, thanks again!

Sorry, I just realised that my post is missing the link to the texture packer code for the 4096x4096 example I gave. It’s here. That’s what you pass the list of image sizes to, and get back where on the texture they would be placed.