Deep Space Defense

A JS1K entry.

Position your destructo-bots so that none of the invaders reach the
right side of the screen.

z, x, and c keys select a bot, clicking moves your bot.

Now and then, a 'big' invader will be spawned, which doesn't die from
just one shot, but has to be lasered for about a second. Make your bot
move along with it, or surround it by more than one bot, to kill it.

The code looks like this (every byte has a reason):

c=document.body.children[0];w=c.width=800;h=c.height=300;function
S(i,x,y){for(r=0;r<10;r++)for(k=0;k<7;k++)
' p $8\0>>IIw6>>>6k'
.charCodeAt(i*10+r)&1<<k&&C.F(x+r*2-4,y+k*2-7,2,2)}M=Math;R=M.random;O='';e=[];
t=[];l=1;X=[];for(a=K=i=Q=0;i<99;i++)X[i]=[R()*w,R()*h],i<3&&(t[i]={X:400,Y:i*99
+52});setInterval("with(C=c.getContext('2d')){C.F=fillRect;lineWidth=3;
W=strokeStyle='#fff';J=++Q%25;R()<(K+60)/2e3&&e.push({x:0,y:R()*280+9|0,J:J?1:30
,s:J?Q%4?Q%2:2:3});C[L='fillStyle']='#000';F(0,0,w,h);C[L]=W;for(i in X)F((X[i]
[0]+Q)%w,X[i][1],1+i%2,2);fillText('Score: '+K+O,4,12);for(i in t)with(t[i]){a&&
(X+=X-a<-1?2:X-a>1?-2:0,Y+=Y-b<-1?2:Y-b>1?-2:0);C[L]=i^l?'#bbf':'#ff7';S(4,X,Y);
for(j in e)with(e[j]){+i||(x+=s^2?3:5,C[L]='#fd7',S(s,x,y));x>w&&(O='  GAME OVER'
,e.splice(j,1))||M.abs(X-x)<28&&M.abs(Y-y)<28&&(beginPath(),moveTo(x,y),lineTo(X,
Y),stroke(),--J||(e.splice(j,1),O||K++))}}}",50);onclick=function(e){t[l].a=
e.pageX;t[l].b=e.pageY};onkeydown=function(e){u=e.keyCode;l=u^90?u^67?1:2:0}

And a more readable version, with comments explaining what is going on:

// All compression was done manually, this is a rewrite that gives the
// variables sane names, adds whitespace, and explains some of the tricks.

// .getElementById('c') would have been the sane, safe way to get the
// canvas element, but this is sligtly shorter.
canvas = document.body.children[0];

// Resize the canvas, storing width and height for later use.
width = canvas.width = 800;
height = canvas.height = 300;

// Renders ship type i at x,y
function ship(i, x, y) {
  // Loop over the pixels in the image.
  for (px = 0; px < 10; px++)
    for (py = 0; py < 7; py++)
      // This is a string containing 5 10x7 pixel graphics. One
      // character encodes a single 7-pixel column. This always leaves
      // bit 8 at 0, so that each character stays in a single UTF-8 byte.
      ' p $8\0>>IIw6>>>6k'
      // Here we extract the bit we need for the current pixel.
      .charCodeAt(i * 10 + px) & 1<<py
      // And if it is non-zero, we go ahead and draw it, subtracting a
      // few units of the coords in order to center the image on the
      // given x,y. (context.F is context.fillRect)
      && context.F(x + px * 2 - 4 , y + py * 2 - 7, 2, 2)
}

// Some short-hands for Math and Math.random.
M=Math;R=M.random;

// This string keeps track of game-over status. It is set to a
// non-empty value when an invader reaches the other side.
gameOver='';

// Arrays of invaders, bots, and stars.
invaders=[];bots=[];stars=[];
// Currently selected bot.
cur=1;

// Initialize the stars and bots.
// a, score, and time are initialized here because it saves a few
// bytes compared to regular, sane initialization.
// a is a screwy global that is needed later on, time is used to
// scroll the starfield and randomize spawned invaders.
for (i=a=score=time=0; i < 99; i++)
  // Use an array to store [x,y], since it is slightly smaller than an
  // object literal.
  stars[i] = [R() * width, R() * height],
  // If i<3, also initialize a bot for this i, using i to determine
  // the y position
  // X and Y are used here, and x and y for invaders, so that both
  // can be with-ed in the same scope.
  i < 3 && (bots[i] = {X: 400, Y: i*99+52});

