ATTENTION READERS! Lucky's VB Gaming Site is no longer active. For updated game programming information and tutorials, please visit The Game Programming Wiki!
Einfache Kollisionsabfrage -
Rechteckig und Kreisförmig
Spiele machen einfach keinen Spaß ohne Kollisionen... Ich
meine, wer würde denn schon Mortal Kombat spielen, wenn es
keinen Kontakt gäbe, kein Blut? ;( Es wäre einfach nur eine Art
von Kung-Fu-Ballet! Nein danke :)
Einfache Kollisionsabfragetechniken sollten für die meisten
Spiele völlig ausreichen. "Side scroller", Puzzle
Spiele, Rollenspiele and viele andere können mit einer
rechteckigen Abfrage gelöst werden. Ego-Shooter und ähnliche
Raum-Spiele (3D-Raum) wären wohl mit einer kreisförmigen
Abfrage besser bedient. Wie ihr seht sind das sehr grundlegende
Techniken.
Lasst mich euch meinen Freund, den IntersectRect API Aufruf,
und seinen Kumpel, den RECT-Datentyp.
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Declare Function IntersectRect Lib "user32" Alias "IntersectRect" (lpDestRect As RECT, lpSrc1Rect As RECT, lpSrc2Rect As RECT) As Long
An die IntersectRect-Funktion werden als Argumente drei
Rechtecke (RECT) übergeben. Sie kontrolliert eine Überlappung
des zweiten und dritten Arguments und speichert das daraus
resultierende Übereinstimmung in das erste Argument. Außerdem
gibt die Funktion den Wert "1" zurück, wenn es eine
Überschneidung gibt, und den Wert "0", wenn es keine
Übereinstimmung gibt.
Offensichtlich könnten wir das gleiche auch manuell, durch
"IF"-Abfragen, erreichen, aber warum die Mühe? Die
IntersectRect API ist leicht zu benutzen und obendrein auch noch
schnell. Seht her:
Mit diesem Ausdruck wird eine Überlappung zwischen mudtRect1
und mudtRect2 abgefragt und die
Übereinstimmende Fläche in das Rechteck udtTempRect
übertragen. Wenn es also eine Überlappung gegeben hat, so wird
die Funktion der Variable mblnCollision vom Typ
Boolean den Wert "True" zuweisen. Wir können also
unsere Aktionen, im weiteren Verlauf des Programms, aufgrund des
Wertes dieser Variable auführen.
Kreisförmige Kollisionsabfrgen können nicht über einen
API-Aufruf ausgeführt werden, deshalb habe ich eine Funktion
geschrieben, um diesen Vorgang etwas zu beschleunigen.
Private Function GetDist(intX1 As Single, intY1 As Single, intX2 As Single, intY2 As Single) As Single
GetDist = Sqr((intX1 - intX2) ^ 2 + (intY1 - intY2) ^ 2)
End Function
Diese Funktion wird den Abstand zweier Punkte auf eine X-,
Y-Fläche zurückgeben. Um herauszufinden wie weit zwei Keise
auseinander liegen, braucht ihr nur die Koordinaten der
Kreismittelpunkte zu übergeben. Dann subtrahiert die Radien der
zwei Kreise und viola! Ihr erhaltet den Abstand der
Kreise!
Analog zum Rechteck-Quellcode oben, wird auch dieser Code
einer Boolean-Variable "True" oder "False"
übergeben, je nach dem Ergebnis der Kollisionsabfrage. Wenn die
Distanz zwischen den Kreismittelpunkten kleiner als die Summe der
Radien ist, handelt es sich um eine Kollision. Es ist so einfach.
Schaut euch das Beispiel Projekt
an, dass ich zusammen gebastelt habe um diese Prinzipien zu
demonstrieren.