2016-12-25 3 views
-1

Ich programmiere einen Space Invaders-Klon in C++ auf der Konsole. Ich habe eine Raumschiffklasse, in der ich die Form auf dem Konsolenbildschirm erstelle. Ich verwende Pfeiltasten, um es horizontal über den Bildschirm zu bewegen. Das Schiff besteht aus 3 Teilen. Hier haben Sie Bilder, die zeigen, wie das Raumschiff nach rechts bewegt wird. http://imgur.com/a/fos5M Und hier haben Sie den CodeTeile der Form bewegen sich nicht

class BaseSpaceShip{ 
protected: 
private: 
    char ship[4][19] = { 
    "  \xDB  ", 
    " \xDB\xDB\xDB\xDB\xDB ", 
    "  \xDB\xDB\xDB\xDB\xDB\xDB\xDB\xDB\xDB" 
    }; 
     const int mapy = 4; 
     int x, y; 
     void Invalidate(); 
     void cls(); 
public: 
    BaseSpaceShip(); 
    ~BaseSpaceShip(); 
    void Init(); 
    virtual void MoveShip(int dx, int dy); 
}; 
BaseSpaceShip::BaseSpaceShip() { 
    x = 130; 
    y = 69; 
    Init(); 
} 
BaseSpaceShip::~BaseSpaceShip() { 
} 
void BaseSpaceShip::Init() { 
    cls(); 
    for (int i = 0; i < mapy; i++) { 
     gotoxy(x - i, y + i); 
     cout << ship[i] << endl; 
    }  
} 
void BaseSpaceShip::MoveShip(int dx , int dy) { 
    x+= dx; 
    y += dy; 
    Init(); 
} 

Warum dieser Fehler auftritt und wie kann ich es lösen? Außerdem habe ich von dem Double-Buffering-Konzept gehört, um das Bildschirmflimmern zu entfernen, wenn ich mein Raumschiff bewege, aber wie kann ich das umsetzen?

+0

ich denke gotoxy (x - i, y + i); sollte nur gotoxy (x, y + i) sein; Sie möchten alle Zeilen des Schiffes auf dem gleichen x Offset drucken – FamZ

+0

Es ist wahrscheinlich Betriebssystem spezifisch. [ncurses] (https://www.gnu.org/software/ncurses/) ist nicht Teil des C++ 14-Standards und nicht auf jedem Betriebssystem verfügbar. –

+0

Tags funktionieren hier sehr gut. Sie brauchen Ihre Hilfe nicht, indem Sie sie auch im Titel redundant hinzufügen. Es ist absolut unnötig, die Tag-Informationen im Titel und Text Ihres Posts zu wiederholen. Lassen Sie die Tags ihre Arbeit machen. –

Antwort

0

gotoxy(x - i, y + i); sollte nur gotoxy(x, y + i); Sie alle Linien des Schiffes auf den gleichen x-Offset drucken wollen. Außerdem müssen Sie darauf achten, dass Ihr Schiff nicht über die Konsolengrenze hinausgeht, x = 130 ist ein bisschen viel, oder? Flackern wird angezeigt, weil Sie die gesamte Konsole beim Aktualisieren löschen. Es gibt zwei Möglichkeiten, dieses

  • Redraw nur aktualisiert Objekte zu lösen:

Angenommen, Sie Ihr Schiff aktualisieren möchten, weil sie bewegt. Du kannst den Cursor einfach zum alten Schiffsplatz bewegen, Räume über das Schiff schreiben, zum neuen Schiffsplatz gehen und das Schiff neu zeichnen.

  • Verwenden Sie die "Double-Buffering" Methode, die Sie in Ihrer Frage erwähnt:

Diese so aussehen würde: Sie haben zwei 2D-char-Arrays (oder ein Array/Vektor von Strings, die besser ist) Bei gleicher Größe Ihrer Szene werden beide am Anfang mit Leerzeichen initialisiert.

// Scene size is 100x100 
std::vector<std::string> buffer_a(100, std::string(100, ' ')); 
std::vector<std::string> buffer_b(100, std::string(100, ' ')); 

Statt nun direkt cout auf dem Bildschirm ing, können Sie Ihre Änderungen an buffer_b schreiben, so dass anstelle von

for (int i = 0; i < mapy; i++) 
{ 
    gotoxy(x, y + i); 
    cout << ship[i] << endl; 
} 

Sie so etwas wie dies tun:

for (unsigned int i = 0; i < ship_width; i++) 
    for(unsigned int j = 0; j < ship_height; ++j) 
     buffer_b[x + i][y + j] = ship[i][j]; 

Wenn Sie mit der Aktualisierung fertig sind, müssen Sie beide Puffer durchlaufen und alle Elemente zeichnen, die nicht mit buffer_a identisch sind, und dann kopieren Sie buffer_b bis buffer_a.

for (unsigned int i = 0; i < scene_width; i++) 
{ 
    for(unsigned int j = 0; j < scene_height; ++j) 
    { 
     if(buffer_a[i][j] != buffer_b[i][j]) 
     { 
      gotoxy(i, j); 
      std::cout << buffer_b[i][j]; 
      buffer_a[i][j] = buffer_b[i][j]; 
     } 
    } 
} 

Beachten Sie, dass, wenn Sie Änderungen an buffer_b schreiben, sagen wir mal, wenn Sie das Schiff bewegen, müssen Sie noch Räume über die alte Schiff Positionen in buffer_b, bevor Sie es aktualisieren, es sei das erste Update wenn buffer_b leer ist. Bei dieser Methode ist es gut, eine Hauptschleife zu implementieren, bei der die Eingabe zuerst gelesen und dann am Ende jeder Iteration aktualisiert und dann Puffer ausgetauscht werden.

Vielleicht ist die erste Methode ist besser, wenn die Szene wirklich groß ist, weil Sie jedes Element der Puffer in dem zweiten Verfahren testen, Es gibt bereits eine große Antwort auf die von Cameron hier: Update console without flickering - c++

+0

Hallo, das x = 130 ist für das Platzieren des Schiffes in der Mitte des Bildschirms, da es eine Vollbild-Konsole App ist. Wenn ich nur das Schiff aktualisiere, würde es immer noch flackern, aber nur das Schiff richtig? es bewegt sich immer noch nicht richtig, gibt es eine Möglichkeit, alle meine Schiffe auf einmal zu drucken, da ich denke, dass das Problem umgeht. –

+0

Ich versuchte Ihren Code und es funktioniert für mich, die einzige Sache, die ich änderte ist, dass ich das Schiff-Array ein String-Array gemacht und einige Leerzeichen am Anfang der 3. Zeichenfolge entfernt Std :: String ship [] {"\ xDB" , "\ xDB \ xDB \ xDB \ xDB \ xDB", "\ xDB \ xDB \ xDB \ xDB \ xDB \ xDB \ xDB \ xDB \ xDB"}; – FamZ

+0

BTW, sollte die untere Linie des Schiffes still stehen oder ist es Teil des Schiffes? das würde alles ändern, auch habe ich die bewegung mit ship.MoveShip (1, 0) getestet; in einer Schleife – FamZ

Verwandte Themen