2015-04-28 10 views
13

Ich mache ein Spiel und Redrawing das Spielfeld ist nicht so nett mit Console.Write() gibt es eine Möglichkeit, dass ich das gesamte Feld schneller neu schreiben kann, ohne dass es "laggy" aussehen? So ziemlich alles, was in dem Spielfeld bewegt, aber es gibt Objekte nur auf Elemente anders als 0 .. (Sie können den vollständigen Code überprüfen hier http://pastebin.com/TkPd37xD und sehen, was ich rede, wenn meine Beschreibung ist nicht genug)C# Etwas schneller als Console.Write()?

for (int Y = 0; Y < playfield.GetLength(0); Y++) 
{ 
    for (int X = 0; X < playfield.GetLength(1); X++) 
    { 
     //destroying the row when it reaches the top 
     if (playfield[0, X] != 0) 
     { 
      for (int i = 0; i < playfield.GetLength(1); i++) 
      { 
       playfield[0, X] = 0; 
       Console.SetCursorPosition(X, 0); 
       Console.Write(" "); 
      } 
     } 
     if (playfield[Y, X] == 3) 
     { 
      playfield[Y - 1, X] = 3; 
      playfield[Y, X] = 0; 
     } 
     else if (playfield[Y, X] == 1) 
     { 
      Console.SetCursorPosition(X, Y - 1); 
      Console.Write("="); 
      playfield[Y - 1, X] = 1; 
      Console.SetCursorPosition(X, Y); 
      Console.Write(" "); 
      playfield[Y, X] = 0; 
     } 
     else if (playfield[Y, X] == 0) 
     { 
      Console.SetCursorPosition(X, Y); 
      Console.Write(" "); 
     } 
    } 
} 
+9

Nur nicht den gesamten Bildschirm neu zeichnen, nur die Teile, die geändert –

+0

Ich dachte, dass das ist, was ich tat, aber anscheinend war ich nicht, nur jetzt habe ich gemerkt, dass mein letztes "Else if" nicht notwendig ist, da ich das selbe am else mache, wenn when == 1, entfernte ich die letzte Else if und es sieht jetzt viel besser aus! :) – Darkbound

+0

Haben Sie versucht, einen String-Puffer zu verwenden? – Caramiriel

Antwort

12

Es gibt grundsätzlich zwei Ansätze: weniger rendern und schneller rendern.

Render weniger ist in der Regel schwieriger, aber auch weniger intensiv. Das klassische Beispiel wären Carmacks Keen-Spiele - der PC hatte nicht den Mut, den ganzen Bildschirm auf einmal zu rendern, also sorgte Carmack dafür, dass nur die Teile des Bildschirms, die tatsächlich geändert wurden, neu gezeichnet wurden. In Ihrem Fall kann dies so einfach sein wie das Überprüfen des neuen Bildschirms gegen den alten Bildschirm (ohne die Methoden Console natürlich zu verwenden) - abhängig von der Art des Spiels, das Sie schreiben, kann dies Ihnen eine Menge Arbeit ersparen.

Render schneller ist in der Regel einfacher. Die übliche Herangehensweise war in den alten Tagen, direkten Zugriff auf den Ausgabepuffer zu erhalten - anstatt das Spielfeld in einem separaten Speicher zu haben, hatten Sie es direkt in der Grafikkarte - was durchaus in der Lage war, den gesamten Bildschirm so schnell wie nötig neu zu zeichnen Natürlich, sonst würden Sie auf Ihrem Bildschirm nie viel sehen. Diese Option ist weiterhin als Abwärtskompatibilität verfügbar, sodass Sie sie immer noch verwenden können, wenn Sie Ihre Anwendung beispielsweise in Turbo Pascal codieren, aber in C# ist das nicht wirklich so einfach. Es gibt eine Option beim Rendern des gesamten Bildschirms in einem StringBuilder zuerst und dann Console.Write das alles auf einmal. Es wird ein bisschen schneller, aber es ist nicht gerade stellar. char[] können Sie einen zusätzlichen Punkt der Leistung - Sie können Ihr Spielfeld direkt als char[][] darstellen und dann müssen Sie die StringBuilder nicht jedes Mal neu erstellen, wenn Sie etwas ändern - Sie müssen nur Console.Write einmal für jede Spielfeldzeile.

