#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <Misc.au3>
; - Author: name22 (www.autoit.de)
Opt("GUIOnEventMode", 1)
;###-v-SETTINGS-v-###
$iGUIWidth = 600
$iGUIHeight = 400
$iARGB_BG = 0xFFFFFFFF
$nFPS = 60
$nGravity = 0
$nAirFriction = 1
$nGroundFriction = 1
$nBounciness = 1
$iCircles = 10
$nSlowMotion = 10
;###-^-SETTINGS-^-###
$nSleepTime = 1000 / $nFPS
$nTimeMod = 1
$nFPS_Display = 0
$vNTdll = DllOpen("ntdll.dll")
$vUser32Dll = DllOpen("User32.dll")
$tPrecSleep = DllStructCreate("int64 time;")
$pPrecSleep = DllStructGetPtr($tPrecSleep)
$hMain = GUICreate("Physics Engine", $iGUIWidth, $iGUIHeight)
GUISetState()
$hDC_Main = _WinAPI_GetDC($hMain)
$hDC_Buffer = _WinAPI_CreateCompatibleDC($hDC_Main)
$hBitmap_Buffer = _WinAPI_CreateCompatibleBitmap($hDC_Main, $iGUIWidth, $iGUIHeight)
_WinAPI_SelectObject($hDC_Buffer, $hBitmap_Buffer)
_GDIPlus_Startup()
$hGraphics = _GDIPlus_GraphicsCreateFromHDC($hDC_Buffer)
_GDIPlus_GraphicsSetSmoothingMode($hGraphics, 2)
$hBrush_Black = _GDIPlus_BrushCreateSolid(0xFF000000)
$hStringFormat = _GDIPlus_StringFormatCreate()
$hFamily_FPS = _GDIPlus_FontFamilyCreate("Arial")
$hFont_FPS = _GDIPlus_FontCreate($hFamily_FPS, 6)
$hFont_Copyright = _GDIPlus_FontCreate($hFamily_FPS, 8)
$hFont_Number = _GDIPlus_FontCreate($hFamily_FPS, 10)
$aMeasure = _GDIPlus_GraphicsMeasureString($hGraphics, "FPS: 000", $hFont_FPS, _GDIPlus_RectFCreate(), $hStringFormat)
$tLayout_FPS = $aMeasure[0]
$aMeasure = ""
DllStructSetData($tLayout_FPS, "X", $iGUIWidth - DllStructGetData($tLayout_FPS, "Width") - 3)
DllStructSetData($tLayout_FPS, "Y", $iGUIHeight - DllStructGetData($tLayout_FPS, "Height"))
DllStructSetData($tLayout_FPS, "Width", 0)
$tLayout_Copyright = _GDIPlus_RectFCreate(0, $iGUIHeight - 15)
Global $aCircles[$iCircles + 1][6] = [[$iCircles]]
For $i = 1 To $aCircles[0][0]
$aCircles[$i][4] = Random(10, 20, 1) ;Circle Radius/Mass
$aCircles[$i][0] = Random($aCircles[$i][4], $iGUIWidth - $aCircles[$i][4], 1) ;X-Position of Circle Center
$aCircles[$i][1] = Random($aCircles[$i][4], $iGUIHeight - $aCircles[$i][4], 1) ;Y-Position of Circle Center
$aCircles[$i][2] = Random(-1, 1) ;X-Velocity
$aCircles[$i][3] = Random(-1, 1) ;Y-Velocity
$nRandomSpeed = Random(200, 400, 1) * - 1 ^ Random(1, 2, 1)
$aCircles[$i][2] = $aCircles[$i][2] * $nRandomSpeed
$aCircles[$i][3] = $aCircles[$i][3] * $nRandomSpeed
$aCircles[$i][5] = _GDIPlus_BrushCreateSolid("0xFF" & Hex(Random(0x000000, 0xFFFFFF, 1), 6)) ;Brush
Next
GUISetOnEvent($GUI_EVENT_CLOSE, "_Close", $hMain)
OnAutoItExitRegister("_Shutdown")
$nT_Sleep = TimerInit() + $nSleepTime
$nT_UpdateFPS = TimerInit()
While True
DllStructSetData($tPrecSleep, "time", -10000 * ($nSleepTime - TimerDiff($nT_Sleep)))
DllCall($vNTdll, "dword", "ZwDelayExecution", "int", 0, "ptr", $pPrecSleep)
$nFrameTime = TimerDiff($nT_Sleep)
$nT_Sleep = TimerInit()
$nFPS_Cur = 1000 / $nFrameTime
If TimerDiff($nT_UpdateFPS) >= 500 Then
$nFPS_Display = $nFPS_Cur
$nT_UpdateFPS = TimerInit()
EndIf
Switch _IsPressed("20", $vUser32Dll)
Case True
$nTimeMod = $nSlowMotion
Case False
If $nTimeMod <> 1 Then $nTimeMod = 1
EndSwitch
$nFPS_Cur *= $nTimeMod
_GDIPlus_GraphicsClear($hGraphics, $iARGB_BG)
For $i1 = 1 To $aCircles[0][0]
$aCircles[$i1][3] += $nGravity
$aCircles[$i1][2] *= $nAirFriction
$aCircles[$i1][3] *= $nAirFriction
Switch True
Case $aCircles[$i1][0] + $aCircles[$i1][2] / $nFPS_Cur <= $aCircles[$i1][4]
$aCircles[$i1][2] *= -$nBounciness
$aCircles[$i1][3] *= $nGroundFriction
$aCircles[$i1][0] = $aCircles[$i1][4]
Case $aCircles[$i1][0] + $aCircles[$i1][2] / $nFPS_Cur >= $iGUIWidth - $aCircles[$i1][4]
$aCircles[$i1][2] *= -$nBounciness
$aCircles[$i1][3] *= $nGroundFriction
$aCircles[$i1][0] = $iGUIWidth - $aCircles[$i1][4]
EndSwitch
Switch True
Case $aCircles[$i1][1] + $aCircles[$i1][3] / $nFPS_Cur <= $aCircles[$i1][4]
$aCircles[$i1][3] *= -$nBounciness
$aCircles[$i1][2] *= $nGroundFriction
$aCircles[$i1][1] = $aCircles[$i1][4]
Case $aCircles[$i1][1] + $aCircles[$i1][3] / $nFPS_Cur >= $iGUIHeight - $aCircles[$i1][4]
$aCircles[$i1][3] *= -$nBounciness
$aCircles[$i1][2] *= $nGroundFriction
$aCircles[$i1][1] = $iGUIHeight - $aCircles[$i1][4]
EndSwitch
For $i2 = $i1 + 1 To $aCircles[0][0]
$nX_V = ($aCircles[$i1][2] - $aCircles[$i2][2]) / $nFPS_Cur
$nY_V = ($aCircles[$i1][3] - $aCircles[$i2][3]) / $nFPS_Cur
$nL_V = Sqrt($nX_V ^ 2 + $nY_V ^ 2)
$nX_N = $nX_V / $nL_V
$nY_N = $nY_V / $nL_V
$nX_C = $aCircles[$i2][0] - $aCircles[$i1][0]
$nY_C = $aCircles[$i2][1] - $aCircles[$i1][1]
$nL_C = Sqrt($nX_C ^ 2 + $nY_C ^ 2)
Switch $nL_V > 0
Case True
Switch $nL_C - ($aCircles[$i1][4] + $aCircles[$i2][4]) <= $nL_V
Case True
$nD = $nX_N * $nX_C + $nY_N * $nY_C
Switch $nD >= 0
Case True
$nF = $nL_C ^ 2 - $nD ^ 2
Switch $nF <= ($aCircles[$i1][4] + $aCircles[$i2][4]) ^ 2
Case True
$nDistance = $nD - Sqrt(($aCircles[$i1][4] + $aCircles[$i2][4]) ^ 2 - $nF)
Switch $nDistance <= $nL_V
Case True
$nQ = $nDistance / $nL_V
$aCircles[$i1][0] += $aCircles[$i1][2] / $nFPS_Cur * $nQ
$aCircles[$i1][1] += $aCircles[$i1][3] / $nFPS_Cur * $nQ
$aCircles[$i2][0] += $aCircles[$i2][2] / $nFPS_Cur * $nQ
$aCircles[$i2][1] += $aCircles[$i2][3] / $nFPS_Cur * $nQ
$nX_C = $aCircles[$i2][0] - $aCircles[$i1][0]
$nY_C = $aCircles[$i2][1] - $aCircles[$i1][1]
$nL_C = Sqrt($nX_C ^ 2 + $nY_C ^ 2)
$nX_UN = $nX_C / $nL_C
$nY_UN = $nY_C / $nL_C
$nVel1_N = ($nX_UN * $aCircles[$i1][2] + $nY_UN * $aCircles[$i1][3]) * $nBounciness
$nVel2_N = ($nX_UN * $aCircles[$i2][2] + $nY_UN * $aCircles[$i2][3]) * $nBounciness
$nVel1_T = (-$nY_UN * $aCircles[$i1][2] + $nX_UN * $aCircles[$i1][3]) * $nGroundFriction
$nVel2_T = (-$nY_UN * $aCircles[$i2][2] + $nX_UN * $aCircles[$i2][3]) * $nGroundFriction
$nVel1_N_New = ($nVel1_N * ($aCircles[$i1][4] - $aCircles[$i2][4]) + 2 * $aCircles[$i2][4] * $nVel2_N) / ($aCircles[$i1][4] + $aCircles[$i2][4])
$nVel2_N_New = ($nVel2_N * ($aCircles[$i2][4] - $aCircles[$i1][4]) + 2 * $aCircles[$i1][4] * $nVel1_N) / ($aCircles[$i1][4] + $aCircles[$i2][4])
$aCircles[$i1][2] = $nVel1_N_New * $nX_UN + $nVel1_T * - $nY_UN
$aCircles[$i1][3] = $nVel1_N_New * $nY_UN + $nVel1_T * $nX_UN
$aCircles[$i2][2] = $nVel2_N_New * $nX_UN + $nVel2_T * - $nY_UN
$aCircles[$i2][3] = $nVel2_N_New * $nY_UN + $nVel2_T * $nX_UN
EndSwitch
EndSwitch
EndSwitch
EndSwitch
EndSwitch
Next
$aCircles[$i1][0] += $aCircles[$i1][2] / $nFPS_Cur
$aCircles[$i1][1] += $aCircles[$i1][3] / $nFPS_Cur
_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])
Next
_GDIPlus_GraphicsDrawStringEx($hGraphics, "FPS: " & Round($nFPS_Display, 1), $hFont_FPS, $tLayout_FPS, $hStringFormat, $hBrush_Black)
_GDIPlus_GraphicsDrawStringEx($hGraphics, "© name22", $hFont_Copyright, $tLayout_Copyright, $hStringFormat, $hBrush_Black)
_WinAPI_BitBlt($hDC_Main, 0, 0, $iGUIWidth, $iGUIHeight, $hDC_Buffer, 0, 0, $SRCCOPY)
WEnd
Func _Close()
Exit
EndFunc ;==>_Close
Func _Shutdown()
_WinAPI_ReleaseDC($hMain, $hDC_Main)
_WinAPI_DeleteDC($hDC_Buffer)
_WinAPI_DeleteObject($hBitmap_Buffer)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_BrushDispose($hBrush_Black)
For $i = 1 To $aCircles[0][0]
_GDIPlus_BrushDispose($aCircles[$i][5])
Next
_GDIPlus_StringFormatDispose($hStringFormat)
_GDIPlus_FontFamilyDispose($hFamily_FPS)
_GDIPlus_FontDispose($hFont_FPS)
_GDIPlus_Shutdown()
DllClose($vNTdll)
DllClose($vUser32Dll)
EndFunc ;==>_Shutdown
;- Copyright: name22, Donnerstag 12. Mai 2011
; #FUNCTION#;===============================================================================
;
; Name...........: _HighPrecisionSleep()
; Description ...: Sleeps down to 0.1 microseconds
; Syntax.........: _HighPrecisionSleep( $iMicroSeconds, $hDll=False)
; Parameters ....: $iMicroSeconds - Amount of microseconds to sleep
; $hDll - Can be supplied so the UDF doesn't have to re-open the dll all the time.
; Return values .: None
; Author ........: Andreas Karlsson (monoceres)
; Modified.......:
; 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.
; Related .......:
; Link ..........;
; Example .......; No
;
;;==========================================================================================
Func _HighPrecisionSleep($iMicroSeconds, $hDll = False)
Local $hStruct, $bLoaded
If Not $hDll Then
$hDll = DllOpen("ntdll.dll")
$bLoaded = True
EndIf
$hStruct = DllStructCreate("int64 time;")
DllStructSetData($hStruct, "time", -1 * ($iMicroSeconds * 10))
DllCall($hDll, "dword", "ZwDelayExecution", "int", 0, "ptr", DllStructGetPtr($hStruct))
If $bLoaded Then DllClose($hDll)
EndFunc ;==>_HighPrecisionSleep