Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

11

09.02.2013, 16:33

1000 Geschosse, die alle gegenseitig kollidieren können? Oder wohl doch eher nur 1000 Geschosse mit ein paar wenigen anderen Objekten. Daher schätze ich ist auch das n² wohl nicht zutreffend.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

12

09.02.2013, 16:49

Man kann IMO einen recht eleganten Hybrid-Ansatz fahren, die Flixel-Engine macht das auch so ähnlich:

Tilemaps sind große Objekte, die genauso wie jedes andere Objekt in einen Quadtree kommen können. Der Quadtree wird natürlicherweise für die Broadphase benutzt.

Jedes Objekt hat eine Hülle für den Quadtree und eine Hülle, die bei einer möglichen Überschneidung individuell für ein Objekt, mit dem kollidiert wird, zurückgegeben werden kann (in einer Art Midphase).

Nachdem die Broadphase mit dem Quadtree eine mögliche Überscheidung der Hüllen festgestellt hat und vor jeder möglichen Kollision zwischen zwei Objekten (vor der Narrowphase/Separierung) wird also eine Funktion mit dem jeweils anderen kollidierenden Objekt als Parameter aufgerufen, um die tatsächliche detaillierte Kollisionshülle zu ermitteln (die Midphase).

Bei einer Tilemap sorgt das dafür, dass nur der Teil der Karte zurückgegeben wird, der mit dem übergebenen Objekt kollidieren kann, das wären bei einer Tilemap also eine Art Gruppe aus einigen Tiles bzw. nur ein Tile.

Ein Quadtree ist denke ich sinnvoller, wenn viel schnelle Bewegung stattfindet, auch zwischen den Objekten Kollisionen stattfinden sollen und viele Objekte nicht gut in ein Tile passen und so häufig in mehrere einsortiert werden müssen.

Dieser Beitrag wurde bereits 13 mal editiert, zuletzt von »Chromanoid« (09.02.2013, 17:10)


13

09.02.2013, 17:33

Hmm mich überzeugt der Ansatz mit "Tile weiß, welche Objekte sie berühren und Objekt weiß, welche Tiles er berührt" noch ^^
Vielleicht könnte man - wenn sehr viele Objekte pro Tile vorhanden sind - die Anordnung der Objekte im Tile mittels Quadtree organisieren... :search:

Wenn ich den neuen Standpunkt der Figur kenne, kann ich ein ein Rechteck drum legen und dann die Tiles, die darin liegen einzeln abfahren. Dabei wäre es dann sinnvoll nicht in 1er Schritten sondern TILE_WIDTH- / TILE_HEIGHT-er Schritten vorzugehen. Dann ist der Aufwand die neuen Kacheln - mit denen die Figur am neuen Standpunkt kollidieren könnte - nicht mehr ganz so groß.

Am Besten arbeite ich erstmal mit dem Gitter weiter. Wenn mir das nicht reicht, muss ich später den Quadtree implementieren. Da ich Daten und Darstellung eh trenne, wirft die nachträgliche Quadtree-Implementierung schonmal die Ausgabelogik nicht durcheinander :D

LG Glocke :pillepalle:

14

14.02.2013, 11:12

Heyho,

ich habe jetzt mal ein paar Tage nicht über die Kollisionserkennung nachgedacht und mir die Vorschläge eben nochmal angesehen. Manchmal hilft es etwas Distanz zu bekommen ^^

Ich werde die Kollision erstmal nur kreisbasiert implementieren, d.h. ohne Polygone. Die Kreise kann ich später als Approximation der Polygone betrachten und für die grobe Kollisionserkennung verwenden. Über die Sache mit den Objekt- bzw. Kachel-Listen in den Kacheln bzw. Objekten habe ich noch einmal nachgedacht; mit folgendem Ergebnis:
  • Ich werde jeder Kachel eine Liste von Objekten geben, deren Kollisionsradius diese Kachel berührt oder umfasst.
  • Die Kacheln ordne ich im Grid entsprechend ihrer Kachel-Position an (quasi std::map, also assoziatives Array mit entsprechendem Key).
  • Dem Objekt an sich werde ich nur seine "Welt-Position" und den entsprechenden Kollisionsradius geben.
  • Die Kollisionserkennung werde ich in zwei Phasen durchführen:
