29/09/2012 - 23:20
Creé un repositorio git aquí:
https://github.com/ArthurWulfWhite/Bezier-Distance/
Puede descargar los archivos de origen como un archivo zip desde allí. También incluye una demostración que puede compilar con FlashDevelop. Para usar la demostración, abra el proyecto en Flash Develop y haga clic en 'Probar proyecto'. Mientras ejecuta la demostración, haga clic en el LMB para aleatorizar una nueva curva de Bezier y un nuevo círculo.
¡Buena suerte!
El enlace zip es difícil de ver, solo use Ctrl + F y escriba zip. Esta fuente representa un par de semanas de investigación y programación, espero que lo disfruten.
Si planea dividir el bezier de forma recursiva en segmentos y buscar colisiones con ellos, sugiero hacer una matriz de 100.100 (cuadrícula) y colocar cada segmento en los cuatro cuadrados más cercanos, por lo que solo tiene que verificar las colisiones con 4 / 10,000 de los segmenta cada cuadro.
Creo que te beneficiarás de box2d como programador y como creador de juegos, ya que hay muchos pequeños obstáculos ocultos para hacer un motor de física 'simple' que haga que el movimiento parezca un poco irregular y menos fluido de lo que podría ser.
Antigua respuesta: El camino puro.
En realidad, puede ver si un círculo colisiona con una curva de Bezier, verificando la distancia entre la distancia entre el centro del círculo y el punto más cercano en la curva.
La ecuación para la distancia (en general)
explicado:
Ecuación de Bezier:
q(t) = (1-t) * ((1-t) * start.(x,y) + t * control.(x,y)) + t*(t * control.(x,y) + (1 - t) * end.(x,y))
Esto se puede resumir en (con algo de álgebra): omitiré (x, y) para facilitar la lectura (siguen siendo puntos, no un número)
q(t) = (start -2 * cont + end) t^2 + (-2 * start + 2 * control) + start
La distancia desde el punto (x, y) es:
sqrt ((q(t).x - point.x)^2 + (q(t).y - point.y)^2)
Para encontrar el punto más cercano en el bezier a la pelota, necesitas derivar y encontrar todos los puntos donde la derivada es igual a cero (las raíces). Es un polinomio de tercer grado, por lo que podría usar una fórmula cerrada, pero podría no ser confiable ya que la precisión de las fracciones representadas por coma flotante de la computadora puede no ser suficiente. Es mucho mejor usar Newton o algo así.
La derivada que necesita para encontrar las raíces es:
Suponiendo: a = inicio b = control c = final d = punto central del círculo
La parte difícil es multiplicar estos puntos, tienes que usar el producto punto.
Si lo desea, tengo el código para esto y puedo compartirlo aquí en forma de una función que simplemente devuelve un valor booleano si hay una colisión o no y un ángulo de colisión. Algunos problemas podrían aparecer en la implementación ingenua de un motor de colisión como este, por ejemplo, una bola en movimiento rápido podría quedar atrapada entre dos curvas.
Recomiendo evitarlo por ahora, solo sume los coeficientes para el eje x y para el eje y y sumelos.
Utilice cualquier método confiable que pueda elegir, como Newton, para encontrar las raíces, verifique la distancia desde los puntos raíz en el bezier, 0 <= t <= 1 al centro del círculo y verifique la distancia para los dos extremos del bezier (comience y final) al centro del círculo, el que esté más cerca, le dirá si hay una colisión.
Si el radio es más pequeño que la distancia mínima, hay una colisión.
El ángulo es aproximadamente el que está entre el centro del círculo y el punto más cercano en el bezier.
Dicho esto, si realmente deseas hacer un juego con física de colisión, te sugiero que solo repitas el juego.
q(t) = (1-t) * ((1-t) * start.(x,y) + t * control.(x,y)) + t*(t * control.(x,y) + (1 - t) * end.(x,y))
Divida cada pieza en el medio de forma recursiva hasta que sea lo suficientemente pequeña, digamos 10 píxeles o menos, luego construya el bezier más o menos a partir de cajas y use Box2d para la física porque es posible que escribir todo este código de detección de colisión resulte ser excelente sumidero de tiempo que no mejora mucho la jugabilidad. Usar Box2d ha demostrado su valía en innumerables proyectos en el pasado.