Las simulaciones de física tienen una característica increíble: se pueden detener, rebobinar y reproducir. Esta es una herramienta muy poderosa que puede usarse para generar mundos inusuales. En esta publicación, describiré cómo usé esto para sincronizar el sonido de las bolas golpeando música famosa. ¡Pregunto a los interesados bajo el corte!
Introducción
Me encanta crear todo tipo de visualizaciones sofisticadas, simulaciones de física y todo ese tipo de cosas. Entonces, hace dos o tres años, cuando estaba desarrollando mi siguiente idea , tuve una idea, pero ¿y si generamos el mundo físico para que los procesos que tienen lugar en él creen una melodía? De hecho, en una simulación por computadora, siempre podemos retroceder, revisar las opciones, elegir la mejor y, al mismo tiempo, tenemos toda la información sobre la melodía: notas, tiempo de reproducción de una nota. Entonces tuve esta idea de vivir en mi cabeza hasta tiempos mejores, hasta que tuve tiempo de escribir algo en cuarentena, así apareció este proyecto con este artículo.
Modelo
Para empezar, decidí elegir un modelo bastante simple. En mi modelo, solo hay dos tipos de objetos: canicas y plataformas o tablas. Las plataformas tienen coordenadas estrictamente fijas, se establecen en dos puntos finales y tienen un ancho constante. Las bolas caen bajo la influencia de la gravedad y pueden rebotar en las plataformas de acuerdo con las leyes de la física. Además, decidí usar solo colisiones absolutamente elásticas para que la energía del sistema siempre permanezca sin cambios. Pero lo más importante es que cuando la bola y la plataforma chocan, se reproduce un sonido, cada plataforma tiene su propio sonido y puede constar de varias notas a la vez.
Por lo tanto, nuestro mundo consta de muchas plataformas, cada una de las cuales tiene un sonido asignado. Y las bolas que caen en este mundo pueden crear una secuencia de sonidos, y en nuestro caso, incluso una melodía.
Algoritmo
Descubrimos el modelo, pero ¿cómo generar un mundo así para que los sonidos de las bolas que golpean se alineen en una melodía conocida ?
Decidí usar el más torpe, sin embargo, que resultó ser bastante buena, la fuerza bruta recursiva, y en la gente común de fuerza bruta . Pero para que todo funcionara como debería, tuve que usar algunos trucos. Todos los pasos posteriores se realizan dentro de una función recursiva:
- Simulamos el mundo, hasta el próximo momento en que necesites tocar una nota.
- Si durante la simulación hubo una colisión no deseada, volvemos al nivel superior.
- , , , . , .
. «» ( , , ).+ 70 ∘ - 4. .
- 5. ,
- 6. , ,
tics, no se produjeron colisiones y, de ser así, devolver el mundo resultante como resultado.metro
En la imagen se puede ver la visualización de un paso de este algoritmo:
Nota
, , , . , , . , . , .
Recursion atascada
Como cualquier algoritmo de fuerza bruta , este tiene un inconveniente en forma de "recursividad estancada", esto sucede cuando alguna plataforma "mala" no permite que el mapa se genere en el futuro, pero al mismo tiempo te permite generar una parte suficientemente grande del mismo, pero no completamente ... En este caso, la recursividad se bloqueará hasta que enumere todas las opciones en el subárbol de recursividad que genera esta plataforma "mala". No hay problema cuando la altura de este subárbol no supera los 4-8 niveles de recursividad, pero a veces puede llegar a los 20-30 niveles, lo que hace que sea simplemente imposible iterar a través de todas las variantes de este subárbol.
Por lo tanto, en mi implementación, decidí usar una heurística para superar el estancamiento. La idea es colapsar parte de la recursividad cuando se detectan tales casos. Me pareció más obvio volver a
Puede ver el resultado de esta heurística en la demostración, cuando el progreso de la generación de mapas a veces se restablecerá en un 10%. Pero al mismo tiempo, te permite completar la generación de la tarjeta en un tiempo razonable.
Generación iterativa
Ahora solucionemos el siguiente problema: después del inicio de la generación del mapa, la página se congela durante 10-30 segundos y es imposible entender lo que está sucediendo, todo se ha caído, o simplemente lleva mucho tiempo generar el mapa. Por lo tanto, decidí escribir también una implementación iterativa del algoritmo de generación para que puedas construir consistentemente un mapa en pequeñas porciones.
No tuve que inventar algo nuevo, simplemente reescribí el algoritmo recursivo en una pila explícita. Así, apareció una barra de progreso en la página que te ayudará a entender que el código no ha caído, solo lleva bastante tiempo encontrar una ubicación adecuada de plataformas para tu pista.
En algunos casos, la generación puede tardar demasiado, para esto agregué el botón Reproducir , que detiene la generación e inicia la simulación del mundo.
Descargar tono de llamada
Para descargar la melodía, utilizo archivos midi, pero antes de eso lo ejecuté a través de tonejs.github.io/Midi para convertirlo en un json compatible con el navegador (pero en este momento la demostración no tiene la funcionalidad de descargar mi archivo, solo está disponible una opción de una lista preparada).
También es importante tener en cuenta que a menudo habrá varias pistas paralelas dentro del archivo midi, pero dado que mi algoritmo hasta ahora solo funciona con una bola, solo una pista se cargará con la mayor cantidad de notas.
resultados
Después de agregar algunos efectos, grabé el primer video:
Después de revisarlo varias
El video puede mostrar una desincronización, lo noté más tarde. Si va a la página con la demostración , no debería haber ninguna desincronización (el sonido en realidad se reproduce solo cuando se registra el ritmo).
¿Que sigue?
Tengo planes de agregar la capacidad de generar tales mapas para varias bolas a la vez. Tengo ideas sobre cómo hacer esto, probé varias opciones, pero hasta ahora todas funcionan muy lentamente para generar una pista completa.
Otra idea mía fue agregar nuevos objetos: botones, trampolines, pistolas (?), Anillos ... la lista se puede complementar :) Pueden diversificar significativamente el mundo.
El código
Puede encontrar todo el código fuente en mi repositorio. ¡
Cualquier sugerencia, solicitud de extracción, cuestionario es bienvenida!