Code to create PyGame Sparkler Fireworks Effect Sprite

For fun, I wanted to do a sprite for PyGame that would implement a Sprite to do a sparkler.

Here are some gifs that show the resulting examples in this code:

example1.py ouput

example1.py ouput

example2.py ouput

example2.py ouput

First I had to look at the science behind a sparkler. It launches little particles of metal that are white hot. And it is these little particles that your eyes see as streaks of light.

Here is a good video that explains it and shows a slow motion video of a sparkler.

How do sparklers work Produced by the American Chemical Society

Preparing to code:

I observed that most of the tracks of the particles end close to the head of the sparkler. So I searched for a way to create a random distribution of distance that grouped most of the particle decay close to the starting point. I found that a ‘gamma’ distribution did this

I wrote a small python program (plot_gamma.py) to plot gamma distributions. I played around with the two parameters G_SHAPE and G_SCALE in Sparker.py till I found one that did a nice distribution from 0 to 1.

output of plot_gamma.py

output of plot_gamma.py

After looking at videos of real sparklers, I saw that they happened so fast that every frame of the video was unique and I could not see any relation to the previous frame. This implied that I could just create a new random fresh sparkler pattern in every frame in PyGame.

I then thought about the parts that needed to be drawn. See this diagram that shows what is happening in the final design:

  1. Have start points that are evenly distributed in a small circle simulating the burning area at the tip of the sparkler. I refer to these as spikes.
  2. I use a random angle and a distance that is a random gamma value for the endpoint
  3. I randomly choose some endpoint to cause more sparks to simulate the real-world way sparklers spawn little tiny sparklers at the end of some of the spikes.

The Code

You can find the code at github.com/gerryjenkinslb/SparklerSprite.

Here are the files in the repository:

example1.py - main program to create 1 large sparkler example2.py - main program to create 3 sparklers and move them around

sparkler.py - the Sparkler Class code

plot_gamma.py - program that plots the gamma curve

Make sure you also add the extra modules using pip that are imported in the program. (numpy for sparkler, and matplotlib and scipy for plot_gamma)

I assume here that you are familiar with sprites and the basic game loop in PyGame. You may want to watch my video on DirtySprite and Pygame (PyGame draw cycle, flip, sprites, and dirty sprites for speed)

I will just be covering the basic parts of sparkler.py and the derived class in example2.py.

sparkler.py

A step through of the important parts of the code:

(1) You will need to add numpy module with pip in your system. I am running this code in Python 3.10

(2) I have a reference here to the NumPy: np.random.gamma function that will compute and return an array of almost 2,000 samples from a Gamma distribution with a given SHAPE and SCALE, which I choose to give me a rapid falloff curve.

(3) I wrote a function (point_from_polar) to convert a polar ( origin point, angle in radians, distance from origin) to (x,y) conversion function here that will be used later.

(1) This is the declaration of the Sparkler class. The constructor inherits from DirtySprite.

size is the pixel width and height of a square area for the sparkler. The actual sparkler will be cut off within a circle in that square. The sparker will be all white, but you can pass an optional parameter to pass a list or tuple of colors to change the color of the sparkler or have it be multi-colored.

(2) When I create the surface for the sprite, I use SRCALPHA so the background is transparent for the sparkler.

(1) Each tick, 50 to 300 spikes will be drawn for the sparkler, using this loop

(2) The length of the spark will be randomly picked for the gamma samples, and the angle will be evenly distributed from 0 to to cover an entire circle.

(3) The origin will be a random point within a circle around the center 1/20th of the total sparkler diameter. So I choose a random polar angle and length in this smaller area.

(4) The start and end points for this line are then converted to x,y values

(5) and then drawn with a random color picked from the colors parameter and a thickness of random width of 1, 2, or 3 pixels.

This code is right after the drawing of the spike.

We use an if statement that is true 30% of the time.

The for-loop will draw 1 to 10 sparks drawn starting from the end of the spike. The length of the spark is randomly sampled from the LEN_SAMPLES array divided by 3 to make it shorter.

The spark is then drawn similarly to the spike with a random choice of color and width.

example1.py:

The code in example1.py just draws a large sparkler that is 800x800 in a 800x800 window.

This segment of code pictured above shows the steps typical to just using the Sparkler class to create a sparkler. The obj.rect.x, and rect.y set its position on the screen surface. Note you can also set the obj. rect.center = (x,y) to set the center instead.

Example2.py:

This code subclasses the Sparkler class to move the sparkler around a circle. The main method example2() creates three sparklers to demonstrate. Let’s examine the code for the class:

Class CirclingSparkler:

(1) The arguments control the placement of the center of the circle of movement (origin), and the speed of the movement (negative speed is counterclockwise). And the radius of the circle of spin. We also have a named parameter to provide a different start_angle of movement.

(2) this code sets the initial center of the sparkler.

(1) In update() we move the center of the sparkler around the circle by the speed. By adding seed to the previous angle and then recomputing the x,y value for the center of the sparkler.rect

example2() main method, before the event loop:

Create sparkler1 with the size of 500, and
(1) color parameter,
(2) screen origin to rotate around, and
(3) the radius of the circle of rotation

(4) Sparkler2 has the speed parameter set to a negative value to rotate counterclockwise.

(5) Sparkler3 has the start_angle set to start at a different angle from the other sparklers.

Also, Note that each sparkler has a different color list.


I hope you find this article helpful.

– Gerry Jenkins_