Console Flackert wegen System("cls"), Alternative?



  • EdwardBlack schrieb:

    Der Debugger gibt mir "'gotoxy': Bezeichner wurde nicht gefunden." aus, nachdem ich system("cls") durch gotoxy(0,0) ersetzt habe? Was mach ich falsch?

    Der Threadersteller hat es bereits eingebaut ...

    http://www.spieleprogrammierer.de/18-c-cplusplus-csharp-java-und-andere-sprachen/21261-hilfe-bei-einem-programm-cursor-bewegen-auf-der-console/



  • Sincap80 schrieb:

    Erstmal Danke das du mir hilfst 😃
    Wenn ich das mit gotoxy löse, ist das genau das gleiche, als würde ich system cls benutzen 😞

    Nur das es nicht mehr flackert.

    Wenn es doch flackert liegt es daran, das nicht alle Zeilen auf den Screen passsen. Wenn du das
    Fenster versuchsweise etwas vergroesserst flackert da nichts, da immer an den gleichen Stellen
    gezeichnet wird. Ich wuerde empfehlen das Zeichenfeld etwas zu verkleinern, oder notfalls
    das Consolenfenster zu vergroessern.

    Besser wäre natürlich nur die Zeichen zu zeichnen, die sich wirklich ändern.

    Es gibt dann natürlich auch noch die Möglichkeit mit zwei verschiedenen Screens
    zu arbeiten. -> Siehe meinen Link "Weitere Routinen für Console"



  • merano schrieb:

    Besser wäre natürlich nur die Zeichen zu zeichnen, die sich wirklich ändern.

    Ja habe ich mir auch gedacht, aber da weis ich jetzt nicht wie. Ich habe es nun so gemacht dass ich nur 1x Die ganze Map ausgebe und dann nur noch den Player. Das funktioniert aber nicht. Wie soll ich das machen?



  • Sincap80 schrieb:

    merano schrieb:

    Besser wäre natürlich nur die Zeichen zu zeichnen, die sich wirklich ändern.

    Ja habe ich mir auch gedacht, aber da weis ich jetzt nicht wie. Ich habe es nun so gemacht dass ich nur 1x Die ganze Map ausgebe und dann nur noch den Player. Das funktioniert aber nicht. Wie soll ich das machen?

    Wo soll das Problem sein ?

    Wir gehen davon aus, das du weisst wo der player ist. Ausserdem gibt es ein array das
    den Hintergrund enthält. Für die Fläche (in diesem Fall nur ein zeichen) holst Du aus dem array
    die Fläche auf der aktuell der Player ist und zeichnest das an die Stelle wo der Player ist.

    Zum Schluss zeichnest Du den Player an der neuen Position neu 😃



  • Sincap80 schrieb:

    nur 1x Die ganze Map ausgebe und dann nur noch den Player. Das funktioniert aber nicht. Wie soll ich das machen?

    Zum Beispiel so (einfach mal auf die Schnelle aus dem Ärmel gespuckt, unter Zuhilfenahme einiger Konsolenroutinen, die ich mir im Laufe der Zeit mal zusammengeschrieben habe):

    #include <windows.h>
    
    void SetCursorPosition(int x, int y)
    {
        COORD pos = {x, y};
    
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
    }
    
    void SetCursorVisible(BOOL v)
    {
        CONSOLE_CURSOR_INFO ci;
    
        GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ci);
    
        ci.bVisible = v;
    
        SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &ci);
    }
    
    void DruckSimpleText(int x, int y, char const *text)
    {
        COORD target = {x, y};
        DWORD written;
    
        WriteConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), text,
                                                strlen(text),
                                                target, &written);
    }
    
    void DruckSimpleChar(int x, int y, char c)
    {
        char text[2] = {c, 0};
    
        DruckSimpleText(x, y, text);
    }
    
    void ClearScreen(WORD attribute = 7)
    {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        COORD target = {0, 0};
        DWORD written;
    
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
        FillConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), ' ',
                                                csbi.dwSize.X * csbi.dwSize.Y,
                                                target, &written);
        FillConsoleOutputAttribute(GetStdHandle(STD_OUTPUT_HANDLE), attribute,
                                                csbi.dwSize.X * csbi.dwSize.Y,
                                                target, &written);
    }
    
    int getInput()
    {
        INPUT_RECORD ir;
    
        DWORD dummy;
        do
        {
            ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &ir, 1, &dummy);
        }while(ir.EventType != KEY_EVENT || !ir.Event.KeyEvent.bKeyDown);
    
        return ir.Event.KeyEvent.uChar.AsciiChar;
    }
    
    int peekInput()
    {
        INPUT_RECORD ir;
    
        DWORD anz;
    
        PeekConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &ir, 1, &anz);
    
        if(ir.EventType == KEY_EVENT && !ir.Event.KeyEvent.bKeyDown)
        {
          ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &ir, 1, &anz);
          return 0;
        }
    
        return anz;
    }
    
    void SetWindowExt(int x, int y, int yMulti = 1)
    {
        SMALL_RECT sr_window = {0, 0, x - 1, y - 1};
        COORD      extension;
        CONSOLE_SCREEN_BUFFER_INFO csbi;
    
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    
        extension.X = max(x, csbi.dwMaximumWindowSize.X);
        extension.Y = max(y, csbi.dwMaximumWindowSize.Y);
    
        SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), extension);
        SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &sr_window);
    
        extension.X = x;
        extension.Y = y * yMulti;
        SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), extension);
    }
    
    void move(char dir)
    {
       static int x = 5;
       static int y = 5;
       static char aktDir = 'd';
    
       DruckSimpleChar(x, y, ' ');
    
       if(dir == 'a' || dir == 'w' || dir == 's' || dir == 'd')
          aktDir = dir;
    
       switch(aktDir)
       {
          case 'a': x--; if(x < 2) x = 17; break;
          case 'w': y--; if(y < 2) y = 17; break;
          case 'd': x++; if(x > 17) x = 2; break;
          case 's': y++; if(y > 17) y = 2; break;
       }
    
       DruckSimpleChar(x, y, 'O');
    }
    
    int main()
    {
       SetWindowExt(20, 15); SetWindowExt(50, 30);
       ClearScreen();
       SetCursorVisible(false);
    
       //Spielfeldbegrenzung
       DruckSimpleText(1, 1, "------------------");
       DruckSimpleText(1, 18, "------------------");
    
       for(int y = 2; y < 18; ++y)
          DruckSimpleText(1, y, "|                |");   
    
       DruckSimpleText(1, 21, "Richtung? (a, w, s, d, x)");
    
       char Richtung = 'd';
    
       do
       {
          if(peekInput())
             Richtung = getInput();
    
          if(Richtung == 'x')
             break;
    
          move(Richtung);
    
          Sleep(200);
    
       }while(true);
    
       SetCursorVisible(true);
    
    }
    


  • Belli schrieb:

    Zum Beispiel so (einfach mal auf die Schnelle aus dem Ärmel gespuckt, unter Zuhilfenahme einiger Konsolenroutinen, die ich mir im Laufe der Zeit mal zusammengeschrieben habe):

    Ok haha ich hoffe die Routine bekomme ich auch 😃
    Leide kann ich es nicht Kompilieren da er komischerweise das "max" in der 97 Zeiler als Fehler markiert, es sei nicht deklariert. Was nu?



  • merano schrieb:

    Wo soll das Problem sein ?

    Wir gehen davon aus, das du weisst wo der player ist. Ausserdem gibt es ein array das
    den Hintergrund enthält. Für die Fläche (in diesem Fall nur ein zeichen) holst Du aus dem array
    die Fläche auf der aktuell der Player ist und zeichnest das an die Stelle wo der Player ist.

    Zum Schluss zeichnest Du den Player an der neuen Position neu 😃

    Ich nehme es aus der Array Position z.b. array[1][1] mache dort ein ' ' und dann auf array[1][2] zeichne ich den Player ein. Dann muss ich es doch wieder ausgeben. Dann habe ich doch wieder das Problem dass es entweder in der Console verrutscht oder mit system cls flackert.

    Sry wenn ich dich nerve 😃



  • Sincap80 schrieb:

    Leide kann ich es nicht Kompilieren da er komischerweise das "max" in der 97 Zeiler als Fehler markiert, es sei nicht deklariert. Was nu?

    Hast Du das Programm so, wie es oben ist, ohne Änderungen übernommen? Dann sollte es kompilieren (mit einem C++ - Compiler).

    Ansonsten könntest Du versuchen, das Makro selbst zu definieren, siehe:
    http://msdn.microsoft.com/en-us/library/windows/desktop/dd757150(v=vs.85).aspx

    Andere Möglichkeit wäre, max aus dem Namensraum std (Header algorithm) zu nehmen ...



  • Ich musste gerade feststellen, das der Threadersteller selbst mit einfachsten for() Schleifen nicht
    klarkommt. Nun ist mir klar warum er mit vielen Dingen hier völlig überfordert ist.

    http://www.c-plusplus.net/forum/p2360612#2360612



  • Das ist natürlich keine gute Vorraussetzung. Die Grundlagen sollte man natürlich beherrschen, schließlich muss man auch verstehen was man macht, nur Copy & Pasten bringt wenig Lernerfolg.


Anmelden zum Antworten