Tiled Map - Multiplayer Indie Game - Gether

Tiled Map - Multiplayer Indie Game - Gether

Die Spielwelt!

Nachdem wir den Charakter realisiert haben, der sich frei bewegen kann, benötigen wir noch irgendwas, was den schwarzen Hintergrund ersetzt. Ein Level, eine Map, eine Welt.

Für Gether benutzen wir tiled, den vermutlich bekanntesten 2D Level Editor. Tiled hat eine sehr einfach aufgebaute Oberfläche. Man muss nur ein Spritesheet mit allen Tiles hinzuzufügen um loszulegen.

Sehr simpler Spritesheet bestehend aus 3 Tiles.

Nachdem dieser von tiled geladen wurde, kann schon eine Map erstellt werden. Wenn man erst mal einigermaßen zufrieden ist, kann man anschließend die Map in vielen verschiedenen Formaten speichern oder exportieren. Unter anderem im CSV Format, welches vermutlich dass simpelste Format ist und das Format, mit welchem wir arbeiten werden.

Beispiel Map

Um eine Map im CSV Format zu exportieren, muss man unter tiled Datei -> Export -> Dateityp "CSV-Dateien (*.csv)" wählen.

Mit C++ eine Tiled Map laden

Jetzt haben wir eine CSV Datei, in welcher die Level Daten in einem einfachen Format vorliegen.

CSV Datei - Sieht wilder aus als es ist.

Jede Zahl repräsentiert ein Tile. Die Zahl -1 steht für "kein Tile". Die Tiles im Spritesheet werden der Reihenfolge nach nummeriert, angefangen oben links von 0 bis x.

Inhalt in einen String laden

Mit diesem Wissen lässt sich sehr einfach eine Methode realisieren, um diese Datei zu laden. Ich empfehle den kompletten Inhalt der Datei in einen String zu packen.

std::ifstream file("pfad/zur/map.csv");
std::string content((std::istreambuf_iterator<char>(file)), (std::istreambuf_iterator<char>()));

Zahlen parsen

Haben wir erst einmal den Inhalt in einem String, können wir durch jedes Zeichen iterieren und Zahlen zusammensetzen (wenn die Zahl > 9 ist).

std::string number = "";

for(int i = 0; i < content.length(); ++i)
{
// Ist es kein Komma und kein Zeilenumbruch?
if(content.at(i) != ',' && content.at(i) != '\n')
{
// Dann ist es eine Ziffer
number += content.at(i);
}
else
{
// Es war ein Komma oder ein Zeilenumbruch
// Also kommt jetzt die nächste Zahl (das nächste Tile)
number = "";
}
}

Container verwenden

Um alle Zahlen in einer Liste zu haben, nehmen wir einen STL Vector.

Vielleicht auch interessant
Der Charakter - Multiplayer Indie Game - Gether
Der Charakter - Multiplayer Indie Game - Gether

Weiter geht es mit dem Hauptcharakter für Gether.

std::vector<int> tiles;

// ...
// STOI => String to Integer
tiles.push_back(std::stoi(number));
number = "";

Jetzt müssen wir nur noch den Fall Zeilenumbruch beachten. Wenn nämlich ein Zeilenumbruch vorkommt, addieren wir später zur Y Koordinate eine Tilehöhe hinzu.

// ...
// Ist das aktuelle Zeichen ein Zeilenumbruch?
if(content.at(i) == '\n')
{
tiles.push_back(-2);
}

Die passenden Tiles laden

Nachdem wir nun alle tile IDs in einer Liste haben, können wir diese interpretieren, die sprites erstellen und anschließend positionieren.

int px = 0;
int py = 0;
int tileSize = 32;
	
for(auto it = tiles.begin(); it != tiles.end(); ++it)
{
if(*it != -1)
{
// ... Tile erstellen

if(*it != -2)
{
// Spritesheet Breite, nicht die Tile Breite!
int textureWidth = tile->getTexture()->getSize().x;

// Anzahl der Tiles in einer Reihe (im Spritesheet)
int tilesPerRow = std::floor(textureWidth / tileSize);
int index = (*it);
int row = 0;

// Ist die Tile ID in der ersten Reihe?
if(index+1 > tilesPerRow)
{
// Nein, also berechne den richtigen Index
// Beispiel: 5 Tiles pro Zeile im Spritesheet. Insgesamt 2 Reihen.
// Der gesuchte Index: 7
// 7 / 5 = 1,4 => abgerundet => 1
// 7 % 5 = 2
// = Reihe 1, das zweite Tile
row = std::floor(index / tilesPerRow);
index %= tilesPerRow;
}

tile->setTextureRect(sf::IntRect(index*tileSize, row*tileSize, tileSize, tileSize));
tile->setPosition(px, py);
m_objects.push_back(tile);

px += tileSize;
}
else
{
// Da -2 => neue Zeile
// X Koordinate wieder auf 0 setzen und auf Y Tilehöhe addieren
px = 0;
py += tileSize;
}
}
}
Nächster Artikel
Coop Modus - Multiplayer Indie Game - Gether
Hinterlasse gerne einen Like oder Kommentar (~‾▿‾)~
Name Text