Loading SWFs into CCSpriteFrameCache

If I were a betting man, I would bet that Flash is one of the most common asset creation tools for 2d sprite based games. In the past this meant that some poor schmuck would have to export all these nice vector based images out to PNGs. Compared to a SWF file the resulting PNGs take up a huge amount of space. This places restrictions on the quality and quantity of art in iOS games if you want to limbo under that magical bar.

I've been dreaming of loading SVGs or SWFs directly into cocos2d, but I never bit the bullet and built something to do it. Well yesterday dreams came true. I came across a post on the cocos2d forums pointing to a great post by Luke at zinc roe. Using the MonkSWF project by Micah Pearlman, Luke put together a nice cocos2d wrapper called SWFNode which let's you create an animated cocos2d node from a SWF. Each frame in the SWF becomes a frame in the animation. Go read his blog post, download and setup the Xcode 4 workspace he provides, and start playing!

It is important to note that MonkSWF and MonkVG do not support everything that Flash supports, so some files will not load properly.

Not Supported by MonkSWF:

  • Bitmap fills and strokes
  • Gradient fills and strokes
  • Font rendering
  • Morph targets

I also experienced a number of crashes when loading extremely large and complex SWFs. I have not tracked down the source yet.

SWF to CCSprite

Some projects may need to do a bit more than create a looping SWF node. I can think of a number of helpful cocos2d extensions that go beyond SWFNode that have yet to be built. So let's get started!

If you already have a project underway and you want to take advantage of the space savings that SWF provides, then you may need to use SWF frames as sprites. One way to do that is to write the SWF frames to a CCRenderTexture and then save them to CCSpriteFrameCache. Last night I wrote a category to extend CCSpriteFrameCache to do just that:

You simply pass the filename of the SWF resource to this method and it will add each frame to the sprite frame cache. If the filename is 'taco.swf' and it has 50 frames, then 50 CCSpriteFrames will be added to the cache named: "taco_1.png", "taco_2.png", …, "taco_50.png".

Here is the full method:

Improvements

This is just a quick example of what can be done quite easily using cocos2d and MonkSWF. There are likely to a number of performance improvements, bug fixes, etc that can be made on this code. When I begin to integrate it into a real project I will post any improvements I make back here. Please feel free to contribute to, expand, or take the sample above for your own use.

One of the issues with the sample above is that the quality of the sprite generated by writing to CCRenderTexture is lower than if I write directly to the screen. It appears as if partial transparency is not being taken into account when writing to the texture. I will continue to look into it, but if anyone with more experience with CCRenderTexture has any thoughts please let me know.

Example:

Update:

The rendering issue was resolved by utilizing multisampling. In cocos2d multisampling is enabled by default, but it is not applied to CCRenderTexture. I will do a follow up post detailing the changes. For now here are some lovely puppies: