Laden...

Flackern trotz DoubleBuffered = true

Erstellt von Joe86 vor 14 Jahren Letzter Beitrag vor 14 Jahren 2.315 Views
J
Joe86 Themenstarter:in
37 Beiträge seit 2007
vor 14 Jahren
Flackern trotz DoubleBuffered = true

Hallo alle zusammen.

Ich übe mich gerade in Zeichenoperationen und wollte mir dazu ein kleines Snake-Game erstellen.
Jedoch habe ich nun das Problem, das wenn ich direkt auf meine Form etwas Zeichne, es zu dem typischen Grafikflackern kommt.
Der Witz jedoch ist, bei mir tritt der Effekt auf, obwohl DoubleBuffered der Form auf true ist. Es macht keinen Unterschied, wenn ich es auf false oder true setze.

Die Zeichenoperation ist eigentlich noch relativ simpel:


// Rendert die Spielwelt
        public void Rendern(Graphics g)
        {
            // Als erstes Zeichne den Hintergrund
            g.FillRectangle(Brushes.SkyBlue, spielForm.ClientRectangle);

            // Zeichne die Schlange
            foreach (Körperteil_Schlange körper in welt.schlange.Körperteile)
            {
                if (körper.Körperteil == Körperteil_Schlange.Körperteile.Kopf)
                    g.DrawImageUnscaled(BildDrehen(Properties.Resources.kopf, körper.Richtung), körper.Ort);
                else if (körper.Körperteil == Körperteil_Schlange.Körperteile.Bauch)
                    g.DrawImageUnscaled(BildDrehen(Properties.Resources.bauch, körper.Richtung), körper.Ort);
                else
                    g.DrawImageUnscaled(BildDrehen(Properties.Resources.schwanz, körper.Richtung), körper.Ort);
            }
        }

Diese Methode wird bei dem Paint-Event der Form sowie alle 100ms aufgerufen.
Wenn ich testhalber noch ein Rectangle für einen Rahmen um die Spieloberfläche zeichne flackert es sogar noch mehr...

Hoffe ihr könnt mir einen Tipp geben wie ich das flackern besser in den Griff kriege.
LG

J
Joe86 Themenstarter:in
37 Beiträge seit 2007
vor 14 Jahren

So, ich hab mir nun meinen eigenen BackBuffer zusammengebastelt auf dem zuerst alles gezeichnet und anschließend auf die Form übertragen wird.
Dies funktioniert zwar wie gewünscht, denoch meine Frage ob dies mit dem Form-Internen DoubleBuffer nicht zu erreichen ist?

A
8 Beiträge seit 2009
vor 14 Jahren

Hi! Hatte genau dasselbe Problem, bei mir hat Form1.DoubleBuffered = true auch nicht wirklich funktioniert.
Habe aber dann im Internet den entscheidenden Tipp gefunden.
Du platzierst den folgenden Code einfach in der Form-Designer.cs Datei:


public class DoubleBufferPanel : System.Windows.Forms.Panel
{
public DoubleBufferPanel()
{
// Set the value of the double-buffering style bits to true.
this.SetStyle(System.Windows.Forms.ControlStyles.DoubleBuffer |
System.Windows.Forms.ControlStyles.UserPaint |
System.Windows.Forms.ControlStyles.AllPaintingInWmPaint,
true);

this.UpdateStyles();
}
}

Du musst dann einfach überall in der Form-Designer.cs Datei den Typ "Panel" mit "DoubleBufferPanel" ersetzen!

Gelöschter Account
vor 14 Jahren

@AlexBond007:
das ist das selbe, wie die eigenschaft "DoubleBuffered" zu setzen. zudem wird das das problem nciht beheben.

@Joe86:
warum wird alle 100 ms die paint methode aufgerufen? das machst du doch nicht etwa mit einem timer?

allgemeiner hinweis zum flackern: [FAQ] Flackernde Controls vermeiden / Schnelles, flackerfreies Zeichnen

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo JAck30lena,

