Hi there,
ich hab mich die letzten Tage, rein aus interesse, mal mit Vektoren beschäftigt und bin dann auch auf AABB gestoßen. AABB ist der Algorythmus der in abgewandelter Form in jedem Shooter benutzt wird um Die Kollision Kugel -> Hitbox zu überprüfen. Der Vorteil von AABB ist, das man keine Schleife braucht die die Schussbahn entlag geht und alle 2 Millimeter einzeln überprüft ob eine Kollision stattfindet.
Falls sich jemand noch weiter mit der Materie beschäftigen möchte, dem kann ich nur die Videos von Jorge Rodriguez empfehlen
Eventuell noch etwas zu dem Skript:
- Mit $vBoxMin,$vBoxMax wird das Viereck definiert
- $v1 ist ein Bezugspunkt der gebraucht wird um einen Vektor zu bilden, der letztenendes mit dem Viereck kollidieren soll
Spoiler anzeigen
#include <gdiplus.au3>
#include <GuiConstantsEx.au3>
#include <Misc.au3>
_GDIPlus_Startup();
HotKeySet("{Esc}", "_Exit")
[/autoit] [autoit][/autoit] [autoit]Global $iWindowH = 500
Global $iWindowW = 500
Global $dMouseAngle = 0.0
Global $rad2pi = 180 / 3.1415926535
$hWindow = GUICreate("Test", $iWindowH, $iWindowW)
GUISetState()
$hGr = _GDIPlus_GraphicsCreateFromHWND($hWindow)
_GDIPlus_GraphicsClear($hGr, 0xFFFFFFFF)
Global $vBoxMin[2] = [50, 50]
Global $vBoxMax[2] = [120, 120]
Global $v1[2] = [300, 300]
Global $vInter[2];
$hRed = _GDIPlus_PenCreate(0xFFFF0000)
$hGreen = _GDIPlus_PenCreate(0xFF00FF00)
$hBlue = _GDIPlus_PenCreate(0xFF0000FF)
While 1
Sleep(10)
Local $coord = GUIGetCursorInfo($hWindow)
If $coord[0] < 0 Or $coord[1] < 0 Then ContinueLoop
Local $vMouse[2] = [$coord[0], $coord[1]]
_GDIPlus_GraphicsClear($hGr, 0xFFFFFFFF)
Local $fCollision = False;
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]if (LineIntersection($vBoxMin,$vBoxMax,$vMouse,$v1,$vInter)) Then
$fCollision = True
EndIf
If $fCollision Then
_GDIPlus_GraphicsDrawRect($hGr, $vBoxMin[0], $vBoxMin[1], $vBoxMax[0] - $vBoxMin[0], $vBoxMax[1] - $vBoxMin[1], $hGreen)
Else
_GDIPlus_GraphicsDrawRect($hGr, $vBoxMin[0], $vBoxMin[1], $vBoxMax[0] - $vBoxMin[0], $vBoxMax[1] - $vBoxMin[1], $hRed)
EndIf
_GDIPlus_GraphicsFillRect($hGr, $v1[0], $v1[1], 5, 5)
_GDIPlus_GraphicsDrawLine($hGr, $vMouse[0], $vMouse[1], $v1[0], $v1[1])
WEnd
Func LineIntersection($vBoxMin, $vBoxMax, $v0, $v1,ByRef $vInter)
Local $f_low = 0;
$f_high = 1;
if (not ClipLine(0,$vBoxMin,$vBoxMax,$v0,$v1,$f_low,$f_high)) Then
return False
EndIf
if (not ClipLine(1,$vBoxMin,$vBoxMax,$v0,$v1,$f_low,$f_high)) Then
return False
EndIf
Local $b = vecSubtract($v1,$v0)
$vInter = vecAdd($v0, vecMultiply($b,$f_low))
return true;
EndFunc ;==>LineIntersect
Func ClipLine($d, $Pmin, $Pmax, $v0, $v1, ByRef $f_low, ByRef $f_high)
Local $f_lowDim = 0, $f_highDim = 1
Local $Len = ($v1[$d] - $v0[$d])
if $Len = 0 then return false
[/autoit] [autoit][/autoit] [autoit]$f_lowDim = ($Pmin[$d] - $v0[$d]) / $Len
$f_highDim = ($Pmax[$d] - $v0[$d]) / $Len
If ($f_lowDim > $f_highDim) Then
swap($f_lowDim, $f_highDim)
EndIf
If ($f_highDim < $f_low) Then
Return False;
EndIf
If ($f_lowDim > $f_high) Then
Return False;
EndIf
$f_low = max($f_lowDim, $f_low);
$f_high = min($f_highDim, $f_high);
If ($f_low > $f_high) Then
Return False
EndIf
Return True;
EndFunc ;==>ClipLine
Func swap(ByRef $a, ByRef $b)
Local $tmp = $a;
$a = $b
$b = $tmp
EndFunc ;==>swap
Func max($a, $b)
If $a > $b Then
Return $a
Else
Return $b;
EndIf
EndFunc ;==>max
Func min($a, $b)
If $a < $b Then
Return $a
Else
Return $b;
EndIf
EndFunc ;==>min
Func _Exit()
_GDIPlus_PenDispose($hGreen)
_GDIPlus_PenDispose($hGreen)
_GDIPlus_PenDispose($hRed)
_GDIPlus_GraphicsDispose($hGr)
_GDIPlus_Shutdown()
Exit
EndFunc ;==>_Exit
Func vecAdd($v1, $v2)
Local $rVec[2]
$rVec[0] = $v1[0] + $v2[0]
$rVec[1] = $v1[1] + $v2[1]
Return $rVec
EndFunc ;==>vecAdd
Func vecMultiply($v1, $fVal)
Local $rVec[2]
$rVec[0] = $v1[0] * $fVal
$rVec[1] = $v1[1] * $fVal
Return $rVec
EndFunc ;==>vecMultiply
Func vecSubtract($v2, $v1)
Local $rVec[2]
$rVec[0] = $v2[0] - $v1[0]
$rVec[1] = $v2[1] - $v1[1]
Return $rVec
EndFunc ;==>vecSubtract
(Jaja ich weiß der Code ist nicht wirklich das Gelbe vom Ei... Es ist ja nur zum Testen)
//Edit: Was ich evt. noch vergessen hab zu erwähnen: Man kann dieses 2D Beispiel auch auf 3D erweitern.
Dazu müsste man nur alle Vektoren noch eine Z Koordinate verpassen und noch eine weitere Dimensionsüberprüfung für Z hinzufügen
;Func LineIntersection()
if (not ClipLine(2,$vBoxMin,$vBoxMax,$v0,$v1,$f_low,$f_high)) Then
return False
EndIf