Verschiedene GDI+ Grafiken zeichnen und verschieben

  • Hi Community,

    ich stehe wieder vor einem Problem mit GDI+. Vorerst möchte ich 4 Grafiken zeichnen lassen und diese in einem Array abspeichern ($aGrafiken[4] = [ <Grafik1>, <Grafik2>, <Grafik3>, <Grafik4>]).

    Spoiler anzeigen

    Später möchte ich dann über eine Funktion die einzelnen Grafiken verschieben können. Pseudo: MoveGraphic($Grafik,$x,$y): (Die Grafik soll an das Pfeilende "rutschen")

    Spoiler anzeigen

    Ich habe versucht durch das Script von UEZ - Hier - ein Script zu machen, welche mehrere Grafiken zeichnet. Doch bereits da scheitere ich, da die Grafiken entweder immer verschwinden oder die Gezeichnete bleibt.

  • Was auf die Schnelle um die Uhrzeit!

    Spoiler anzeigen
    [autoit]


    ;Coded by UEZ 2009.12.11
    #include <GDIplus.au3>
    Opt("GUIOnEventMode", 1)

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_Startup()
    Global $load_background = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\Background.png")
    Global $load_foreground = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\Smiley.png")
    Global $width = _GDIPlus_ImageGetWidth($load_background)
    Global $height = _GDIPlus_ImageGetHeight($load_background)
    Global $dx = _GDIPlus_ImageGetWidth($load_foreground)
    Global $dy = _GDIPlus_ImageGetHeight($load_foreground)
    Global Const $pi_div_180 = 4 * ATan(1) / 180
    Global $radius = 60
    Global $i

    [/autoit] [autoit][/autoit] [autoit]

    Global $hwnd = GUICreate("GDI+: Example by UEZ", $width, $height, -1, -1, Default)
    GUISetOnEvent(-3, "_Exit")
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    Global $graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)
    Global $bitmap = _GDIPlus_BitmapCreateFromGraphics($width, $height, $graphics)
    Global $backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap)

    [/autoit] [autoit][/autoit] [autoit]

    ;~ _GDIPlus_GraphicsSetSmoothingMode($backbuffer, 4)

    [/autoit] [autoit][/autoit] [autoit]

    Global $size_x = $dx / 4, $size_y = $dy / 4
    Global $coordinate[4][2]
    $coordinate[0][0] = $size_x
    $coordinate[0][1] = 0
    $coordinate[1][0] = 3 * $size_x
    $coordinate[1][1] = 0
    $coordinate[2][0] = 5 * $size_x
    $coordinate[2][1] = 0
    $coordinate[3][0] = 7 * $size_x
    $coordinate[3][1] = 0
    $i = 0
    While Sleep(30)
    _GDIPlus_GraphicsDrawImage($backbuffer, $load_background, 0, 0) ;draw background
    _GDIPlus_GraphicsDrawImageRect($backbuffer, $load_foreground, $coordinate[0][0], $coordinate[0][1] + $i, $size_x, $size_y)
    _GDIPlus_GraphicsDrawImageRect($backbuffer, $load_foreground, $coordinate[1][0], $coordinate[1][1], $size_x, $size_y)
    _GDIPlus_GraphicsDrawImageRect($backbuffer, $load_foreground, $coordinate[2][0], $coordinate[2][1], $size_x, $size_y)
    _GDIPlus_GraphicsDrawImageRect($backbuffer, $load_foreground, $coordinate[3][0], $coordinate[3][1] + $i, $size_x, $size_y)
    $i += 2
    If $coordinate[0][1] + $i >= $height Then $i = -$size_y
    _GDIPlus_GraphicsDrawImageRect($graphics, $bitmap, 0, 0, $width, $height)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _Exit()
    _GDIPlus_BitmapDispose($bitmap)
    _GDIPlus_GraphicsDispose($backbuffer)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_Shutdown()
    Exit
    EndFunc

    [/autoit]

    Gruß,
    UEZ

  • Wie immer ein geniales Script UEZ! Danke dir! :thumbup:

    Also dem Code kann ich entnehmen, dass immer erst alle Grafiken gezeichnet werden müssen und diese werden dann als Bild angezeigt. Es gibt also keine Möglichkeit nur eine einzelne Grafik über eine Funktion "anzusprechen" und diese dann an anderer Stelle zu zeichnen. Das sehe ich doch richtig so oder?

  • Es gibt also keine Möglichkeit nur eine einzelne Grafik über eine Funktion "anzusprechen" und diese dann an anderer Stelle zu zeichnen. Das sehe ich doch richtig so oder?

    Verstehe dich nicht - wie meinst du das?

    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Ich meinte es so: (Pseudo) _GDIPlus_MoveImage($Graphic[1],$xCoor,$yCoor)

    Also nur eine einzelne Grafik per Funktion verschieben. Die Grafik ($Graphic[1]) ist zum Beispiel das zweite Smilie und nur das wird dann zu Punkt($xCoor/$yCoor) verschoben. Aber es scheint so als müsste immer alle Grafiken neu gezeichnet werden. Ein "ansprechen" einer einzelnen Grafik ist wohl nicht möglich.

    Ich hatte nämlich an sowas gedacht: (Beispiel mit GuiCtrlCreateGraphic)

    [autoit]


    For $i = 0 to 3
    $Graphic[$i] = GUICtrlCreateGraphic($x,$y,10,10)
    Next

    [/autoit][autoit][/autoit][autoit]

    GUICtrlSetPos($Graphic[1],$x,$y)

    [/autoit]


    -> Jede Grafik kann einzeln verschoben werden, ohne dass die anderen auch noch gezeichnet werden müssen.

    So ich hoffe mal ich war diesmal etwas verständlicher ;)

  • Genau, denn du erstellst ja das Gesamtbild, indem du einzelne Objekte in den Buffer schreibst und anschließend das komplette Bild in den sichtbaren Bereich kopierst.

    Es sei denn, du hast n Layer die du übereinander legen würdest (pro Objekt), dann könntest du jedes Objekt einzeln ansprechen.

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • so wie ich das verstehe meint er eine Funktion analog zu

    [autoit]

    controlmove()

    [/autoit]

    @Jautois
    Der große Vorteil von GDI+ ist die einfache Darstellung von Bildern, Pixeln, Zeichnungen über fertige Funktionen.
    Für Vorhaben, für die es keine fertige Funktion gibt, wie z.B. dein "Spritemove", musst du das bei GDI+ selbst in die Hand nehmen.
    Das Problem für die meisten ist, daß es nur eine einzige "Leinwand" gibt, auf der alle Operationen stattfinden.
    Für Deinen "Spritemove" nun die Vorgehensweise in Pseudocode:
    1. Hintergrund zeichnen
    Für eine "Bewegung" des Sprites ist es wichtig, den Hintergrund an der Spriteposition zu sichern! Denn der wird überschrieben, sobald du an dieser Position das Sprite zeichnest. Wenn dein Sprite sich "über" den Hintergrung bewegen soll, dann ist das eine Folge von Hintergrund zeichnen, Sprite an neuer Position zeichnen, Hintergrund zeichnen, Sprite an neuer Position zeichnen, uswusf
    Das schnelle "Zeichnen" auf den Hintergrund geht wunderbar mittels BitBlt (blitten), dabei wird ein Speicherbereich (dein Sprite) an eine andere Position im Speicher (den Hintergrund) verschoben. vgl (

    [autoit]

    _WinAPI_BitBlt()
    _GDIPlus_GraphicsDrawImageRectRect () ;der gdi+ "wrapper" zu bitblt

    [/autoit]

    )

    Beispiel aus der Hilfe ein bissl aufgepeppt und verschiedene Techniken gezeigt: Bitte mit Scite im Fullscreen ausführen (wg des AutoItlogos^^)

    Spoiler anzeigen
    [autoit]

    #include <GuiConstantsEx.au3>
    #include <GDIPlus.au3>
    #include <ScreenCapture.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Opt('MustDeclareVars', 1)

    [/autoit] [autoit][/autoit] [autoit]

    _Main()

    [/autoit] [autoit][/autoit] [autoit]

    Func _Main()
    Local $hGUI1, $hGUI2, $hHintergrund, $hGraphic1, $hGraphic2, $hSprite, $backbuffer, $bitmap

    [/autoit] [autoit][/autoit] [autoit]

    ; Capture top left corner of the screen
    _ScreenCapture_Capture(@MyDocumentsDir & "\Hintergrund.jpg", 0, 0, 800, 600) ;hintergrund erstellen
    _ScreenCapture_Capture(@MyDocumentsDir & "\Sprite.jpg", 0, 0, 20, 20) ;Sprite erstellen
    ; Create a GUI for the original image
    $hGUI1 = GUICreate("Original", 800, 600, 0, 0)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    ; Initialize GDI+ library and load image
    _GDIPlus_Startup()
    $hHintergrund = _GDIPlus_ImageLoadFromFile(@MyDocumentsDir & "\Hintergrund.jpg") ;das ist der Hintergrund
    $hSprite = _GDIPlus_BitmapCreateFromFile(@MyDocumentsDir & "\Sprite.jpg") ;das ist das Sprite
    ; Draw original image
    $hGraphic1 = _GDIPlus_GraphicsCreateFromHWND($hGUI1) ;"Leinwand" erstellen auf der gemalt werden kann
    _GDIPlus_GraphicsDrawImage($hGraphic1, $hHintergrund, 0, 0) ;hintergrund auf diese Leinwand malen
    MsgBox(0, 0, "Hintergrund gezeichnet")

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_GraphicsDrawImageRectRect($hGraphic1, $hSprite, 0, 0, 20, 20, 0, 0, 40, 40) ;das sprite wird doppelt so groß

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox(0, 0, "sprite gezeichnet, es folgt die Bewegung")

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To 300 Step 2
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic1, $hSprite, 0, 0, 20, 20, $i, $i, 40, 40)
    Next
    MsgBox(0, 0, "Das war gut, aber der Hintergrund wurde nicht aktualisiert, also nochmal....")

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To 300 Step 2
    _GDIPlus_GraphicsDrawImage($hGraphic1, $hHintergrund, 0, 0) ;hintergrund auf diese Leinwand malen
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic1, $hSprite, 0, 0, 20, 20, $i, $i, 40, 40)
    Next
    MsgBox(0, 0, "wars so gut? Nein, es flackert...wir benutzen einen sog. backbuffer, dabei wird das gesamte Bild im backbuffer erstellt und dieser danach erst komplett dargestellt")

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $bitmap = _GDIPlus_BitmapCreateFromGraphics(800, 600, $hGraphic1) ;Objekt erstellen
    $backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap) ;backbuffer erstellen, eine 2. Leinwand im Hintergrund sozusagen
    For $i = 0 To 300 Step 2
    _GDIPlus_GraphicsDrawImage($backbuffer, $hHintergrund, 0, 0) ;hintergrund in den backbuffer malen
    ; _GDIPlus_GraphicsDrawImage($backbuffer, $hsprite, $i, $i) ;Sprite in den backbuffer malen
    _GDIPlus_GraphicsDrawImageRectRect($backbuffer, $hSprite, 0, 0, 20, 20, $i, $i, 40, 40)
    _GDIPlus_GraphicsDrawImageRect($hGraphic1, $bitmap, 0, 0, 800, 600);gesamten backbuffer darstellen
    Next
    MsgBox(0, 0, "wars so gut? ja, so soll es sein ;-)")

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; Release resources
    _GDIPlus_GraphicsDispose($hGraphic1)
    _GDIPlus_GraphicsDispose($backbuffer)
    _GDIPlus_ImageDispose($hHintergrund)
    _GDIPlus_Shutdown()

    [/autoit] [autoit][/autoit] [autoit]

    ; Clean up screen shot file
    FileDelete(@MyDocumentsDir & "\Hintergrund.jpg")
    FileDelete(@MyDocumentsDir & "\sprite.jpg")
    ; Loop until user exits
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    EndFunc ;==>_Main

    [/autoit]

    /edit/ richtig schnell wird es, wenn so wenig Daten wie möglich bewegt werden müssen. Dazu wäre es sinnvoll, nicht den gesamten Hintergrund neu zu zeichnen, sondern nur das kleine Stück, welches vom "aktuellen" Sprite verdeckt wird

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (18. Dezember 2009 um 15:38)

  • Hej Andy. Denau das hatte ich gemeint. Dein Beispiel ist echt spitze! Danke :thumbup:

    Ich probiere nun selbst mal mit den Funktionen herum. Mal schaun ob das was wird :D

  • Spoiler anzeigen
    [autoit]

    #include <GuiConstantsEx.au3>
    #include <GDIPlus.au3>
    #include <ScreenCapture.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Opt('MustDeclareVars', 1)

    [/autoit] [autoit][/autoit] [autoit]

    _Main()

    [/autoit] [autoit][/autoit] [autoit]

    Func _Main()
    Local $hGUI1, $hGUI2, $hHintergrund, $hGraphic1, $hGraphic2, $hSprite, $backbuffer, $bitmap

    [/autoit] [autoit][/autoit] [autoit]

    ; Capture top left corner of the screen
    _ScreenCapture_Capture(@MyDocumentsDir & "\Hintergrund.jpg", 0, 0, 800, 600) ;hintergrund erstellen
    _ScreenCapture_Capture(@MyDocumentsDir & "\Sprite.jpg", 0, 0, 20, 20) ;Sprite erstellen
    ; Create a GUI for the original image
    $hGUI1 = GUICreate("Original", 800, 600, 0, 0)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    ; Initialize GDI+ library and load image
    _GDIPlus_Startup()
    $hHintergrund = _GDIPlus_ImageLoadFromFile(@MyDocumentsDir & "\Hintergrund.jpg") ;das ist der Hintergrund
    $hSprite = _GDIPlus_BitmapCreateFromFile(@MyDocumentsDir & "\Sprite.jpg") ;das ist das Sprite
    ; Draw original image
    $hGraphic1 = _GDIPlus_GraphicsCreateFromHWND($hGUI1) ;"Leinwand" erstellen auf der gemalt werden kann
    _GDIPlus_GraphicsDrawImage($hGraphic1, $hHintergrund, 0, 0) ;hintergrund auf diese Leinwand malen
    MsgBox(0, 0, "Hintergrund gezeichnet")

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_GraphicsDrawImageRectRect($hGraphic1, $hSprite, 0, 0, 20, 20, 0, 0, 40, 40) ;das sprite wird doppelt so groß

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox(0, 0, "sprite gezeichnet, es folgt die Bewegung")

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To 300
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic1, $hSprite, 0, 0, 20, 20, $i, $i, 40, 40)
    Next
    MsgBox(0, 0, "Das war gut, aber der Hintergrund wurde nicht aktualisiert, also nochmal....")

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To 300
    _GDIPlus_GraphicsDrawImage($hGraphic1, $hHintergrund, 0, 0) ;hintergrund auf diese Leinwand malen
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic1, $hSprite, 0, 0, 20, 20, $i, $i, 40, 40)
    Next
    MsgBox(0, 0, "wars so gut? Nein, es flackert...wir benutzen einen sog. backbuffer, dabei wird das gesamte Bild im backbuffer erstellt und dieser danach erst komplett dargestellt")

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $bitmap = _GDIPlus_BitmapCreateFromGraphics(800, 600, $hGraphic1) ;Objekt erstellen
    $backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap) ;backbuffer erstellen, eine 2. Leinwand im Hintergrund sozusagen

    [/autoit] [autoit][/autoit] [autoit]

    local $t=timerinit()
    For $i = 10 To 300
    ;_GDIPlus_GraphicsDrawImage($backbuffer, $hHintergrund, 0, 0) ;hintergrund in den backbuffer malen
    ; _GDIPlus_GraphicsDrawImage($backbuffer, $hsprite, $i, $i) ;Sprite in den backbuffer malen
    _GDIPlus_GraphicsDrawImageRectRect($backbuffer, $hhintergrund, $i-1,$i-1, 40, 40, $i-1, $i-1, 40, 40)
    _GDIPlus_GraphicsDrawImageRectRect($backbuffer, $hSprite, 0, 0, 20, 20, $i, $i, 40, 40)
    _GDIPlus_GraphicsDrawImageRect($hGraphic1, $bitmap, 0, 0, 800, 600);gesamten backbuffer darstellen
    Next
    local $m=int (timerdiff($t))
    MsgBox(0, 0, "wars so gut? ja, so soll es sein ;) aber immer noch langsam^^ "&$m&" Millisekunden")

    [/autoit] [autoit][/autoit] [autoit]

    $t=timerinit()
    For $i = 10 To 300
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic1, $hhintergrund, $i-1,$i-1, 40, 40, $i-1, $i-1, 40, 40)
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic1, $hSprite, 0, 0, 20, 20, $i, $i, 40, 40)
    ; _GDIPlus_GraphicsDrawImageRect($hGraphic1, $bitmap, 0, 0, 800, 600);gesamten backbuffer darstellen
    Next
    $m=int (timerdiff($t))
    MsgBox(0, 0, "wars so gut? ja, so soll es sein ;) "&$m&" Millisekunden")

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; Release resources
    _GDIPlus_GraphicsDispose($hGraphic1)
    _GDIPlus_GraphicsDispose($backbuffer)
    _GDIPlus_ImageDispose($hHintergrund)
    _GDIPlus_Shutdown()

    [/autoit] [autoit][/autoit] [autoit]

    ; Clean up screen shot file
    FileDelete(@MyDocumentsDir & "\Hintergrund.jpg")
    FileDelete(@MyDocumentsDir & "\sprite.jpg")
    ; Loop until user exits
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    EndFunc ;==>_Main

    [/autoit]

    10x schneller^^ ohne backbuffer, aber bei vielen "sprites" wird der Verwaltungsaufwand ziemlich groß...
    Aber der "eigentliche" Sinn des Backbuffers ist ja, das 2. Bild schon zu zeichnen während das erste mit dem Kathodenstrahl auf den Bildschirm gemalt wird! Dann muß man nur noch zum richtigen Zeitpunkt den Backbuffer in den speicher der Grafikkarte blitten und ZAAAAPPPP....

  • Zitat

    Und ohne Backbuffer flackern die Objekte!

    das lag an meinem "refresh", bei dem Objekte übereinander gemalt werden, richtigerweise geht das so:

    Spoiler anzeigen
    [autoit]

    #include <Misc.au3>
    #include <GDIPlus.au3>
    #include <ScreenCapture.au3>
    Local $hGUI1, $hGUI2, $hHintergrund, $hGraphic1, $hGraphic2, $hSprite, $backbuffer, $bitmap
    Local $dll = DllOpen("user32.dll")
    Global $milliseconds = 10
    ; Capture top left corner of the screen
    _ScreenCapture_Capture(@MyDocumentsDir & "\Hintergrund.jpg", 0, 0, 800, 600) ;hintergrund erstellen
    _ScreenCapture_Capture(@MyDocumentsDir & "\Sprite.jpg", 0, 0, 20, 20) ;Sprite erstellen
    ; Create a GUI for the original image
    $hGUI1 = GUICreate("", 800, 600, 0, 0)
    WinSetTitle($hGUI1, "", "mit + und - die Geschwindigkeit ändern, Delay = " & $milliseconds & " Millisekunden")
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    ; Initialize GDI+ library and load image
    _GDIPlus_Startup()
    $hHintergrund = _GDIPlus_ImageLoadFromFile(@MyDocumentsDir & "\Hintergrund.jpg") ;das ist der Hintergrund
    $hSprite = _GDIPlus_BitmapCreateFromFile(@MyDocumentsDir & "\Sprite.jpg") ;das ist das Sprite
    ; Draw original image
    $hGraphic1 = _GDIPlus_GraphicsCreateFromHWND($hGUI1) ;"Leinwand" erstellen auf der gemalt werden kann
    _GDIPlus_GraphicsDrawImage($hGraphic1, $hHintergrund, 0, 0) ;hintergrund auf diese Leinwand malen

    [/autoit] [autoit][/autoit] [autoit]

    $x = 754 ;startposition
    $y = 220
    $sx = 1 ;richtung
    $sy = -1
    While 1
    If $y > 555 Then $sy = -1
    If $y < 2 Then $sy = 1
    If $x > 755 Then $sx = -1
    If $x < 2 Then $sx = 1
    $x += $sx
    $y += $sy
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic1, $hHintergrund, $x - 1, $y - 1, 1, 42, $x - 1, $y - 1, 1, 42) ;obere seite des sprites wiederherstellen (1 Pixel breit)
    ;sleep(1000) ;sleeps einschalten um das löschen der zeile/spalte zu sehen
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic1, $hHintergrund, $x - 1, $y - 1, 42, 1, $x - 1, $y - 1, 42, 1) ;linke seite des sprites wiederherstellen (1 Pixel breit)
    ;sleep(1000) ;sleeps einschalten um das löschen der zeile/spalte zu sehen
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic1, $hHintergrund, $x + 41, $y - 1, 1, 43, $x + 41, $y - 1, 1, 43) ;untere seite des sprites wiederherstellen (1 Pixel breit)
    ;sleep(1000) ;sleeps einschalten um das löschen der zeile/spalte zu sehen
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic1, $hHintergrund, $x - 1, $y + 41, 43, 1, $x - 1, $y + 41, 43, 1) ;rechte seite des sprites wiederherstellen (1 Pixel breit)
    ;sleep(1000) ;sleeps einschalten um das löschen der zeile/spalte zu sehen
    ;sleep(1000)
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic1, $hSprite, 0, 0, 20, 20, $x, $y, 40, 40)
    ;sleep(1000)
    delay($milliseconds) ;wartezeit
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    ; Release resources
    _GDIPlus_GraphicsDispose($hGraphic1)
    _GDIPlus_GraphicsDispose($backbuffer)
    _GDIPlus_ImageDispose($hHintergrund)
    _GDIPlus_Shutdown()

    [/autoit] [autoit][/autoit] [autoit]

    ; Clean up screen shot file
    FileDelete(@MyDocumentsDir & "\Hintergrund.jpg")
    FileDelete(@MyDocumentsDir & "\sprite.jpg")
    ; Loop until user exits

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func delay(ByRef $milliseconds)
    If _IsPressed("1B", $dll) Then Exit ;ESC
    If _IsPressed("6B", $dll) Then ;numpad +
    $milliseconds += 1
    Sleep(50)
    WinSetTitle($hGUI1, "", "mit + und - die Geschwindigkeit ändern, Delay = " & $milliseconds & " Millisekunden")
    EndIf
    If _IsPressed("6D", $dll) Then ;numpad -
    $milliseconds -= 1
    Sleep(50)
    WinSetTitle($hGUI1, "", "mit + und - die Geschwindigkeit ändern, Delay = " & $milliseconds & " Millisekunden")
    EndIf
    $t = TimerInit()
    Do
    Until TimerDiff($t) > $milliseconds
    EndFunc ;==>delay

    [/autoit]

    mit Numpad + und - kann man die Wartezeit zwischen der Darstellung der Sprites einstellen. Kein Flimmern.
    "Früher" wurde überhaupt kein delay in Millisekunden eingesetzt, da waren Prozessoren und Grafikkarten so langsam, da richtete man sich nach dem Prozessortakt^^. Das heisst, es wurden einfach "Warteschleifen" eingesetzt.
    Das führte dann dazu, daß Spiele auf der nächstschnelleren Prozessorgeneration völlig unspielbar, weil viel zu schnell, wurden

    /EDIT/ habe mal eine "schönere" Animation eingebaut, mit den numpad + und - Tasten kann man das Delay einstellen. Richtig optimal wird es, wenn je nach Richtung des Sprites nur die Stellen auf dem Hintergrund restauriert werden, die "hinter" dem sprite liegen, aber sollen die anderen doch auch was machen^^

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (18. Dezember 2009 um 20:44)

  • Update des Scripts im vorherigen Post, ohne backbuffer und ohne Flimmern extrem schnell....

    UEZ, ist das noch zu toppen? (Das ist weder überheblich noch rethorisch gemeint, mich interessiert einfach, was "noch geht" und da bin ich bei dir an der richtigen Adresse :thumbup: )

  • Ich glaube für ein Objekt gibt es nichts wirklich schnelleres, außer ASM Code, aber wie würde das Ganze aussehen, wenn nicht 1 Objekt, sondern 100 Objekte so bewegt werden würden?
    Und was ist mit der Größe der "Sprites"?

    Ich habe es nicht getestet, aber ich glaube, dass ab einer Anzahl von n Objekte, in Abhängigkeit der Größe der Sprites, der Zeitgewinn sich gegenüber der Buffer Methode ammortisiert.

    Anyway, da ich durch ein paar simple GDI+ Beispiele hier einen zu guten Ruf bekommen habe, werde ich mal überlegen, ob was noch geht!

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Zitat

    in Abhängigkeit der Größe der Sprites, der Zeitgewinn sich gegenüber der Buffer Methode ammortisiert.

    ja, das vermute ich auch. Wenn man mal sieht, wie ein einzelnes IF in so einer Schleife zeitmäßig reinhaut, wird es einem anders. Hehe, wie in alten Turbo-Basic-Tagen....die "Gui" in Basic und den Rest in Assembler...bin eh die nächsten Monate ausser Gefecht gesetzt, wg einer oder mehrerer heftiger Hand-OP´s, da hab ich Zeit mir mal was zurechtzulegen. Das eigentlich aufwendige ist ja nur die Berechnung der Positionen der Sprites und das Schreiben in den Buffer, blitten geht ja relativ fix. Aber da Rad jedesmal neu erfinden bringt ja auch nix, die prospeed.dll hat ja eigentlich so gut wie alles erforderliche an Bord.