Introducción
El algoritmo de Boids es una demostración relativamente simple del comportamiento emergente en un grupo. Tiene tres reglas principales, según lo descrito por su creador, Craig Reynolds:
El modelo básico de flocado consta de tres comportamientos de dirección simples que describen cómo un individuo boid maniobra en función de las posiciones y velocidades de sus compañeros cercanos:
- Separación : diríjase para evitar abarrotar a los compañeros locales.
- Alineación : diríjase hacia el rumbo promedio de los compañeros locales.
- Cohesión : dirígete para avanzar hacia la posición promedio de los compañeros locales.
Cada boid tiene acceso directo a la descripción geométrica de toda la escena, pero el agrupamiento requiere que reaccione solo a los compañeros de grupo dentro de un cierto vecindario pequeño a su alrededor. El vecindario se caracteriza por una distancia (medida desde el centro del boid) y un ángulo , medido desde la dirección de vuelo del boid. Los compañeros de manada fuera de este vecindario local son ignorados. El vecindario podría considerarse un modelo de percepción limitada (como el de un pez en aguas turbias), pero probablemente sea más correcto pensar que define la región en la que los compañeros de manada influyen en la dirección de un barco.
No soy perfecto para explicar las cosas, por lo que recomiendo consultar la fuente . También tiene algunas fotos súper informativas en su sitio.
Desafío
Dado el número de boids (entidades simuladas) y el número de cuadros, genera una animación de la simulación.
- Los boids deben representarse como un círculo rojo, con una línea dentro del círculo que muestre su rumbo, que es la dirección en la que apunta el boid:
- El ángulo de cada boid (como lo describe Reynolds) debe ser de 300 grados completos. (no 360)
- El encabezado inicial y la posición de cada boid deben ser uniformemente aleatorios (pero sembrados, de modo que la salida aún esté determinada), así como la posición.
- Si el radio de la boid es 1, entonces el radio de la vecindad debe ser 3.
- El número de boids será de 2 a 20.
- El número de fotogramas será de 1-5000
- La animación debe reproducirse con un mínimo de 10 milisegundos por fotograma y un máximo de 1 segundo por el número de boids. (2 boids = 2 segundos por fotograma máximo, 3 boids = 3 segundos por fotograma máximo, etc.)
- La animación de salida debe ser al menos 5 radios de boid por 5 radios de boid, multiplicado por la mitad del número de boid. Entonces, el tamaño mínimo para 2 boids sería de 10 radios de boid por 10 radios de boid, el mínimo para 3 boids sería de 15 radios de boid por 15 radios de boid, etc.
- El radio de cada boid debe ser un mínimo de 5 píxeles y un máximo de 50 píxeles.
- La velocidad de cada boid necesita ser limitada para que no se mueva más de 1/5 de su radio en un cuadro.
- La salida debe determinarse, de modo que la misma entrada produzca la misma salida si se ejecuta varias veces.
- Si un boid alcanza un borde, debe volver al otro lado. Del mismo modo, el vecindario alrededor de cada boid también debe envolverse alrededor de las fronteras.
Reglas para el algoritmo
En este caso, cada boid tiene un sector a su alrededor que abarca 300 grados, centrado en el encabezado de la boid. Cualquier otro boid en este "vecindario" se considera "vecinos" o (para usar el término de Reynolds) "compañeros de bandada".
Cada boid debe ajustar su rumbo para evitar colisiones y mantener una distancia cómoda de un radio de boid con sus vecinos. (Este es el aspecto de "Separación" del algoritmo. Se puede omitir el radio de boid, pero debe ser como una banda elástica, volviendo a su lugar).
Cada boid debe ajustar adicionalmente su rumbo para estar más cerca del rumbo promedio de los otros boids en su vecindario, siempre que no interfiera con la primera regla. (Este es el aspecto de "Alineación" del algoritmo)
Cada boid debe girar hacia la posición promedio de sus compañeros de manada, siempre que esto no cause colisión o interfiera significativamente con la segunda regla.
En su artículo sobre el tema , explica esto de la siguiente manera:
Para construir una bandada simulada, comenzamos con un modelo boid que admite vuelo geométrico. Agregamos comportamientos que corresponden a las fuerzas opuestas de evitar colisiones y la necesidad de unirse al rebaño. Expresados brevemente como reglas, y en orden de precedencia decreciente, los comportamientos que conducen al flocado simulado son:
- Evitación de colisiones: evite colisiones con compañeros de manada cercanos
- Igualación de velocidad: intente igualar la velocidad con compañeros de banda cercanos
- Centrado de la parvada: intente permanecer cerca de los compañeros de bandada cercanos
Descripción más detallada del movimiento:
- La implementación estándar del algoritmo de Boids generalmente hace un cálculo para cada una de las reglas y las combina.
- Para la primera regla, el boid pasa por la lista de boids vecinos dentro de su vecindario, y si la distancia entre él y el vecino es menor que cierto valor, un vector que empuja el boid lejos de su vecino se aplica al encabezado del boid.
- Para la segunda regla, el boid calcula el encabezado promedio de sus vecinos y agrega una pequeña porción (usaremos 1/10 en este desafío) de la diferencia entre su encabezado actual y el encabezado promedio a su encabezado actual.
- Para la tercera y última regla, el boid promedia las posiciones de sus vecinos, calcula un vector que apunta hacia esta ubicación. Este vector se multiplica por un número aún menor que el que se usó para la regla 2 (para este desafío, se usará 1/50) y se aplica al encabezado.
- El boid se mueve en la dirección de su rumbo.
Aquí hay una útil implementación de pseudocódigo del algoritmo Boids.
Ejemplo de entrada y salida
Entrada:Salida:5, 190 (5 boids, 190 cuadros)
Criterio ganador
Este es el código de golf , por lo que gana la solución más pequeña en bytes.
fuente
Respuestas:
Procesamiento 3.3.6 (Java) ,
932931940928957917904 bytes-1 byte de Jonathan Frech
+11 bytes para que coincida mejor con la especificación
-2 bytes de Kevin Cruijssen
-12 bytes para cambiar args a t ()
+29 bytes porque estaba haciendo un fantasma incorrecto, vea la versión comentada a continuación
-40 bytes para usar para bucles en lugar de llamadas separadas para cada fantasma
-13 bytes para usar frameRate predeterminado, 30
Bueno, es un comienzo para alguien que no practica Java-golf. :)
No conozco ninguna forma razonable de ingresar datos en Processing, por lo que las dos primeras variables son las entradas (y no conté sus valores (5 bytes) hacia el conteo de bytes). Si esto es un problema, puedo probar otras cosas.
Tampoco conozco una buena forma de permitir probarlo en línea (el proyecto Processing.js no puede manejar este estilo de código) sin alojar las cosas yo mismo; y eso es algo que no estoy ansioso por intentar. Avíseme si hay algo inteligente que pueda hacer.
Código formateado, con comentarios
Salida de muestra
n = 15, cuadros = 400:
O, la misma animación, pero mostrando el vecindario de cada boid.
fuente
2*PI
se puede llegarTAU
a guardar un byte?,i,
a,i=0,
y retire eli=0
interior del bucle para. (-1 byte);frameCount%f==0
aframeCount%f<1
(1 byte);&&
a&
en el final if2*d>=p.dist(m)&q.angleBetween(v,q.sub(m,p))<=5*PI/6
(-1 byte). Nuevamente, no estoy seguro de si esto es posible, pero dado que Processing parece bastante similar a Java, creo que lo es. Además, puedes intentar crear un gif con screentogif.com .JavaScript (ES6) + HTML5, 1200 bytes
Aquí está mi solución actual usando la API de Canvas. El
eval()
devuelve una función curry cuya primera entrada es laBoid
población, y segundo es el número de cuadros de animación. Puede usarInfinity
para animación continua.El
eval(...)
es 1187 bytes y<canvas id=c>
es de 13 bytes, lo que hace un total de 1200. La CSS es innecesaria, pero por conveniencia, que le permite ver los bordes de la tela.Editar
Según lo solicitado, otro fragmento con una entrada para la población Boid:
fuente
t.a+v+l/10+f/50
, si cambia eso at.a+v/3+l/10+f/50
, produce un comportamiento algo más interesante, pero el programa actual es más pequeño y aún no se ha especificado.