29/09/2012 - 23:20
Stworzyłem git Repo tutaj:
https://github.com/ArthurWulfWhite/Bezier-Distance/
Stąd możesz pobrać pliki źródłowe w formacie zip. Zawiera także demo, które można skompilować za pomocą FlashDevelop. Aby skorzystać z wersji demo, otwórz projekt we Flash Develop i kliknij „Testuj projekt”. Podczas uruchamiania wersji demo kliknij LMB, aby losowo wyznaczyć nową krzywą Beziera i nowy okrąg.
Powodzenia!
Link zip jest trudny do zobaczenia - wystarczy użyć Ctrl + F i wpisać zip. To źródło przedstawia kilka tygodni badań i programowania, mam nadzieję, że ci się spodoba.
Jeśli planujesz rekurencyjne dzielenie Beziera na segmenty i sprawdzanie kolizji z nimi, sugeruję utworzenie 100 100 tablic (siatki) i umieszczenie każdego segmentu w czterech najbliższych kwadratach, więc musisz tylko sprawdzić kolizje z 4/10 000 z segmentuje każdą ramkę.
Myślę, że skorzystasz z box2d zarówno jako programista, jak i twórca gier, ponieważ istnieje wiele ukrytych przeszkód w tworzeniu „prostego” silnika fizyki, który sprawia, że ruch wydaje się nieco wyboisty i mniej płynny, niż mógłby być.
Stara odpowiedź: czysty sposób.
Możesz faktycznie sprawdzić, czy koło koliduje z krzywą Beziera, sprawdzając odległość między odległością między środkiem okręgu a najbliższym punktem na krzywej.
Równanie odległości (ogólnie)
wyjaśnione:
Równanie Beziera:
q(t) = (1-t) * ((1-t) * start.(x,y) + t * control.(x,y)) + t*(t * control.(x,y) + (1 - t) * end.(x,y))
Można to podsumować do (z pewną algebrą) - pominę. (X, y) dla czytelności (wciąż są punktami, a nie jedną liczbą)
q(t) = (start -2 * cont + end) t^2 + (-2 * start + 2 * control) + start
Odległość od punktu (x, y) wynosi:
sqrt ((q(t).x - point.x)^2 + (q(t).y - point.y)^2)
Aby znaleźć najbliższy punkt beziera do piłki, musisz wyprowadzić i znaleźć wszystkie punkty, w których pochodna jest równa zero (pierwiastki). Jest to wielomian trzeciego stopnia, więc możesz użyć formuły zamkniętej, ale może to być niewiarygodne, ponieważ precyzja ułamków reprezentowanych przez zmiennoprzecinkowy komputer może być niewystarczająca. O wiele lepiej jest użyć Newtona lub czegoś takiego.
Pochodna, dla której musisz znaleźć korzenie, to:
Zakładając: a = początek b = kontrola c = koniec d = punkt środkowy koła
Trudną częścią jest pomnożenie tych punktów, musisz użyć iloczynu.
Jeśli chcesz, mam do tego kod i mogę go tutaj udostępnić w postaci funkcji, która po prostu zwraca wartość logiczną, jeśli występuje kolizja lub nie i kąt kolizji. Podczas naiwnego wdrażania takiego silnika zderzeniowego mogą pojawić się pewne problemy, na przykład szybko poruszająca się kula może zostać złapana między dwiema krzywymi.
Zalecam na razie tego unikać, po prostu zsumuj współczynniki dla osi x i dla osi y i dodaj je.
Użyj dowolnej niezawodnej metody, takiej jak Newton, aby znaleźć pierwiastki, sprawdź odległość od punktów początkowych na ramce, 0 <= t <= 1 do środka okręgu i sprawdź odległość dla dwóch końców bezier (początek i koniec) do środka okręgu, w zależności od tego, który z nich jest najbliższy, powie ci, czy doszło do kolizji.
Jeśli promień jest mniejszy niż minimalna odległość, dochodzi do kolizji.
Kąt jest w przybliżeniu tym, który znajduje się między środkiem okręgu a najbliższym punktem na ramce.
Biorąc to pod uwagę, jeśli naprawdę chcesz stworzyć grę z fizyką kolizyjną, proponuję po prostu iterować bez Beziera
q(t) = (1-t) * ((1-t) * start.(x,y) + t * control.(x,y)) + t*(t * control.(x,y) + (1 - t) * end.(x,y))
Podziel każdy kawałek na środku rekurencyjnie, aż będzie wystarczająco mały, powiedzmy 10 pikseli lub mniej, następnie z grubsza zbuduj bezier z pudełek i użyj Box2d do fizyki, ponieważ możliwe jest, że napisanie całego tego kodu wykrywania kolizji okaże się świetnym czas, który nie poprawia rozgrywki. Korzystanie z Box2d sprawdziło się w wielu projektach w przeszłości.
Aby to zrobić:
Podziel krzywą Beziera na segmenty linii odcinkowej i zapisz je.
Umieść wszystkie te segmenty w wyrównanym do osi obwiedni dla całej krzywej.
Wykrywanie kolizji :
1) sprawdź, czy kula znajduje się w głównym obwiedni. jeśli nie, nie ma kolizji.
2) w przeciwnym razie sprawdź, czy którykolwiek z wyliczonych powyżej poszczególnych segmentów nie koliduje ze sferą. Zobacz artykuł Przecięcie linii i kuli z Wikipedii .
EDYCJA: jeśli potrzebujesz wysokiej precyzji i chcesz dobrej wydajności, możesz również utworzyć główną ramkę graniczną dla całej krzywej, a następnie podzielić krzywą na dwa segmenty (np .:
[0.0 - 0.5]
i[0.5 - 1.0]
). Tworzenie bouding pole dla każdego z nich, a następnie ponownie podzielić każdy z tych segmentów w dwóch segmentów (dając w ten sposób[0 - 0.25]
,[0.25 - 0.5]
a[0.5 - 0.75]
,[0.75 - 1.0]
). Kontynuuj tak, aż osiągniesz wystarczającą precyzję. na końcu będziesz miałbinary tree
obwiednię z głównym obwiednią krzywej w katalogu głównym i segmentami linii w liściach. wyszukiwanie w drzewie da ciO(log n)
zamiastO(n)
(gdzien
= liczba segmentów linii dla krzywej)źródło
Przecięcie linii z krzywą Beziera osiąga się matematycznie, dzieląc krzywą. Oznacza to poleganie na właściwości wypukłego kadłuba krzywej i dzielenie jej na mniejsze łuki z różnymi wielokątami kontrolnymi w sposób podobny do divide-et-impera.
W tym artykule omówiono to do pewnego momentu: http://students.cs.byu.edu/~tom/557/text/cic.pdf .
Zaletą jest to, że algorytm działa z dowolną linią, wystarczy zastosować sztywną transformację do krzywej, aby można było uznać linię docelową za równoległą do osi Ox.
Podobnie możesz sprawdzić względem koła i wielokąta każdego takiego łuku Beziera, gdy podzielisz łuk Beziera na dwa pod-łuki. Okrąg powinien przecinać wielokąt kontrolny łuku, aby test krzywej do okręgu miał sens.
źródło