#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <Array.au3>
HotKeySet("{Esc}", "_Exit")

_GDIPlus_Startup()
$hGUI = GUICreate("Ball Physik Demo by Sprenger120", 500, 500, 50, 50)
$hGUIDC = _WinAPI_GetDC($hGUI)
$hBitmapBackpuffer = _WinAPI_CreateCompatibleBitmap($hGUIDC, 500, 500)
$hDCBackpuffer = _WinAPI_CreateCompatibleDC($hGUIDC)
_WinAPI_SelectObject($hDCBackpuffer, $hBitmapBackpuffer)
$hGraphics = _GDIPlus_GraphicsCreateFromHDC($hDCBackpuffer)
GUISetState(@SW_SHOW)


Global Const $iBall = 5;Größe des Balles
Global Const $iPunkteAnz = 7 ;Anzahl der Punkte
Global Const $iRectAnz = 5;Anzahl der Quadrate

Global Const $ARRAY_X = 0
Global Const $ARRAY_Y = 1
Global Const $ARRAY_StepX = 2
Global Const $ARRAY_StepY = 3
Global Const $ARRAY_NextStepColl = 4
Global Const $ARRAY_Width = 2
Global Const $ARRAY_Height = 3

Dim $aPunkte[$iPunkteAnz][5] ;X|Y|StepX|StepY|NextStepCollision
Dim $aRect[$iRectAnz][4] ;X|Y|W|H

;Punkte Array befüllen

For $x = 0 To $iPunkteAnz - 1
	$aPunkte[$x][$ARRAY_X] = Random(0,500,1)
	$aPunkte[$x][$ARRAY_Y] = Random(0,500,1)
	$aPunkte[$x][$ARRAY_StepX] = 8;Random(5, 10, 1)
	$aPunkte[$x][$ARRAY_StepY] = 8;Random(5, 10, 1)
	If Mod($aPunkte[$x][$ARRAY_StepX], 2) Then $aPunkte[$x][$ARRAY_StepX] += 1
;~ 	If Mod($aPunkte[$x][$ARRAY_StepY], 2) Then $aPunkte[$x][$ARRAY_StepY] += 1
	$aPunkte[$x][$ARRAY_NextStepColl] = 0
Next


;Rect Array befüllen
For $x = 0 To $iRectAnz - 1
	$aRect[$x][0] = Random(100, 400, 1)
	$aRect[$x][1] = Random(100, 400, 1)
	$aRect[$x][2] = Random(20, 90, 1)
	$aRect[$x][3] = Random(20, 90, 1)

	While 1

		;Prüfen ob sich Rechtecke nicht berühren
		For $i = 0 To $iRectAnz - 1
			If $i = $x Then ContinueLoop

			If _RectCollision($aRect[$x][$ARRAY_X], $aRect[$x][$ARRAY_Y], $aRect[$x][$ARRAY_Width], $aRect[$x][$ARRAY_Width], $aRect[$i][0], $aRect[$i][1], $aRect[$i][2], $aRect[$i][3]) Then
				$aRect[$x][0] = Random(100, 400, 1)
				$aRect[$x][1] = Random(100, 400, 1)
				$aRect[$x][2] = Random(20, 90, 1)
				$aRect[$x][3] = Random(20, 90, 1)
				ContinueLoop 2
			EndIf
		Next
		ExitLoop
	WEnd
Next

#cs
	$aPunkte[0][$ARRAY_X] = 0
	$aPunkte[0][$ARRAY_Y] = 125
	$aPunkte[0][$ARRAY_StepX] = 10;Random(5, 15, 1)
	$aPunkte[0][$ARRAY_StepY] = 0;Random(5, 15, 1)
	$aPunkte[0][$ARRAY_NextStepColl] = 0

	$aPunkte[1][$ARRAY_X] = 125
	$aPunkte[1][$ARRAY_Y] = 0
	$aPunkte[1][$ARRAY_StepX] = 0;Random(5, 15, 1)
	$aPunkte[1][$ARRAY_StepY] = 10;Random(5, 15, 1)
	$aPunkte[1][$ARRAY_NextStepColl] = 0


	$aPunkte[2][$ARRAY_X] = 300
	$aPunkte[2][$ARRAY_Y] = 101
	$aPunkte[2][$ARRAY_StepX] = 10;Random(5, 15, 1)
	$aPunkte[2][$ARRAY_StepY] = 0;Random(5, 15, 1)
	$aPunkte[2][$ARRAY_NextStepColl] = 0


	$aPunkte[3][$ARRAY_X] = 101
	$aPunkte[3][$ARRAY_Y] = 300
	$aPunkte[3][$ARRAY_StepX] = 0;Random(5, 15, 1)
	$aPunkte[3][$ARRAY_StepY] = 10;Random(5, 15, 1)
	$aPunkte[3][$ARRAY_NextStepColl] = 0



	$aRect[0][$ARRAY_X] = 100
	$aRect[0][$ARRAY_Y] = 100
	$aRect[0][$ARRAY_Width] = 50
	$aRect[0][$ARRAY_Height] = 50

	$aRect[1][$ARRAY_X] = 150
	$aRect[1][$ARRAY_Y] = 100
	$aRect[1][$ARRAY_Width] = 50
	$aRect[1][$ARRAY_Height] = 50
	$aRect[2][$ARRAY_X] = 200
	$aRect[2][$ARRAY_Y] = 100
	$aRect[2][$ARRAY_Width] = 50
	$aRect[2][$ARRAY_Height] = 50
	$aRect[3][$ARRAY_X] = 125
	$aRect[3][$ARRAY_Y] = 150
	$aRect[3][$ARRAY_Width] = 50
	$aRect[3][$ARRAY_Height] = 50
	$aRect[4][$ARRAY_X] = 175
	$aRect[4][$ARRAY_Y] = 150
	$aRect[4][$ARRAY_Width] = 50
	$aRect[4][$ARRAY_Height] = 50
