Max2D Kollision Teil 1
Max2D Kollision Teil 1
(c) Assari 2006
Ins Deutsche übersetzt von simi
Ein Spiel, bei dem nichts passiert wenn zwei Objekte sich einfach übereinander bewegen, macht keinen Spass. Auch ein simples Spiel wie zum Beispiel Pong braucht Kollision.
Kollision ist nicht anderes als dass sich zwei Objekte überlappen. Lass uns einen Blick auf die einfachste Kollision werfen, wenn zwei Rechtecke sich überschneiden.
Die einfachste Form der Kollisionerkennung ist das Überschneiden von Rechtecken.
Lass uns dies an einem Beispiel anschauen:
Graphics 640,480 While Not KeyHit(key_escape) Or AppTerminate() Cls SetColor 0,255,0 DrawRect 150,200,100,100 SetColor 0,0,255 DrawRect MouseX(),MouseY(),100,100 Flip Wend End |
Wenn du das Programm ausführst, wirst du bemerken dass keine Kollision erkannt wird. Es passiert nichts, wenn sich die beiden Rechtecke gegenseitig überlappen.
Lass uns jetzt eine Kollisionsfunktion, RectsOverlap, hinzufügen und die Farbe des beweglichen Rechtecks ändern, wenn eine Überschneidung stattfindet.
Graphics 640,480 While Not KeyHit(key_escape) Or AppTerminate() Cls SetColor 0,255,0 DrawRect 150,200,100,100 If RectsOverlap(150,200,100,100,MouseX(),MouseY(),100,100) SetColor 255,0,0 Else SetColor 0,0,255 EndIf DrawRect MouseX(),MouseY(),100,100 Flip Wend End Function RectsOverlap:Int(x0, y0, w0, h0, x2, y2, w2, h2) If x0 > (x2 + w2) Or (x0 + w0) < x2 Then Return False If y0 > (y2 + h2) Or (y0 + h0) < y2 Then Return False Return True End Function |
Jetzt können wir sehen, dass das Rechteck rot wird, wenn eine Kollision vorkommt. Jetzt haben wir unsere erste funktionierende Kollisionsfunktion
Jetzt verändern wir unser Programm so, dass wir einen beweglichen Kreis anstatt eines Rechteckes haben:
Graphics 640,480 While Not KeyHit(key_escape) Or AppTerminate() Cls SetColor 0,255,0 DrawRect 150,200,100,100 If RectsOverlap(150,200,100,100,MouseX(),MouseY(),100,100) SetColor 255,0,0 Else SetColor 0,0,255 EndIf DrawOval MouseX()-50,MouseY()-50,100,100 Flip Wend End Function RectsOverlap:Int(x0, y0, w0, h0, x2, y2, w2, h2) If x0 > (x2 + w2) Or (x0 + w0) < x2 Then Return False If y0 > (y2 + h2) Or (y0 + h0) < y2 Then Return False Return True End Function |
Unsere Kollisionsüberprüfen funktioniert nicht mehr so ganz richtig. Wir brauchen jetzt eine andere Funktion, die speziell für das Überprüfen der Kollision zwischen Kreisen (oder Ellipsen!) und Rechtecken geeignet ist.
Graphics 640,480 While Not KeyHit(key_escape) Or AppTerminate() Cls SetColor 0,255,0 DrawRect 150,200,100,100 If CircRectsOverlap(150,200,100,100,MouseX(),MouseY(),50) SetColor 255,0,0 Else SetColor 0,0,255 EndIf DrawOval MouseX()-50,MouseY()-50,100,100 Flip Wend End Function CircRectsOverlap(x0, y0, w0, h0, cx, cy, r) testX=cX testY=cY If TestX < x0 Then TestX=x0 If TestX > (x0+w0) Then TestX=(x0+w0) If TestY < y0 Then Testy=y0 If TestY > (y0+h0) Then Testy=(y0+h0) Return ((cX-TestX)*(cX-TestX)+(cY-TestY)*(cY-TestY))<r*r End Function |
BlitzMax
Wenn wir für jedes verschiedene Paar von Kollisionsobjekten einen andere Funktion bräuchten, gerieten wir in ernste Schwierigkeiten. Du kannst auch sehen, dass wenn wir das simple Rechtecküberlappen verlassen haben, die dahinter steckende Mathematik immer schwieriger wird.
Zum Glück unterstützt BlitzMax (oder genauer gesagt Max2D) mehrere Kollisionsfunktionen um uns das Leben leichter zu machen. Lass uns anschauen, wie wir mit den Max2D-Kollisionsfunktionen die obige Kollision gelöst hätten.
ImagesCollide
Die simpelste Kollisionsfunktion, die von BlitzMax unterstüzt wird, ist ImagesCollide. Sie hat die folgende Syntax
Function ImagesCollide(image1:TImage,x1,y1,frame1,image2:TImage,x2,y2,frame2) |
Die Funktion braucht die beiden Bilder, die wir auf Kollision überprüfen wollen, und deren Koordinaten auf dem Bildschirm. Wir können den Frame-Parameter im Moment ignorieren, indem wir ihn auf 0 setzten.
ImagesCollide(Alien,150,200,0,Player,MouseX(),MouseY(),0) |
In der obigen Codezeile befindet sich das Alien auf der Position 150,200 und der Player an der aktuellen Mausposition.
Führe das untenstehende Programm aus und schau dir die Kollision in Aktion an.
Hinweis: Alle in dieser Tutorialserie verwendeten Bilder findest du im Verzeichnis "media"!
Graphics 640,480 Local URL:String="http::www.hanfgebiet.de/" Local Player:TImage=LoadImage(LoadBank(URL+"blobship_1-1.png")) Local Alien:TImage=LoadImage(LoadBank(URL+"cartoonufo_1-1.png")) While Not KeyHit(key_escape) Or AppTerminate() Cls DrawImage Alien,150,200 DrawImage Player,MouseX(),MouseY() If ImagesCollide(Alien,150,200,0,Player,MouseX(),MouseY(),0) SetClsColor 255,0,0 Else SetClsColor 0,0,0 EndIf Flip Wend End |
Wie du sehen kannst, erspart das benutzen dieser Funktion sehr viel Zeit.
ImagesCollide mit Animation
Lass uns nun eine Blick auf den Frame-Parameter werfen, den wir vorhin übersprungen haben. Wenn du das Programm ausführst, wirst du eine Explosionsanimation sehen, die mit unserem Raumschiff kollidiert.
Graphics 640,480 Local URL:String="http::www.hanfgebiet.de/" Local Player:TImage=LoadImage(LoadBank(URL+"blobship_1-1.png")) Local Alien:TImage=LoadAnimImage(LoadBank(URL+"exp1.png"),64,64,0,16) Local Frame:Int=0 Local AnimDelay:int=10 While Not KeyHit(key_escape) Or AppTerminate() Cls DrawImage Alien,150,200, Frame DrawImage Player,MouseX(),MouseY() If ImagesCollide(Alien,150,200,Frame,Player,MouseX(),MouseY(),0) SetClsColor 255,0,0 Else SetClsColor 0,0,0 EndIf Flip If AnimDelay<0 Then Frame :+ 1 If Frame>15 Then Frame=0 AnimDelay=10 EndIf AnimDelay :- 1 Wend End |
Um ImagesCollide für animierte Funktionen zu benutzen, brauchen wir nur die Bilder mit dem aktuellen Frame zu zeichnen und dann das gleiche Frame für den ImagesCollide-Parameter zu benutzen. AnimDelay und Frame werden für die Animation benutzt.
ImagesCollide mit Skalierung
BlitzMax erlaubt es Bilder mit SetScale in Echtzeit zu skalieren. SetScale hat folgende Syntax:
Function SetScale( scale_x#,scale_y# ) |
Leider funktioniert die ImagesCollide-Funktion nicht mehr richtig, wenn Skalierung involviert ist. Probier den folgende Code aus und beobachte wie die Kollision nicht mehr richtig funktioniert.
Graphics 640,480 Local URL:String="http::www.hanfgebiet,de/" Local Player:TImage=LoadImage(LoadBank(URL+"blobship_1-1.png")) Local Alien:TImage=LoadAnimImage(LoadBank(URL+"exp1.png"),64,64,0,16) Local Frame:Int=0 Local AnimDelay:int=10 Local PlayerSize:Int=1 Local AlienSize:Int=2 While Not KeyHit(key_escape) Or AppTerminate() Cls SetScale AlienSize,AlienSize DrawImage Alien,150,100,Frame SetScale PlayerSize,PlayerSize DrawImage Player,MouseX(),MouseY() If ImagesCollide(Alien,150,200,Frame,Player,MouseX(),MouseY(),0) SetClsColor 255,0,0 Else SetClsColor 0,0,0 EndIf Flip If AnimDelay<0 Then Frame :+ 1 If Frame>15 Then Frame=0 AnimDelay=10 EndIf AnimDelay :- 1 Wend End |
Zum Glück hat BlitzMax eine Variante von ImagesCollide die ImagesCollide2 genannt wird. ImagesCollide2 hat folgende Syntax:
Function ImagesCollide2(image1:TImage,x1,y1,frame1,rot1#,scalex1#,scaley1#,image2:TImage,x2,y2,frame2,rot2#,scalex2#,scaley2#) |
Beachte dass die Rotation und Skalierung des Bildes mit den Parametern angegeben werden kann. Alles was wir machen müssen ist, die folgende Funktion wie folgt zu benützen:
If ImagesCollide2(Alien,150,200,Frame,0,AlienSize,AlienSize,Player,MouseX(),MouseY(),0,0,PlayerSize,PlayerSize) |
Ersetze ImagesCollide im obigen Beispiel durch ImagesCollide2 und sie zu, wie die Kollision nun richtig funktioniert.
ImagesCollide mit Drehung
Ich lasse es also eine Übung für dich, herauszufinden, wie die Rotationsangabe benutzt werden sollte
In diesem Tutorial sahen wir zwei einfache (aber schnelle) Wege auf Kollision zu überprüfen, indem wird die Rechteck- und die Kreis-Rechteck-Funktionen benutzen. Aber die Funktionen gehen nur für Rechtecke und Kreise.
Weil unsere Spiele meistens Bilder verwenden, benötigen wir höher entwickelte Funktionen. Glücklicherweise unterstützt BlitzMax die beiden pixelgenauen Funktionen ImagesCollide und ImagesCollide2.
Im nächsten Tutorial, werden wir sehen, wie wir ein von BlitzMax unterstütztes, hoch entwickeltes Kollisionssystem anwenden können.