Saturday, October 6, 2012

Javascript Physics: The Exploding DIVs Experiment

I decided to have some fun and experiment with creating an explosion effect (try it out in my sandbox). For this demo, I just created a bunch of divs of various sizes on the page, placed a blast point, and then using TweenLite, animated the effect of the large magnitude force applied to those divs.

[caption id="attachment_408" align="alignnone" width="595"> Initial setup of divs[/caption]

In the end, everything boils down this these two animations applied to each div that needs to be affected by the explosion:



timeline.insertMultiple(
[
TweenLite.to(this, (o.mmt - o.sst), {
ease: Power2.easeIn,
css: {
top: off.top+o.my,
left: off.left+o.mx,
rotation: o.rota+'deg'
}
}),

TweenLite.to(this, (o.eet - o.mmt), {
ease: Power2.easeOut,
css: {
top: off.top+o.fy,
left: off.left+o.fx,
rotation: o.rotb+'deg'
}
})
], o.sst, 'sequence', 0);



The first is the acceleration phase and the second is the deceleration. The variables in the calls identify the timing and distance. The acceleration function is handled by the easing feature so all we need to figure out is the when to start moving, when to stop, and how far to go.

An explosion is characterized by a wave of energy radiating out from a source point at a certain speed. The energy and speed are incredibly large in magnitude. For this demo, the initial values of the energy and speed are 105kg*px2/s2 and 3000 px/s, respectively. As a result, there's a very fast displacement of the divs in the first millisecond of the effect.

[caption id="attachment_407" align="alignnone" width="595"> Displacement 0.046 seconds[/caption]

The speed of the explosive wave remains constant as it sweeps out, however, the energy decreases proportionate to the inverse square of the distance from the initial point of the blast. This basic information leads to several important points that we need to consider:


  • Each div will need a fictitious mass to determine the effect of the force

  • We need to know how far each div is from the blast point to find the lose in energy

  • The size of the div affects how long the blast force acts on the div to accelerate it



Now we can find the maximum speed our div will achieve due to the force of the explosion:



// pin: energy of explosion (kg * px^2 / s^2)
// dr: distance from blast point (px)
// surf: surface area being affected by force (px)
// psd: speed of the wave (px/s)
// mass: mass of the div (g)

o.osd = (pin * 1000 / (o.dr * o.dr)) * (o.surf / psd) / o.mass;



In addition to the above values, we need to know how much drag is being applied to slow down our divs so they don't keep moving forever. Using that number and the top speed of the div calculated above we can find how long the div will travel and how far it will go until stopping. Now we have all the information required to find the timing and distance of our divs. The remaining calculations are just finding the points on the line created by the mid-point of the div to the blast point. We just need to extrapolate the line out based on the distance the div will travel.

The meat of the code is at the very bottom of the page source and is not really that much. Its just a lot of math to solve the physics calculations and then some basic trigonometry to find proportionate triangles that define the distance traveled.

The only remaining part that adds another touch of realism is making the divs rotate as they fly apart. That calculation is just a random angle amplified by the distance traveled. The farther/longer the div moves, the more it rotates.

Overall, the effect is pretty good. You can see the divs closest to the blast point move the fastest and furthest (due to the quick loss in energy of the blast). Smaller divs move faster and futher than larger divs as would be expected in an actual explosion (due to the difference in mass). The initial blast might be more abrupt which could be achieved by removing the acceleration animation (which generally lasts for a hundredth of a second if using the higher speed wave) and setting the first movement in the onStart of the deceleration animation. This would avoid any overhead added by the animation calculations since the acceleration is basically instantaneous. However, because I wanted to be able to step through the explosion or use a slower speed blast, I left the animation in this example. I also found that Firefox seemed to skip more than either Chrome and Opera.

If you play with the demo, you can click on a div and watch its motion through out the animation. I also dumped out all the variables in the calculations on the left as a reference. Because the demo is built on the GreenSock TweenLite library, you can also move the slider back and forth and see the effect at a slower speed. Additionally, you can move the blast point around by dragging the green square.

This experiment is a nice starting point for other projects that need this type of effect. The demo shows that it is possible to animate a relatively large set of elements fast enough to look reasonably realistic. Additionally, the easing feature in the animation library simplifies the calculations significantly reducing the complexity of the code. Finally, using the TimelineLite object, enables building the effect in a convenient container that could be combined with other animations to build a more complex series of movements.