Soon we can celebrate the New Year. How can we use TikZ for drawing fireworks? For example like this, photographed by Kurume-Shimin, found on Wikipedia:

Fireworks Aug 5, 2011 in Kurume, Fukuoka, Japan

Click on Image search for getting further impressions. On the Wikipedia page you can see further effects, just click the image. I would like to post a nice drawing on our blog for celebrating New Year, and as addition to the TikZ example gallery on this occasion.

up vote 129 down vote accepted
+200

Here is my take:

Update: More "bling bling", more compilation time... (and trying @Stefan's brilliant idea)

Update 2 Thanks to Stefan, I have seen that the previous version was only working in the QtikZ environment but nowhere(I guess) else. For some reason beyond me, the fadings are still not displayed correctly in Adobe Reader but at least it works (almost) properly in SumatraPDF on Windows. Sorry for the inconvenience and Happy New Year everyone!

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,decorations.pathmorphing}
\pgfdeclareradialshading{someshade}{\pgfpointorigin}{color(0mm)=(pgftransparent!40);color(4mm)=(pgftransparent!50);color(8mm)=(pgftransparent!70);color(2cm)=(pgftransparent!100)}
\pgfdeclareradialshading{somenodeshade}{\pgfpointorigin}{color(0mm)=(pgftransparent!0);color(2mm)=(pgftransparent!0);color(5mm)=(pgftransparent!99);color(20mm)=(pgftransparent!100)}
\pgfdeclareradialshading{invertshade}{\pgfpointorigin}{color(0mm)=(pgftransparent!100);color(10mm)=(pgftransparent!95);color(16mm)=(pgftransparent!60);color(2cm)=(pgftransparent!0)}

\pgfdeclarefading{fadeit}{\pgfuseshading{someshade}}
\pgfdeclarefading{fadein}{\pgfuseshading{invertshade}}

\begin{document}
\begin{tikzpicture}[projectile/.style={decorate,decoration={random steps,segment length=2pt,amplitude=0.5pt}}]
\fill[black] (-4,-3) rectangle (6,4);

\begin{scope}[xshift=0cm,yshift=-0.4cm,transparency group]
\pgfsetfading{fadein}{\pgftransformshift{\pgfpointorigin}}
    \foreach \x in {0,10,..., 360}{\draw[blue!80!white,projectile,line width=1.1pt] (0,0) to [in=90] (10*rand+\x:rand*1mm+2cm);};
\end{scope}

\begin{scope}[xshift=2cm,yshift=1cm]
   \foreach \x in {0,12,..., 360}{\draw [yellow!5,thick,projectile] (0.7,0) to  (3*rand+\x :1mm*rand+2.2cm)  node%
[circle,inner sep=1mm,shade,shading=somenodeshade,opacity=1,outer sep=0] {};}
{\pgfsetfading{fadeit}{\pgftransformshift{\pgfpoint{2.5cm}{1cm}}}};\fill[white] (-3,-3) rectangle (3,3);
\end{scope}

\begin{scope}[xshift=3cm,yshift=-1cm]
\foreach \x in {0,10,..., 360}{\def\r1{rand}\draw [yellow]  ($(0,0)!abs{\r1}!(\x :5mm)$) to [in=90] ($(0,0)!abs{\r1}+0.2!(\x :8mm)$);}
{\pgfsetfading{fadeit}{\pgftransformshift{\pgfpoint{3cm}{-1cm}}}};\fill[yellow,opacity=0.6] (-3,-3) rectangle (3,3);
\end{scope}

\begin{scope}[xshift=-1cm,yshift=1.5cm]
   \foreach \x in {0,12,..., 360}{\def\r2{rand}\draw [red,line width=0.5pt]  ($(0,0)!abs{\r2}!(\x :3mm)$) -- ($(0,0)!abs{\r2}+0.1!(\x :7mm)$);}
{\pgfsetfading{fadeit}{\pgftransformshift{\pgfpoint{-1cm}{1.5cm}}}};\fill[red,opacity=0.6] (-3,-3) rectangle (3,3);
\end{scope}
\end{tikzpicture}
\end{document}

and the updated code gives (see the history for the previous code)

enter image description here

  • 13
    Fading is a very good idea here ! – Alain Matthes Dec 28 '11 at 18:39
  • 3
    Same is your coloring scheme. I loved it! – percusse Dec 28 '11 at 18:42
  • 1
    Incredible, the first one is beautiful and the second one is very realistic! Is fading of projectile paths possible, instead of for example the homogeneous blue? – Stefan Kottwitz Dec 29 '11 at 0:31
  • 2
    I think this is the best one. – user10274 Dec 29 '11 at 13:14
  • 1
    In TL2015 and adobe reader X the spots on the (near-)white firework aren't as pretty as in the above image. It looks like the tranpsarency isn't working properly as they have a black halo. Removing color(20mm)=(pgftransparent!100) from line 5, or replacing the 20mm with 5.1mm helps a lot but doesn't fix it – Chris H Jan 3 '17 at 15:38

Update 4 : it's better with more rays and I add a decoration (Stephan's idea) but the result is aleatory. I change some arguments. With some shading in the center (idea from percusse and bloodworks):

\documentclass{minimal} 
\usepackage[dvipsnames,svgnames]{xcolor} 
\usepackage{tikz}
 \usetikzlibrary{calc} 

 \usetikzlibrary{decorations,decorations.pathmorphing} 

\begin{document}

\begin{tikzpicture}[decoration={bent,aspect=.3}]
  \draw[fill=black] (-8,-3) rectangle (8,5); 
  \foreach \colA/\colB/\sx/\sy in {red/yellow/-4/2,blue/green/-2/1,
                                   yellow/red/0/2,green/blue/4/2,yellow/white/3/1.5} 
{% 
   \draw[shading=radial, inner color=white, outer color=black, opacity=.5]  (\sx,\sy) circle (1cm);   
  \pgfmathparse{rnd}   
  \let\ri\pgfmathresult  
  \begin{scope}[xshift=\sx]
      \foreach \i in {0,...,150}{%  
         \pgfmathparse{rnd}
         \global\let\x\pgfmathresult 
         \pgfmathparse{rnd}  
         \global\let\y\pgfmathresult 
         \pgfmathparse{rnd} 
         \let\c\pgfmathresult 
         \pgfmathsetmacro{\col}{50*\c+50} 
           \draw[decorate,\colA!\col!\colB] %
           ($(360*\x:2*\ri*\y+1) +(\sx,\sy)$) to    ($(360*\x:1*\y) + (\sx,\sy)$);} 
  \end{scope}
} 
\end{tikzpicture} 
\end{document} 

enter image description here

  • Very nice already! Perhaps adding a path morphing decoration would be nice, such as by \begin{tikzpicture}[decoration={bent,aspect=.3}] and \draw[decorate,\colA!\col!\colB] however modified for bending in one direction (wind effect). – Stefan Kottwitz Dec 28 '11 at 18:11
  • Yes there are some possible modifications. – Alain Matthes Dec 28 '11 at 18:25
  • 2
    Very nice! Maybe using \colA for the inner color option would make it even nicer! – percusse Dec 28 '11 at 20:17
  • I try but the result was not fine – Alain Matthes Dec 28 '11 at 20:20
up vote 81 down vote
+200

Happy New Year to all friends in TEX.SX.

This code stands on the ideas from Cmhughes and Bloodworks. I am disappointed that latex isn't allowing me to add sound:

\documentclass{article}
\usepackage{filecontents}%
\begin{filecontents*}{beam.tex}
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing,decorations.shapes,backgrounds}

\begin{document}