Phase 1: Kachel-Kollision
  • Im Umkreis von MAX_RADIUS um das Objekt iteriere ich (quadratisch) durch alle Kacheln. Dazu frage ich die entsprechende Position im Grid ab und erhalte die Kachel.
  • Liegt die Kachel außerhalb des Kreises (ceil(distance(worldPosOfTile, worldPosOfObject)) > radiusOfobject), überprüfe ich diese Kachel nicht weiter.
  • Liegt sie innerhalb, prüfe ich ob sie begehbar ("befliegbar" usw.) ist, so dass ich eine Aussage darüber treffen kann, ob das Objekt auf diese Kachel dürfte, wenn kein anderes Objekt sie blockiert
Am Ende weiß ich, ob die Kacheln begehbar (etc.) sind. Ist eine Kachel z.B. eine Wand, bricht die Kollisionserkennung ab. Sonst geht es weiter:
Phase 2: Objekt-Kollision
  • Im Umkreis von 2*MAX_RADIUS um das Objekt iteriere ich (quadratisch) durch alle Kacheln. Dazu frage ich erneut die entsprechende Position im Grid ab und erhalte die entsprechende Kachel.
  • Liegt die Kachel außerhalb dieses doppeltem Umkreises (analoge Formel, nur mit 2*MAX_RADIUS), prüfe ich diese Kachel weiter.
  • Dann gehe ich durch alle Objekte, die in der Kachel (in der entsprechenden Liste) hinterlegt sind.
  • Wenn das andere Objekt sich von meinem Unterscheidet (effektiv Pointer-basiert - da weiß ich ja ob es != oder == ist - schaue ich, ob sich die Kollisionsradien schneiden (das lässt sich ja einfach berechnen).
  • Wenn ja, bricht die Kollision ab und könnte z.B. anderesObject liefern oder einfach nur einen bool'schen Wert. Ansonsten könnte hier später auch die exakte Kollisionserkennung auf Polygonbasis durchgeführt werden. Falls keine Kollision erkannt wurde, geht es mit dem nächsten Objekt bzw. der nächsten Kachel weitergehen.
/EDIT: Hier kann ich sogar noch weiter optimieren und statt 2*MAX_RADIUS auch object.Radius + MAX_RADIUS nehmen :)
Und am Ende der 2. Phase weiß ich dann exakt ob (oder sogar mit wem, wenn ich das zurückgebe) mein Objekt kollidieren würde.

Die Liste von Kacheln - die das Objekt berührt - lasse ich wie gesagt weg. Ich würde sie nur in Phase 1 brauchen, allerdings macht es wahrscheinlich kaum einen Unterschied: ob ich durch die Tiles (in der Liste meines Objektes) iteriere oder (mit etwas "Ausschuss", durch die quadratische "Abtastung") direkt im Grid in einem ausgewählten Bereich durch die Tiles gehe.... imho macht es sogar einen Performance-Vorteil aus, wenn ich (beim Verschieben des Objektes) nur die Objekt-Liste der Tile ändern muss und nicht noch zusätzlich die Tile-Liste des Objektes.

LG Glocke

PS: "Deine Nachricht enthält folgende zensierte Wörter: umschlie ßt" (ohne Leerzeichen, sonst blockt er wieder). Dann sag ich halt "umfasst" :D Aber warum ist das Wort umschlie*t denn so evil 8| :pillepalle:

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Glocke« (14.02.2013, 11:19)


Sylence

Community-Fossil

Beiträge: 1 663

Beruf: Softwareentwickler

  • Private Nachricht senden

15

14.02.2013, 21:27

PS: "Deine Nachricht enthält folgende zensierte Wörter: umschlie ßt" (ohne Leerzeichen, sonst blockt er wieder). Dann sag ich halt "umfasst" :D Aber warum ist das Wort umschlie*t denn so evil 8| :pillepalle:


Das ist eine gute Frage... eigentlich werden hier öfter mal die Klassiker der Rechtschreibfehler zensiert (voraus mit 2 r und sowas), aber umschlie*t is doch richtig... zumindest schreibt es der Duden so O.o

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

16

14.02.2013, 21:41

Ich vermute mal das Forum zensiert eigentlich "l i e ß t". Das wird gern falsch gemacht, denn es heißt "liest". Das "umsch" davor führt zu einer Fehlerkennung.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

17

14.02.2013, 22:52

Genau so war es. Ich habe das gleich korrigiert. Die Regel war etwas zu lasch, sie zensierte jedes Wort, das mit "lie*t" endet.
Somit wollte ich auch "Wörter" wie "einlie*t" oder "auslie*t" abfangen.
Sorry für den Kollateralschaden ;)

Werbeanzeige