Caminantes Aleatorios (NC1)

Desde hace unos años he tenido la intención de leer el libro The nature of code escrito por Daniel Shiffman. Es un libro que se enfoca en crear animaciones para simular de forma aproximada cosas como movimiento, inercia y fuerzas actuando sobre un cuerpo. Lo que más me gusta del libro es lo gratificante que resulta el ver tu código «vivo» en la pantalla.

En esta serie de artículos hablaré un sobre las ideas presentadas en el libro conforme lo vaya leyendo. Implementaré los ejercicios y ejemplos en Javascript, por medio de p5.js. En el libro Shiffman trabaja con Processing, un dialecto de Java que corre en su propio interprete.

En esta entrada revisaré la introducción del libro, que trata sobre caminantes aleatorios y distribuciones de probabilidad.

La intención del libro y por extensión de esta entrada no es enseñar a programar, sino presentar algunas ideas básicas para animaciones. Estas ideas posteriormente pueden servir para cosas como videojuegos, videos o algún otro tipo de recurso interactivo.

Caminos Aleatorios

Imagina que te paras en el centro de una calle que va de norte a sur. Lanzas una moneda y si cae cara caminas hacia el norte, si cae el reverso caminas hacia el sur. ¿Qué tanto te alejarás del punto inicial después de varios intentos?.

Agreguemos una capa adicional de complejidad y supongamos que no sólo te puedes mover hacia el norte o sur, sino en dirección de cualquiera de los cuatro puntos cardinales. Olvidemos la moneda, generamos cuatro números aleatorios, y dependiendo del resultado (0, 1, 2, 3) elegimos uno de los puntos cardinales.

Implementación

Vamos al código, usando programación orientada a objetos. Crearé una clase que llamada Caminante con las siguientes características:

  • Las coordenadas de su posición.
  • El método mostrar que actualizará la posición en la pantalla.
  • El método caminar que hace avanzar al caminante en alguna dirección aleatoria.
class Caminante
{
   constructor(x, y)
   {
      this.x = x;
      this.y = y;
   }

   mostrar()
   {
      stroke(50);
      fill(204, 51, 10);
      ellipse(this.x, this.y, 10, 10);
   }

   caminar()
   {
      let choice = int(random(4));
      if (choice === 0)
         this.x += 5;
      else if (choice === 1)
         this.x -= 5
      else if (choice === 2)
         this.y += 5;
      else
         this.y -= 5;
   }
}

Este código se puede insertar directamente en una página html usando los tags <script>. En vez de eso voy a poner este código en un archivo llamado Walker.js, para luego importarlo a mi página html.

Nota

Para aprender lo básico sobre programación en javascript y p5.js puedes revisar una serie de videos en el canal de Daniel Shiffman. Subtítulos en español están disponibles.

La clase por sí misma no hace nada, necesito crear un objeto y hacerlo caminar. El código que «dibuja» la animación y crea el caminante en pantalla lo guardaré en el archivo main.js.

var caminante;

function setup()
{
   createCanvas(400, 400);
   caminante = new Caminante(width/2, height/2);
}

function draw()
{
   background(200);
   caminante.mostrar();
   caminante.caminar();
}

La función setup define el estado inicial de la animación: crea un lienzo de 400 pixeles por 400 pixeles, e inicializa el objeto caminante en el centro del lienzo. La función draw corre a 60 cuadros por segundo, redibujando el fondo y el caminante en cada cuadro. El resultado es el siguiente (si vez un recuadro vacío es posible que el caminante aleatorio hay caminado más allá de los bordes visibles. Recarga la página para reiniciar la animación):

Caminante con Ruido Perlin

La implementación de la sección anterior no se ve muy natural. Nada a nuestro alrededor tiene un comportamiento completamente aleatorio. ¿Cómo podemos generar un movimiento que sea errático, pero a la vez natural?. La respuesta más popular a este problema es el ruido Perlin.

El ruido Perlin fue creado en 1982 por Ken Perlin, un experto en animación y multimedia, para la película Tron. Es una función matemática que genera valores ondulatorios que posteriormente se pueden usar para animar objetos, crear texturas, o dibujar relieves.

Ver también

Puedes encontrar información detallada sobre algoritmo de Perlin y su implementación en javascript en el blog de Lanshor.

El ruido Perlin ya está incluido en la librería p5. Es una función que toma como parámetro una variable que representa el tiempo, tiempo que se incrementa en cada cuadro. En este caso como el caminante se mueve en dos ejes estableceré dos variables de tiempo: tx y ty, para luego obtener el valor de ruido Perlin correspondiente.

Implementaré la clase CaminantePerlin que extiende la clase Caminante de la sección anterior. La guardaré en el mismo archivo Walker.js.

class CaminantePerlin extends Caminante
{
   constructor(x, y)
   {
      super(x, y);
   }

   caminar(tx, ty)
   {
      let nx = noise(tx);
      let ny = noise(ty);
      this.x = map(nx, 0, 1, 0, width);
      this.y = map(ny, 0, 1, 0, height);
   }
}

En este caso el método caminar toma dos parámetros: los tiempos que se usarán en la función noise que regresa el ruido Peril correspondiente.

El archivo main.js que muestra las cosas en pantalla es el siguiente:

var caminante;
var tx = 0.5;
var ty = 1.5;

function setup()
{
   createCanvas(400, 400);
   caminante = new CaminantePerlin(width/2, height/2);
}

function draw()
{
   background(200);
   caminante.mostrar();
   caminante.caminar(tx, ty);
   tx += 0.01;
   ty += 0.01;
}

Así se ve un caminante errático «natural»:

El código fuente que genera las animaciones para esta entrada se puede encontrar en gitlab en la subcarpeta noc_1. Dado que las animaciones están embebidas en el blog el código es más complejo que lo explicado.