\foreach \radius in {1,2,...,20}
{
\begin{tikzpicture}
  % background rectangle
  \filldraw[black] (-3,-3) rectangle (5,3);
    \pgfmathparse{100-(\radius)};
   \foreach \x in {-2,-.5,2.3,4}{
   \pgfmathrandominteger{\y}{0}{2.9}
   \node[xshift=5*rnd,blue!\pgfmathresult!white,scale={.8*rnd}]at (\x,\y){$\star$};
   }
  \ifnum\radius<4
  \pgfmathparse{100-(\radius)*4};
  \draw[blue!\pgfmathresult!black,decorate, decoration={random steps,segment length=3pt,amplitude=.5pt},ultra thin] (0.5 , -2.9)--(0,0);
\fi
  \ifnum\radius<11
  \pgfmathparse{100-(\radius-1)*10};
  \fill[shading=radial, inner color=white!\pgfmathresult!black, outer color=black, opacity=.8](0,0) circle (\radius mm -2mm);   
   \foreach \angle in {0,10,...,360}
{
 \draw[red!\pgfmathresult!black,,decorate, decoration={random steps,segment length=1pt,amplitude=.3pt}] (0,0) -- (\angle:\radius mm)node[white!\pgfmathresult!blue, yshift=-.1mm,scale=.35*rnd]{*};
 }
\fi
%%%
  \ifnum\radius>5
  \ifnum\radius<10
  \pgfmathparse{100-(\radius)*4};
  \draw[xshift=1cm,yshift=1cm,red!\pgfmathresult!black,decorate, decoration={random steps,segment length=3pt,amplitude=.5pt},ultra thin] (1 , -3.9)--(0,0);
\fi\fi
\ifnum\radius>5
  \pgfmathparse{100-(\radius-6)*7};
 \fill[xshift=1cm,yshift=1cm,shading=radial, inner color=white!\pgfmathresult!black, outer color=black, opacity=.8](0,0) circle (\radius mm -9mm);
 \foreach \angle in {0,20,...,360}
{
 \draw[xshift=1cm,yshift=1cm,orange!\pgfmathresult!black,decorate, decoration={random steps,segment length=1pt,amplitude=.3pt}] (0,0) -- (\angle:\radius mm -4mm)node[white!\pgfmathresult!blue, yshift=-.1mm,scale=.5*rnd]{*};
 }
 \foreach \angle in {10,30,...,350}{
 \draw[xshift=1cm,yshift=1cm,red!\pgfmathresult!black,decorate, decoration={random steps,segment length=1pt,amplitude=.5pt}] (0,0) -- (\angle:\radius mm -5mm)node[red!\pgfmathresult!black, yshift=-.1mm,scale=.5*rnd]{*};
 }
    \foreach \angle in {15,35,...,355}{
 \draw[xshift=1cm,yshift=1cm,yellow!\pgfmathresult!black,decorate, decoration={random steps,segment length=1pt,amplitude=.5pt},opacity=.5] (0,0) -- (\angle:\radius mm -6mm)node[white!\pgfmathresult!black, yshift=-.1mm,scale=.5*rnd,opacity=1]{*};
 }
     \foreach \angle in {5,25,...,355}{
 \draw[xshift=1cm,yshift=1cm,green!\pgfmathresult!black,decorate, decoration={random steps,segment length=1pt,amplitude=.5pt},opacity=.5] (0,0) -- (\angle:\radius mm -3mm)node[orange!\pgfmathresult!black, yshift=-.1mm,scale=.5*rnd,opacity=1]{*};
 }
 \fi
 % yellow firework
  \ifnum\radius>10
  \ifnum\radius<14
  \pgfmathparse{100-(\radius)*4};
      \draw[xshift=3cm,yshift=1.5cm,blue!\pgfmathresult!black,decorate, decoration={random steps,segment length=3pt,amplitude=.5pt},ultra thin] (1 , -4.5)--(0,0);
\fi\fi
   \ifnum\radius>10
  \pgfmathparse{100-(\radius-1)*5};
   \fill[xshift=3cm,yshift=1.5cm,shading=radial, inner color=green!\pgfmathresult!black, outer color=black, opacity=.8](0,0) circle (\radius mm -10mm);
   \foreach \angle in {0,10,...,360}
{
 \draw[xshift=3cm,yshift=1.5cm,yellow!\pgfmathresult!black,decorate, decoration={random steps,segment length=2pt,amplitude=.5pt},opacity=.5] (0,0) -- (\angle:\radius mm -8mm)node[orange!\pgfmathresult!black, yshift=-.1mm,scale=.8*rnd,opacity=1]{*};
 }
\fi
   % blue green firework
  \ifnum\radius>10
  \ifnum\radius<14
  \pgfmathparse{100-(\radius)*4};
  \draw[xshift=-1.5cm,yshift=1.5cm,green!\pgfmathresult!black,decorate, decoration={random steps,segment length=3pt,amplitude=.5pt},ultra thin] (-1, -4.5)--(0,0);
\fi\fi
   \ifnum\radius>10
  \pgfmathparse{100-(\radius-1)*5};
       \fill[xshift=-1.5cm,yshift=1.5cm,shading=radial, inner color=yellow!\pgfmathresult!black, outer color=black, opacity=.8](0,0) circle (\radius mm -10mm);
   \foreach \angle in {10,20,...,360}
{
 \draw[xshift=-1.5cm,yshift=1.5cm,green!\pgfmathresult!black,decorate, decoration={random steps,segment length=2pt,amplitude=.5pt},opacity=.5] (0,0) -- (\angle:\radius mm -8mm)node[red!\pgfmathresult!black, yshift=-.1mm,scale=.8*rnd,opacity=1]{*};
 }
\fi
\end{tikzpicture}
}
\end{document}

\end{filecontents*}
%create the beam.pdf.
\immediate\write18{pdflatex beam}
% convert to GIF animation
\immediate\write18{convert -delay 15 -loop 0 -density 200 -alpha remove beam.pdf beam.gif}

\begin{document}
 Look for the beam.gif file in the same directory as this file.
\end{document}

Compile it with pdflatex and you should have installed imagemagick for generating .gif file.

enter image description here

  • 3
    TikZ rules. Nice one. – user10274 Jan 1 '13 at 9:44
  • 4
    Reminds me of the Death Star while destroying planets. Nice work. – Harold Cavendish Jan 1 '13 at 12:45
  • 1
    Great! Very good TikZ animation - impressive! – Stefan Kottwitz Jan 1 '13 at 23:16
  • 3
    what, no sound? ;-) Very nice! – GTK Jan 3 '13 at 6:43
  • 2
    A nice animation but firing at the speed of light makes it less realistic. :-) – kiss my armpit Jan 3 '13 at 15:41

Happy New Year everyone!

screenshot

\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing,decorations.shapes}

\begin{document}

\foreach \radius in {1,2,...,20}
{
\begin{tikzpicture}
  % background rectangle
  \filldraw[black] (-3,-3) rectangle (5,3);
  % skyline
  \filldraw[black!80!blue](-3,-3)--(-3,-2)--(-2.5,-2)--(-2.5,-1)--(-2.25,-1)--(-2.25,-2)--(-2,-2)
                            --(-2,-1)--(-1.75,-0.75)--(-1.5,-1)
                            --(-1.5,-2)--(-1.1,-2)--(-1.1,0)--(-0.5,0)--(-0.5,-2)
                            --(0,-2)--(0,-1.5)--(1,-1.5)--(1.25,-0.5)--(1.5,-1.5)--(1.5,-2)
                            --(2,-2)--(2,0)--(2.5,0)--(2.5,-2)
                            --(3,-2)--(3,-1)--(4,-1)--(4,-2)--(5,-2)--(5,-3)--cycle;
  % moon- what a hack!
  \filldraw[white] (4,2.5) arc (90:-90:20pt);
  \filldraw[black] (3.8,2.5) arc (90:-90:20pt);
  % fireworks
  \pgfmathparse{100-(\radius-1)*10};
  % red firework
  \ifnum\radius<11
      \draw[decorate,decoration={crosses},red!\pgfmathresult!black] (0,0) circle (\radius ex);
  \fi
  % orange firework
  \pgfmathparse{100-(\radius-6)*10};
  \ifnum\radius>5
      \ifnum\radius<16
          \draw[decorate,decoration={crosses},orange!\pgfmathresult!black] (1,1) circle ( \radius ex-5ex);
      \fi
  \fi
  % yellow firework
  \pgfmathparse{100-(\radius-11)*10};
  \ifnum\radius>10
      \draw[decorate,decoration={crosses},yellow!\pgfmathresult!black] (2.5,1) circle (\radius ex-10ex);
  \fi
\end{tikzpicture}
}
\end{document}

The above code will produce a pdf file with each frame. See How to convert pstricks animation to GIF file? for the full details of the remaining two (very easy) steps, which were

