direkt in den Ausgabe-Buffer schreiben [C++ Konsolenanwendung]

OP #6418789
Hi all, ich habe eine Bitte an euch. Könntet ihr mir sagen, wie ich 
direkt in den Ausgabe-Buffer scrheibe? Ich habe gehört, dass das geht.

Zum Problem: Ich habe ein char-Array, in dem das Spielfeld ist. Dieses 
ist 28*36 Felder groß. Da das Feld ständig neu gezeichnet werden muss, 
bekomme ich eine Flimmerkiste. Ich weiß, diese nested for loops sind ein 
Flaschenhals, aber mit diesem char-Array konnte ich bisher so leicht 
arbeiten.
1
void Spiel::render_output()
2
{
3
  Konsole_leeren();
4
  Spielfeld_Original[Gegner.Y][Gegner.X] = '\xB2'; //▓
5
  Spielfeld_Original[du.Y][du.X] = 'O';
6

7
  for (int i = 0; i < vert; i++)
8
  {
9
    for (int j = 0; j < hor; j++)
10
    {
11
      std::cout << Spielfeld_Original[i][j];
12
    }
13
    std::cout << '\n'; //optimiert
14
  }
15

16
  Spielfeld_Original[Gegner.Y][Gegner.X] = ' ';
17
  Spielfeld_Original[du.Y][du.X] = ' ';
18
}

Ach ja und
1
Konsole_leeren();
 wurde hier bereits behandelt. 
Beitrag "Warum ist diese Prozedur schneller als system("cls")"
Angehängte Dateien:
#6418928
Hi,

Bartosz B. schrieb:
> Hi all, ich habe eine Bitte an euch. Könntet ihr mir sagen, wie ich
> direkt in den Ausgabe-Buffer scrheibe? Ich habe gehört, dass das geht.

Darauf hab ich jetzt ad-hoc leider keine Antwort -- aber wahrscheinlich 
ist das gar nicht nötig, um das Flimmern zu beseitigen: ich vermute dass 
es nur daher kommt, dass Du die Konsole vor dem Rendern leeren lässt. 
Dadurch verschwinden alle Zeichen für kurze Zeit, und werden dann neu 
geschrieben. Alle Zeichen, die sich gegenüber dem vorigen Rendern nicht 
geändert haben, werden dadurch immer wieder kurz schwarz (oder welche 
Farbe der Hintergrund eben hat) -- das wird als Flimmern sichtbar.

Es sollte reichen, vor dem Rendern nur den Cursor nach links oben zu 
setzen -- und nicht noch die Konsole mit Leerzeichen zu füllen.

Also z.B. Konsole_leeren nur noch ganz am Anfang mal aufrufen, und in 
render_output dann stattdessen nur noch diesen Teil davon:
1
SetConsoleCursorPosition(hOut, topLeft);
OP #6419325
Danke an @Mathias für die Idee und Erklärung.
1
void Spiel::render_output()
2
{
3
  HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
4
  SetConsoleCursorPosition(hOut, { 0,0 });
5

6
  Spielfeld_Original[Gegner.Y][Gegner.X] = '\xB2'; //▓
7
  Spielfeld_Original[du.Y][du.X] = 'O';
8

9
  for (int i = 0; i < vert; i++)
10
  {
11
    for (int j = 0; j < hor; j++)
12
    {
13
      std::cout << Spielfeld_Original[i][j];
14
    }
15
    std::cout << '\n'; //optimiert
16
  }
17

18
  Spielfeld_Original[Gegner.Y][Gegner.X] = ' ';
19
  Spielfeld_Original[du.Y][du.X] = ' ';
20
}
 funktioniert schon viel besser, das Flimmern ist weg – bis auf dass man 
den Cursor von oben nach unten hin- und herspringen sieht. Aber das 
bekommt man wohl nicht weg?


> Ich bin zu doof eine Suchmaschine zu benutzen.
Nein, ich habe mir die Mühe gemacht, aber ich kam mit den Beispielen und 
Dokus nicht zurecht. @cppbert s Link ist schon besser ^^
#6420103
Bartosz B. schrieb:
> funktioniert schon viel besser, das Flimmern ist weg – bis auf dass man
> den Cursor von oben nach unten hin- und herspringen sieht. Aber das
> bekommt man wohl nicht weg?

Freut mich!  Doch, den Cursor bekommt man auch weg: man kann ihn 
unsichtbar schalten. In deinem Fall bietet sich an, entweder ausschalten 
am Beginn von render_output und am Ende wieder einschalten (dann blinkt 
er in der rechten unteren Ecke), oder ganz am Anfang mal ausschalten und 
erst beim Beenden des Spiels wieder einschalten.

Wie das ein/ausschalten genau geht weiß ich gerade nicht auswendig, und 
hängt auch vom verwendeten Terminal ab. Meist ist es eine bestimmte 
Escape-Sequenz (d.h. eine Zeichenkette, die mit dem ASCII-Code für 
Escape (=27) beginnt und die, wenn man sie auf dem Terminal ausgibt, 
dort eine Aktion ausführt). Müsste aber per Google gut zu finden sein 
wie das beim Windows Terminal geht.
Gast #6420140
Von stackoverflow
1
#include <windows.h>
2

3
void hidecursor()
4
{
5
   HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
6
   CONSOLE_CURSOR_INFO info;
7
   info.dwSize = 100;
8
   info.bVisible = FALSE;
9
   SetConsoleCursorInfo(consoleHandle, &info);
10
}

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 6 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.