das ist das selbe, wie die eigenschaft "DoubleBuffered" zu setzen. zudem wird das das problem nciht beheben.

hm, also das AllPaintingInWmPaint kann schon einen entscheidenden Unterschied machen.

herbivore

J
Joe86 Themenstarter:in
37 Beiträge seit 2007
vor 14 Jahren

Hi! Hatte genau dasselbe Problem, bei mir hat Form1.DoubleBuffered = true auch nicht wirklich funktioniert.
Gabe aber dann im Internet den entscheidenden Tipp gefunden.

Du musst dann einfach überall in der Form-Designer.cs Datei den Typ "Panel" mit "DoubleBufferPanel" ersetzen!

Hallo, danke für den Tipp. Habs damit versucht. Rein gefühlstechnisch ist es zwar besser geworden, ein flackern tritt aber noch immer auf.

warum wird alle 100 ms die paint methode aufgerufen? das machst du doch nicht etwa mit einem timer?

Ähm, doch... Zurzeit schon 😃
Hab ihm moment die Bewegung der Schlange timergesteuert integriert, und in diesem Event wird am Ende auch das Zeichnen der Form aufgerufen.

1.346 Beiträge seit 2008
vor 14 Jahren

Ein Spiel in Winforms zu mache finde ich nicht wirklich sinnvoll. Das ist dazu viel zu langsam. Sobald du nähmlich ein paar Effekte oder ähnlches haben willst, Siehst du jeden Frame. Außerdem hast du nicht die Möglichkeit Shader zu benutzen.

Meine Empfehlung XNA

Gruß pdelvo

J
Joe86 Themenstarter:in
37 Beiträge seit 2007
vor 14 Jahren

XNA ist dafür sicherlich besser.
Ich wollte mit dem Snake eigentlich nur meine GDI-Fähigkeiten etwas verbessern um später für eigene Controls besser gerüstet zu sein 😉

1.346 Beiträge seit 2008
vor 14 Jahren

Wollte nur sagen dass du damit keine Freude haben wirst. Habe mal ein Ping Pong in gdi gemacht. Das ruckelt aufm Quad Core.

Gruß pdelvo

Gelöschter Account
vor 14 Jahren

Wollte nur sagen dass du damit keine Freude haben wirst. Habe mal ein Ping Pong in gdi gemacht. Das ruckelt aufm Quad Core.

dann hast du vermutlich was falsch gemacht. gdi ist nciht so langsam wie die meisten glauben.

@Joe86:
das mit dem timer ist keine gute idee. du sollst immer nur das neuzeichnen lassen, was sich geändert hat. das aber auch erst, nachdem du alle änderungen durchgeführt hast.

kein grund alles immer zyklisch neuzeichnen zu lassen.

K
133 Beiträge seit 2009
vor 14 Jahren

Die frage ist wie lang deine Schlange denn ist. umso länger der Zeichenvorgang in deiner foreach-Schleife blockiert wird umso höher wird die Verzögerung.

Auch frage ich mich was die funktion g.DrawImageUnscaled(BildDrehen(Properties.Resources.kopf, körper.Richtung), körper.Ort); macht. Sollte diese funktion tatsächlich ein bitmap drehen würde ich dir empfehlen alle möglichen Richtungen vorher zu cachen! Du kannst nicht in einem Paintereigniss solch "komplexe" Aufgaben bewältigen!

F
9 Beiträge seit 2007
vor 14 Jahren

Hi,

in den meisten Fällen wenn es flackert ist es das PaintBackground
nicht überschrieben wurde. Da dort immer wieder ein Clear des kompletten Bereichs mit der gesetzten Hintergrundfarbe durchgeführt wird. Dadurch
flackert es immer.

Man sollte diese Methode überschreiben und leer
lassen und in Deiner Render Methode auf Dein BackBuffer die Hintergrundfarbe setzen (wenn es die gesamte Fläche einnimmt).

Gruß
Firgor