29/09/2012 - 23:20
Ho creato un Repto git qui:
https://github.com/ArthurWulfWhite/Bezier-Distance/
Da qui puoi scaricare i file sorgente come zip. Include anche una demo che puoi compilare usando FlashDevelop. Per utilizzare la demo, apri il progetto in Flash Develop e fai clic su "Test progetto". Durante l'esecuzione della demo, fai clic su LMB per randomizzare una nuova curva di Bezier e un nuovo cerchio.
In bocca al lupo!
Il collegamento zip è difficile da vedere: basta usare Ctrl + F e digitare zip. Questa fonte rappresenta un paio di settimane di ricerca e programmazione, spero che ti piaccia.
Se hai intenzione di dividere il bezier in modo ricorsivo in segmenti e di verificare la presenza di collisioni con loro, ti suggerisco di creare un array di 100.100 (griglia) e di posizionare ogni segmento nei quattro quadrati più vicini, quindi devi solo verificare le collisioni con 4 / 10.000 del segmenta ogni fotogramma.
Penso che trarrai beneficio da box2d sia come programmatore che come creatore di giochi, dal momento che ci sono molti piccoli ostacoli nascosti nel creare un motore fisico "semplice" che fa sembrare il movimento un po 'irregolare e meno fluido di quanto potrebbe essere.
Vecchia risposta: il modo puro.
Puoi effettivamente vedere se un cerchio si scontra con una curva di Bezier, controllando la distanza tra la distanza tra il centro del cerchio e il punto più vicino sulla curva.
L'equazione per la distanza (in generale)
ha spiegato:
Equazione di Bezier:
q(t) = (1-t) * ((1-t) * start.(x,y) + t * control.(x,y)) + t*(t * control.(x,y) + (1 - t) * end.(x,y))
Questo può essere riassunto in (con un po 'di algebra) - Ometterò. (X, y) per leggibilità (sono ancora punti, non un numero)
q(t) = (start -2 * cont + end) t^2 + (-2 * start + 2 * control) + start
La distanza dal punto (x, y) è:
sqrt ((q(t).x - point.x)^2 + (q(t).y - point.y)^2)
Per trovare il punto più vicino sul bezier alla palla, è necessario derivare e trovare tutti i punti in cui la derivata è uguale a zero (le radici). È un polinomio di terzo grado, quindi è possibile utilizzare una formula chiusa ma potrebbe non essere affidabile poiché la precisione delle frazioni rappresentate in virgola mobile del computer potrebbe non essere sufficiente. È molto meglio usare Newton o qualcosa del genere.
Il derivato di cui hai bisogno per trovare le radici è:
Supponendo: a = inizio b = controllo c = fine d = punto centrale del cerchio
La parte difficile sta moltiplicando questi punti, devi usare il prodotto punto.
Se vuoi, ho il codice per questo e posso condividerlo qui sotto forma di una funzione che restituisce semplicemente un valore booleano se c'è una collisione o meno e un angolo di collisione. Alcuni problemi potrebbero apparire nell'implementazione ingenua di un motore di collisione come questo, ad esempio una palla in rapido movimento potrebbe rimanere intrappolata tra due curve.
Consiglio di evitarlo per ora, basta sommare i coefficienti per l'asse xe per l'asse y e sommarli.
Usa qualsiasi metodo affidabile che puoi scegliere come Newton per trovare le radici, controllare la distanza dai punti radice sul Bezier, 0 <= t <= 1 al centro del cerchio e controllare la distanza per le due estremità del Bezier (inizio e fine) al centro del cerchio, qualunque sia il più vicino, ti dirà se c'è una collisione.
Se il raggio è inferiore alla distanza minima, si verifica una collisione.
L'angolo è approssimativamente quello tra il centro del cerchio e il punto più vicino sul Bezier.
Detto questo, se desideri davvero fare un gioco con la fisica delle collisioni, ti suggerisco di ripetere il più bezier
q(t) = (1-t) * ((1-t) * start.(x,y) + t * control.(x,y)) + t*(t * control.(x,y) + (1 - t) * end.(x,y))
Dividi ogni pezzo nel mezzo in modo ricorsivo fino a quando non è abbastanza piccolo, diciamo 10 pixel o meno, quindi costruisci il bezier approssimativamente dalle scatole e usa Box2d per la fisica perché è possibile che scrivere tutto questo codice di rilevamento delle collisioni si rivelerà un grande perdita di tempo che non migliora molto il gameplay. L'uso di Box2d si è dimostrato valido in innumerevoli progetti in passato.