Und natürlich könnten Sie einfach die Änderungen ausschreiben, sobald sie auftreten; Je nach dem Spiel, das Sie schreiben, kann dies von "trivial mit großartigen Ergebnissen" bis hin zu "ziemlich hart und nicht gut" reichen. Und da der Pufferbereich der Konsole größer als die Fenstergröße sein kann, könnten Sie ihn sogar in einen versteckten Teil des Puffers ziehen und dann Console.MoveBufferArea verwenden, um die gesamte Änderung auf einmal zu zeichnen - dies wird normalerweise "Backbuffering" genannt. Ich bin mir nicht sicher, ob es gut aussehen wird - das Konsolenfenster erlaubt es Ihnen heutzutage, im Puffer zu scrollen, was für Ihren Anwendungsfall schädlich sein kann.

Es gibt immer noch Möglichkeiten, um viel schneller Zugriff auf die Konsolenpuffer zu bekommen, aber nicht während Sie vollständig in .NET bleiben - Sie müssen P/Invokes verwenden. Eine gute Antwort zu diesem Thema gibt es hier - How can I write fast colored output to Console?.Auf modernen Systemen entspricht das einem Back-Buffer und "Zeichnen" auf einmal - es ist unglaublich schnell. Und wieder können Sie den Backbuffer für Ihre Spieldaten direkt verwenden - es funktionierte vor 20-30 Jahren, und es funktioniert noch heute; Es ist eine gute Übung, mit begrenzten Ressourcen herumzuspielen. Kannst du ein Spiel schreiben, das nur den Konsolen-Textpuffer für alles oder zumindest fast alles nutzt? Es macht Spaß, mit solchen Sachen herumzuspielen. Sie können eine ganze Fülle von Spielen wie diesem schreiben, einschließlich Spiele wie Tetris oder Lode Runner. Natürlich funktioniert das nur unter Windows. Wenn Sie also andere Systeme unterstützen wollen, ist das viel schwieriger.

Und schließlich können Sie einfach Ihre eigene Konsole schreiben (oder besser, verwenden Sie jemand bereits geschrieben und getestet). Es ist eine gute Übung, wenn Sie im Laufe der Zeit größeren Herausforderungen nachgehen wollen und es Ihnen ermöglichen wird, im Laufe der Zeit mit leistungsfähigeren Technologien zu spielen. Das typische Beispiel wären Spiele wie Dwarf Fortress - immer noch textbasiert, immer noch Konsolen-ähnlich, aber tatsächlich grafisch gezeichnet, mit Technologien wie SDL. Dies ist nicht nur auf modernen Systemen wesentlich schneller (da Sie nicht direkt auf die Textpuffer zugreifen können), sondern eröffnet auch die Möglichkeit, ziemlich einfach auf ein grafisch gekacheltes Spiel umzusteigen. Es ist ein weiteres Sprungbrett auf der Treppe, um Dinge zu kühlen :))

0

eine alternative ist, den API-Aufruf in der Verbindung angegeben verwenden https://msdn.microsoft.com/en-gb/library/windows/desktop/aa363362%28v=vs.85%29.aspx

[DllImport("kernel32.dll")] 
static extern void OutputDebugString(string lpOutputString); 

Sie können auch geringen Leistungsgewinn durch die Ausgänge Pufferung in Ihrem für Schleifen in einen String und sich nach jedem für die Schleife ausgibt. Dies ist möglicherweise nicht notwendig, je nachdem, was Sie mit Ihrem Programm erreichen möchten.

+2

So muss es nicht gehen, es gibt eine verwaltete 'Debug.WriteLine', die in der verwalteten Welt dasselbe tut. – Blindy

0

Wenn Sie das Ausgabe-cmd-Fenster ausblenden, wird es von Windows nicht neu gezeichnet, und Ihre Anwendung wird schneller ausgeführt, als wenn sie auf dem Bildschirm geöffnet ist.

Wenn dies nur ein Debug-Problem ist, können Sie einfach das Fenster minimieren und eine kleine Leistungssteigerung feststellen.

+0

Aus OPs Verwendung des Begriffs "Spielfeld" vermute ich, dass es sich um ein Spiel handelt und nicht um Debug-Ausgaben. – Rawling