ich habe ein kleines Problem bei meiner Collision Detection von meiner Engine festgestellt...
Ich benutze eine BoundingSphere für die kontakte mit wänden etc.. klappt auch wunderbar, nur... wenn ich meinen Spieler bewege, mache ich die Schrittweite abhängig von der aktuellen FPS, was leider dazu führt das wenn die FPS sehr niedrig sind meine Schritte so groß werden das ich einfach durch wände hindurch laufen kann...
Normal würde ich sagen kann man ja einfach noch nen Ray-Intersection test machen von der alten position zur neuen und dementsprechend schauen ob was im weg war, allerdings wäre das recht ungenau. Denn die Sphere hat ja einen radius, der strahl nicht... der Strahl würde also nur testen ob in der mitte der Sphere etwas im weg war, nicht am rand..
5 strahlen testen finde ich aber auch irgendwie unschön... wie wird denn so ein problem normalerweise gelöst?
wie wird denn so ein problem normalerweise gelöst?
Ich hab vor Jahren auch mal versucht so was zu implementieren. Es gibt wohl verschiedene Ansätze:
Es ist generell ratsam, dass die Physik mit einem festen Zeitfenster läuft, z.B. konstant 30 oder 60 fps. So sind die Ergebnisse reproduzierbar, was insbesondere im Netzwerk wichtig ist. Wenn ein Zeitschritt zu groß wird unterteile ihn in kleinere. Wenn ein Zeitschritt zu klein wird, führe kein Update der Physik durch, bewege die Objekte einfach nur. Idealerweise läuft die Physik ja sowieso in einem eigenen Thread, dann liest man einfach immer nur den gerade aktuellen Stand aus.
Wenn Reproduzierbarkeit nicht relevant ist kannst du auch einfach nur zu große Zeitschritte in kleinere teilen.
Teile nicht (nur) zeitlich sondern räumlich. Bei schnellen Objekten (z.B. einem Geschoss) teile die Berechnung in Schritte von sagen wir 5cm. Das ist nicht leicht, wenn verschieden schnelle Objekte kollidieren können, etc...
Führe einen Sweep-Test durch: Du testest keine Kugel sondern eine "Capsule", quasi einen Zylinder mit kugelförmigen-Enden.
Die meisten (kostenlosen) Physikengines benutzen glaube ich Variante 1 oder 2.
Registriert: Di Okt 13, 2009 17:25 Beiträge: 365
Programmiersprache: C++
Hi! Ehrlich gesagt finde ich den Ansatz von Coolcat, keine bewegten Objekte auf Kollision zu testen, sondern die Bewegung in Zeitabschnitte zu unterteilen und beim Kollisionstest von keiner Bewegung auszugehen etwas faul.
Ich habe schon Spiele gespielt, die offenbar genau das machen - das Ergebnis: Wenn man z.B. in einem Auto mit 200 Sachen auf eine Wand zurast, schafft man es u.U. dadurch zu kommen (weil keiner der unbewegten Kollisionstests eine Kollision feststellen konnte). Der Spieler befindet sich jetzt möglicherweise in einem Raum, aus dem er nicht mehr herauskommt, weil dieser zu klein ist, um wieder auf 200 zu beschleunigen. Damit wäre der Spieler für den Rest des Spiels gefangen - insbesondere im Multiplayer, sehr ärgerlich.
Man kann natürlich, wie von Coolcat schon vorgeschlagen, den Rhytmus extrem erhöhen, sodass sowas nie vorkommen kann. Das kostet dann aber wieder Performance, was das Spiel vielleicht erst zum ruckeln bringt.
Es gibt jedoch noch einen anderen Weg, zu testen ob zwei Kugeln, von denen sich eine bewegt, kollidieren: Zuerst betrachtet man die sich bewegende Kugel als Linie und die stillstehende als Punkt. Nun gilt es, die Stelle auf der Linie zu finden, die sch am dichtesten beim Punkt befindet. Wenn man diesen Punkt mit dem Mittelpunkt der stillstehenden Kugel verbindet, hat man einen rechten Winkel zur ersten Linie. Das tolle daran ist, dass man nun eine rechtwinkeliges Dreieck mit dem Punkten vSphere1Start, vSphere1End und vSphere2 hat. Im rechtwinkligen Dreieck ist alles einfach . Man kann sich eine weitere Linie zwischen vSphere1Start und vSphere2 denken (Hypotenuse). Nimmt man deren Länge mal den Kosinus (aus dem Punktprodukt der Normalisierten Differenzvektoren) von Alpha, hat man die Länge der Differenz zwischen den Punkten vSphere1Start und vNearest.
Nun können wir wieder mit Kugeln (= Punkte mit Radius) denken: Wenn die Strecke zwischen vNearest und vSphere2 kleiner ist als Radius1 + Radius2, dann kollidieren die Kugeln miteinander, sonst nicht. Nicht vergessen darf man, dass es sich bei der Strecke zwischen vSphere1Start und vSphere1End um eine Linie und nicht um ene Gerade handelt. Daher gilt es noch, zu überprüfen ob die Kollision noch zwischen vSphere1Start und vSphere1End stattfindet.
Das ganze lässt sich glaube ich auch noch optimieren... Statt der berechnung des Kosinus usw. (wozu immerhin 2 Wurzeln nötig sind), könnte man auch die Hypotenuse auf die Linie |vSphere1End-vSphere1Start| porjezieren. Das habe ich allerdings noch nicht getestet.
Ich hoffe ich konnte dir helfen
mrtrain
Edit: Wenn du mit C++ programmierst oder es in deine Programmiersprache übersetzen kannst kann ich auch den C++-Code hochladen, wenn dir das hilft.
Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.