name22

Circle Collision

Jun 29th, 2011
105
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <WindowsConstants.au3>
  2. #include <GUIConstants.au3>
  3. #include <GDIPlus.au3>
  4. #include <WinAPI.au3>
  5. #include "VectorMath.au3"
  6. #include <Array.au3>
  7. #include <Misc.au3>
  8.  
  9. ; - Author: name22 (www.autoit.de)
  10.  
  11. Opt("GUIOnEventMode", 1)
  12.  
  13. ;###-v-SETTINGS-v-###
  14.  
  15. $iGUIWidth = 600
  16. $iGUIHeight = 400
  17. $iARGB_BG = 0xFFFFFFFF
  18. $nFPS = 50
  19.  
  20. $iCircles = 5
  21. $nSlowMotion = 10
  22.  
  23. $nFriction = 1
  24. $nGravity = 0
  25.  
  26. ;###-^-SETTINGS-^-###
  27.  
  28. $nSleepTime = 1000 / $nFPS
  29.  
  30. $nTimeMod = 1
  31. $nFPS_Display = 0
  32.  
  33. $vNTdll = DllOpen("ntdll.dll")
  34. $vUser32Dll = DllOpen("User32.dll")
  35.  
  36. $tPrecSleep = DllStructCreate("int64 time;")
  37. $pPrecSleep = DllStructGetPtr($tPrecSleep)
  38.  
  39. $hMain = GUICreate("Example by name22", $iGUIWidth, $iGUIHeight)
  40. GUISetState()
  41.  
  42. $hDC_Main = _WinAPI_GetDC($hMain)
  43. $hDC_Buffer = _WinAPI_CreateCompatibleDC($hDC_Main)
  44. $hBitmap_Buffer = _WinAPI_CreateCompatibleBitmap($hDC_Main, $iGUIWidth, $iGUIHeight)
  45. _WinAPI_SelectObject($hDC_Buffer, $hBitmap_Buffer)
  46.  
  47. _GDIPlus_Startup()
  48.  
  49. $hGraphics = _GDIPlus_GraphicsCreateFromHDC($hDC_Buffer)
  50. _GDIPlus_GraphicsSetSmoothingMode($hGraphics, 2)
  51.  
  52. $hBrush_Black = _GDIPlus_BrushCreateSolid(0xFF000000)
  53.  
  54. $hStringFormat = _GDIPlus_StringFormatCreate()
  55. $hFamily_FPS = _GDIPlus_FontFamilyCreate("Arial")
  56. $hFont_FPS = _GDIPlus_FontCreate($hFamily_FPS, 6)
  57. $hFont_Number = _GDIPlus_FontCreate($hFamily_FPS, 10)
  58.  
  59. $aMeasure = _GDIPlus_GraphicsMeasureString($hGraphics, "FPS: 000", $hFont_FPS, _GDIPlus_RectFCreate(), $hStringFormat)
  60. $tLayout_FPS = $aMeasure[0]
  61. $aMeasure = ""
  62. DllStructSetData($tLayout_FPS, "X", $iGUIWidth - DllStructGetData($tLayout_FPS, "Width") - 3)
  63. DllStructSetData($tLayout_FPS, "Y", $iGUIHeight - DllStructGetData($tLayout_FPS, "Height"))
  64. DllStructSetData($tLayout_FPS, "Width", DllStructGetData($tLayout_FPS, "Width") + 3)
  65.  
  66. $tLayout_Number = _GDIPlus_RectFCreate()
  67.  
  68. Global $aCircles[$iCircles + 1][6] = [[$iCircles]]
  69.  
  70. For $i = 1 To $aCircles[0][0]
  71.     $aCircles[$i][4] = Random(10, 20, 1) ;Circle Radius/Mass
  72.     $aCircles[$i][0] = Random($aCircles[$i][4], $iGUIWidth - $aCircles[$i][4], 1) ;X-Position of Circle Center
  73.     $aCircles[$i][1] = Random($aCircles[$i][4], $iGUIHeight - $aCircles[$i][4], 1) ;Y-Position of Circle Center
  74.     $aCircles[$i][2] = Random(-1, 1) ;X-Velocity
  75.     $aCircles[$i][3] = Random(-1, 1) ;Y-Velocity
  76.     $nRandomSpeed = Random(100, 200, 1) * -1 ^ Random(1, 2, 1)
  77.     $aCircles[$i][2] = $aCircles[$i][2] * $nRandomSpeed
  78.     $aCircles[$i][3] = $aCircles[$i][3] * $nRandomSpeed
  79.     $aCircles[$i][5] = _GDIPlus_BrushCreateSolid("0xFF" & Hex(Random(0x000000, 0xFFFFFF, 1), 6)) ;Brush
  80. Next
  81.  
  82. GUISetOnEvent($GUI_EVENT_CLOSE, "_Close", $hMain)
  83. OnAutoItExitRegister("_Shutdown")
  84. HotKeySet("i", "_DisplayInfo")
  85.  
  86. $nT_Sleep = TimerInit() + $nSleepTime
  87. $nT_UpdateFPS = TimerInit()
  88. While True
  89.     DllStructSetData($tPrecSleep, "time", -10000 * ($nSleepTime - TimerDiff($nT_Sleep)))
  90.     DllCall($vNTdll, "dword", "ZwDelayExecution", "int", 0, "ptr", $pPrecSleep)
  91.     $nFrameTime = TimerDiff($nT_Sleep)
  92.     $nT_Sleep = TimerInit()
  93.  
  94.     $nFPS_Cur = 1000 / $nFrameTime
  95.     If TimerDiff($nT_UpdateFPS) >= 500 Then
  96.         $nFPS_Display = $nFPS_Cur
  97.         $nT_UpdateFPS = TimerInit()
  98.     EndIf
  99.  
  100.     Switch _IsPressed("20", $vUser32Dll)
  101.         Case True
  102.             $nTimeMod = $nSlowMotion
  103.         Case False
  104.             If $nTimeMod <> 1 Then $nTimeMod = 1
  105.     EndSwitch
  106.  
  107.  
  108.     $nFPS_Cur *= $nTimeMod
  109.  
  110.     _GDIPlus_GraphicsClear($hGraphics, $iARGB_BG)
  111.  
  112.     For $i1 = 1 To $aCircles[0][0]
  113.         $aCircles[$i1][3] += $nGravity / $nFPS_Cur
  114.         $aCircles[$i1][2] *= $nFriction
  115.         $aCircles[$i1][3] *= $nFriction
  116.  
  117.         $aCircles[$i1][0] += $aCircles[$i1][2] / $nFPS_Cur
  118.         $aCircles[$i1][1] += $aCircles[$i1][3] / $nFPS_Cur
  119.  
  120.         _GDIPlus_GraphicsFillEllipse($hGraphics, $aCircles[$i1][0] - $aCircles[$i1][4], $aCircles[$i1][1] - $aCircles[$i1][4], $aCircles[$i1][4] * 2, $aCircles[$i1][4] * 2, $aCircles[$i1][5])
  121.         DllStructSetData($tLayout_Number, "X", $aCircles[$i1][0] - 5)
  122.         DllStructSetData($tLayout_Number, "Y", $aCircles[$i1][1] - 8)
  123.         _GDIPlus_GraphicsDrawStringEx($hGraphics, $i1, $hFont_Number, $tLayout_Number, $hStringFormat, $hBrush_Black)
  124.  
  125.         For $i2 = $i1 + 1 To $aCircles[0][0]
  126.             Switch ($aCircles[$i1][0] - $aCircles[$i2][0]) ^ 2 + ($aCircles[$i1][1] - $aCircles[$i2][1]) ^ 2 <= ($aCircles[$i1][4] + $aCircles[$i2][4]) ^ 2
  127.                 Case True
  128.                     $aCircles[$i1][0] -= $aCircles[$i1][2] / $nFPS_Cur
  129.                     $aCircles[$i1][1] -= $aCircles[$i1][3] / $nFPS_Cur
  130.                     $aCircles[$i2][0] -= $aCircles[$i2][2] / $nFPS_Cur
  131.                     $aCircles[$i2][1] -= $aCircles[$i2][3] / $nFPS_Cur
  132.  
  133.                     $nQ = _Circle_FixCircle_GetCollisionPointRatio($aCircles[$i1][0], $aCircles[$i1][1], $aCircles[$i2][0], $aCircles[$i2][1], $aCircles[$i1][4], $aCircles[$i2][4], ($aCircles[$i1][2] - $aCircles[$i2][2]), ($aCircles[$i1][3] - $aCircles[$i2][3]))
  134.                     $aCircles[$i1][0] += $aCircles[$i1][2] * $nQ
  135.                     $aCircles[$i1][1] += $aCircles[$i1][3] * $nQ
  136.                     $aCircles[$i2][0] += $aCircles[$i2][2] * $nQ
  137.                     $aCircles[$i2][1] += $aCircles[$i2][3] * $nQ
  138.  
  139.                     $nX_UN = $aCircles[$i1][0] - $aCircles[$i2][0]
  140.                     $nY_UN = $aCircles[$i1][1] - $aCircles[$i2][1]
  141.                     $nL_UN = Sqrt($nX_UN ^ 2 + $nY_UN ^ 2)
  142.                     $nX_UN = $nX_UN / $nL_UN
  143.                     $nY_UN = $nY_UN / $nL_UN
  144.  
  145.                     $nX_UT = -$nY_UN
  146.                     $nY_UT = $nX_UN
  147.  
  148.                     $nVel1_N = $nX_UN * $aCircles[$i1][2] + $nY_UN * $aCircles[$i1][3]
  149.                     $nVel2_N = $nX_UN * $aCircles[$i2][2] + $nY_UN * $aCircles[$i2][3]
  150.                     $nVel1_T = $nX_UT * $aCircles[$i1][2] + $nY_UT * $aCircles[$i1][3]
  151.                     $nVel2_T = $nX_UT * $aCircles[$i2][2] + $nY_UT * $aCircles[$i2][3]
  152.  
  153.                     $nVel1_N_New = ($nVel1_N * ($aCircles[$i1][4] - $aCircles[$i2][4]) + 2 * $aCircles[$i2][4] * $nVel2_N) / ($aCircles[$i1][4] + $aCircles[$i2][4])
  154.                     $nVel2_N_New = ($nVel2_N * ($aCircles[$i2][4] - $aCircles[$i1][4]) + 2 * $aCircles[$i1][4] * $nVel1_N) / ($aCircles[$i1][4] + $aCircles[$i2][4])
  155.  
  156.                     $aCircles[$i1][2] = $nVel1_N_New * $nX_UN + $nVel1_T * $nX_UT
  157.                     $aCircles[$i1][3] = $nVel1_N_New * $nY_UN + $nVel1_T * $nY_UT
  158.                     $aCircles[$i2][2] = $nVel2_N_New * $nX_UN + $nVel2_T * $nX_UT
  159.                     $aCircles[$i2][3] = $nVel2_N_New * $nY_UN + $nVel2_T * $nY_UT
  160.             EndSwitch
  161.         Next
  162.         Switch True
  163.             Case $aCircles[$i1][0] <= $aCircles[$i1][4] And $aCircles[$i1][2] < 0
  164.                 $aCircles[$i1][2] *= -1
  165.                 $aCircles[$i1][0] = $aCircles[$i1][4]
  166.             Case $aCircles[$i1][0] >= $iGUIWidth - $aCircles[$i1][4] And $aCircles[$i1][2] > 0
  167.                 $aCircles[$i1][2] *= -1
  168.                 $aCircles[$i1][0] = $iGUIWidth - $aCircles[$i1][4]
  169.         EndSwitch
  170.         Switch True
  171.             Case $aCircles[$i1][1] <= $aCircles[$i1][4] And $aCircles[$i1][3] < 0
  172.                 $aCircles[$i1][3] *= -1
  173.                 $aCircles[$i1][1] = $aCircles[$i1][4]
  174.             Case $aCircles[$i1][1] >= $iGUIHeight - $aCircles[$i1][4] And $aCircles[$i1][3] > 0
  175.                 $aCircles[$i1][3] *= -1
  176.                 $aCircles[$i1][1] = $iGUIHeight - $aCircles[$i1][4]
  177.         EndSwitch
  178.     Next
  179.  
  180.     _GDIPlus_GraphicsDrawStringEx($hGraphics, "FPS: " & Round($nFPS_Display, 1), $hFont_FPS, $tLayout_FPS, $hStringFormat, $hBrush_Black)
  181.     _WinAPI_BitBlt($hDC_Main, 0, 0, $iGUIWidth, $iGUIHeight, $hDC_Buffer, 0, 0, $SRCCOPY)
  182. WEnd
  183.  
  184. Func _Circle_FixCircle_GetCollisionPointRatio($nX_CirclePos, $nY_CirclePos, $nX_FixCirclePos, $nY_FixCirclePos, $nRadiusCircle, $nRadiusFixCircle, $nX_CircleVel, $nY_CircleVel)
  185.     $nVectorLength = Sqrt($nX_CircleVel ^ 2 + $nY_CircleVel ^ 2)
  186.     $nX_CircleDir = $nX_CircleVel / $nVectorLength
  187.     $nY_CircleDir = $nY_CircleVel / $nVectorLength
  188.  
  189.     $nD = Abs(($nX_FixCirclePos - $nX_CirclePos) * $nX_CircleDir + ($nY_FixCirclePos - $nY_CirclePos) * $nY_CircleDir)
  190.     $nDistance = $nD - Sqrt(($nRadiusCircle + $nRadiusFixCircle) ^ 2 - (($nX_FixCirclePos - $nX_CirclePos) ^ 2 + ($nY_FixCirclePos - $nY_CirclePos) ^ 2 - $nD ^ 2))
  191.  
  192.     Return $nDistance / $nVectorLength
  193. EndFunc
  194.  
  195. Func _DisplayInfo()
  196.     $nTmp = TimerDiff($nT_Sleep)
  197.     _ArrayDisplay($aCircles)
  198.     $nT_Sleep = TimerInit() - $nTmp
  199. EndFunc
  200.  
  201. Func _Close()
  202.     Exit
  203. EndFunc
  204.  
  205. Func _Shutdown()
  206.     _WinAPI_ReleaseDC($hMain, $hDC_Main)
  207.     _WinAPI_DeleteDC($hDC_Buffer)
  208.     _WinAPI_DeleteObject($hBitmap_Buffer)
  209.  
  210.     _GDIPlus_GraphicsDispose($hGraphics)
  211.     _GDIPlus_BrushDispose($hBrush_Black)
  212.     For $i = 1 To $aCircles[0][0]
  213.         _GDIPlus_BrushDispose($aCircles[$i][5])
  214.     Next
  215.     _GDIPlus_StringFormatDispose($hStringFormat)
  216.     _GDIPlus_FontFamilyDispose($hFamily_FPS)
  217.     _GDIPlus_FontDispose($hFont_FPS)
  218.     _GDIPlus_Shutdown()
  219.  
  220.     DllClose($vNTdll)
  221.     DllClose($vUser32Dll)
  222. EndFunc
  223.  
  224.  
  225. ; #FUNCTION#;===============================================================================
  226. ;
  227. ; Name...........: _HighPrecisionSleep()
  228. ; Description ...: Sleeps down to 0.1 microseconds
  229. ; Syntax.........: _HighPrecisionSleep( $iMicroSeconds, $hDll=False)
  230. ; Parameters ....:  $iMicroSeconds      - Amount of microseconds to sleep
  231. ;                  $hDll  - Can be supplied so the UDF doesn't have to re-open the dll all the time.
  232. ; Return values .: None
  233. ; Author ........: Andreas Karlsson (monoceres)
  234. ; Modified.......:
  235. ; Remarks .......: Even though this has high precision you need to take into consideration that it will take some time for autoit to call the function.
  236. ; Related .......:
  237. ; Link ..........;
  238. ; Example .......; No
  239. ;
  240. ;;==========================================================================================
  241. Func _HighPrecisionSleep($iMicroSeconds,$hDll=False)
  242.     Local $hStruct, $bLoaded
  243.     If Not $hDll Then
  244.         $hDll=DllOpen("ntdll.dll")
  245.         $bLoaded=True
  246.     EndIf
  247.     $hStruct=DllStructCreate("int64 time;")
  248.     DllStructSetData($hStruct,"time",-1*($iMicroSeconds*10))
  249.     DllCall($hDll,"dword","ZwDelayExecution","int",0,"ptr",DllStructGetPtr($hStruct))
  250.     If $bLoaded Then DllClose($hDll)
  251. EndFunc
RAW Paste Data