// The interval code was a string, but is made into a function here to
// allow newlines to be used inside of it.
setInterval(function() {
  with(context = canvas.getContext('2d')) {
    // Create a shortcut for fillRect
    context.F = fillRect;
    // Fatter lines for more awesome laser effects
    lineWidth = 3;
    // Lasers are the only strokes we use, and they are white. Save
    // the color in W for later.
    W = strokeStyle = '#fff';
    // Update the time, and if it is %25, save that for later.
    bigInvader = ++time % 25;
    // Magic random formula based on the score, so that the chance
    // that this true gets bigger when score is higher.
    R() < (score + 60) / 2e3
    // If the above is true, spawn an invader. |0 is a way to round the y.

    // H is invader health, T is invader type. Note that bigInvader is
    // 0 (false) when a big invader is being spawned.

    // Regular enemies get 1 health, meaning they die as soon as they
    // are shot. 'big' invaders get 30, and have to be lasered for 30
    // frames.

    // The conditional under T uses more modulo-time magic to
    // determine whether this is a fast invader, and if not, whether
    // it is a type-0 or type-1 regular invader (those just have
    // different graphics). As seen above, one in 25 spawned enemies
    // is 'big'. One in 4 is fast.

    && invaders.push({x: 0, y: R() * 280 + 9|0,
                      H: bigInvader ? 1 : 30,
                      T: bigInvader ? time%4 ? time%2 : 2 : 3});

    // Set fillstyle to black, save fillStyle word for later.
    context[L='fillStyle'] = '#000';
    // Clear the screen (F is fillRect)
    F(0, 0, width, height);

    // Back to white (to draw the stars and status text)
    context[L] = W;
    for (i in stars)
      // The + time % width part causes the scrolling.
      // The i%2 is used to create bigger and smaller stars.
      F((stars[i][0] + time) % width, stars[i][1], 1+i%2, 2);

    // Since gameOver is a string, it can just be appended to the text
    // here.
    fillText('Score: ' + score + gameOver, 4, 12);

    // Go over all the bots
    for (i in bots)
      with (bots[i]) {
        // Only try to move the bot if it has its a (goal x) set.
        // Otherwise, this will see the global a, which is 0.
        a&&
        // Unfortunately, assignments always need parentheses when
        // put after && or ||.
        // Compare current x,y to target x,y. Update if necessary.
        (X += X - a < -1 ? 2 : X-a > 1 ? -2 : 0,
         Y += Y - b <- 1 ? 2 : Y-b > 1 ? -2 : 0);

        // Set the fillStyle based on whether this bot is selected.
        // i^cur (exclusive or) returns 0 only if i==l, and it's shorter.
        context[L] = i^cur ? '#bbf' : '#ff7';
        // Draw the bot (bot graphic lives at position 4 in the bitmap)
        ship(4, X, Y);

        // Go over all invaders (note that we are still in the bot loop)
        for (j in invaders)
          with (invaders[j]) {
            // If i=='0' (+ converts to integer, || is used as if(!..)
            +i ||
            // Move invader. Type 2 invaders are faster.
            (x += T^2 ? 3 : 5,
             // Fill color
             context[L] = '#fd7',
             // Draw the invader. T corresponds to the bitmap position.
             ship(T, x, y));

            // If this one has reached the right side of the screen.
            x > width &&
            // Set the gameOver flag
            (gameOver = '  GAME OVER',
             // Remove this invader from the array
             invaders.splice(j, 1))
            // else (not reached right side)
            ||
            // if the distance (on either x or y) between this
            // invader and the current bot is less than 28
            M.abs(X - x) < 28 && M.abs(Y - y) < 28 &&
            // Draw the laser beam
            (beginPath(), moveTo(x, y), lineTo(X, Y), stroke(),
             // Subtract 1 hit point. If that was the last, remove
             // this invader and update the score if not gameOver.
             --H || (invaders.splice(j, 1), gameOver || score++))
          }
      }
  }
}, 50); // 20 frames per second

// Set the current bot's target x,y based on the mouse position
onclick = function(event) {
  bots[cur].a = event.pageX;
  bots[cur].b = event.pageY;
};

// Select a bot based on the cursor code (pressing
// anything other than z or c will select the middle bot)
onkeydown = function(event) {
  code = event.keyCode;
  cur = code^90 ? code^67 ? 1 : 2 : 0;
}