Moin,
Im Verdacht habe ich das schon lange. Ob es wirklich zu 100% daran liegt kann ich leider nicht sagen.
Deshalb gibts ein kleines Beispiel.
Spoiler anzeigen
#include <GDIPlus.au3>
Opt('GUIOnEventMode', 1)
Opt('MustDeclareVars', 1)
Opt('GUICloseOnESC', 0)
Global Const $iFPS = 60
Global Const $iW = 600, $iH = 480
Global Const $sTitel = 'Test', $iSpeed = 5
Global $hGUI, $hIMG, $hDC, $hGFX, $hBUF, $hBRU
[/autoit] [autoit][/autoit] [autoit]_GDIPlus_Startup()
[/autoit] [autoit][/autoit] [autoit]$hGUI = GUICreate($sTitel, $iW, $iH)
$hIMG = _Image_Create($iW, $iH)
$hBUF = DllStructGetData($hIMG, 1)
$hDC = _WinAPI_GetDC($hGUI)
$hGFX = _GDIPlus_GraphicsCreateFromHDC($hBUF)
$hBRU = _GDIPlus_BrushCreateSolid(0xFFFFFFFF)
GUISetState(@SW_SHOW, $hGUI)
GUISetOnEvent(-3, '_Exit', $hGUI)
GUIRegisterMsg(0xF, 'WM_PAINT')
OnAutoItExitRegister('_Freigeben')
While FPS($iFPS)
_GDIPlus_GraphicsClear($hGFX, 0xFF000000)
_Rect()
WM_PAINT()
WEnd
Func _Rect()
Local Static $x = 0, $y = 100
$x += $iSpeed * 60 / $iFPS
If $x > $iW Then
$x -= $iW + 64
$y = Random(0, $iH - 64, 1)
EndIf
_GDIPlus_GraphicsFillRect($hGFX, $x, $y, 64, 64, $hBRU)
EndFunc
Func FPS($W)
Local Static $1 = TimerInit(), $2, $3
Local $s = TimerDiff($1)
$2 += (1000 / $W - $s)
$3 = TimerInit()
If $2 > 0 Then Sleep($2)
$2 -= TimerDiff($3)
$1 = TimerInit()
Return True
EndFunc ;==>_Sleep
Func WM_PAINT()
Local Static $nFPS = 0, $iTimer = TimerInit()
$nFPS += 1
If TimerDiff($iTimer) > 1000 Then
WinSetTitle($hGUI, '', $sTitel & ' FPS: ' & $nFPS)
$iTimer = TimerInit()
$nFPS = 0
EndIf
;~ _WinAPI_RedrawWindow($hGUI)
_WinAPI_BitBlt($hDC, 0, 0, $iW, $iH, $hBUF, 0, 0, 0xCC0020)
EndFunc
[/autoit] [autoit][/autoit] [autoit]Func _Exit()
Exit
EndFunc
Func _Freigeben()
_GDIPlus_BrushDispose($hBRU)
_GDIPlus_GraphicsDispose($hGFX)
_Image_Delete($hIMG)
_GDIPlus_Shutdown()
EndFunc
Func _Image_Create($iW, $iH)
Local $Ptr, $hDC, $hBmp, $tBMI, $aDIB, $vStruct
$hDC = _WinAPI_CreateCompatibleDC(0)
$tBMI = DllStructCreate($tagBITMAPINFO)
DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4)
DllStructSetData($tBMI, "Width", $iW)
DllStructSetData($tBMI, "Height", -$iH)
DllStructSetData($tBMI, "Planes", 1)
DllStructSetData($tBMI, "BitCount", 32)
$aDIB = DllCall('GDI32.DLL', 'ptr', 'CreateDIBSection', 'hwnd', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', 0, 'ptr*', 0, 'ptr', 0, 'uint', 0)
$hBmp = $aDIB[0]
$Ptr = $aDIB[4]
_WinAPI_SelectObject($hDC, $hBmp)
$vStruct = DllStructCreate('int[5]')
DllStructSetData($vStruct, 1, $hDC, 1)
DllStructSetData($vStruct, 1, $iW, 2)
DllStructSetData($vStruct, 1, $iH, 3)
DllStructSetData($vStruct, 1, $Ptr, 4)
DllStructSetData($vStruct, 1, $hBmp, 5)
Return $vStruct
EndFunc ;==>_Image_Create
Func _Image_Delete(ByRef $vStruct)
_WinAPI_DeleteObject(DllStructGetData($vStruct, 1, 5))
_WinAPI_DeleteDC(DllStructGetData($vStruct, 1, 1))
$vStruct = 0
EndFunc ;==>_Image_Delete
Zu sehen ist (bei mir jedenfalls) folgendes:
Das Bild Ruckelt obwohl es mit 60 FPS läuft. (FPS einstellung auf euren Monitor anpassen in Zeile 8).
Daraus schließe ich: Der Bildschirm überspringt öfters mal Einzelbilder. Es ist also nicht immer wenn das Skript Zeichnen will grade an der Zeit zu zeichnen.
Stellt man die FPS auf exorbitante Werte (z.B. 2000 bei mir) läuft das Rechteck absolut flüssig. Das liegt daran, dass alle 60 Bilder in der Sekunde jeweils genau die Aktuelle Situation vorliegen haben.
Nun möchte ich aber nicht 1940 FPS vergeigen (die wird mein Endprogramm eh nicht erreichen).
Daher die Frage: Wie bekomme ich die ganze Sache Ruckelfrei (also mit dem Monitor synchronisiert).
Mein Ansatz ist:
Irgendwie muss ich jetzt eine Möglichkeit haben zu erfahren wann der Monitor fertig aktualisiert hat. (das müsste die Grafikkarte wissen)
Nach der Aktualisierung wartet die Graka ja 17ms (bei 60 FPS) bis sie das nächste mal etwas an den Schirm schickt.
In diesen 17ms (am besten unmittelbar) muss das neue Bild per BitBlt rübergeschaufelt werden. Dann müsste alles flüssig sein.
Wenn jemand eine Idee hat möge er sich Melden.
Ich bitte aber darum ein funktionierendes (oder nicht funktionierendes) Beispiel mitzubringen, sodass ich verstehe wie vorgegangen wurde.