pdfcrop myfile.pdf
convert -delay 20 -loop 0 -density 300 myfile-crop.pdf fireworks.gif
  • Placing a displaced black disk on a white one seems to be an easier hack to create a crescent. – kiss my armpit Jan 1 '13 at 2:33
  • @AdorableCreature that's pretty much what I did- hence the, 'what a hack' comment :) happy new year! – cmhughes Jan 1 '13 at 2:34
  • Happy New Year too! – kiss my armpit Jan 1 '13 at 2:36

Not quite as smart as the two above but well thats what i have. I (almost) used no commands starting with pgf.

\documentclass[border=5mm]{standalone}

\usepackage{tikz}
\usetikzlibrary{decorations}
\usetikzlibrary{decorations.pathmorphing} 

\begin{document}

\begin{tikzpicture}
 \draw[fill=black] (-5,-15) rectangle (25,15);
 \foreach \mya in {1,10,20}{
  \pgfmathrandominteger{\myb}{1}{10}
  \draw[shading=radial, inner color=white, outer color=black, opacity=.5](\mya , \myb) circle (5cm);
  \foreach \x in {-3.1,-2,-1.1,0.1,1.2,2.3,3.1}{%
  \foreach \y in {-3.2,-2.1,-1.2,0,1.1,2,3.2}{%
  \draw[red, thick, decorate, decoration={random steps,segment length=3pt,amplitude=1pt}, rotate around={10:(\mya , \myb)}, opacity=0.7](\mya , \myb)--(\mya+\x, \myb+\y)node[red, yshift=-.1mm]{*};%
  \draw[blue,decorate, decoration={random steps,segment length=3pt,amplitude=1pt}, rotate around={20:(\mya , \myb)}](\mya , \myb)--(\mya+\x, \myb+\y)node[red, yshift=-.1mm]{*};%
  \draw[red!50!yellow, decorate, decoration={random steps,segment length=3pt,amplitude=1pt}, rotate around={50:(\mya , \myb)}](\mya , \myb)--(\mya+\x,  \myb+\y);
 }
 }
 \draw[decorate, decoration=snake, red, thick] (0 , -13)--(\mya , \myb);
}


\end{tikzpicture}
\end{document}

enter image description here

It takes a while to compile!

  • 19
    I can't look at it without the virtual "Piiuuuuuuw" sound in my head :) – percusse Dec 28 '11 at 22:03
up vote 25 down vote
+500

Updated and final version: fireworks!

The code runs to 856 lines:


\documentclass{article}
\usepackage{tikz}
\usepackage{ifthen}
\usetikzlibrary{calc,decorations.pathmorphing,shapes}
\pgfdeclareradialshading{someshade}{\pgfpointorigin}{color(0mm)=(pgftransparent!40);color(4mm)=(pgftransparent!50);color(8mm)=(pgftransparent!70);color(2cm)=(pgftransparent!100)}
\pgfdeclareradialshading{somenodeshade}{\pgfpointorigin}{color(0mm)=(pgftransparent!0);color(2mm)=(pgftransparent!0);color(5mm)=(pgftransparent!99);color(5.1mm)=(pgftransparent!100)}
\pgfdeclareradialshading{flameshade}{\pgfpointorigin}{color(0mm)=(pgftransparent!20);color(3mm)=(pgftransparent!50);color(8mm)=(pgftransparent!80);color(2cm)=(pgftransparent!100)}
\pgfdeclareradialshading{invertshade}{\pgfpointorigin}{color(0mm)=(pgftransparent!100);color(5mm)=(pgftransparent!95);color(16mm)=(pgftransparent!40);color(3cm)=(pgftransparent!0)}
\pgfdeclarehorizontalshading{romanshade}{4cm}{color(0cm)=(pgftransparent);color(1cm)=(pgftransparent!50);color(2cm)=(pgftransparent)}
\pgfdeclareverticalshading{trailshade}{10cm}{color(0cm)=(pgftransparent);color(3cm)=(pgftransparent!0)}
\pgfdeclarefading{fadetrail}{\pgfuseshading{trailshade}}
\pgfdeclarefading{fadeit}{\pgfuseshading{someshade}}
\pgfdeclarefading{fadein}{\pgfuseshading{invertshade}}
\pgfdeclarefading{faderoman}{\pgfuseshading{romanshade}}
\pgfdeclarefading{fadeflame}{\pgfuseshading{flameshade}}
%bursts(rocket/mortar)
\def\burst{
    \pgfgettransform{\mycurrenttransform}
    \pgfmathdeclarerandomlist{colour}{{\basecolour}{\basecolour!90!black}{\basecolour!80!black}{\basecolour!90!white}{\basecolour!70!\secondcolour}{\basecolour!80!\secondcolour}}
    \node [coordinate] at(0,0) (burstpoint){};
    \ifthenelse{\equal{\smoke}{true}}{
        \pgfsetfading{fadeit}{\pgfsettransform{\mycurrenttransform}};\fill[\smokecolour,opacity=.8] (current bounding box.north west) rectangle (current bounding box.south east);
    }{}
    \ifthenelse{\equal{\centreblob}{true}}{
        \pgfsetfading{fadeit}{\pgfsettransform{\mycurrenttransform}\pgftransformscale{.3}}
        \node [circle,minimum width=\centreblobwidth, minimum height=\centreblobwidth, inner sep=0mm,fill=\centreblobcolour,opacity=.5,outer sep=0] at (0,0){};
    }{}
    \foreach \x in {\anglemin,\angletwo,...,\anglemax}{%
        \pgfmathrandomitem{\c}{colour}%
        \pgfsetfading{fadeit}{\pgftransformshift{\pgfpoint{2cm}{1cm}}}
        \def\r{3*rand+\x}%
        \def\d{1mm*rand+\burstwidth}%
        \def\inangle{90+rand*30}
        \draw [draw=\c] (burstpoint) to  [out=\r,in=\inangle] (\r:\d) {} node [coordinate, inner sep=0, outer sep =0] (end\x){};        
        \pgfsetfading{fadeit}{\pgfsettransform{\mycurrenttransform}\pgftransformshift{\pgfpointanchor{end\x}{center}}\pgftransformscale{0.3}}
        \begin{scope}[transparency group]
            \foreach \y in {\bursttwoanglemin,\bursttwoangletwo,...,\bursttwoanglemax}{
                \ifthenelse{\equal{\bursttwo}{true}}{
                    \ifthenelse{\equal{\smoke}{true}}{
                        \pgfsetfading{fadeit}{\pgfsettransform{\mycurrenttransform}\pgftransformshift{\pgfpointanchor{end\x}{center}}\pgftransformscale{0.3}};\fill[\smokecolour,opacity=.4] ($(end\x)+(-\burstwidth,-\burstwidth)$) rectangle ($(end\x)+(\burstwidth,\burstwidth)$);%shading
                    }{}
                    \draw [draw=\c,projectiletwo,line width=0.5pt]  ($(end\x.center)$) -- ($(end\x.center)+(\y :\bursttwowidthrandom*rand+\bursttwowidth)$);

                }{}
            }
        \end{scope}

        \ifthenelse{\equal{\endblob}{true}}{
            \pgfsetfading{fadeit}{\pgfsettransform{\mycurrenttransform}\pgftransformshift{\pgfpointanchor{end\x}{center}}\pgftransformscale{\endblobwidth/2cm}}
            \node [circle,minimum width=\endblobwidth, minimum height=\endblobwidth, inner sep=0mm,fill=\endblobcolour,opacity=1,outer sep=0] at (end\x){};
        }{}
    }
}
%roman candle
\def\candle{
    \pgfmathdeclarerandomlist{colour}{{\basecolour}{\basecolour!90!white}{\basecolour!80!white}{\basecolour!80!green}{\basecolour!80!red}{\basecolour!80!blue}}
    \pgfsetfading{fadein}{\pgftransformshift{\pgfpoint{0cm}{-3cm}}}
    \node [coordinate] at(0,0)(basepoint){};
    \node [coordinate]at(0,0.5*\candleheight) (smokepoint){};
    \foreach \x in {\candleanglemin,\candleangletwo,...,\candleanglemax}{%
        \pgfmathrandomitem{\c}{colour}
        \def\r{rand*\candleheightrandom+\candleheight}
        \def\xx{5*rnd+\x}
        \node[coordinate] at ($(0,0)+(\xx:\r)$) (endpoint){};
        \draw[draw=\c,line width=0.5] (0,0) to [out=\x,in=90] (endpoint);%
    }
    \ifthenelse{\equal{\smoke}{true}}{
        \pgfsetfading{fadeit}{\pgftransformrotate{\candleanglemax-90}\pgftransformxscale{0.3}\pgftransformshift{\pgfpointanchor{smokepoint}{center}}};
        \fill[\smokecolour] [draw=none, line width=0.5,smooth cycle] (0,0) to (\candleanglemax+10:\candleheight*2) to ($(\candleanglemin/2+\candleanglemax/2,\candleheight*2)$) to (\candleanglemin-7:\candleheight*2) to (0,0);
    }{}
}
%cloud
\def\cloud{
    \pgfgettransform{\mycurrenttransform}
    \node[coordinate] at(0,0)(cloudpoint){};
    \pgfsetfading{fadeit}{\pgfsettransform{\mycurrenttransform}\pgftransformscale{0.5}\pgftransformyscale{0.3}}
    \node[cloud, cloud puffs=10, cloud puff arc=60,cloud ignores aspect, minimum width=\cloudwidth, minimum height=\cloudheight, align=center, draw=none, fill=\cloudcolour, fill opacity=.4] (cloud) at (cloudpoint) {};
}
%flame
\def\flame{
    \pgfgettransform{\mycurrenttransform}
    \pgfsetfading{fadeflame}{\pgfsettransform{\mycurrenttransform}\pgftransformshift{\pgfpoint{0}{-4.5}}\pgftransformxscale{0.05}\pgftransformyscale{0.08}}%
    \path(0,0) pic{flame};
}
%based on raindrop@  http://tex.stackexchange.com/a/195642/28808
    \tikzset{%
  flame/.pic={
    code={\tikzset{scale=1/10}
 \clip [preaction={top color=red!80, bottom color=red!40!yellow}]
 (0,0)  .. controls ++(0,-1) and ++(0,1) .. (1,-2)
 arc (360:180:1)
 .. controls ++(0,1) and ++(0,-1) .. (0,0) -- cycle ;
 \foreach \j in {1,3,...,20}
 \shade [top color=red, shift=(270:0), xscale=1-\j/40,yscale=1-\j/80, red!50!yellow, opacity=1/8]
 [rotate=-\j] (0,0)  .. controls ++(0,-1) and ++(0,1) .. (1,-2)
 arc (360:180:1)
 .. controls ++(0,1) and ++(0,-1) .. (0,0) -- cycle;
  }}}
