Version 2.0!
Features
Tutorials
Files
Glossary
Projects
Contact
Links
Message Board
Extras
LuckyCam
Old News
Sign Guestbook
View Guestbook
VB Horoscope
VB Photo Album
.
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:

    mblnCollision = IntersectRect(udtTempRect, mudtRect1, mudtRect2)

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!

    mblnCollision = GetDist(msngCircle1X, msngCircle1Y, msngCircle2X, msngCircle2Y) <= RADIUS1 + RADIUS2

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.