Assignment Chef icon Assignment Chef
All German tutorials

Programming lesson

Spielkarten-Layouts in Demolition Man: Eine Einführung in die Map-Verarbeitung mit C++

Lerne, wie du in C++ Spielkarten für das Arcade-Spiel Demolition Man parseen, validieren und rendern kannst – mit praktischen Beispielen und modernen Trends.

Demolition Man Spielkarte C++ Map-Layout ArcadeRetro Assignment3 Software Engineering 265 Map-Validierung C++ Spieleentwicklung C++ KI-generierte Maps Trend Bomb Guy C++ 2D-Array C++ Spielkarten parsen config.json C++ nlohmann json Pathfinding A* C++ Game Development Studium C++ Objektorientierung Map-Datei einlesen

Einführung in die Map-Verarbeitung für ArcadeRetro

In der aktuellen Assignment3 für Software Engineering 265 entwickelst du für ArcadeRetro das Spiel Demolition Man. Du steuerst Bomb Guy durch ein Gitter aus 13 Zeilen und 15 Spalten, wobei jede Zelle 32×32 Pixel groß ist. Die Karten werden in Textdateien als mehrdimensionale Zeichen-Arrays gespeichert. In diesem Tutorial lernst du, wie du solche Karten in C++ einliest, auf Gültigkeit prüfst und für das Spiel aufbereitest – ganz ohne die komplette Lösung zu verraten.

Warum Map-Layouts heute wichtig sind

Ähnlich wie bei Minecraft oder Fortnite, wo prozedural generierte Welten den Spielspaß ausmachen, basiert auch Demolition Man auf klar definierten Karten. Der Trend zu KI-generierten Inhalten (z. B. in Roblox oder Unity) zeigt, wie wichtig strukturierte Datenformate sind. Dein Code muss flexibel sein, um verschiedene Map-Designs zu unterstützen – ein Muss für jedes moderne Game-Development-Projekt.

Die Map-Datei verstehen

Eine gültige Map hat einen umlaufenden Rand, eine Startposition für Bomb Guy (dargestellt durch 'P') und ein Ziel ('G'). Andere Zeichen wie 'E' für Gegner oder 'W' für Wände sind möglich. Die Map wird als Textdatei gespeichert, z. B.:

WWWWWWWWWWWWWWW
W.....P.......W
W....E........W
W.............W
W........G....W
WWWWWWWWWWWWWWW

In diesem Beispiel ist die erste und letzte Zeile komplett aus 'W' (Wand), und 'P' und 'G' sind platziert. Deine Aufgabe ist es, solche Dateien zu parsen und die Daten in einer geeigneten Datenstruktur zu speichern.

Schritt 1: Die Konfiguration aus config.json laden

Der Dateipfad zur Map steht in der Datei config.json. Du kannst eine Bibliothek wie nlohmann/json verwenden, um JSON in C++ zu parsen. Ein Beispiel:

#include <nlohmann/json.hpp>
#include <fstream>

std::string getMapPath() {
    std::ifstream configFile("config.json");
    nlohmann::json config;
    configFile >> config;
    return config["path"];
}

Beachte: Der Pfad könnte relativ zum Arbeitsverzeichnis sein. Teste mit verschiedenen Pfaden, um sicherzustellen, dass dein Programm flexibel ist.

Schritt 2: Die Map-Datei einlesen

Die Map ist ein 2D-Array von Zeichen. Du kannst sie zeilenweise einlesen und in einem std::vector<std::string> speichern. Achte darauf, dass die Zeilen konsistent lang sind (15 Zeichen plus Newline). Ein einfacher Ansatz:

#include <vector>
#include <string>
#include <fstream>

std::vector<std::string> readMap(const std::string& path) {
    std::ifstream file(path);
    std::vector<std::string> map;
    std::string line;
    while (std::getline(file, line)) {
        map.push_back(line);
    }
    return map;
}

Vergiss nicht, auf Fehler zu prüfen: Datei existiert? Zeilenlänge korrekt?

Schritt 3: Validierung der Map

Nicht alle Maps sind gültig. Du solltest folgende Checks implementieren:

  • Randprüfung: Die erste und letzte Zeile sowie die erste und letzte Spalte jeder Zeile müssen 'W' sein.
  • Start- und Zielpräsenz: Genau ein 'P' und ein 'G' müssen vorhanden sein.
  • Größenprüfung: Die Map muss 13 Zeilen und 15 Spalten haben (ohne Newline).

Ein Beispiel für eine Randprüfung:

bool isValidBorder(const std::vector<std::string>& map) {
    if (map.size() != 13) return false;
    for (int i = 0; i < 13; ++i) {
        if (map[i].size() != 15) return false;
        if (i == 0 || i == 12) {
            for (char c : map[i]) if (c != 'W') return false;
        } else {
            if (map[i][0] != 'W' || map[i][14] != 'W') return false;
        }
    }
    return true;
}

Teste auch mit ungültigen Maps, um sicherzustellen, dass dein Code robust reagiert (z. B. Exception werfen oder Fehlermeldung ausgeben).

Schritt 4: Speicherung in einer Spielstruktur

Statt nur Zeichen zu speichern, kannst du eine Klasse Tile definieren, die den Typ (Wand, Weg, Start, Ziel, Gegner) und ggf. eine Textur-ID enthält. Das erleichtert die spätere grafische Darstellung. Beispiel:

enum class TileType { WALL, EMPTY, START, GOAL, ENEMY };

struct Tile {
    TileType type;
    bool walkable;
};

class GameMap {
private:
    std::vector<std::vector<Tile>> grid;
public:
    bool loadFromFile(const std::string& path);
    Tile getTile(int row, int col) const;
};

Diese objektorientierte Herangehensweise ist typisch für moderne Spieleentwicklung – ähnlich wie bei Unity oder Unreal Engine, wo jedes Spielelement ein Objekt ist.

Schritt 5: Integration mit der Spielschleife

Nach dem Laden der Map muss Bomb Guy die Karte erkunden können. Du könntest eine Pathfinding-Klasse (z. B. A*) implementieren, um den kürzesten Weg zum Ziel zu finden – ein häufiges Feature in KI-gesteuerten Gegnern (wie in Pac-Man oder Among Us). Achte darauf, dass Bomb Guy nur durch leere Felder (inkl. Start und Ziel) gehen kann, nicht durch Wände.

Trend-Beispiel: Wie KI Maps generiert

In Spielen wie No Man's Sky oder Diablo IV werden Karten algorithmisch erzeugt. Dein statischer Map-Parser ist der erste Schritt, um später prozedurale Generierung zu verstehen. Stell dir vor, du müsstest eine Map mit zufälligen Wänden und Gegnern füllen – das Prinzip bleibt gleich: Du liest Zeichen aus einer Datei oder generierst sie.

Häufige Fehler vermeiden

  • Zeilenumbruch: Unter Windows kann \r\n vorkommen. Entferne \r mit line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());.
  • Leerzeichen: Manche Map-Dateien enthalten Leerzeichen. Behandle sie als ungültig oder ignoriere sie.
  • Dateipfad: Verwende relative Pfade ausgehend vom Ausführungsverzeichnis. Teste mit verschiedenen Ordnern.

Fazit

Mit diesen Grundlagen kannst du die Map für Demolition Man laden, validieren und in einer flexiblen Datenstruktur speichern. Der nächste Schritt ist die grafische Darstellung mit SFML oder SDL – aber das ist ein Thema für ein weiteres Tutorial. Denk daran: Gute Spieleentwicklung beginnt mit soliden Datenstrukturen und robuster Fehlerbehandlung. Viel Erfolg bei deiner Assignment3!