C# WinForm "Mini-Game"

steppi

Commander
Registriert
Apr. 2012
Beiträge
2.161
Hallo Zusammen,

erstmal ein weniger Input. Ich habe eine typische Studien-Aufgabe, wo eine Art abgespecktes Pac-Man gebaut werden soll, dass mittels Datei eingelesen wird und auf einer Form dargestellt werden muss "#" = Wänden, "." = Items, "@" = Spielfigur.

Stand:
Ich habe ein komplett den Anforderungen entsprechenden lauffähigen Code, der das "Labyrinth" aus einem Textfile einliest und auf die Form bringt. Mithilfe der Pfeiltasten lässt sich meine Spielfigur durch das Labyrinth bewegen, wobei es an Wänden stoppt und Items aufsammelt (die verschwinden dann).

Problem:
Das Aktualisieren der Form flackert, da ich die Form mittels this.Refresh(); erneut "triggere" und damit meine Zeichenmethode erzwinge.

Eigene Implementierung:
Ich habe das Labyrinth zeilenweise eingelesen und die Zeilen dann in seine Chars zerlegt und habe am Ende ein 2D-Array mit Strings Spielfeld [Zeile, Spalte].
Danach habe ich einen PaintEventHandler verwendet und eine Methode erstellt, die mir entsprechend mein Array zeilenweise ausliest und dabei direkt auf die Form zeichnet. Ich hatte mal testweise mit "CreateGraphics()" und mit e.Graphics gezeichnet, beides verhält sich ähnlich. Zeichnen erfolgt dann mittels DrawString(...) direkt auf die Form. Abschluss der Methode bildet dann das Dispose() aller verwendeten Objecte (Font, Brush, Format, Form).
Bei Tastendruck wird das "Spielfeld-Array" geändert und die neue Version wieder auf das Form geschrieben mit selber Methode wie ursprünglich.
Ich hatte versucht das ganze mit einer override OnPaint()-Methode zu bewerkstelligen, aber es hat leider hinten und vorn nicht funktioniert. Die Studienhefte sind leider auch nicht sehr aufschlussreich was die Verwendung und Implementierung angeht und da es ein Fernstudium ist, ist man auch etwas auf sich gestellt. Mit den MS-Docs komme ich auch nicht so recht weiter.

P.S.:
Den Code direkt möchte ich nur auf Anfrage zur Verfügung stellen, da es sich um eine Hausarbeit handelt und später auch bewertet wird. Ich weiß dass das die Sache erschwert, aber ich denke es ist nicht ideal wenn der Code einfach und schnell im Netz zu finden ist. Ich hatte auch schon gesehen, dass hier scheinbar vor Jahren schonmal Leute diese Aufgabe hatten. ^^
 
Erstelle dir eine eigene Klasse die von Panel erbt und setze die Eigenschaft DoubleBuffered = true; im Konstruktor. Dieses Panel musst du dann zum zeichnen benutzen. Das sollte das Flackern deutlich verringern.
 
SomeDifferent schrieb:
Erstelle dir eine eigene Klasse die von Panel erbt und setze die Eigenschaft DoubleBuffered = true; im Konstruktor. Dieses Panel musst du dann zum zeichnen benutzen. Das sollte das Flackern deutlich verringern.
Das hatte ich schonmal überlegt, aber zunächst wieder verworfen. Die anderen Aufgaben war alle sehr explizit auf die Studienhefte bezogen und dort wird maßgelbich direkt auf die Form gezeichnet und mit OnPaint gearbeitet und aktualisiert. Ich glaub hier frage ich einfach nochmal den Tutor.
Ergänzung ()

Tornhoof schrieb:
Hatte ich tatsächlich schon gefunden und auch versucht zu adaptieren, aber dabei keine Erfolg.
 
SomeDifferent schrieb:
Erstelle dir eine eigene Klasse die von Panel erbt und setze die Eigenschaft DoubleBuffered = true; im Konstruktor. Dieses Panel musst du dann zum zeichnen benutzen. Das sollte das Flackern deutlich verringern.
Das habe ich jetzt mal ausprobiert und auch dieser Code läuft. Es fühlt sich tatsächlich etwas "flüssiger" an bzw. flackert es jetzt schneller. Ich denke mein Problem liegt daran, dass ich das Form bzw. jetzt das Panel Zeichen für Zeichen beschreibe, wobei wir aktuell von ~15x20 Zeichen sprechen, die dann gezeichnet werden, wobei die Zeichen noch unterschieden werden. Ich denke den Code-Schnippsel kann ich ohne Probleme posten:

Code_Entfernt*

Das liegt alles in einer äußeren Schleife (i) und einer inneren Schleife (j). Nach jedem Durchlauf der inneren Schleife wird gezeichnet (Methode-DrawString). Ich denke, dass die Interationen das sind was ich als Flackern sehe.
Gibt es vlt. eine Variante wie ich zuerst die Matrix bauen kann mit allen Formatierungen und dann nur ein einziges Mal zeichne? Ich denke das würde den Code massiv optimieren und das Flackern beseitigen.

P.S.:
Was ich mich auch noch Frage.
Wie nutzt man eigentlich diese OnPaint()-Methode richtig. Das habe ich auch öfter gelesen, dass diese verwendet wird, bekomme Sie aber selbst nicht wirklich angesprochen/ genutzt. Ich hatte es dort zwar auch mal mit einen Override probiert, aber am Ende brauch ich immer noch eine zweite Methode die tatsächlich zeichnet. (über den PaintEventHandler) Das wäre vlt. auch noch ein Ansatz. Der Code oben steckt in dieser Methode: public void SpielfeldZeichnen(object sender, PaintEventArgs e).


EDIT:
Also das flackern kommt von den Schleifen. Ich hatte jetzt noch was anderes probiert, wodurch der Code nochmal etwas langsamer wurde und da hat man gesehen, dass der Aufbau von Oben-Links nach Unten-Rechts erfolgt, was dann eben flackert. Lösung wäre also das Zeug vorher irgendwie zusammenzustellen und dann als ein "Gesamt-Object" zu zeichnen.
 
Zuletzt bearbeitet:
Tornhoof schrieb:
Erzeug die Fonts nicht jedesmal neu, sondern einmal und referenzier die mehrmals.
Ich weiß nicht, ob du es so meinst.
Ich habe jetzt drawFont, SolidBrush, StringFormat vor die Methode gezogen (also new ...) und ändere diese in der Methode nur noch ab. Das entsprechende Dispose der fällt damit auch jeweils weg.
Der Aufbau wird dadurch aber nicht wirklich schneller.
Ergänzung ()

Ich habe jetzt aus folgendem Thread, den letzten Post gefunden und verwendet:
https://www.computerbase.de/forum/t...verhindern-von-flackern.1965736/post-24546806

Zusammen mit dem Panel bzw. DoubleBuffered=true funktioniert die Bewegung jetzt ohne zu flackern,

ABER:
Er macht das "Bild" jetzt nicht wirklich "neu". D.h. die Spielfigur zieht eine Spur:

Bild entfernt*

EDIT:
Ich habe es gelöst... Vielen Dank für die Hilfe.
Ich hatte den Bitmap _BackBuffer außerhalb der Methode deklariert.
 
Zuletzt bearbeitet:
Zurück
Oben