%rocket trail
\pgfdeclaredecoration{irregular fractal line}{init}
{
  \state{init}[width=\pgfdecoratedinputsegmentremainingdistance]
  {
    \pgfpathcircle{\pgfpoint{random*\pgfdecoratedinputsegmentremainingdistance}{(random*\pgfdecorationsegmentamplitude-0.02)*\pgfdecoratedinputsegmentremainingdistance}}{.5pt}\pgfusepath{fill};
  }
}
\tikzset{
   trail/.style={decoration={irregular fractal line, amplitude=0.2},
           decorate}
}


\begin{document}
\pgfmathsetseed{1}
\begin{tikzpicture}[projectile/.style={decorate,decoration={random steps,segment length=2pt,amplitude=0.5pt}}, projectiletwo/.style={decorate,decoration={random steps,segment length=2pt,amplitude=0.2pt}}]
\fill[black] (-6,-5) rectangle (9,8);
\clip (-6,-5) rectangle (9,8);
%rockets with trails of sparks
\def\trailcolour{white}
\def\launchangle{80}
\begin{scope}
    \pgfsetfading{fadetrail}{\pgftransformscale{5}}
    \pgfsetfillcolor{\trailcolour}
    \draw [draw=\trailcolour] {decorate[trail]{decorate[decoration={random steps, segment length=2pt, amplitude=1pt}]{
        (-3cm,-2.6cm) to [out=\launchangle+rand*5, in=300+rand*15] (-3cm,5cm)
     }}};
    \draw [draw=\trailcolour] {decorate[trail]{decorate[decoration={random steps, segment length=2pt, amplitude=1pt}]{
        (5cm,-2.6cm) to [out=\launchangle+rand*5, in=300+rand*15] (5cm,5cm)
     }}};
     \draw [draw=\trailcolour] {decorate[trail]{decorate[decoration={random steps, segment length=2pt, amplitude=1pt}]{
        (1cm,-2.6cm) to [out=\launchangle+rand*5, in=300+rand*15] (1cm,6cm)
     }}};
\end{scope}
\def\basecolour{red}
\def\secondcolour{red!50!yellow}
\def\smoke{true}
\def\bursttwo{true}
\def\bursttwoanglemin{0}
\def\bursttwoangletwo{60}
\def\bursttwoanglemax{359}
\def\bursttwowidth{2mm}
\def\bursttwowidthrandom{1.5mm}
\def\smokecolour{gray}
\def\burstwidth{1.7cm}
\def\anglemin{0}
\def\angletwo{10}
\def\anglemax{359}
\def\endblob{false}
\def\endblobwidth{2mm}
\def\endblobcolour{red}
\def\centreblob{false}
\def\centreblobwidth{0.75cm}
\def\centreblobcolour{yellow}
\begin{scope}[xshift=1cm, yshift=6cm]
    \burst
    \def\anglemin{5}
    \def\angletwo{15}
    \def\anglemax{359}
    \def\smoke{false}
    \def\centreblob{true}
    \burst
\end{scope}
\def\basecolour{magenta}
\def\secondcolour{red!40!white}
\def\smoke{true}
\def\bursttwo{false}
\def\bursttwoanglemin{0}
\def\bursttwoangletwo{60}
\def\bursttwoanglemax{359}
\def\bursttwowidth{2mm}
\def\bursttwowidthrandom{1.5mm}
\def\smokecolour{gray!50!magenta}
\def\burstwidth{1.7cm}
\def\anglemin{0}
\def\angletwo{10}
\def\anglemax{359}
\def\endblob{true}
\def\endblobwidth{2mm}
\def\endblobcolour{magenta}
\def\centreblob{false}
\def\centreblobwidth{0.75cm}
\def\centreblobcolour{magenta!50!white}
\begin{scope}[xshift=-3cm, yshift=5cm]
    \burst
    \def\anglemin{5}
    \def\angletwo{15}
    \def\anglemax{359}
    \def\smoke{false}
    \def\centreblob{true}
    \burst
\end{scope}
\def\basecolour{blue}
\def\secondcolour{cyan}
\def\smoke{true}
\def\bursttwo{false}
\def\bursttwoanglemin{0}
\def\bursttwoangletwo{60}
\def\bursttwoanglemax{359}
\def\bursttwowidth{2mm}
\def\bursttwowidthrandom{1.5mm}
\def\smokecolour{gray!50!blue}
\def\burstwidth{1.7cm}
\def\anglemin{0}
\def\angletwo{10}
\def\anglemax{359}
\def\endblob{true}
\def\endblobwidth{2mm}
\def\endblobcolour{cyan}
\def\centreblob{false}
\def\centreblobwidth{0.75cm}
\def\centreblobcolour{blue!50!white}
\begin{scope}[xshift=5cm, yshift=5cm]
    \burst
    \def\anglemin{5}
    \def\angletwo{15}
    \def\anglemax{359}
    \def\smoke{false}
    \def\centreblob{true}
    \burst
\end{scope}
%roman candles. Up to 5 candles/colour at 2 positions
%reflections in water: 4 per colour
%red
\tikzset{romanstyle/.style={line width=0.5}}
\tikzset{romansmokestyle/.style={draw=none}}
\def\basecolour{red}
\def\candleanglemin{80}
\def\candleangletwo{82}
\def\candleanglemax{100}
\def\candleheight{2cm}
\def\candleheightrandom{5mm}
\def\smoke{true}
\def\smokecolour{red}
\def\cloudwidth{1.5cm}
\def\cloudheight{0.6cm}
\begin{scope}[xshift=-2.1cm,yshift=-2.8cm,opacity=0.5]
    \candle
    \flame
