3 puntos por GN⁺ 2024-05-21 | 1 comentarios | Compartir por WhatsApp

City In A Bottle – sistema de raycasting de 256 bytes

  • Introducción

    • Hoy presentamos un pequeño motor de raycasting y generador de ciudades contenido en un archivo HTML de 256 bytes.
    • Este programa reúne varios conceptos en un espacio diminuto y puede entenderse como si se resolviera un rompecabezas.
    • Sus componentes principales son el código HTML, el bucle de actualización de frames, el sistema de renderizado, el motor de raycasting y la propia ciudad.
  • Código completo

    • Este código no es un simple snippet de JavaScript, sino un programa HTML completo.
    • <canvas style=width:99% id=c onclick=setInterval('for(c.width=w=99,++t,i=6e3;i--;c.getContext`2d`.fillRect(i%w,i/w|0,1-d*Z/w+s,1))for(a=i%w/50-1,s=b=1-i/4e3,X=t,Y=Z=d=1;++Z<w&(Y<6-(32<Z&27<X%w&&X/9^Z/8)*8%46||d|(s=(X&Y&Z)%3/Z,a=b=1,d=Z/w));Y-=b)X+=a',t=9)>
      

Código HTML

  • Código HTML
    • La parte HTML está compuesta por un elemento canvas sencillo y un evento onclick.
    • <canvas style=width:99% id=c onclick=setInterval('',t=9)>
      
    • El id del elemento canvas está configurado como c, para poder acceder a él desde JavaScript.
    • El evento onclick inicia el programa y crea el bucle de actualización mediante una llamada a setInterval.

Código JavaScript

  • Código JavaScript

    • Código JavaScript de 199 bytes que se ejecuta cuando se hace clic en el canvas.
    • for(c.width=w=99,++t,i=6e3;i--;c.getContext`2d`.fillRect(i%w,i/w|0,1-d*Z/w+s,1))for(a=i%w/50-1,s=b=1-i/4e3,X=t,Y=Z=d=1;++Z<w&(Y<6-(32<Z&27<X%w&&X/9^Z/8)*8%46||d|(s=(X&Y&Z)%3/Z,a=b=1,d=Z/w));Y-=b)X+=a
      
  • Análisis del código

    • Se descompone el código para facilitar su lectura.
    • c.width = w = 99
      ++t
      for (i = 6e3; i--;){
        a = i%w/50 - 1
        s = b = 1 - i/4e3
        X = t
        Y = Z = d = 1
        for(; ++Z<w &  (Y < 6 - (32<Z & 27<X%w && X/9^Z/8)*8%46 ||  d | (s = (X&Y&Z)%3/Z, a = b = 1, d = Z/w));) {
          X += a
          Y -= b
        }
        c.getContext`2d`.fillRect(i%w, i/w|0, 1 - d*Z/w + s, 1)
      }
      
  • Explicación del código paso a paso

    • c.width = w = 99: inicializa el canvas y establece el ancho en 99 píxeles.
    • ++t: incrementa la variable de tiempo para crear la animación.
    • for (i = 6e3; i--;){}: determina el brillo de cada píxel a través de un bucle.
    • a = i % w / 50 - 1: calcula el componente horizontal del vector de cámara.
    • b = s = 1 - i / 4e3: calcula el componente vertical del vector de cámara.
    • X = t: usa el valor del tiempo como posición inicial en X.
    • Y = Z = d = 1: inicializa los valores Y, Z y d.
    • for(; ++Z<w & ...;): el sistema de raycasting itera hasta detectar una colisión.
    • c.getContext2d.fillRect(i%w, i/w|0, 1 - d*Z/w + s, 1): dibuja cada píxel para formar la imagen final.

Aprendizaje adicional

  • Aprendizaje adicional
    • Este demo fue presentado en la demoparty Revision 2022 y puede verse en Pouet.
    • También se puede encontrar una versión ampliada como shader de 256 bytes en Shadertoy.
    • Mediante una herramienta interactiva creada por Daniel Darabos, es posible manipular en tiempo real distintos aspectos del programa.

Opinión de GN⁺

  • Puntos interesantes

    • Este programa muestra cómo generar gráficos complejos con código extremadamente pequeño.
    • Solo utiliza matemáticas básicas, fáciles de entender incluso para ingenieros de software principiantes.
    • Es un buen ejemplo de optimización de código y minimalismo, y puede ser útil en competencias como code golf.
  • Visión crítica

    • El código está tan comprimido que su legibilidad puede verse afectada.
    • Es más adecuado para fines artísticos y experimentales que para aplicaciones prácticas.
  • Tecnologías relacionadas

    • En proyectos similares, se pueden revisar diversos ejemplos de shaders en Shadertoy.
    • También se pueden explorar otros ejemplos de código pequeño en plataformas como Dwitter.
  • Consideraciones para adoptar la tecnología

    • Al adoptar esta técnica, hay que considerar la legibilidad y mantenibilidad del código.
    • También hay que tener en cuenta las dificultades de optimización de rendimiento y depuración que implica implementar funciones complejas con código muy pequeño.

1 comentarios

 
GN⁺ 2024-05-21
Comentarios en Hacker News

Resumen de comentarios de Hacker News

  • 1K Pinball Game in JavaScript:

    • "Sorprende que se pueda meter tanta información con tan poco código."
    • "Esto es realmente genial, pero mientras leía el artículo el loop seguía corriendo y mi laptop se sobrecalentó."
    • "Material relacionado: cómo se construyó el mundo de [Atari 2600] Pitfall, generación procedural, evaluación perezosa, etc."
  • Generación procedural y evaluación perezosa:

    • "Se compartieron varios enlaces con materiales sobre generación procedural."
    • "Observación sobre la similitud entre la evaluación perezosa y los algoritmos de ray tracing."
  • Otros comentarios:

    • "¡Está increíble! Bien hecho."
    • "Tanto el trabajo como el artículo son sorprendentes."
    • "Remnants by Alcatraz, similar a una demo de 256 bytes para MS-DOS, con enlace a YouTube incluido."
    • "Es aún más impresionante por estar hecho en JavaScript."
    • "Realmente sorprendente."
    • "Da gusto leerlo."
    • "Si te gusta esto, probablemente también te guste #tweetcart en Twitter: programas del tamaño de un tuit para la consola virtual Pico-8."