Ich verwende MatterJs für ein physikbasiertes Spiel und habe keine Lösung für das Problem gefunden, zu verhindern, dass Körper von der Maus gewaltsam durch andere Körper gezogen werden. Wenn Sie einen Körper in einen anderen Körper ziehen, kann sich der gezogene Körper in und durch den anderen Körper zwingen. Ich suche nach einem zuverlässigen Weg, um zu verhindern, dass sie sich überschneiden. Sie können diesen Effekt in jeder MatterJS-Demo beobachten, indem Sie einen Körper mit der Maus auswählen und versuchen, ihn durch einen anderen Körper zu zwingen. Hier ist ein typisches Beispiel:
https://brm.io/matter-js/demo/#staticFriction
Leider werden dadurch Spiele oder Simulationen je nach Drag & Drop unterbrochen. Ich habe zahlreiche Lösungen versucht, z. B. das Aufheben der Mausbeschränkung bei einer Kollision oder das Verringern der Beschränkungssteifigkeit, aber nichts, was zuverlässig funktioniert.
Anregungen willkommen!
Antworten:
Ich denke, dass die beste Antwort hier eine umfassende Überarbeitung des
Matter.Resolver
Moduls wäre, um eine vorausschauende Vermeidung physischer Konflikte zwischen Körpern zu implementieren. Alles andere scheitert unter bestimmten Umständen garantiert . Davon abgesehen gibt es zwei "Lösungen", die in Wirklichkeit nur Teillösungen sind. Sie sind unten aufgeführt.Lösung 1 (Update)
Diese Lösung hat mehrere Vorteile:
Die Idee hinter diesem Ansatz ist es, das Paradoxon dessen zu lösen, was passiert, " wenn eine unaufhaltsame Kraft auf ein unbewegliches Objekt trifft ", indem die Kraft stoppbar gemacht wird. Dies wird durch das ermöglicht
Matter.Event
beforeUpdate
, wodurch die absolute Geschwindigkeit und der absolute Impuls (oder besser gesagtpositionImpulse
, der nicht wirklich physikalische Impuls) in jeder Richtung auf benutzerdefinierte Grenzen beschränkt werden können.Im Beispiel beschränke ich das
velocity
undpositionImpulse
inx
undy
auf eine maximale Größe von25.0
. Das Ergebnis ist unten dargestelltWie Sie sehen können, ist es möglich, die Körper ziemlich heftig zu ziehen, und sie werden sich nicht gegenseitig durchdringen. Dies unterscheidet diesen Ansatz von anderen: Die meisten anderen potenziellen Lösungen schlagen fehl, wenn der Benutzer beim Ziehen ausreichend gewalttätig ist.
Das einzige Manko, auf das ich bei dieser Methode gestoßen bin, ist, dass es möglich ist, einen nicht statischen Körper zu verwenden, um einen anderen nicht statischen Körper so hart zu treffen, dass er eine ausreichende Geschwindigkeit erreicht, bis das
Resolver
Modul die Kollision nicht erkennt und die Kollision zulässt zweiter Körper, der durch andere Körper geht. (Im Beispiel für statische Reibung ist die erforderliche Geschwindigkeit ungefähr vorhanden50.0
. Ich habe dies nur einmal erfolgreich durchgeführt, und folglich habe ich keine Animation, die dies darstellt.)Lösung 2
Dies ist eine zusätzliche Lösung, eine faire Warnung: Es ist nicht einfach.
Im Großen und Ganzen funktioniert dies, um zu überprüfen, ob der gezogene Körper
dragBody
mit einem statischen Körper kollidiert ist und ob sich die Maus seitdem zu weit bewegt hat, ohne zudragBody
folgen. Wenn festgestellt wird, dass der Abstand zwischen der Maus und der MausdragBody
zu groß geworden ist, wird der Ereignis-Listener entfernt und durch eine andere Mausbewegungsfunktion ersetzt . Diese Funktion prüft, ob die Maus in eine bestimmte Nähe des Körperzentrums zurückgekehrt ist. Leider konnte ich die eingebaute Methode nicht richtig zum Laufen bringen, so dass ich sie direkt einbinden musste (jemand, der mehr über Kenntnisse in Javascript verfügt als ich, muss dies herausfinden). Wenn ein Ereignis erkannt wird, wechselt es zurück zum normalen Listener.Matter.js
mouse.mousemove
mouse.element
mousemove()
Matter.Mouse._getRelativeMousePosition()
mouseup
mousemove
Nach dem Anwenden des Ereignis-Listener-Schaltschemas verhalten sich die Körper nun ähnlicher
Ich habe dies ziemlich gründlich getestet , kann aber nicht garantieren, dass es in jedem Fall funktioniert. Es ist auch zu beachten, dass das
mouseup
Ereignis erst erkannt wird, wenn sich die Maus zum Zeitpunkt des Auftretens innerhalb der Zeichenfläche befindet. Dies gilt jedoch für jede Matter.js-mouseup
Erkennung, sodass ich nicht versucht habe, dies zu beheben.Wenn die Geschwindigkeit ausreichend groß ist,
Resolver
keine Kollision erkannt werden kann und der Körper keine vorbeugende Verhinderung dieses Geschmacks von physischen Konflikten aufweist, kann er wie hier gezeigt passieren.Dies kann durch Kombination mit Lösung 1 behoben werden .
Ein letzter Hinweis hier: Es ist möglich, dies nur auf bestimmte Wechselwirkungen anzuwenden (z. B. zwischen einem statischen und einem nicht statischen Körper). Dies wird durch Ändern erreicht
zu (für zB statische Körper)
Fehlgeschlagene Lösungen
Falls zukünftige Benutzer auf diese Frage stoßen und beide Lösungen für ihren Anwendungsfall als unzureichend empfinden, sind hier einige der Lösungen aufgeführt, die ich versucht habe und die dies nicht getan haben funktioniert haben. Eine Art Leitfaden für das, was man nicht tun sollte.
mouse.mouseup
Direkt : Objekt sofort gelöscht.mouse.mouseup
überEvent.trigger(mouseConstraint, 'mouseup', {mouse: mouse})
: überschrieben vonEngine.update
, Verhalten unverändert.Matter.Body.setStatic(body, false)
oderbody.isStatic = false
).(0,0)
viasetForce
bei Annäherung an einen Konflikt: Objekt kann immer noch passieren, müsste implementiert werden,Resolver
um tatsächlich zu funktionieren.mouse.element
zu einer anderen Zeichenfläche übersetElement()
oder durchmouse.element
direktes Mutieren : Objekt sofort gelöscht.collisionStart
: Inkonsistente Kollisionserkennung ermöglicht weiterhin den Durchgang mit dieser Methodequelle
Ich hätte das Feature auf andere Weise verwaltet:
quelle
matter.js
mit schleppenden Körpern um? von hier "... wie eine virtuelle Feder, die an der Maus befestigt ist. Beim Ziehen ... wird die Feder [am Körper] befestigt und zieht in Richtung der Maus ..."Resolver
zu entscheiden, was bei kollidierenden Körpern zu tun ist. Nachdem Sie diesen Code ein wenig durchgesehen haben, würde es sich unter vielen Umständen immer noch dafür entscheiden, das Durchziehen zuzulassen auch Ihre eigene Version implementiertsolveVelocity
undsolvePosition
aber an diesem Punkt sind Sie immer noch manuell tun , was Sie MatterJS direkt zu handhaben wollen ....Um die Kollision beim Ziehen zu steuern, müssen Sie Kollisionsfilter und Ereignisse verwenden .
Erstellen Sie Körper mit Standardkollisionsfiltermaske
0x0001
. Fügen Sie Fangstartdrag
undenddrag
Ereignisse hinzu und legen Sie verschiedene Filterkategorien für Körperkollisionen fest , um Kollisionen vorübergehend zu vermeiden.quelle
Dies scheint mit Problem 672 auf der GitHub-Seite zu tun zu haben, was darauf hindeutet, dass dies auf einen Mangel an CCD (Continuous Collision Detection) zurückzuführen ist.
Ein Versuch , hier Abhilfe zu schaffen wurde gemacht , und der Code für sie gefunden werden kann hier aber die Frage ist noch offen , so dass es aussieht wie Sie den Motor zu bauen CCD in es selbst bearbeiten benötigen.
quelle