\end{scope}
\def\basecolour{yellow}
\def\candleanglemin{86}
\def\candleangletwo{88}
\def\candleanglemax{96}
\def\candleheight{1.5cm}
\def\smoke{false}
\def\cloudwidth{1.5cm}
\def\cloudheight{0.6cm}
\begin{scope}[xshift=-2.1cm,yshift=-2.8cm,opacity=0.3]
    \candle
\end{scope}
%reflection
\begin{scope}[xshift=-2.1cm, yshift=-3.8cm]
    \def\candleheight{2cm}
    \def\candleheightrandom{0cm}
    \def\basecolour{red}
    \def\candleanglemin{280}
    \def\candleangletwo{278}
    \def\candleanglemax{260}
    \def\smoke{false}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.3, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
    \def\basecolour{yellow}
    \def\candleanglemin{274}
    \def\candleangletwo{276}
    \def\candleanglemax{264}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.2, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
\end{scope}
\def\basecolour{red}
\def\candleanglemin{80}
\def\candleangletwo{82}
\def\candleanglemax{100}
\def\candleheight{2cm}
\def\smoke{true}
\begin{scope}[xshift=-2cm,yshift=-3cm]
    \candle
    \flame
\end{scope}
\def\basecolour{yellow}
\def\candleanglemin{86}
\def\candleangletwo{88}
\def\candleanglemax{96}
\def\candleheight{1.5cm}
\def\smoke{false}
\def\cloudwidth{1.5cm}
\def\cloudheight{0.6cm}
\begin{scope}[xshift=-2cm,yshift=-3cm,opacity=0.5]
    \candle
\end{scope}
\def\basecolour{yellow!50!white}
\def\candleanglemin{88}
\def\candleangletwo{90}
\def\candleanglemax{94}
\def\candleheight{1.2cm}
\def\smoke{false}
\def\cloudwidth{1.2cm}
\def\cloudheight{0.6cm}
\begin{scope}[xshift=-2cm,yshift=-3cm,opacity=0.9]
    \candle
\end{scope}
\begin{scope}[xshift=-2cm, yshift=-3.6cm]
    \def\candleheight{2cm}
    \def\candleheightrandom{0cm}
    \def\basecolour{red}
    \def\candleanglemin{280}
    \def\candleangletwo{278}
    \def\candleanglemax{260}
    \def\smoke{false}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.3, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
    \def\basecolour{yellow}
    \def\candleanglemin{274}
    \def\candleangletwo{276}
    \def\candleanglemax{264}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.2, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
\end{scope}
%green
\def\candleanglemin{88}
\def\candleangletwo{89}
\def\candleanglemax{105}
\def\basecolour{green!70!white}
\def\smokecolour{green!50!black}
\def\candleheight{2cm}
\def\smoke{true}
\begin{scope}[xshift=-.1cm,yshift=-2.8cm,opacity=0.5]
    \candle
    \flame
\end{scope}
\def\smoke{false}
\def\candleanglemin{92}
\def\candleangletwo{94}
\def\candleanglemax{100}
\def\basecolour{green!20!white}
\begin{scope}[xshift=-.1cm,yshift=-2.8cm,opacity=0.3]
    \candle
\end{scope}
\begin{scope}[xshift=-.1cm, yshift=-3.8cm]
    \def\candleheight{2cm}
    \def\candleheightrandom{0cm}
    \def\basecolour{green}
    \def\candleanglemin{272}
    \def\candleangletwo{271}
    \def\candleanglemax{255}
    \def\smoke{false}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.3, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
    \def\basecolour{green!20!white}
    \def\candleanglemin{268}
    \def\candleangletwo{266}
    \def\candleanglemax{260}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.2, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
\end{scope}
\def\smoke{true}
\def\candleanglemin{88}
\def\candleangletwo{89}
\def\candleanglemax{105}
\def\basecolour{green!70!white}
\def\candleheight{2cm}
\begin{scope}[xshift=0cm,yshift=-3cm]
    \candle
    \flame
\end{scope}
\def\smoke{false}
\def\candleanglemin{92}
\def\candleangletwo{94}
\def\candleanglemax{100}
\def\basecolour{green!20!white}
\def\candleheight{1.5cm}
\begin{scope}[xshift=0cm,yshift=-3cm]
    \candle
\end{scope}
\begin{scope}[xshift=0cm, yshift=-3.6cm]
    \def\candleheight{2cm}
    \def\candleheightrandom{0cm}
    \def\basecolour{green}
    \def\candleanglemin{272}
    \def\candleangletwo{271}
    \def\candleanglemax{255}
    \def\smoke{false}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.2, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
    \def\basecolour{green!20!white}
    \def\candleanglemin{268}
    \def\candleangletwo{266}
    \def\candleanglemax{260}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.15, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
\end{scope}
%pink
\def\candleanglemin{88}
\def\candleangletwo{89}
\def\candleanglemax{105}
\def\basecolour{magenta!70!white}
\def\smokecolour{magenta!50!black}
\def\secondcolour{red!50!white}
\def\candleheight{2cm}
\def\smoke{true}
\begin{scope}[xshift=1.9cm,yshift=-2.8cm,opacity=0.5]
    \candle
    \flame
\end{scope}
\def\smoke{false}
\def\candleanglemin{92}
\def\candleangletwo{94}
\def\candleanglemax{100}
\def\basecolour{magenta!20!white}
\begin{scope}[xshift=1.9cm,yshift=-2.8cm,opacity=0.3]
    \candle
\end{scope}
\begin{scope}[xshift=1.9cm, yshift=-3.8cm]
    \def\candleheight{2cm}
    \def\candleheightrandom{0cm}
    \def\basecolour{magenta}
    \def\candleanglemin{272}
    \def\candleangletwo{271}
    \def\candleanglemax{255}
    \def\smoke{false}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.2, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
    \def\basecolour{magenta!70!white}
    \def\candleanglemin{268}
    \def\candleangletwo{266}
    \def\candleanglemax{260}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.15, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
\end{scope}
\def\smoke{true}
\def\candleanglemin{80}
\def\candleangletwo{81}
\def\candleanglemax{100}
\def\basecolour{magenta!70!white}
\def\candleheight{2cm}
\begin{scope}[xshift=2cm,yshift=-3cm]
    \candle
    \flame
\end{scope}
\def\smoke{false}
\def\candleanglemin{92}
\def\candleangletwo{94}
\def\candleanglemax{100}
\def\basecolour{magenta!20!white}
\def\candleheight{1.5cm}
\begin{scope}[xshift=2cm,yshift=-3cm]
    \candle
\end{scope}
\begin{scope}[xshift=2cm, yshift=-3.6cm]
    \def\candleheight{2cm}
    \def\candleheightrandom{0cm}
    \def\basecolour{magenta}
    \def\candleanglemin{272}
    \def\candleangletwo{271}
    \def\candleanglemax{255}
    \def\smoke{false}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.2, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
    \def\basecolour{magenta!70!white}
    \def\candleanglemin{268}
    \def\candleangletwo{266}
    \def\candleanglemax{260}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.15, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
\end{scope}
%blue
\def\secondcolour{cyan}
\def\candleanglemin{82}
\def\candleangletwo{83}
\def\candleanglemax{100}
\def\basecolour{blue!70!cyan}
\def\smokecolour{blue!50!black}
\def\candleheight{2cm}
\def\smoke{true}
\begin{scope}[xshift=3.9cm,yshift=-2.8cm,opacity=0.5]
    \candle
    \flame
\end{scope}
\def\smoke{false}
\def\candleanglemin{92}
\def\candleangletwo{94}
\def\candleanglemax{100}
\def\basecolour{blue!20!cyan}
\begin{scope}[xshift=3.9cm,yshift=-2.8cm,opacity=0.3]
    \candle
\end{scope}
\begin{scope}[xshift=3.9cm, yshift=-3.8cm]
    \def\candleheight{2cm}
    \def\candleheightrandom{0cm}
    \def\basecolour{blue}
    \def\candleanglemin{272}
    \def\candleangletwo{271}
    \def\candleanglemax{255}
    \def\smoke{false}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.2, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
    \def\basecolour{blue!20!cyan}
    \def\candleanglemin{268}
    \def\candleangletwo{266}
    \def\candleanglemax{260}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.15, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
