Flackern beim Redraw (GDI+)

  • Wahrscheinlich wurde das bereits Tausende Male gefragt, aber die bisherigen Tips die ich so gefunden habe haben nicht wirklich weiter geholfen.

    Es geht darum, dass ein Bild als Hintergrundbild benutzt wird und eins als Vordergrund.

    Wenn ich das vordere bild etwas verschieben möchte muss ich zwangsläufig das hintere auch wieder neu zeichnen.
    Dadurch ist das vordere Bild aber kurzfristig von der Bildfläche verschwunden.

    Ein Lösungsansatz von mir währe, beide bilder VOR dem Zeichnen zu verbinden, und das Vordere Bild schon direkt an der richtigen Position hinbasteln.
    Das würde ein flackern unterbinden...


    Bei meinem Beispiel handelt es sich um ein noch in der Entwicklung befundliches Game: Miner VGA - Reloaded (was sich Freunde und ich zusammen ausgedacht haben)
    Davon gibt es das berühnte DOS-Spiel. (Liegt auch in der .rar bei für alle Zocker von früher ;) )
    (Das von mir geschriebene Game ist wahrscheinlich vom Code noch nicht optimal. es ist aber auch noch nicht fertig ;) )

    Die lebensanzeige ist an die Pfeil Hoch bzw Runter Taste gebunden. Das ist natürlich nur zum Testen und soll garantiert nicht so bleiben.

    Aber dadurch kann man schon sehen wie das Fenster andauernd neu gezeichnet wird und das Bild so schön Flackert.
    Im Originalspiel wird man erkennen, dass der Programmierer anscheinend ein ähnliches Problem hatte, denn dort flackert es genau so. Aber ich will es ja besser machen^^

    Deshalb meine Frage:

    Entweder:
    Wie bekomme ich die beiden Bilder übereinandergelegt, OHNE dass es Flackert

    Oder:
    Kann man nur das Vordere Bild verschieben und das hintere iwie Gepuffert lassen (bzw nur Teile des hintergrunds nachzeichnen und nicht das ganze Bild)

    Oder:
    Kann man beide Bilder Kombinieren und direkt zusammen Zeichnen. (Mein Favorit falls es klappen sollte!)

    Ich bin weder Anfänger noch Profi. Das bitte bei der erklärung beachten.

    Danke schonmal im vorraus.

  • Zitat

    aber die bisherigen Tips die ich so gefunden habe haben nicht wirklich weiter geholfen.

    ...und in all diesen Tips ist niemals von einem "Backbuffer" die Rede gewesen?

  • Wenn ich das jetzt richtig verstehe soll das Bild, das angezeigt werden soll im Hintergrund (Backbuffer) schonmal fertig gezeichnet werden und dann nur in den Vordergrund gerückt werden.

    Edit: Dooch der ist natürlich erwähnt. (und ich kannte ihn auch schon). Aber die Funktionsweise war mir nicht so ganz klar. Hab jetzt aber mal geschaut wies klappen könnte.

    Lol EliteMatttihas als Member xD.
    Biste denn hier anerkannt oder auch schon verflucht ? (wenn ich mich so ans Andere Forum erinnere^^)

    --> Wird gleich versucht !

  • Zu der Funktionsweise hab ich dir mal nen Beispiel geschireben

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    _GDIPlus_Startup()
    $Hoehe = 150
    $Breite = 150

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

    $hGui = GUICreate("Test", $Breite, $Breite)
    GUISetState()

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

    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGui)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics($Breite, $Hoehe, $hGraphic);Ein Bitmap von den Frontpuffer Erstellen
    $hBackpuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap); Backpuffer Erzeugen

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

    $hPen = _GDIPlus_PenCreate(0xFF000000, 5) ;Musste sich von selbst erklären
    _GDIPlus_GraphicsDrawEllipse($hBackpuffer, 10, 10, 50, 100, $hPen);Eine Ellipse zeichnen <--- Auf $hBackpuffer Achten

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

    _GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap, 0, 0);Von dem Backpuffer in den Frontpuffer zeichnen

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

    While GUIGetMsg() <> -3
    WEnd
    ;Resourcen entladen
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_GraphicsDispose($hBackpuffer)
    _GDIPlus_Shutdown()

    [/autoit]
  • Also noch mal zur Funktionsweise des Backbuffers:
    Wie du schon gemerkt hast, kommt das "flackern" daher, daß deine Grafikobjekte nacheinander angezeigt werden. Da der Hintergrund auch eines dieser Objekte ist, werden alle anderen Objekte "übermalt".
    Um das zu vermeiden, werden (nicht sichtbar) der Hintergrund und alle anderen Objekte nacheinander auf eine einzige "Leinwand" gemalt, und diese dann komplett angezeigt.
    Der eigentliche Vorteil daran ist, daß man z.B. bei bewegten Objekten nicht jedes mal den kompletten Hintergrund neu in den Backbuffer zeichnen muß, sondern nur den Teil, welchen das bewegte Objektgerade verdeckt hat (damit der Hintergrund an dieser Stelle wieder hergestellt wird). Das Geschwindigkeitsproblem tritt nämlich dann auf, wenn die übertragenen Daten "zu viel" werden. Wieso jedes Mal 1900x1200 Pixel des Hintergrundes in den Backbuffer schreiben, wenn doch von dem bewegten Objekt nur 60x80 Pixel überdeckt werden?
    Auch mehrere Backbuffer sind keine Seltenheit.
    Wer weiß, wie "früher" z.B. Zeichentrickfilme hergestellt wurden (Folientechnik) der kann dieses Prinzip 1:1 für seine Grafiken übernehmen...

  • Danke Andy, Danke Sprenger

    Ich habs schonmal hinbekommen, dass das Flackern so ziemlich erloschen ist.
    Das Problem was ich hatte war immer, dass man in den Backbuffer schreiben muss, aber dann das Bitmap zeichnet. (das ist mir immernoch etwas unverständlich^^)
    Dazu musste ich ja nur meine bisherige Redraw Funktion etwas umbauen und Kleinigkeiten abändern.

    Das nur teile des Backbuffers neu bemalt werden müssen bekomm ich wahrscheinlich auch noch hin.

    Das Glück ist natürlich, dass dieses Spiel nur seehr wenig Grafische Ansprüche an Bewegungen stellt.
    Es wird ja eigentlich nichts wirklich Bewegt. (es läuft ja alles in Großen Sprüngen ab, sodass richtige Bewegungen nicht zustande kommen.)

    im Anhang ist das neue Skript.
    Das sollte mit den Gleichen Grafiken aus dem ersten Post laufen.

    mfg
    Mars(i)
    Das i hab ich eig nur, weil Mars schon vergeben war^^