You may have seen fun projects/demoes where a webpage is demolished using lifelike physics animations. Wario Land Shake It is a good example of that and it’s also allows the user to drag page elements around after the video is done playing. This however is created as a full page Flash, trying to look like a HTML page. Similar cases has also been done just by pre-rendering all into a video. So I wanted to have a go at doing this in HTML, as I haven’t seen that done before.
Continuing on what I learned creating my previous post about Box2d for JavaScript, I wanted to take it a step further replacing the debug renderer with elements from a webpage. The elements should be working as a blue print for the Box2d objects, and the transformation into the physics world should be transparent. I created a quick webpage using <div> elements with some mockup content and started on the steps to make it work:
- Scan the appropriate part of a webpage for <div> elements, creating the corresponding counterparts in the Box2d world. This turned out to be pretty straight forward, using a jQuery selector with the each() method looping through and creating boxes in Box2D. Positions and dimensions were extracted from CSS, being absolute positioned for the sake of simplicity. After they where reset to a 0,0 position, ready for letting the animation engine handle the positions later. A reference to the <div> was injected into the m_userdata of each of the Box2d bodies.
- Animating is done by looping through all fixtures within the bodies in the Box2d world, retrieving the position and rotation of the objects. Thus having rotation of the boxes, just using god ol’ top & left for positioning and animating had to be forfeit. Instead we use the transform property on CSS3, offsetting the position from 0,0 and setting the correct rotation. An added super bonus is setting transform: translateZ(0) in the parent element, we get super fast GPU accelerated animation. Using the -webkit vendor prefix, we even get pretty decent performance on iOS devices.
- Checking that all was in a 1:1 relationship between the browser rendering of the <div> elements and it’s Box2d counterparts also had to be done. I did this by using the debug renderer on a canvas, being displayed behind the elements. In the example you can turn it on and off, also making the <div> elements transparent to see both “worlds” at the same time.
- Handling both mouse and touch events is always a bit of a chore when you just want to focus at the task at hand. So I wrote my first Javascript tool ever, MouseAndTouch.js that handles both types of input in your typical “press-draw-up-end” manner. The code setup is probably not quite kosher, but writing it helped me along the way of learning JavaScript.
Ok, thats quite enough talk already. Go ahead and take it for a spin! Make sure that you drag the elements after they have been dropped And please comment, esp. on my novice setup on the MouseAndTouch.js as a standalone tool.
For those of you that like more technical details, here are some things I found in the development process:
- The rotate() method of CSS3 transform does not like negative values or infinite number of decimals. So you need to normalize the angle and fix the number of decimals. I ended up specifying the angle with degrees and setting the number of decimals to two.
- Creating some shorthand methods for creating Box2d items helps speed up the development process.