Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Jul 10, 2025 03:25

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 4 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Mo Dez 28, 2009 15:35 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2105
Wohnort: Vancouver, Canada
Programmiersprache: C++, Python
Hi,

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?

Aya~


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Dez 28, 2009 15:52 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
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:
  1. 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.
  2. Wenn Reproduzierbarkeit nicht relevant ist kannst du auch einfach nur zu große Zeitschritte in kleinere teilen.
  3. 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...
  4. 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.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Dez 29, 2009 01:55 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2105
Wohnort: Vancouver, Canada
Programmiersprache: C++, Python
Coolcat hat geschrieben:
[*]Wenn Reproduzierbarkeit nicht relevant ist kannst du auch einfach nur zu große Zeitschritte in kleinere teilen.


Auf die Idee hätte ich irgendwie auch selbst kommen können... :)

Danke~


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Dez 30, 2009 15:54 
Offline
DGL Member

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 :wink: . 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.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 4 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

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.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.007s | 16 Queries | GZIP : On ]