I would probably do something like this:
\documentclass[tikz]{standalone}
\usetikzlibrary{backgrounds}
\tikzset{
relative to node/.style={
shift={(#1.center)},
x={(#1.east)},
y={(#1.north)},
},
kolben/.pic={
\node[fill=white,draw,minimum width=1.5cm,minimum height=1.3cm] (-a) at (0,0.2) {};
\begin{scope}[relative to node=-a]
\draw (-1,0.2) -- ++(2,0);
\draw (-1,0.3) -- ++(2,0);
\draw (-1,0.4) -- ++(2,0);
\end{scope}
\draw (0,0) circle(0.07) coordinate (-pivot);
}
}
\begin{document}
\foreach \x [evaluate=\x as \case using {int(mod(\x/90,4))}, evaluate=\x as \d using {10/36*\x}] in {0,10,...,359}
{
\begin{tikzpicture}
\useasboundingbox (-2,-2) rectangle (2,6);
\pic (kolben) at (0,{3+sin(\x)}) {kolben};
\fill[black,radius=.1] (\x:1) circle;
\begin{pgfonlayer}{background}
\draw[double distance=15mm] (0,1.45) -- (0,4.85);
\draw[rotate=\x] (0,.5) arc(90:270:.5) -- cycle;
\draw[double distance=1mm] (0,0) -- (\x:1);
\draw[double distance=1mm] (\x:1) -- (kolben-pivot);
\end{pgfonlayer}
\node[anchor=base] at (1.25,3) {$ x $};
\ifnum\x=0
\fill[red] (1,3) circle (1.5pt);
\else
\ifnum\x=180
\fill[red] (1,3) circle (1.5pt);
\else
\draw[->,red,ultra thick] (1,3) -- +(0,{sin(\x)});
\fi
\fi
\node[anchor=base] at (1.75,3) {$ \dot{x} $};
\ifnum\x=90
\fill[blue] (1.5,3) circle (1.5pt);
\else
\ifnum\x=270
\fill[blue] (1.5,3) circle (1.5pt);
\else
\draw[->,blue,ultra thick] (1.5,3) -- +(0,{cos(\x)});
\fi
\fi
\ifcase\case
\draw[line width=14.9mm,red!\d] (kolben-a.north) -- (0,4.85);
\or
\pgfmathsetmacro{\aa}{.5*\d}
\draw[line width=14.9mm,blue!\aa] (kolben-a.north) -- (0,4.85);
\or
\pgfmathsetmacro{\aa}{.5*\d}
\draw[line width=14.9mm,blue!\aa] (kolben-a.north) -- (0,4.85);
\or
\pgfmathsetmacro{\aa}{.2*\d}
\draw[line width=14.9mm,gray!\aa] (kolben-a.north) -- (0,4.85);
\fi
\end{tikzpicture}
}
\end{document}
The changes that I made:
- I used
\x in degrees, so that you can get the animation as smooth as you wish, up to one degree stepsize, by only changing the second entry in the foreach list;
- I split the animation in four cases (quadrants) in which the gas color is changed (I have not touched the actual colors as I wouldn't know what to do with them anyway);
- I drew the arrows continuously from one point, I think it is distracting if the starting point of the arrow changes;
- I added a physical quantity to the arrows, because if there is no idea behind annotations, you might as well omit them;
- I changed the
kolben style to a pic, because if \pgfextra is not needed, you probably shouldn't use it.
- The rest of the changes are probably personal coding preferences, and don't really add to the functionality, but you can always learn from seeing different code do the same thing :)
The result of course:

Edit
Just for fun, some small aesthetic improvements, and an attempt to display the states of the engine as described by Skillmon:

Code:
\documentclass[tikz]{standalone}
\usetikzlibrary{shapes}
\tikzset{
relative to node/.style={
shift={(#1.center)},
x={(#1.east)},
y={(#1.north)},
},
kolben/.pic={
\node[fill=white,draw,minimum width=1.5cm,minimum height=1.3cm] (-a) at (0,0.2) {};
\begin{scope}[relative to node=-a]
\draw (-1,0.2) -- ++(2,0);
\draw (-1,0.3) -- ++(2,0);
\draw (-1,0.4) -- ++(2,0);
\end{scope}
\draw (0,0) circle(0.07);
},
valve/.pic={
\draw[fill=white] (-0.175,0) -- (-0.125,0.05) -- (-0.05,0.05) -- (-0.05,0.15) -- (-0.075,0.15) -- (-0.075,0.2) -- (0.075,0.2) -- (0.075,0.15) -- (0.05,0.15) -- (0.05,0.05) -- (0.125,0.05) -- (0.175,0) -- cycle;
},
cylinder/.pic={
\draw (-0.75,1.55) -- (-0.8,1.55) -- (-0.8,5.05) -- (-0.5,5.05) -- (-0.55,5) -- (-0.75,5) -- cycle;
\draw (-0.25,5.05) -- (-0.2,5) -- (0.2,5) -- (0.25,5.05) -- cycle;
\draw[xscale=-1] (-0.75,1.55) -- (-0.8,1.55) -- (-0.8,5.05) -- (-0.5,5.05) -- (-0.55,5) -- (-0.75,5) -- cycle;
},
crank/.pic={
\draw[fill=white,rounded corners=1mm] (90:0.75) arc (90:270:0.75) -- (0,-0.1) [rounded corners=0mm] -- (1,-0.1) arc (-90:90:0.1) [rounded corners=1mm] -- (0,0.1) -- cycle (1,0) circle (0.05);
}
}
\begin{document}
\foreach \phase [
evaluate=\phase as \x using {int(mod(\phase + 90,360))},
evaluate=\phase as \case using {int(mod(\phase/180,4))},
evaluate=\x as \d using {40*sin(\x)+50},
] in {0,5,...,719}{
\begin{tikzpicture}
\useasboundingbox (-2,-2) rectangle (2,6);
\coordinate (pivot) at (0,{3+sin(\x)});
\coordinate (piston-top) at (0,{3+sin(\x)+1.3/2+0.2});
\ifcase\case
\colorlet{gascolor}{blue!10}
\pgfmathsetmacro\valveone{1}
\pgfmathsetmacro\valvetwo{0}
\or
\colorlet{gascolor}{blue!\d}
\pgfmathsetmacro\valveone{0}
\pgfmathsetmacro\valvetwo{0}
\or
\colorlet{gascolor}{red!\d}
\pgfmathsetmacro\valveone{0}
\pgfmathsetmacro\valvetwo{0}
\or
\colorlet{gascolor}{gray!10}
\pgfmathsetmacro\valveone{0}
\pgfmathsetmacro\valvetwo{1}
\fi
\draw[line width=14.9mm,gascolor] (piston-top) -- (0,5);
\pic (cylinder) at (0,0) {cylinder};
\pic (valve1) at (-0.375,{5-0.1*\valveone}) {valve};
\pic (valve2) at (0.375,{5-0.1*\valvetwo}) {valve};
\draw[double distance=2mm-\pgflinewidth,line cap=round] (\x:1) -- (pivot);
\pic[rotate=\x] (crank) at (0,0) {crank};
\pic (kolben) at (pivot) {kolben};
\node[anchor=base] at (1.25,3) {$ x $};
\ifnum\x=0
\fill[red] (1,3) circle (1.5pt);
\else
\ifnum\x=180
\fill[red] (1,3) circle (1.5pt);
\else
\draw[->,red,ultra thick] (1,3) -- +(0,{sin(\x)});
\fi
\fi
\node[anchor=base] at (1.75,3) {$ \dot{x} $};
\ifnum\x=90
\fill[blue] (1.5,3) circle (1.5pt);
\else
\ifnum\x=270
\fill[blue] (1.5,3) circle (1.5pt);
\else
\draw[->,blue,ultra thick] (1.5,3) -- +(0,{cos(\x)});
\fi
\fi
\ifnum\phase=360
\begin{scope}
\clip (-7.5mm,5cm-0.5\pgflinewidth) rectangle (7.5mm,3cm);
\node[starburst,starburst point height=3mm,inner color=yellow,outer color=red,draw=orange] at (0,5) {};
\end{scope}
\fi
\end{tikzpicture}
}
\end{document}
xshiftif you do\draw[->,red,ultra thick] (1.5,1.5) -- (1.5,1.5 |- a.north east);and so on. – Aug 28 '18 at 18:21