\end{scope}
\def\smoke{true}
\def\candleanglemin{88}
\def\candleangletwo{89}
\def\candleanglemax{105}
\def\basecolour{blue!70!cyan}
\def\candleheight{2cm}
\begin{scope}[xshift=4cm,yshift=-3cm]
    \candle
\end{scope}
\def\smoke{false}
\def\candleanglemin{92}
\def\candleangletwo{94}
\def\candleanglemax{100}
\def\basecolour{blue!20!cyan}
\def\candleheight{1.5cm}
\begin{scope}[xshift=4cm,yshift=-3cm]
    \candle
    \flame
\end{scope}
\begin{scope}[xshift=4cm, yshift=-3.6cm]
    \def\candleheight{2cm}
    \def\candleheightrandom{0cm}
    \def\basecolour{blue}
    \def\candleanglemin{272}
    \def\candleangletwo{271}
    \def\candleanglemax{255}
    \def\smoke{false}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.2, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
    \def\basecolour{blue!20!cyan}
    \def\candleanglemin{268}
    \def\candleangletwo{266}
    \def\candleanglemax{260}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.15, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
\end{scope}
%yellow
\def\candleanglemin{82}
\def\candleangletwo{83}
\def\candleanglemax{100}
\def\basecolour{yellow}
\def\secondcolour{red}
\def\smokecolour{yellow!80!red}
\def\cloudcolour{yellow!80!red}
\def\candleheight{2cm}
\def\smoke{true}
\begin{scope}[xshift=5.9cm,yshift=-2.8cm,opacity=0.5]
    \candle
    \flame
\end{scope}
\def\smoke{false}
\def\candleanglemin{92}
\def\candleangletwo{94}
\def\candleanglemax{100}
\def\basecolour{yellow!80!red!20!white}
\def\cloudcolour{yellow!80!red}
\begin{scope}[xshift=5.9cm,yshift=-2.8cm,opacity=0.3]
    \candle
\end{scope}
\begin{scope}[xshift=5.9cm, yshift=-3.8cm]
    \def\candleheight{2cm}
    \def\candleheightrandom{0cm}
    \def\basecolour{yellow}
    \def\candleanglemin{272}
    \def\candleangletwo{271}
    \def\candleanglemax{255}
    \def\smoke{false}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.2, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
    \def\basecolour{yellow!80!red}
    \def\candleanglemin{268}
    \def\candleangletwo{266}
    \def\candleanglemax{260}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.15, decoration={snake,amplitude=.1mm+rand*0.05mm,segment length=2mm+rand*0.5mm}}}
    \candle
\end{scope}
\def\smoke{true}
\def\candleanglemin{88}
\def\candleangletwo{89}
\def\candleanglemax{105}
\def\basecolour{yellow!80!red}
\def\candleheight{2cm}
\begin{scope}[xshift=6cm,yshift=-3cm]
    \candle
    \flame
\end{scope}
\def\smoke{false}
\def\candleanglemin{92}
\def\candleangletwo{94}
\def\candleanglemax{98}
\def\basecolour{yellow!80!red!20!white}
\def\candleheight{1.5cm}
\begin{scope}[xshift=6cm,yshift=-3cm]
    \candle
\end{scope}
\begin{scope}[xshift=6cm, yshift=-3.6cm]
    \def\candleheight{2cm}
    \def\candleheightrandom{0cm}
    \def\basecolour{yellow}
    \def\candleanglemin{272}
    \def\candleangletwo{271}
    \def\candleanglemax{255}
    \def\smoke{false}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.2, decoration={snake,amplitude=.3mm+rand*0.1mm,segment length=2mm+rand*0.5mm}}}
    \candle
    \def\basecolour{yellow!80!red}
    \def\candleanglemin{268}
    \def\candleangletwo{266}
    \def\candleanglemax{260}
    \tikzset{romanstyle/.style={line width=0.5,decorate,opacity=0.15, decoration={snake,amplitude=.3mm+rand*0.1mm,segment length=2mm+rand*0.5mm}}}
    \candle
\end{scope}
%mortar bursts 3/colour
%red
\def\basecolour{red!80!yellow}
\def\secondcolour{yellow!80!white}
\def\smoke{true}
\def\bursttwo{false}
\def\bursttwoanglemin{0}
\def\bursttwoangletwo{60}
\def\bursttwoanglemax{359}
\def\smokecolour{red}
\def\burstwidth{1.2cm}
\def\anglemin{0}
\def\anglemax{359}
\def\angletwo{10}
\def\endblob{false}
\def\endblobwidth{2mm}
\def\endblobcolour{red}
\def\centreblob{true}
\def\centreblobwidth{0.5cm}
\def\centreblobcolour{yellow}
\begin{scope}[xshift=-2cm, yshift=1cm,opacity=0.6]
    \burst
\end{scope}
\begin{scope}[xshift=-1.8cm,yshift=1.2cm,opacity=0.3]
    \burst
\end{scope}
\def\smoke{true}
\def\smokecolour{red}
\def\burstwidth{1.3cm}
\def\anglemin{0}
\def\anglemax{359}
\def\angletwo{10}
\def\centreblob{true}
\def\centreblobwidth{0.5cm}
\def\centreblobcolour{yellow}
\begin{scope}[xshift=-2.3cm, yshift=1.3cm]
    \burst
\end{scope}
%green
\def\basecolour{green}
\def\secondcolour{cyan!50!white}
\def\smoke{true}
\def\bursttwo{false}
\def\bursttwoanglemin{0}
\def\bursttwoangletwo{60}
\def\bursttwoanglemax{359}
\def\smokecolour{green!80!black}
\def\burstwidth{1.2cm}
\def\anglemin{0}
\def\anglemax{359}
\def\angletwo{10}
\def\endblob{false}
\def\endblobwidth{2mm}
\def\endblobcolour{green}
\def\centreblob{true}
\def\centreblobwidth{0.5cm}
\def\centreblobcolour{green!80!white}
\begin{scope}[xshift=0, yshift=1cm,opacity=0.6]
    \burst
\end{scope}
\begin{scope}[xshift=.2cm,yshift=1.2cm,opacity=0.3]
    \burst
\end{scope}
\def\smoke{true}
\def\smokecolour{green!80!black}
\def\burstwidth{1.3cm}
\def\anglemin{0}
\def\anglemax{359}
\def\angletwo{10}
\def\centreblob{true}
\def\centreblobwidth{0.5cm}
\def\centreblobcolour{green!80!white}
\begin{scope}[xshift=-0.3cm, yshift=1.3cm]
    \burst
\end{scope}
%pink
\def\basecolour{magenta}
\def\secondcolour{magenta!20!white}
\def\smoke{true}
\def\bursttwo{false}
\def\bursttwoanglemin{0}
\def\bursttwoangletwo{60}
\def\bursttwoanglemax{359}
\def\smokecolour{magenta!80!black}
\def\burstwidth{1.2cm}
\def\anglemin{0}
\def\anglemax{359}
\def\angletwo{10}
\def\endblob{false}
\def\endblobwidth{2mm}
\def\endblobcolour{magenta}
\def\centreblob{true}
\def\centreblobwidth{0.5cm}
\def\centreblobcolour{magenta!80!white}
\begin{scope}[xshift=2cm, yshift=1cm,opacity=0.6]
    \burst
\end{scope}
\def\burstwidth{1cm}
\begin{scope}[xshift=2.2cm,yshift=1.2cm,opacity=0.3]
    \burst
\end{scope}
\def\smoke{true}
\def\smokecolour{magenta!80!black}
\def\burstwidth{1.3cm}
\def\anglemin{0}
\def\anglemax{359}
\def\angletwo{10}
\def\centreblob{true}
\def\centreblobwidth{0.5cm}
\def\centreblobcolour{magenta!80!white}
\begin{scope}[xshift=1.7cm, yshift=0.9cm]
    \burst
\end{scope}
%blue
\def\basecolour{blue}
\def\secondcolour{cyan!80!white}
\def\smoke{true}
\def\bursttwo{false}
\def\bursttwoanglemin{0}
\def\bursttwoangletwo{60}
\def\bursttwoanglemax{359}
\def\smokecolour{blue!80!black}
\def\burstwidth{1.2cm}
\def\anglemin{0}
\def\anglemax{359}
\def\angletwo{10}
\def\endblob{false}
\def\endblobwidth{2mm}
\def\endblobcolour{blue!80!cyan}
\def\centreblob{true}
\def\centreblobwidth{0.5cm}
\def\centreblobcolour{blue!20!white}
\begin{scope}[xshift=4cm, yshift=1cm,opacity=0.6]
    \burst
