134

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.

cmhughes
  • 100,947
Stefan Kottwitz
  • 231,401

8 Answers8

138

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

percusse
  • 157,807
116

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

Alain Matthes
  • 95,075
87

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

60

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
cmhughes
  • 100,947
48

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!

bloodworks
  • 10,178
44

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.

Chris H
  • 8,705
  • 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 04 '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 04 '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 04 '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 04 '17 at 17:52
  • 1
    The final code will appear -- but I'm still working on it – Chris H Jan 05 '17 at 16:41
  • 2
    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 05 '17 at 16:42
  • @StefanKottwitz my views on code sharing were formed back in the days of usenet when no-one bothered with licensing and just shared freely. I've learnt a lot from other people sharing code (not least here). The only thing stopping me from sharing more is the lack of QA/comments/general polish. – Chris H Jan 05 '17 at 16:47
  • Bounty well deserved. No worries :-) – percusse Jan 06 '17 at 16:01
  • This has to be the final version. Compilation times are back under a minute (since removing a lot of random path decorations), but Evince on a decent desktop takes ~2 minutes to render. I mainly did this on my commute on a Chromebook (ARM CPU) - LaTeX runs fine on that but the last time I compiled, Evince took >10 minutes to display it. – Chris H Jan 07 '17 at 17:57
  • I still hope to do some tidying up/commenting on the code. Eventually I'd like to make it a lot easier to use but as you'll see if you brave the source, I took the chance to experiment with tikz features and syntax. This is also the 1st time I've hit the character limit on an answer - the code is also on github which I'll update when I get round to adding comments – Chris H Jan 07 '17 at 18:01
  • Coming back to this, Sumatra doesn't work too well on Windows any more -- out of 7 programs that can open pdfs on this machine, only GIMP can display it properly. Most others give up part way through. – Chris H Apr 12 '17 at 08:32
15

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

11

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.

CarLaTeX
  • 62,716