Diva's Magic Dream: juego en menos de 1K de Javascript

Cuando se anunció la nueva edición del concurso JS1K 2017 con el tema de Magia, decidí participar con un juego de scroll horizontal. El resultado fue Diva's Magic Dream.
El juego se trata de una diva que está soñando que es perseguida por sus fans, así que usa su magia para defenderse y de paso destruir algunas cabezas de pascua.
La forma de uso es sencilla: utilice las flechas para moverse a la izquierda y derecha, oprima la barra espaciadora desquiciadamente para poder salvar a la diva.
Tenía planes de desarrollar los dibujos utilizando las funciones de curvas integras en el marcador <canvas> pero al final recordé que podía utilizar caracteres Unicode justo como en mi ajedrez JS1K, más reciente son los emoticones que están integrados a todo color en los sistemas operativos más recientes.
Si bien la implementación de los emoticones Unicode es más bien anarquica, por ejemplo, en Mac OS X la diva es rubia, en Windows tiene el cabello negro, en Android es un negrito (misteriosamente parecido a Michael Jackson), y en la mayoría de las versiones de Linux todos las figuras aparecen como dibujos de línea.
Aproveché además algunas funciones de seno para realizar pequeñas animaciones dentro del juego, como las nubes fluctuantes y el salto de la cabeza de pascua, y la puntuación "crece" cada vez que se destruye un enemigo.
Esta participación no entró en el top 10, siendo mi tercera participación sin premio, así que decidí retirarme de futuras participaciones en el concurso JS1k.

Código fuente

Note que el JS1K "provee" de algunas variables cargadas con datos importantes, similar a esto:
<canvas id="c">
</canvas><script>
var c=document.getElementById("c");
var a=c.getContext("2d");
</script>
<script src="diva-magic-dream.js">
</script>
Aquí está mi código fuente original:
// Diva's Magic Dream por Óscar Toledo G. http://nanochess.org
//
// Creación: 16-feb-2017 4pm-9pm
// Revisión: 17-feb-2017 perfeccionamiento
// Revisión: 26-feb-2017 Mayor optimización y nuevo compresor
// Revisión: 27-feb-2017 Se agrega un sol feliz y cámaras (paparazzi)
//
// Tu diva sueña con las nubes, detén los fans a cualquier precio y ¡cuidado
// con las cabezas de Pascua!
// Utiliza las flechas izq. y der., oprime barra espaciadora para disparar magia
//
// Comprimido con https://siorki.github.io/regPack.html (gracias a @siorki)

// Matriz para el teclado
K=[];
// Matriz de personajes
o=[];
// Espera que se oprima una tecla
onkeydown=w=>K[w.which]=5;
// Espera que se suelte una tecla
onkeyup=w=>K[w.which]=0;
// r = Puntuación actual
// f = Cuadro actual
// h = Último cuadro con un fan nuevo
// Juego principal a 60hz
setInterval(w=>
            {
            // Sí, este juego necesita canvas
            with(c)
            // Sí, este juego necesita matemáticas
            with(Math){
            // Crea el cielo
            fillStyle="#28f";
            fillRect(0,0,640,240);
            // Color de la puntuación o emojis si tu navegador es antiguo
            fillStyle="#fff";
            // Tamaño de la lista de personajes
            d=o.length;
            // Verifica el comienzo del juego
            if(!d){
            K[37]=K[39]=q=r=h=f=0;
            // Pone la diva
            o[o.length]={x:40,y:200,s:64,t:0,h:0};
            // Pone la puntuación
            o[o.length]={x:8,y:32,s:24,t:5};
            // Pone las nubes
            while(d<18)
            o[o.length]={x:d++*40,y:260,s:96,t:6}
            }
            // Un sol feliz
            font=80+5*sin(.1*f)+'px Emojione,"Segoe UI emoji","Lucida Grande"';
            fillText("🌞",480,80);
            // Ilustra personajes
            while(d--)
            // Trabaja directamente con el personaje
            with(o[d]){
            // Cada uno puede tener tamaño diferente
            // Busca Emojione (Linux), Segoe UI emoji (Win7) o Lucida Grande (Mac)
            font=s+'px Emojione,"Segoe UI emoji","Lucida Grande"';
            // Todos los hermosos gráficos son cortesía de Unicode
            // Diva,Muerte,Magia,Explosión,Bonus,Puntos,Nubes,Fan,Pascua
            fillText(["💃","☠️","🌟","💥","🏅",r*100,"☁️",f&8?"🏃":"🚶","🗿","📹"][t],x,y);
            // Verifica si muere
            if(l=t-8?0:32,e=0,t>6&abs(x+l-o[e].x)<l+16&abs(y-o[e].y)<24)
            o[e].t=1;
            // 0:Movimiento de diva
            [w=>{
             // Izq/Der
             x=min(400,max(24,x+K[39]-K[37])),
             // Pequeña sinosoidal para animación de caminar
             y=200+5*sin(.1*f);
             // Mira si dispara magia (barra espaciadora)
             if(!q&K[32])o[o.length]={x:x+32,y:y-10,s:32,t:2};
             q=K[32]},
             // 1:Movimiento de muerte
             w=>{
             // Brinco
             y=200+80*sin(.1*++h);
             // Reinicia juego al terminar
             if(h>49)
             o=[]},
             // 2:Movimiento de magia
             w=>{
             // Adelanta estrella
             x+=10;
             // Busca colisiones
             e=o.length;
             l=0;
             while(e--)
             if(o[e].t>6&abs(x+l-o[e].x)<l+16&abs(y-o[e].y)<24)
             // Mira cuantos choques
             if(x=640,!--o[e].h)
             // La puntuación "crece"
             o[1].s=40,
             // Convierte a explosión o bonus
             r+=o[e].t-8?1:(o[o.length]={x:320,y:0,s:64,t:4},250),
             o[e].t=3;
             x>639&&o.splice(d,1)},
             // 3:Animación de explosión
             w=>{
             s+=4;
             s%32<1&&o.splice(d,1)},
             // 4:Animación de bonus
             w=>{
             if(y<140)
             y+=2;
             ++s>239&&o.splice(d,1)},
             // 5:Animación de puntuación
             w=>{s>24&&--s},
             // 6:Desplazamiento de nubes
             w=>{
             // Desplaza
             x=x<-80?640:--x,
             // Las nubes pulsan
             s=96+5*sin(.1*x)},
             // 7:Animación de fan
             w=>{
             // Cae
             if(y<200)y+=20;
             // Corre
             x-=8+f/1e4;
             x<0&&o.splice(d,1)},
             // 8:Animación de cabeza de pascua
             w=>{
             // Desplaza en una dirección
             x-=z;
             // ¡Boink!
             x<z|x>400&&(z=-z);
             // ¡Resorte!
             y=100+100*sin(.1*f)},
             // 9:Cámara
             w=>{
             y+=y/9;
             y>280&&o.splice(d,1)
             }][t]()
            }
            // Inserta un nuevo fan o una cámara
            if(random()<.1&f-h>20){
            h=f;
            if(random()<.1)o[o.length]={x:o[0].x,y:1,s:64,t:9,h:1};
            else o[o.length]={x:640-200*random(),y:0,s:64,t:7,h:2};
            }
            // Inserta una cabeza de Pascua (¿Acaso no jugaste Gradius? ;))
            if(f++&&f%1500<1)
            o[o.length]={x:400,y:0,s:192,t:8,h:15,z:1+f/2e4}
            }
            },15);

Relacionado

Última modificación: 22-mar-2017