#ce

$hBrushPunkte = _GDIPlus_BrushCreateSolid(0xFF22b14c)
While Sleep(20)
	_GDIPlus_GraphicsClear($hGraphics, 0xFFFFFFFF)

	;Punkte Zeichnen
	For $x = 0 To $iPunkteAnz - 1
		_GDIPlus_GraphicsFillRect($hGraphics, $aPunkte[$x][$ARRAY_X] + $iBall / 2, $aPunkte[$x][$ARRAY_Y] + $iBall / 2, $iBall, $iBall, $hBrushPunkte)
	Next

	;Rect's zeichnen
	For $x = 0 To $iRectAnz - 1
		_GDIPlus_GraphicsDrawRect($hGraphics, $aRect[$x][0], $aRect[$x][1], $aRect[$x][2], $aRect[$x][3])
	Next

	For $x = 0 To $iPunkteAnz - 1
		;Seitenwände
		If $aPunkte[$x][$ARRAY_X] > 500 Then $aPunkte[$x][$ARRAY_StepX] *= -1 ;Rechts
		If $aPunkte[$x][$ARRAY_Y] > 500 Then $aPunkte[$x][$ARRAY_StepY] *= -1 ;Unten
		If $aPunkte[$x][$ARRAY_X] < 0 Then $aPunkte[$x][$ARRAY_StepX] *= -1 ;Links
		If $aPunkte[$x][$ARRAY_Y] < 0 Then $aPunkte[$x][$ARRAY_StepY] *= -1 ;Oben

		Switch $aPunkte[$x][$ARRAY_NextStepColl]
			Case True
				Switch $aPunkte[$x][$ARRAY_NextStepColl]
					Case 1 ;oben, unten
						$aPunkte[$x][$ARRAY_StepY] *= -1
					Case 2 ;rechts, links
						$aPunkte[$x][$ARRAY_StepX] *= -1
					Case 3 ;beide Achsen umkehren
						$aPunkte[$x][$ARRAY_StepX] *= -1
						$aPunkte[$x][$ARRAY_StepY] *= -1
				EndSwitch
				$aPunkte[$x][$ARRAY_NextStepColl] = 0
				$aPunkte[$x][$ARRAY_StepX] = Int($aPunkte[$x][$ARRAY_StepX])
				$aPunkte[$x][$ARRAY_StepY] = Int($aPunkte[$x][$ARRAY_StepY])
			Case False
				If $aPunkte[$x][$ARRAY_StepX] = 0 Then $aPunkte[$x][$ARRAY_StepX] = 0.0000001
				If $aPunkte[$x][$ARRAY_StepY] = 0 Then $aPunkte[$x][$ARRAY_StepY] = 0.0000001

				;ein schritt weitersetzen
				$aPunkte[$x][$ARRAY_X] += $aPunkte[$x][$ARRAY_StepX]
				$aPunkte[$x][$ARRAY_Y] += $aPunkte[$x][$ARRAY_StepY]

				$iTempX = $aPunkte[$x][$ARRAY_X] + $aPunkte[$x][$ARRAY_StepX]
				$iTempY = $aPunkte[$x][$ARRAY_Y] + $aPunkte[$x][$ARRAY_StepY]

				$m = 0
				;Steigung errechnen
				If $iTempX - $aPunkte[$x][$ARRAY_X] <> 0 Then
					$m = ($iTempY - $aPunkte[$x][$ARRAY_Y]) / ($iTempX - $aPunkte[$x][$ARRAY_X])
					$b = $aPunkte[$x][$ARRAY_Y] - $m * $aPunkte[$x][$ARRAY_X]
				Else
					$m = 0
				EndIf

