One of the most difficult issues to deal with is animation of complex objects. In our case, we are talking about creatures such as the imp depicted here. This shows a creature in an attack animation. The goal is to render tens of these creatures live on screen using HTML5 Canvas.
Two challenges pose themselves when dealing with this issue. Firstly, we want to reduce the bandwidth as much as possible, sending as little information as possible from the server to the client while still rendering high-quality animation. Secondly, we want to be actually able to render the animations in real-time in the browser, even on older systems.
Another problem is that our animator Hanne works in Adobe Flash, using all available functionality of Flash such as inverse kinematics (IK), layers, hierarchies and complex tweens to produce high-quality animations. The creature is split up into lots of small parts (arms, hands, fingers, …) and each part is animated separately in a complex hierarchy. Somehow, these animations have to be exported so that they can be used in HTML5 Canvas directly. There are 3 ways to go about doing this, ranging from extremely demanding for the browser rendering engine and cheap on bandwidth to easy to render but high on bandwidth. We will discuss the pro’s and con’s of each approach next.
Method 1: screenshots
This is the easiest method to code, and the fastest to render. Basically, you take screenshots of the animation every few frames, place them in a sprite sheet and send them to the browser, which draws the different parts of the sprite sheet in the correct order on the screen. Such a sprite sheet would look something like this:
While this method is extremely efficient to render in the browser, its bandwidth usage is often unacceptable. The above image is about 500KB large and the creature is relatively small. Things can quickly add up of lots of sprite sheets are to be displayed on screen. Yet, it doesn’t need any additional software to bridge the gap between the animator (Adobe Flash) and the user.
Method 2: live animation
The other extreme is to export the raw animation data from Flash, and to reconstruct the entire animation live in the browser. Instead of sending multiple screenshots of the same creature in different poses, we now send multiple small images, each containing a small body part of the creature. Then we send all the animation data (translation, scaling, rotation, hierarchy, bones, tween ease details etc) to the browser as well, and we animate the creature in real-time.
This method is extremely bandwidth-efficient. Sending numbers instead of pixels saves a massive amount of bandwidth. One issue might be that sending lots of small images results in a lot of overhead in HTTP requests, but this can be solved by compiling the different components in a spritesheet.
Of course, I didn’t deal with the elephant in the room yet. How do you reconstruct a flash animation in real-time in the browser, if you’re not using Adobe Flash player? This has been a tricky issue. Google Swiffy can read an SWF file and output a data structure that can be embedded in a browser, but it’s not open source and the data structure is a binary blob, which is hard to interpret and animate using your own engine/framework.
That is why I developed Silenus. Silenus is an open-source java library that reads CS5 .FLA files and emulates the Flash animation engine in order to reconstruct the animation in java to the smallest detail. This basically allows you to run flash movies without using flash or flash player.
Silenus takes advantage of the new data format that was adopted by Adobe in Flash CS5. Instead of the original binary format, CS5 .FLA files are now simply zip files with XML files in them. These XML files contain every little detail of the animation, up to the layer you last selected in the editor.
Silenus reads this data and builds a data structure in java that contains everything you need to reconstruct the animation in flash. Additionally, Silenus also reconverts the binary format that flash stores its images in, and creates clean PNG files that are easily portable.
Method 3: the holy grail (pre-render)
Method 3 combines the advantages of both methods, and produces output that is easy to render and cheap on the bandwidth. Instead of sending the raw animation data, we allow Silenus to compute the final location and orientation of each component for each frame in the animation, and we just send those numbers to the client, along with a spritesheet containing the different bodyparts.
This functionality is available through the RawDataRenderer, which simulates an entire rendering of the animation, and stores the locations of the different bodyparts at each frame, both in a serializable java structure and in json. As with the other approach, Silenus will also produce png’s that you can use in your browser with the rendering engine of your choosing.
To demonstrate that this actually works (and works fast!), Silenus is also available as a web service that allows you to upload an .FLA file and get back the data you need to reproduce your animation anywhere you want! It will also animate your .FLA live in the browser. The Silenus web service computes the final locations of the bodyparts once on the server, and then sends only this information back to the client, which can then render the animation at high speeds.
This method is a little more expensive in terms of bandwidth than method 2. It is also the only method that demands some computation on the server-side, as in both method 1 and 2, the the server only has to send the necessary data to the client. However, since the animation has to be rendered only once and the output can be stored in a database, this becomes a non-issue. And this approach more than makes up for it in rendering speed, while the bandwidth increase is negligible anyway. It’s really the best of both worlds.
A side-by-side comparison of the three methods can be found in the following table:
We proposed three methods for animating complex sprite-based objects in the browser. All these methods assume that the animation was done with Adobe Flash; this is very often the case, as Flash is an excellent tool for producing complex, layered animations. However, the methodology applies to pretty much all animation software.
Silenus brings the third method, which is both low on bandwidth and fast to compute, within reach for every game developer out there. Silenus will help you convert the complex animation data produced by flash into easily readable and compact JSON data, that can be stored in a database and retrieved for live animation in the browser later.
Silenus is an open source project, and contributions are greatly encouraged. More details on distributions, versions and user guides for Silenus can be found on the Google Code page of the project.