\end{scope}
\def\burstwidth{1cm}
\begin{scope}[xshift=4.2cm,yshift=1.4cm,opacity=0.3]
    \burst
\end{scope}
\def\smoke{true}
\def\smokecolour{blue!80!black}
\def\burstwidth{1.3cm}
\def\anglemin{0}
\def\anglemax{359}
\def\angletwo{10}
\def\centreblob{true}
\def\centreblobwidth{0.5cm}
\def\centreblobcolour{blue!80!white}
\begin{scope}[xshift=3.8cm, yshift=0.9cm]
    \burst
\end{scope}
%yellow
\def\basecolour{yellow!80!red}
\def\secondcolour{yellow!50!red}
\def\smoke{true}
\def\bursttwo{false}
\def\bursttwoanglemin{0}
\def\bursttwoangletwo{60}
\def\bursttwoanglemax{359}
\def\smokecolour{yellow!80!black}
\def\burstwidth{1.2cm}
\def\anglemin{0}
\def\anglemax{359}
\def\angletwo{10}
\def\endblob{false}
\def\endblobwidth{2mm}
\def\endblobcolour{yellow}
\def\centreblob{true}
\def\centreblobwidth{0.5cm}
\def\centreblobcolour{yellow!80!white}
\begin{scope}[xshift=6cm, yshift=1.3cm,opacity=0.6]
    \burst
\end{scope}
\def\burstwidth{1.5cm}
\begin{scope}[xshift=6.1cm,yshift=1.2cm,opacity=0.3]
    \burst
\end{scope}
\def\smoke{true}
\def\smokecolour{yellow!80!black}
\def\burstwidth{1.3cm}
\def\anglemin{0}
\def\anglemax{359}
\def\angletwo{10}
\def\centreblob{true}
\def\centreblobwidth{0.5cm}
\def\centreblobcolour{yellow!80!white}
\begin{scope}[xshift=5.7cm, yshift=0.9cm]
    \burst
\end{scope}
\def\cloudcolour{red}
\begin{scope}[xshift=-3.3cm, yshift=-1cm]
    \cloud
\end{scope}
\def\cloudcolour{green}
\begin{scope}[xshift=-1.4cm, yshift=-1.2cm]
    \cloud
\end{scope}
\def\cloudcolour{magenta}
\begin{scope}[xshift=.75cm, yshift=-.9cm]
    \cloud
\end{scope}
\def\cloudcolour{blue}
\begin{scope}[xshift=2.5cm, yshift=-1cm]
    \cloud
\end{scope}
\def\cloudcolour{yellow}
\begin{scope}[xshift=4.9cm, yshift=-1.1cm]
    \cloud
\end{scope}
\fill[black, opacity=0.6] (-6,-5) rectangle (9,-3.4);
\end{tikzpicture}
\end{document}

The only viewers I can persuade this to render in are Evince 3.14/3.18 for Linux, GIMP 2.8 and Gnome print previewer (probably the same code as Evince). SumatraPDF, Adobe reader X, Inkscape and Evince 2 for windows give the general idea at best but fail to varying extents. Ghostscript and ImageMagick show one rocket trail, then cry and give up. In fact there's a bug even in this: the reflections in the water should be wavy.

  • Although the bounty drew my attention to the question, even if my result deserved it (which I don't believe it does) all the hard work was doen by @percusse. I just treated it as a chance to learn a bit more TikZ . – Chris H Jan 4 '17 at 10:35
  • Great! Perhaps some "glow" could be added and having opacity letting things sum up to compensate the fading. – Stefan Kottwitz Jan 4 '17 at 13:08
  • 1
    @StefanKottwitz any form of opacity gradient appears to be the issue withinconsistent handling. As percusse found years ago, sumatraPDF has the best rendering. I'll have a look at some glow tonight – Chris H Jan 4 '17 at 13:51
  • Interestingly evince for linux works just fine. And compiling this on a chromebook is more than a little slow. – Chris H Jan 4 '17 at 17:52
  • 1
    Thank you for your very nice work! I look forward to your final code. :-) I also like that you provide your code with a public domain license, instead of the default commercial site backlink requiring CC license on top of author attribution that goes without saying. – Stefan Kottwitz Jan 5 '17 at 16:42

Using my answer here, Make fireworks with only text, except with -, \_, {$\bullet$} and . as the firework components, instead of actual text.

\documentclass{article}
\usepackage{rotating, xcolor}
\usepackage[margin=4cm]{geometry}
\newcounter{Kdegrees}
\newcounter{KdegreeIncrement}
\newcounter{degrees}

% More than 360 repetitions will max out TeX's memory
% Print error message and end document if more than 360 reps are requested
\newcommand{\textwheelErrorTest}[1]{%
    \ifnum#1 > 360 
        \typeout{%
            ERROR: You asked for #1 repetitions in 
            \noexpand\textwheel, but the maximum is 360.
            I am stopping before TeX exceeds its memory capacity.%
        }%
        \def\erroraction{\end{document}}
    \else
        \def\erroraction{\relax}
    \fi
    \erroraction
}

