Animations play a crucial role in bringing any user interface to life. They not only make the user interface more visually appealing but also provide feedback to the user, creating a more engaging experience
In this article, we’ll explore how to create such particle explosion effect using jetpack compose, without relying on any external dependencies
We’ll take a step-by-step approach, breaking down each stage of the animation, understanding the underlying physics and mathematics involved, and translating those concepts into code
So, let’s dive in!
Anatomy of an explosion
In a typical explosion, a sudden release of energy throws debris into the air which consists of elements of varying sizes that are propelled in all directions.
Each particle is then pulled downwards by gravity, resulting in it following a parabolic trajectory before ultimately falling back down to the ground.
When the particle moves upward, the gravitational acceleration acts in the opposite direction, leading to a change in its velocity over time
To better understand this concept, consider this moving sledge as an example
Rocket Sledder by physicsclassroom.com
Initially, the sledge is moving steadily to the right with a constant velocity. When the boosters are activated in the opposite direction, the sledge experiences a net force in the opposite direction, which causes it to undergo negative acceleration
Eventually, the sledge comes to a complete stop, having zero velocity. As time passes, the sledge experiences a displacement in the left direction and starts moving in the opposite direction
Similarly, in our scenario, gravity provides a net force in the downward direction to our particle, which causes it to slow down and eventually stop momentarily before it starts accelerating in the opposite direction.
Particle explosion
With this in mind, let’s plot the trajectory of a single particle on a 2D canvas We will write some basic compose code, to begin with.
The Explosion
composable utilizes a canvas to draw the particle trajectory. It also draws the X and Y axis along with a thin border and takes a progress argument as an input ranging between 0 to 1
The ControlledExplosion
composable then simply wraps the Explosion
composable, allowing us to precisely control the explosion progress using a Slider
To control the position of the particle on the canvas, we pass an Offset
with X and Y coordinates to the center
parameter of the drawCircle()
function
Considering velocity sizePx/unit
and time controlled by the Slider
progres, the distance travelled by a particle with constant velocity in a fixed time is given by:
distance = velocity * time = sizePx * progress
By default, the canvas draws every element from the top-left corner, where the coordinates (0,0) are located
But if we want the particle to start from the center, we need to add sizePxHalf
to both the X and Y coordinates
Also, when calculating the Y displacement value, we need to subtract it instead of adding it to ensure that the particle goes up instead of down
Perfect, Now let’s consider the effect of gravity on the particle
To calculate the vertical displacement of the particle with constant velocity and acceleration due to gravity, we can use the second kinematic motion equation
s = ut + 0.5at^2
where
- s = displacement (distance from initial position)
- u = initial velocity
- a = constant acceleration
- t = time
Here’s how the updated code looks like
We still need to determine the velocity and acceleration of the particle based on maximum height it can reach
So let’s derive the formula using the variables in control i.e. displacement and time, from the fact that
- The particle returns to its original position after time t
- The velocity on reaching maximum height is 0
Similarly, we know that the acceleration is the change in velocity over time
Job Offers
With this in place, the particle moves in a nice parabolic trajectory
To increase the number of particles, we create a Particle
class to hold the state of each particle, including color, X & Y coordinates, and other properties
We also add some variation to maxHorizontalDisplacement
and maxVerticalDisplacement
for each particle so that it follows its own trajectory
This variation is randomized to provide diversity in each particle’s path, producing a more realistic effect
And finally, let’s assign each particle a random color
Here’s our updated code with a separate Particle
class
Now, Let’s perform some additional tweaks to the animation
Firstly, we want the particle to travel beyond its final position. To achieve this, we can increase the particle’s max travel time (1s) by adding an arbitrary value of 0.4s
Furthermore, even though the particles are moving along their designated trajectory, the overall explosion still looks quite uniform. To create a more realistic explosion effect, we can introduce randomness by adjusting each particle’s start and end time.
visibilityThresholdLow
is a delay that each particle experiences before it starts its motion relative to the explosion progress. Its value ranges between 0 and 0.14, representing a fraction of the overall animation progress. This parameter improves the initial animation by allowing the particles to appear more like they are being sprayed out, rather than all starting to move at the same time
Another parameter, visibilityThresholdHigh
, determines the end gap between the animation progress and particle progress
Consider an example where the value of visibilityThresholdLow
is 0.1 and visibilityThresholdHigh
is 0.4. In this case, the particle will complete its trajectory from 0 to 1, as the animation progresses from 0.1 to 0.6 (1 – 0.4), and otherwise remain invisible
Overall, the parameters visibilityThresholdLow
and visibilityThresholdHigh
create a more realistic explosion effect by introducing randomness by controlling the start and end time of each particle’s trajectory
Here’s the updated Particle
class
How can we make further improvements to our animation?
Let’s examine additional characteristics of a real explosion
Explosion with Debris (by BestGreenScreen)
Upon closer inspection, we can notice some differences from our current animation
- The debris does not originate from a single center point
- As the debris moves closer or farther from the viewer, it seems to alter in size
- Certain debris disappears while in mid-air
Let’s try to bring these changes to our animation
We can assign a random initialDisplacement
ranging randomly between -10dp to 10dp to each particle so it doesn’t start from the center
val initialDisplacement = 10.dp.toPx() * randomInRange(-1f, 1f)
To vary particle size over time, we first set the initial radius of all particles to 2dp
Then, we split the particles into two groups. The minority group (20%) expands from 2dp to a random size between 2dp and 7dp during the explosion. The majority group, on the other hand, gradually decreases their radius from 2dp to a random value between 1dp and 2dp
This simple adjustment gives the impression of 3D movement, as if the particles are also travelling on the Z-axis
Finally, we adjust the particles’ transparency so that as they move towards the end of their trajectory (70% to 100%), their transparency decreases gradually (100% to 0%), producing a fade out effect
Here’s our final Particle
class
Find the code above in this gist
In the next part, we will develop a library based on this explosion animation
Stay tuned!
Thanks to Rocket Sled and ExplosionField
Check out ExplodingComposable on Github
This article was previously published on proandroiddev.com