Projekt 2: "Animierte ASCII-Kunst"
5. Film abspielen
Worum geht es?
Im letzten Teil des Projekts werden wir die eingelesenen Bilder über die Kommandozeile abspielen. Damit das funktioniert, müssen zwei Bedingungen erfüllt sein:
- Der Zeitabstand zwischen den angezeigten Bildern muss sinnvoll gewählt werden, damit der Eindruck einer Animation entsteht.
- Die Höhe des Terminal-Fensters muss so angepasst werden, dass die Anzahl der sichtbaren Zeilen zum jeweiligen Film passt.
Sobald die Höhe angepasst ist (nicht in der Browser-Version), werden in einer Schleife die einzelnen Bilder nacheinander im Terminal-Fenster abgespielt. Damit der Eindruck einer flüssigen Animation entsteht, muss allerdings für eine definierte Zeit gewartet werden, bevor das nächste Bild angezeigt wird. Nach Erreichen des letzten Bildes wird das Programm dann schließlich beendet.
Da die Browser-Version einige Einschränkungen hat (kein Terminal-Fenster, keine Animation), solltest du den Code zusätzlich lokal auf deinem Rechner ausführen.
Was kannst du danach?
- Mit einer Doppelschleife über einen 2D-Vektor laufen
- Eine leere Eingabe (ENTER) von der Kommandozeile erkennen
- Die Ausführung mit Hilfe der <thread>-Blibliothek pausieren
Der zu öffnende Dateiname kann hier eingegeben werden:
Hinweis: Im Beispiel wurden nur die ersten 5 Bilder verwendet.
Die komplette Datei kann hier heruntergeladen werden.
#include <string> #include <iostream> #include <fstream> #include <vector> #include <thread> using namespace std; int main() { // Dateiname einlesen string filename; cout << "Bitte Filmdatei angeben : "; cin >> filename; cout << filename << endl; // Datei zum Lesen öffnen ifstream movie_data(filename); if (!movie_data.is_open()) { cout << "Fehler beim Öffnen!" << endl; exit(1); // Programm mit Fehlercode beenden } else { cout << "Datei erfolgreich geöffnet!" << endl; } // Datenstrukturen für Filmdaten string title; // Titel des Films string line; // eine Zeile vector<string> image; // ein Bild vector<vector<string>> images; // eine Bilderserie // Filmdaten zeilenweise auslesen while (getline(movie_data, line)) // zeilenweise auslesen { // Titel extrahieren if (line[0] == '@') // Markierung für Titel { title = line.substr(1, line.size() - 1); } // Aktuelle Zeile in Bild speichern if (line[0] == '"') // Markierung für Bilder { image.push_back(line); } // Fertiges Bild in Serie speichern if (line[0] == ' ' && image.size() > 0) { images.push_back(image); // Bild in Liste kopieren image.clear(); // Bild wieder löschen } } movie_data.close(); cout << "Filmtitel = " << title << endl; cout << "Anzahl Bilder = " << images.size() << endl; // Filmstatistiken berechnen int symbols{0}, lines{0}; for (int i = 0; i < images.size(); i++) { // Anzahl Zeilen if (images[i].size() > lines) { lines = images[i].size(); // Maximum speichern } // Anzahl Zeichen for (int j = 0; j < images[i].size(); j++) { symbols += images[i][j].size(); } } cout << "Anzahl Zeilen / Bild = " << lines << endl; cout << "Anzahl Zeichen = " << symbols << endl; // Bildhöhe anpassen (nur lokal sinnvoll) /* for (int i = 0; i < lines - 5; i++) // Statistik berücksichtigen { cout << endl; } cout << "Terminal bis Titel zusammenschieben, dann ENTERn"; cin.ignore(); // evtl. vorhandene Daten in cin ignorieren cin.get(); // Auf Enter-Taste als Eingabe warten */ // Film abspielen for (int i = 0; i < images.size(); i++) { // Aktuelles Bild ausgeben for (int j = 0; j < images[i].size(); j++) { cout << images[i][j] << endl; } // Ausführung für Animationsdauer anhalten this_thread::sleep_for( chrono::milliseconds(250) ); } cout << "\nTHE END\n"; return 0; }