% For calculating length of string for kerning
\newlength{\strlen}
\newlength\biaslength
\def\biasfrac{.0}% 0 to 1
\biaslength=0pt% \ge 0pt (0pt produces circular symmetry
\def\biasstrut{\rule[-\biasfrac\biaslength]{0pt}{\biaslength}}
% #1 text to repeat, #2 color of text, #3 number of times to repeat it
\newcommand{\textwheel}[5]{\leavevmode\smash{%
    \gdef\innercolor{#2}%
    \gdef\outercolor{#3}%
    \textwheelErrorTest{#4}%
    \def\FadeL{#5}%
    %
    \setcounter{KdegreeIncrement}{360000}%
    \setcounter{Kdegrees}{0}%
    \divide\value{KdegreeIncrement} by #4%
    \settowidth{\strlen}{#1}%
    \ifdim\FadeL=0pt\def\FadeL{\the\strlen}\fi%
    %
    \loop
      \setcounter{degrees}{\value{Kdegrees}}%
      \divide\value{degrees} by 1000\relax%
      \ifnum\value{degrees}<90
        \rlap{\rotatebox[origin=l]{\value{degrees}}{%
         \biasstrut\color{#2}\smash{\FadeAfter{\FadeL}{#1}}}%
        }%
      \else
        \ifnum\value{degrees}<270%
          \kern+\biaslength%
          \llap{\rotatebox[origin=l]{\value{degrees}}{%
           \biasstrut\color{#2}\smash{\FadeAfter{\FadeL}{#1}}}%
          }%
          \kern-\biaslength%
        \else
          \rlap{\rotatebox[origin=l]{\value{degrees}}{%
           \biasstrut\color{#2}\smash{\FadeAfter{\FadeL}{#1}}}%
          }%
        \fi
      \fi
    \addtocounter{Kdegrees}{\value{KdegreeIncrement}}%
    \ifnum\value{Kdegrees} < 359000%
    \repeat%
}}
%%%
\usepackage{xcolor,ifthen}
\newcounter{tmpcounter}
\newlength\cumlength
\newlength\critlength
\newlength\tmplength
\newcount\mynum
\newcount\myden
\makeatletter
\newcommand\FadeAfter[2]{%
  \critlength=#1\relax\cumlength=0pt\relax%
  \def\cumstring{}\fahelp{#1}{#2}}
\newcommand\fahelp[2]{\prefahelper#2 \relax\fahelper#2\relax}
\def\prefahelper#1 #2\relax{\gdef\wordremaining{#1}}
\def\fahelper#1#2\relax{%
  \global\protected@edef\cumstring{\cumstring#1}%
  \ifthenelse{\equal{#1}{\wordremaining}}{%
    \global\protected@edef\cumstring{\cumstring\ }}{}%
  \setbox0=\hbox{\cumstring}%
  \tmplength=.01\critlength\relax%
  \mynum=\wd0\relax%
  \myden=\tmplength\relax%
  \divide\mynum by\myden%
  \setcounter{tmpcounter}{\numexpr100-\the\mynum}%
  \ifnum\thetmpcounter<0\setcounter{tmpcounter}{0}\fi%
  \textcolor{\innercolor!\thetmpcounter!\outercolor!90}{#1}%
  \ifthenelse{\equal{#1}{\wordremaining}}{\ }{}%
    \ifx\relax#2\relax\else\fahelp{\critlength}{#2}\fi%
}
\makeatother
\usepackage{stackengine}
\begin{document}
% CAN EXPERIMENT WITH ASYMMETRIC BIAS WITH THESE TWO PARAMETERS
%\def\biasfrac{.4}% 0 to 1 ROTATES THE ASYMMETRY OF \biaslength
%\biaslength=8pt% \ge 0pt (0pt produces circular symmetry)

\pagecolor{black}

\begin{minipage}{0.45\linewidth}
%
\vspace{4cm}

\hspace{3.15cm}
\biaslength1pt\def\biasfrac{-.1}
\savestack\XT{\textwheel{..}{blue}{cyan}{4}{0.4cm}}
\biaslength0pt\def\biasfrac{-.1}
\savestack\ST{\textwheel{\_\_\_\_\_\XT}{yellow!60!orange}{green!60!orange}{13}{0.6cm}}
\biaslength6pt\def\biasfrac{-.1}
\textwheel{{$\bullet$}--------------------------------------------\ST}{red}{blue}{17}{7cm}

\vspace{3cm}

\hspace{0cm}
\biaslength1pt\def\biasfrac{-.1}
\savestack\XT{\textwheel{...}{blue!50!red}{cyan}{3}{0.6cm}}
\biaslength0pt\def\biasfrac{-.1}
\savestack\ST{\textwheel{\_\_\_\_\XT}{yellow!60!orange}{red}{11}{0.6cm}}
\biaslength6pt\def\biasfrac{-.1}
\textwheel{{$\bullet$}-------------------------------\ST}{yellow}{blue}{13}{5cm}


\vspace{10cm}

\hspace{9cm}
\biaslength1pt\def\biasfrac{-.1}
\savestack\XT{\textwheel{..}{blue}{cyan}{4}{0.4cm}}
\biaslength0pt\def\biasfrac{-.1}
\savestack\ST{\textwheel{\_\_\_\XT}{yellow!60!orange}{green!60!orange}{13}{0.6cm}}
\biaslength6pt\def\biasfrac{-.1}
\textwheel{{$\bullet$}-----------------------------------\ST}{red}{blue}{23}{7cm}

\vspace{-11pt}\hspace{9cm}
\biaslength1pt\def\biasfrac{-.1}
\savestack\XT{\textwheel{..}{blue}{cyan}{3}{0.4cm}}
\biaslength0pt\def\biasfrac{-.1}
\savestack\ST{\textwheel{\_\_\_\_\XT}{yellow!60!orange}{green!60!orange}{11}{0.6cm}}
\biaslength6pt\def\biasfrac{-.1}
\textwheel{{$\bullet$}------------------------\ST}{red}{blue}{17}{5cm}

\vspace{-11pt}\hspace{9cm}
\biaslength1pt\def\biasfrac{-.1}
\savestack\XT{\textwheel{..}{blue}{cyan}{3}{0.4cm}}
\biaslength0pt\def\biasfrac{-.1}
\savestack\ST{\textwheel{\_\_\_\_\_\XT}{yellow!60!orange}{green!60!orange}{11}{0.6cm}}
\biaslength6pt\def\biasfrac{-.1}
\textwheel{{$\bullet$}------------\ST}{red}{blue}{7}{3cm}


\end{minipage}

\end{document}

enter image description here

The second set of fireworks are laid concentrically, to give a slightly different effect.

enter image description here

  • Thank you for that nice alternative solution! I enjoy it, even though I gave the bounty to a TikZ solution. Nice work with stackengine, I also used that package to show a solution in my LaTeX cookbook. – Stefan Kottwitz Jan 5 '17 at 16:45
  • @StefanKottwitz Thanks for your kind words. It is a fun problem. – Steven B. Segletes Jan 5 '17 at 16:49

Math symbol fireworks (edit: I've added a random positioning):

enter image description here

% arara: pdflatex
% arara: convert: {density: 160, otheroptions: -dispose previous -delay 10 -loop 10, format: gif}
\documentclass[tikz]{standalone}
\usepackage{amsmath, amssymb}
\usepackage[outline]{contour}
\contourlength{.05em}
\usetikzlibrary{decorations,shapes}
% customized decorations
\newcommand{\decorazione}[4]{% 
    \pgfdeclaredecoration{#1}{initial}{%
        \state{initial}[width=30pt]
        {\pgfnode{circle}{center}{\Huge\textcolor{#2}{\contour{#3}{#4}}}{}{}}
        \state{final}[width=30pt]
        {\pgfnode{circle}{center}{\Huge\textcolor{#2}{\contour{#3}{#4}}}{}{}}
}}
\decorazione{sommatoria}{red}{yellow}{$\sum$}
\decorazione{minore}{white}{red}{$\le$}
\decorazione{integrale}{green}{white}{$\int$}
\decorazione{unione}{yellow}{green}{$\bigcap$}
\decorazione{stella}{red}{yellow}{$\star$}
\decorazione{radice}{white}{red}{$\sqrt{}$}
\decorazione{produttoria}{green}{white}{$\prod{}$}
\decorazione{frecciacirc}{yellow}{green}{$\circlearrowleft$}
\decorazione{perogni}{red}{yellow}{$\forall$}
\decorazione{esiste}{white}{red}{$\exists$}
\decorazione{triangolo}{green}{white}{$\triangleleft$}
\decorazione{freccia}{yellow}{green}{$\Rightarrow$}

\newcommand{\cerchio}[2]{\path[decorate, decoration=#1,inner sep=0,font={\bfseries\Huge}] (#1) circle (#2)}

\begin{document}
    % tikzpicture out of the loop to set coordinates
    \begin{tikzpicture}
    \fill[blue] (0,0) rectangle (30,20);
    \foreach \tema in {sommatoria, minore, integrale, unione,%
        stella, radice}{%
        \path (rnd*20+5,rnd*10+5) coordinate (\tema);
        \cerchio{\tema}{.5};    
    }
    \end{tikzpicture}
    % main loop 
    \foreach \raggio in {1,1.5,...,4}{%
        \begin{tikzpicture}
        \fill[blue] (0,0) rectangle (30,20);
        \foreach \tema in {sommatoria, minore, integrale, unione,%
            stella, radice}{%
            \cerchio{\tema}{\raggio};   
        }   
        \end{tikzpicture}
    }
    % tikzpicture out of the loop to set coordinates
    \begin{tikzpicture}
    \fill[blue] (0,0) rectangle (30,20);
    \foreach \tema in {produttoria, frecciacirc,%
        perogni, esiste, triangolo, freccia}{%
        \path (rnd*20+5,rnd*10+5) coordinate (\tema);
        \cerchio{\tema}{.5};    
    }
    \end{tikzpicture}
    % main loop 
    \foreach \raggio in {1,1.5,...,4}{%
        \begin{tikzpicture}
        \fill[blue] (0,0) rectangle (30,20);
        \foreach \tema in {produttoria, frecciacirc,%
            perogni, esiste, triangolo, freccia}{%
            \cerchio{\tema}{\raggio};   
        }   
        \end{tikzpicture}
    }
\end{document}

In order to get the .gif file use this ImageMagick command:

convert -alpha remove -density 160 -dispose previous -delay 10 -loop 10 "file.pdf" -quality 100 "file.gif"

or an arara rule like this one.

  • 1
    Cool! Let us have formulas explode. :-) – Stefan Kottwitz Jan 4 '17 at 13:10
  • @StefanKottwitz I was thinking of how to do LaTeX-related fireworks... and this is the result! – CarLaTeX Jan 4 '17 at 13:20
  • I preferred the more graphical solution, but thank you very much for that great idea! – Stefan Kottwitz Jan 5 '17 at 16:43
  • @StefanKottwitz Don't worry, I'll do something TeXnically more sophisticated when I'm more experienced. Maybe you can answer my duck question, instead! Hahaha! – CarLaTeX Jan 5 '17 at 16:54

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.