;~ 				ConsoleWrite("m=" & $m & @CRLF)

				;Testen ob der Punkt ein Quadrat berühren wird im nächsten step
				For $i = 0 To $iRectAnz - 1
					If Not _RectCollision($iTempX, $iTempY, 1, 1, $aRect[$i][$ARRAY_X], $aRect[$i][$ARRAY_Y], $aRect[$i][$ARRAY_Width], $aRect[$i][$ARRAY_Height]) Then ContinueLoop
					;Ermitteln woher der Ball kommt
					#cs
						.__2__
						|     |
						1	  3
						|__4__|
					#ce
					$ForStep = 1
					If $aPunkte[$x][$ARRAY_StepX] < 0 Then $ForStep = -1

					;Bestimmen woher die Kugel kommt
					For $f = $aPunkte[$x][$ARRAY_X] To $aPunkte[$x][$ARRAY_X] + $aPunkte[$x][$ARRAY_StepX] Step $ForStep
						$y = $m * $f + $b

						;Ecke
						If $f = $aRect[$i][$ARRAY_X] And $y = $aRect[$i][$ARRAY_Y] Then ;oben links
							ConsoleWrite("Ecke: oben links" & @CRLF)
							$aPunkte[$x][$ARRAY_NextStepColl] = 3
							ExitLoop 2
						EndIf

						If $f = $aRect[$i][$ARRAY_X] + $aRect[$i][$ARRAY_Width] And $y = $aRect[$i][$ARRAY_Y] Then ;oben rechts
							ConsoleWrite("Ecke: oben rechts" & @CRLF)
							$aPunkte[$x][$ARRAY_NextStepColl] = 3
							ExitLoop 2
						EndIf

						If $f = $aRect[$i][$ARRAY_X] + $aRect[$i][$ARRAY_Width] And $y = $aRect[$i][$ARRAY_Y] + $aRect[$i][$ARRAY_Height] Then ;unten rechts
							ConsoleWrite("Ecke: unten rechts" & @CRLF)
							$aPunkte[$x][$ARRAY_NextStepColl] = 3
							ExitLoop 2
						EndIf

						If $f = $aRect[$i][$ARRAY_X] And $y = $aRect[$i][$ARRAY_Y] + $aRect[$i][$ARRAY_Height] Then ;unten links
							ConsoleWrite("Ecke: untenlinks" & @CRLF)
							$aPunkte[$x][$ARRAY_NextStepColl] = 3
							ExitLoop 2
						EndIf



						;Seiten
						If $y = $aRect[$i][$ARRAY_Y] And $f >= $aRect[$i][$ARRAY_X] And $f <= $aRect[$i][$ARRAY_X] + $aRect[$i][$ARRAY_Width] Then ; oben
							ConsoleWrite("oben" & @CRLF)
							$aPunkte[$x][$ARRAY_NextStepColl] = 1
							ExitLoop 2
						EndIf
						If $y = $aRect[$i][$ARRAY_Y] + $aRect[$i][$ARRAY_Height] And $f >= $aRect[$i][$ARRAY_X] And $f <= $aRect[$i][$ARRAY_X] + $aRect[$i][$ARRAY_Width] Then ;unten
							ConsoleWrite("unten" & @CRLF)
							$aPunkte[$x][$ARRAY_NextStepColl] = 1
							ExitLoop 2
						EndIf
						If $f = $aRect[$i][$ARRAY_X] And $y >= $aRect[$i][$ARRAY_Y] And $y <= $aRect[$i][$ARRAY_Y] + $aRect[$i][$ARRAY_Height] Then ; links
							ConsoleWrite("links" & @CRLF)
							$aPunkte[$x][$ARRAY_NextStepColl] = 2
							ExitLoop 2
						EndIf
						If $f = $aRect[$i][$ARRAY_X] + $aRect[$i][$ARRAY_Width] And $y >= $aRect[$i][$ARRAY_Y] And $y <= $aRect[$i][$ARRAY_Y] + $aRect[$i][$ARRAY_Height] Then ; rechts
							ConsoleWrite("rechts" & @CRLF)
							$aPunkte[$x][$ARRAY_NextStepColl] = 2
							ExitLoop 2
						EndIf
					Next
				Next
		EndSwitch
	Next
	_WinAPI_BitBlt($hGUIDC, 0, 0, 500, 500, $hDCBackpuffer, 0, 0, $SRCCOPY)
WEnd

While GUIGetMsg() <> -3
WEnd


Func _RectCollision($iX1, $iY1, $iWidth1, $iHeight1, $iX2, $iY2, $iWidth2, $iHeight2)
	;Author: Faweyr
	Return $iX1 + $iWidth1 > $iX2 And $iX1 < $iX2 + $iWidth2 And $iY1 + $iHeight1 > $iY2 And $iY1 < $iY2 + $iHeight2
EndFunc   ;==>_RectCollision


Func _Exit()
	_GDIPlus_GraphicsDispose($hGraphics)
	_WinAPI_DeleteObject($hBitmapBackpuffer)
	_WinAPI_DeleteDC($hDCBackpuffer)
	_WinAPI_ReleaseDC($hGUI, $hGUIDC)
	_GDIPlus_BrushDispose($hBrushPunkte)
	_GDIPlus_Shutdown()
	Exit
EndFunc   ;==>_Exit