Elemental Master game in less than 1K of Javascript

I had some hours free and I wanted to code a nice game for the newest edition of the JS1K contest, for 2016 the theme was Elemental. So I went and code Elemental Master.
The corrected version can be played here (post-contest): Elemental Master.
The purpose of this game is to catch yellow atoms and avoid red ones while moving in a fast lane tunnel-like, inspired by old vectorial games.
As always I worked hard in this one, unfortunately I introduced a bug in the last optimization pass making it non-playable in mobile phones (I forgot to change width to W). Probably this alone prevented me getting into the top 10. (more recently I discovered it only works well in iPhone and it's slow in Android phones)
The usage is easy: use arrows to move left and right and in mobile phones press over half-left of screen to move left, and press over half-right to move right.

Source code

Note that the JS1K "provides" some variables loaded with important data, similar to this:
<canvas id="c">
</canvas><script>
var c=document.getElementById("c");
var a=c.getContext("2d");
</script>
<script src="elemental-master.js">
</script>
Here is my original (and fixed) commented source code, note the source code is compressed for JS1K using @aivopass JS compressor available at http://www.iteral.com/jscrush/

        // Elemental master (Mar/13/2016) by Oscar Toledo G. http://nanochess.org/
        // Catch the yellow atoms, don't touch the red ones.
        // Use keyboard or touch your screen.
        // Size
        W = a.width / 2,
        H = a.height / 2,
        Z = W > H ? H : W,
        // Coming elements, lifes / difficulty
        O = [{t:2,d:L=R=1}],
        // Time for next one
        Q = new Date().valueOf() + 1e3,
        // Score
        S = 0,
        // Start angle
        G = 4,
        // Keys
        K = [];
        // Compression of <canvas> function names
        for(M in c)c[M[0]+(M[6]||M[2])]=c[M];

        onkeydown = function(w){K[w.which-37] = 1};
        a.addEventListener("touchstart", function(w){K[w.touches[0].clientX<W?0:2]=1}, 0);

        setInterval(function(w){
                    with (Math) {
                    P = PI / 18;
                    with(c){
                    sv(),
                    // Clear canvas
                    fc(0, 0, W*2, H*2),
                    // Show score
                    strokeStyle = shadowColor = "#0f0",
                    shadowBlur = 5,
                    lineCap = "round",
                    sT("Score: " + S, 16, 16),
                    // Prepare rotated canvas
                    ta(W, H),
                    rt(G * P - P * 4.5),
                    sa(Z, Z * .8),
                    // Draw border
                    U = new Date().valueOf(),
                    strokeStyle = "#" + (999 - U / 250 % 900 | 0),
                    i = .3 + U / 2e3 % .1;
                    while (i < 1)
                    lineWidth = 4 * i / Z,
                    ba(),
                    ac(0, 0, i, 0, P * 36),
                    sr(),
                    i += i / 4;
                    // Draw perspective lines
                    ba(),
                    lineWidth = 2 / Z,
                    i = P * 27;
                    while (i < P * 46)
                    mv(0, 0),
                    ln(sin(i), cos(i)),
                    i += P * 2;
                    sr(),
                    // Move player
                    K[0] && G && --G,
                    K[2] && G < 9 && ++G,
                    K[0] = K[2] = 0,
                    // Draw atoms
                    O[0].x = G,
                    j = O.length;
                    while (j-- > (L > 3))
                    fillStyle = "#f00#ff0#08f".substr(O[j].t * 4, 4),
                    i = O[j].x * P * 2 + P * 27,
                    ba(),
                    ac(sin(i) / O[j].d, cos(i) / O[j].d, 25 / Z / (j ? O[j].d : L), 0, P * 36),
                    fl(),
                    j && (O[j].d -= (U - T) / 60) < 1 && (
                    O[j].x == G & L < 3.5 ? O[j].t ? S++ : (L += .5) : 0, O.splice(j, 1));

                    re(),
                    T = U,
                    // Add new atoms
                    Q < T &&
                    (Q = T + random() * (L < 3.5 ? 1e3 / R : 100),
                    O[O.length] = {x: random() * 10 | 0, d: 25, t: random() > .7 | 0},
                     R += 1e-4);
                    }}
                    }, 15);

Useful links

Last modified: Jan/28/2017