Używam MatterJs do gry opartej na fizyce i nie znalazłem rozwiązania problemu zapobiegania przeciąganiu ciał przez mysz przez inne ciała. Jeśli przeciągniesz ciało do innego ciała, przeciągane ciało może wtłoczyć się do i przez inne ciało. Szukam niezawodnego sposobu, aby zapobiec ich przecięciu. Możesz zaobserwować ten efekt w dowolnej wersji demonstracyjnej MatterJS, wybierając ciało myszką i próbując przepchnąć je przez inne ciało. Oto typowy przykład:
https://brm.io/matter-js/demo/#staticFriction
Niestety łamie to wszelkie gry lub symulacje w zależności od przeciągania i upuszczania. Próbowałem wielu rozwiązań, takich jak przełamanie ograniczenia myszy w przypadku kolizji lub zmniejszenie sztywności ograniczenia, ale nic, co działa niezawodnie.
Wszelkie sugestie mile widziane!
Odpowiedzi:
Myślę, że najlepszą odpowiedzią na to pytanie będzie znaczący przegląd
Matter.Resolver
modułu w celu wdrożenia predykcyjnego unikania fizycznych konfliktów między dowolnymi ciałami. Jest coś brakuje, że gwarantowane niepowodzenie w pewnych okolicznościach. Mówi się tutaj o dwóch „rozwiązaniach”, które w rzeczywistości są tylko rozwiązaniami częściowymi. Są one przedstawione poniżej.Rozwiązanie 1 (aktualizacja)
To rozwiązanie ma kilka zalet:
Ideą tego podejścia jest rozwiązanie paradoksu tego, co dzieje się „ kiedy siła nie do powstrzymania napotyka nieruchomy obiekt ” poprzez uczynienie siły możliwą do zatrzymania. Jest to możliwe dzięki temu
Matter.Event
beforeUpdate
, który pozwala na ograniczenie bezwzględnej prędkości i impulsu (a raczejpositionImpulse
, który tak naprawdę nie jest impulsem fizycznym) w każdym kierunku w granicach określonych przez użytkownika.Na przykład ja jestem jego ograniczania
velocity
ipositionImpulse
wx
iy
do maksymalnej wielkości25.0
. Wynik pokazano poniżejJak widać, przeciąganie ciał może być dość gwałtowne i nie będą się one przenikać. Oto, co wyróżnia to podejście od innych: większość innych potencjalnych rozwiązań zawodzi, gdy użytkownik jest wystarczająco gwałtowny podczas przeciągania.
Jedyną wadą, jaką napotkałem przy tej metodzie, jest to, że można użyć ciała niestatycznego, aby uderzyć inne ciało niestatyczne wystarczająco mocno, aby zapewnić mu wystarczającą prędkość do punktu, w którym
Resolver
moduł nie wykryje kolizji i pozwoli drugie ciało, aby przejść przez inne ciała. (W przykładzie tarcia statycznego jest wymagana wymagana prędkość50.0
, udało mi się to zrobić tylko raz, a zatem nie mam animacji przedstawiającej to).Rozwiązanie 2
Jest to dodatkowe rozwiązanie, jednak uczciwe ostrzeżenie: nie jest proste.
Mówiąc ogólnie, sposób ten polega na sprawdzeniu, czy przeciągane ciało
dragBody
nie zderzyło się ze statycznym ciałem i czy myszka odtąd zbyt daleko się posunęła, niedragBody
podążając za nim. Jeśli wykryje, że rozdzielenie między myszą adragBody
stał się zbyt duży usuwa detektor zdarzeń z i zastępuje ją inną funkcją mousemove, . Ta funkcja sprawdza, czy mysz powróciła do określonej odległości od środka ciała. Niestety nie udało mi się sprawić, by wbudowana metoda działała poprawnie, musiałem więc uwzględnić ją bezpośrednio (ktoś bardziej obeznany z JavaScriptem będzie musiał to rozgryźć). Wreszcie, jeśli zostanie wykryte zdarzenie, przełącza się z powrotem na normalny odbiornik.Matter.js
mouse.mousemove
mouse.element
mousemove()
Matter.Mouse._getRelativeMousePosition()
mouseup
mousemove
Po zastosowaniu schematu przełączania nasłuchiwania zdarzeń ciała zachowują się teraz mniej więcej tak
Przetestowałem to dość dokładnie, ale nie mogę zagwarantować, że zadziała w każdym przypadku. Należy również zauważyć, że
mouseup
zdarzenie nie jest wykrywane, chyba że mysz znajdzie się w obszarze roboczym, gdy wystąpi - ale dotyczy to każdegomouseup
wykrycia Matter.js, więc nie próbowałem tego naprawić.Jeśli prędkość jest wystarczająco duża,
Resolver
nie wykryje żadnej kolizji, a ponieważ nie ma predykcyjnego zapobiegania temu smakowi fizycznego konfliktu, pozwoli ciału przejść, jak pokazano tutaj.Można to rozwiązać, łącząc się z rozwiązaniem 1 .
I ostatnia uwaga: można to zastosować tylko do niektórych interakcji (np. Między ciałem statycznym i niestatycznym). Robi się to poprzez zmianę
do (np. ciał statycznych)
Nieudane rozwiązania
W przypadku, gdy przyszli użytkownicy napotkają to pytanie i stwierdzą, że oba rozwiązania są niewystarczające dla ich przypadku użycia, oto niektóre rozwiązania, które próbowałem, które nie działały. Przewodnik po tym, czego nie robić.
mouse.mouseup
Bezpośrednie wywołanie : obiekt natychmiast usunięty.mouse.mouseup
przezEvent.trigger(mouseConstraint, 'mouseup', {mouse: mouse})
: zastąpione przezEngine.update
, zachowanie niezmienione.Matter.Body.setStatic(body, false)
lubbody.isStatic = false
).(0,0)
poprzezsetForce
kiedy zbliża się konflikt: obiekt może nadal przechodzą, będą musiały być wdrożone wResolver
celu faktycznie pracują.mouse.element
na inne płótno poprzezsetElement()
lub poprzezmouse.element
bezpośrednią mutację : obiekt natychmiast usuwany.collisionStart
: niespójne wykrywanie kolizji nadal pozwala przejść przez tę metodęźródło
Zarządzałbym tą funkcją w inny sposób:
źródło
matter.js
radzi sobie z przeciąganiem ciał? z o „... jak wirtualnego sprężyny, która wiąże z myszy Podczas przeciągania ... sprężyna jest dołączone [w organizmie] i ciągnie w kierunku myszy ...”.Resolver
aby zdecydować, co zrobić z kolidującymi ciałami - po przejrzeniu tego kodu spodziewam się, że w wielu okolicznościach nadal zdecydowałby się na przeciąganie przez ... może działać, jeśli również realizowane własną wersjęsolveVelocity
, asolvePosition
jednak w tym momencie jesteś jeszcze ręcznie robić to, co chcesz MatterJS obsługiwać bezpośrednio ....Aby kontrolować kolizję podczas przeciągania, należy użyć filtra kolizji i zdarzeń .
Utwórz ciała z domyślną maską filtra kolizyjnego
0x0001
. Dodaj połówstartdrag
ienddrag
zdarzenia oraz ustaw inną kategorię filtrów kolizji, aby tymczasowo uniknąć kolizji.źródło
Wydaje się, że jest to związane z problemem 672 na stronie GitHub, który sugeruje, że dzieje się tak z powodu braku ciągłego wykrywania kolizji (CCD).
Podjęto próbę rozwiązania tego problemu, a kod można znaleźć tutaj, ale problem jest nadal otwarty, więc wygląda na to, że być może będziesz musiał edytować silnik, aby sam w nim wbudować CCD.
źródło