folgende Ausgangssituation: Auf einer schachbrettartigen Map gibt es Punkte mit x- und y-Koordinate und Objekte, die sich auf genau einem (oder keinem) Punkt befinden.
Bei der Bewegung der Objekte sollte die eventuelle Kollision mit anderen Objekten berücksichtigt werden. Nun erhalte die Map zusätzlich Kollisions-Informationen (wer welches Feld blockiert).
Zusammenfassung:
- Schachbrettartige Map
- Enthält ein assoziatives Array für die Objekte (Index: Koordinate, Wert: Zeiger auf das Objekt, was dort ist)
- Enthält ein assoziatives Array für die Kollision (Index: Koordinate, Wert: Zeiger auf das Objekt, was dieses Feld aktuell blockiert)
Kollisionsradius
Jedes Objekt hat einen Kollisionsradius (z.B. 2 Felder). Dabei kann über Map.getObjectOnPosition(X, Y) das Objekt, welches sich an X, Y befindet, ermittelt werden. Die Berechnung, ob ein Punkt im Radius eines Objektes liegt, lässt sich über den Euklidischen Abstand ermitteln.
Code: Alles auswählen
Function CollisionTest(Map, Object, Target):
Foreach X from (Target.X - Object.Radius) to (Target.X + Object.Radius) do
Foreach Y from (Target.Y - Object.Radius) to (Target.Y + Object.Radius) do
If (Point(X, Y) is NOT inside Radius of Object)
Continue // Position ist außerhalb des Radius
End If
AnotherObject = Map.getObjectOnPosition(X, Y)
If (AnotherObject != None) and (AnotherObject != Object)
Return "Blocked"
End If
End Foreach
End Foreach
Return "Free"
End Function
Jedes Objekt hat eine Kollisionsmaske, ein assoziatives Array mit Index: "Differenzkoordinate" (im Vergleich zur aktuellen Position) und als Wert true oder false (true für "blockiert dieses Feld"). Dabei kann über Map.getObjectOnPosition(X, Y) das Objekt, welches sich an X, Y befindet, ermittelt werden. Object.CollisionWidth und Object.CollisionHeight geben die Breite und Höhe der Kollisionsmaske an. Object.getCollisionFlag(X, Y) liefert das true oder false aus der Kollisionsmaske
Code: Alles auswählen
Function CollisionTest(Map, Object, Target):
Foreach X from - Object.CollisionWidth / 2 to Object.CollisionWidth / 2 Do
Foreach Y from - Object.CollisionHeight / 2 to Object.CollisionHeight / 2 Do
If Object.getCollisionFlag(X, Y) == false
Continue // An der Stelle kann das Objekt mit nichts kollidieren
End If
Pos = Object.Pos + Point(X, Y)
AnotherObject = Map.getObjectOnPosition(Pos.X, Pos.Y)
If (AnotherObject != None) and (AnotherObject != Object)
Return "Blocked"
End If
End Foreach
End Foreach
Return "Free"
End Function
Code: Alles auswählen
01110
11111
01110
- Vom Rechenaufwand her, sollte die Radius-Geschichte kein Problem sein.
- Mit dem Kollisionsradius lassen sich dann aber keine "Eckigen Objekte" (z.B. keine korrekte Kollision mit einem Rechteckigen Gebäude realisieren).
- Der Rechenaufwand bei Verwendung der Kollisionsmaske wächst (durch die Abfrage des Flags - das wird ja ein Zugriff auf ein assoziatives Array, und das in einer geschachtelten Schleife).
- Dafür sind mit der Kollisionsmaske quasi beliebige Kollisionen (auch mit Lücke drinnen) möglich..
- Nur ahne ich schon "Ungenauigkeiten", wenn die Höhe oder Breite der Maske geradzahlig ist. Bei z.B. Breite 5 und Höhe 5 wäre in jede Richtung 2 Felder Kollisionsbereich und das aktuelle Mittlere Feld das Feld des Objektes selber. Hab ich nun Breite 4 und Höhe 4, hängt die Kollisionsabfrage ein stück nach links oben (wegen Integer-Division)
LG Glocke