Dateiformat für Mapfiles und andere Spielinhalte

SQL, Dateimanagement - Sprachunabhängige Datenhaltung
Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Dateiformat für Mapfiles und andere Spielinhalte

Beitrag von Glocke » Mi Jan 16, 2013 9:56 pm

Hallo, in einigen anderen Threads hatte ich bereits davon erzählt: ich bastle (hauptsächlich um Neues zu lernen) an einem Framework (mit C++ und SDL) für 2D-Spiele mit isometrischer Darstellung (Diablo 2, Command & Conquer Tiberian Sun usw.).

Dabei brauche ich eine Art Dateiformat für Mapfiles (welche Kachel wo liegt usw.), Tilesets (welche Teile welcher Kacheln sind begehbar usw.) und "Entities". Unter Entities subsummiere ich alles was auf der Karte kreucht und fleucht: Skelette, Panzer, Feuerbälle, und was man sich alles überlegen kann.

Weil es so schön einfach ist einen Parser dafür zu schreiben - und weil die Art Dateien extrem einfach von Hand zu bearbeiten sind - verwende ich bisher INI-Files (wer die nicht mehr kennt: http://de.wikipedia.org/wiki/Initialisi ... tei#Aufbau)

Zum Beispiel folgendes Tileset:
dungeon.ini

Code: Alles auswählen

[init]
height=128
width=64
rows=5
cols=10

[block]
; row #1
0=0,0,0,0|0,0,0,0|0,0,0,0|0,0,0,0 ; plain
1=0,0,0,0|0,0,0,0|0,0,0,0|0,0,0,0 ; plain
2=1,1,1,1|1,1,1,1|1,1,1,1|1,1,1,0 ; nw wall
3=1,1,1,1|1,1,1,1|1,1,1,1|0,1,1,1 ; ne wall
4=1,0,0,0|1,1,0,0|1,1,0,0|1,0,0,0 ; outer w wall
5=0,0,0,1|0,0,1,1|0,0,1,1|0,0,0,1 ; outer e wall
6=1,1,1,1|0,1,1,0|0,0,0,0|0,0,0,0 ; outer n wall
7=1,1,1,1|1,1,1,1|1,0,0,1|0,0,0,0 ; inner n wall
;8=,,,|,,,|,,,|,,,
;9=,,,|,,,|,,,|,,,
; row #2
;10=,,,|,,,|,,,|,,,
;11=,,,|,,,|,,,|,,,
12=0,0,0,0|1,0,0,0|1,1,0,0|1,1,1,0 ; sw wall
13=0,0,0,0|0,0,0,1|0,0,1,1|0,1,1,1 ; se wall
14=1,1,1,0|1,1,0,0|1,1,0,0|1,1,1,0 ; inner w wall
15=0,1,1,1|0,0,1,1|0,0,1,1|0,1,1,1 ; inner e wall
16=0,0,0,0|1,0,0,1|1,1,1,1|1,1,1,1 ; inner s wall
17=0,0,0,0|0,0,0,0|0,1,1,0|1,1,1,1 ; outer s wall
;=17,,,|,,,|,,,|,,,
;=18,,,|,,,|,,,|,,,
;=19,,,|,,,|,,,|,,,
; row #3
;=20,,,|,,,|,,,|,,,
;=21,,,|,,,|,,,|,,,
;=22,,,|,,,|,,,|,,,
;=23,,,|,,,|,,,|,,,
;=24,,,|,,,|,,,|,,,
;=25,,,|,,,|,,,|,,,
;=26,,,|,,,|,,,|,,,
;=27,,,|,,,|,,,|,,,
;=28,,,|,,,|,,,|,,,
;=29,,,|,,,|,,,|,,,
; row #4
;=30,,,|,,,|,,,|,,,
;=31,,,|,,,|,,,|,,,
;=32,,,|,,,|,,,|,,,
;=33,,,|,,,|,,,|,,,
;=34,,,|,,,|,,,|,,,
;=35,,,|,,,|,,,|,,,
;=36,,,|,,,|,,,|,,,
;=37,,,|,,,|,,,|,,,
;=38,,,|,,,|,,,|,,,
;=39,,,|,,,|,,,|,,,
; row #5
;=40,,,|,,,|,,,|,,,
;=41,,,|,,,|,,,|,,,
;=42,,,|,,,|,,,|,,,
;=43,,,|,,,|,,,|,,,
;=44,,,|,,,|,,,|,,,
;=45,,,|,,,|,,,|,,,
;=46,,,|,,,|,,,|,,,
;=47,,,|,,,|,,,|,,,
;=48,,,|,,,|,,,|,,,
;=49,,,|,,,|,,,|,,,
Dazu gehört eine Grafik mit mehreren Tiles, die ich anhand der Tilegröße und ihrer Indices (sowie etwas div und modulo ^^) rausschneiden und blitten kann.

Oder auch folgende Mapfile:
demo.ini

Code: Alles auswählen

[init]
tileset=dungeon
width=10
height=7

[tiles]
floor=0,0,0,0,0,0,0,0,0,0|0,0,0,0,0,0,0,0,0,0|0,0,0,0,0,0,0,0,0,0|0,0,0,0,0,0,0,0,0,0|0,0,0,0,0,0,0,0,0,0|0,0,0,0,0,0,0,0,0,0|0,0,0,0,0,0,0,0,0,0
wall=,,,,,,,,,|,,,,,,,,,|,,,,,,,,,|,,,,,,,,,|,,,,,,,,,|,,,,,,,,,|,,,,,,,,,

[entities]
4,5=skeleton
Dabei unterscheide ich Boden-Kacheln (floor) und Wand-Kacheln (wall). Und auf Position (4,5) steht ein Skelett, das durch folgende Datei beschrieben wird:

skeleton.ini

Code: Alles auswählen

[init]
width=128
height=128
default=stand
gfx=stand,move;,die
sfx=die

[collision]
width=1
height=1
mask=1

[stand]
duration=6
length=4

[move]
duration=3
length=8
speed=13
Ich will jetzt nicht jedes Detail der Dateien erklären - ist denke ich auch gar nicht notwendig.
Beim Laden einer Entity bekommt der Konstruktor den Dateinamen der Konfiguration, lädt diese erstmal und verpasst den Membervariablen dann den entsprechenden Wert.

Was haltet ihr von dieser Art der Datenhaltung? Sicherlich wird der ein oder andere mir zu XML raten. Wie wird es aber bei den "großen" Spielen (ich denke dabei an die MPQ-Dateien von Diablo2 oder die BIG-Dateien von C&C) gemacht? Soweit ich das überblicke, stecken da ja die Grafiken und Sounds mit drinnen, und sicher auch Konfigurationen :) Allein die Struktur der Daten finde ich schon hässlich:

Code: Alles auswählen

data\
    entity\
        skeleton\
            config.ini
            die.ogg
            move.ogg
            move.png
            stand.png
        fireball\
            config.ini
            die.ogg
            move.png
            stand.png
    map\
        demo.ini
        foobar.ini
    music\
        theme.ogg
    tiles\
        dungeon.ini
        dungeon.png
        forest.ini
        forest.png
    widget\
        button\
            config.ini
            frameset.png
        checkbox\
            config.ini
            frameset.png
Ich weiß nicht so richtig, ob ich das so lassen sollte oder doch anders aufbaue (nicht nur die Ordnerstruktur ^^)

LG Glocke :)

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3123
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Dateiformat für Mapfiles und andere Spielinhalte

Beitrag von cloidnerux » Mi Jan 16, 2013 10:20 pm

Viele Programme nutzen zip-Archive, die sie dann umbenennen, also statt *.zip iwas wie *.cmf für "custom map file" oder was auch immer.
Dann wäre XML eine Option, wenn deine Maps größer werden kann man auch über binäre Datenspeicherung nachdenken, also ein int als int speichern und nicht als Text und du bildest dann einfach nur deine Datenstrukturen in der Datei nach. So wird es in der Regel für 3D-Modelle gemacht, weil bei mehreren Tausenden Punkten und Linien würde das mit Text nen leichten overheap bekommen.
Redundanz macht wiederholen unnötig.
quod erat expectandum

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: Dateiformat für Mapfiles und andere Spielinhalte

Beitrag von Glocke » Sa Jan 19, 2013 10:01 am

cloidnerux hat geschrieben:Viele Programme nutzen zip-Archive, die sie dann umbenennen, also statt *.zip iwas wie *.cmf für "custom map file" oder was auch immer.
Die Idee kam mir auch schon. Das wäre für viele kleine Dateien sicher hilfreich.
cloidnerux hat geschrieben:Dann wäre XML eine Option, wenn deine Maps größer werden kann man auch über binäre Datenspeicherung nachdenken, also ein int als int speichern und nicht als Text und du bildest dann einfach nur deine Datenstrukturen in der Datei nach.
Ich denke darauf wird es sicherlich hinauslaufen was die maps angeht.

Prinzipiell könnte man auch Bilder (via SDL mit SDL_RWops) in eine Binärdatei schreiben. Nur weiß ich noch nicht, wie ich so eine Datei sinnvoll aufbaue. Effektiv brauche ich ja eine Art "Inhaltsverzeichnis", so nach dem Motto "Bild 1 ist x Bytes lang, Bild 2 y Bytes lang", damit ich dann die Bilder rauslesen kann. Sehe ich das richtig?

LG Glocke

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Dateiformat für Mapfiles und andere Spielinhalte

Beitrag von Xin » Sa Jan 19, 2013 12:06 pm

Glocke hat geschrieben:Prinzipiell könnte man auch Bilder (via SDL mit SDL_RWops) in eine Binärdatei schreiben. Nur weiß ich noch nicht, wie ich so eine Datei sinnvoll aufbaue. Effektiv brauche ich ja eine Art "Inhaltsverzeichnis", so nach dem Motto "Bild 1 ist x Bytes lang, Bild 2 y Bytes lang", damit ich dann die Bilder rauslesen kann. Sehe ich das richtig?
Ich hatte mit Yoghurt kürzlich eine längere Aktion wegen serialisieren in Deiner Netzwerkfrage. Das Problem ist identisch: Du musst die Daten serialisieren. Du kannst Strukturen 1:1 wegschreiben - solange keine Zeiger enthalten sind.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: Dateiformat für Mapfiles und andere Spielinhalte

Beitrag von Glocke » Sa Jan 19, 2013 12:30 pm

Okay, ist der Ansatz mit diesem "Inhaltsverzeichnis" (nach wie vielen Bytes was zu finden ist und wie viele Bytes das lang ist) sinnvoll?

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Dateiformat für Mapfiles und andere Spielinhalte

Beitrag von Xin » Sa Jan 19, 2013 1:21 pm

Glocke hat geschrieben:Okay, ist der Ansatz mit diesem "Inhaltsverzeichnis" (nach wie vielen Bytes was zu finden ist und wie viele Bytes das lang ist) sinnvoll?
Gibt verschiedene Möglichkeiten. Inhaltsverzeichnisse sind eine Möglichkeit, häufig finden sich sogenannte Chunks. Das Format selbst hat also keine geordnete Struktur, man findet einen Chunk-Identifier. Chunk-Identifier können beispielsweise ein Int sein, was quasi vier Buchstaben sein könnten. Zum Beispiel "MAP-" und hinter jedem Chunk die Größe des Chunks. Interessiert Dich "MAP-" nicht, springst Du einfach die entsprechenden Bytes weiter.
Hinter Map erwartest Du zuerst eine Struktur, die Breite und Höhe angibt: 2 ints. Danach folgen Breite mal Höhe Informationen mit dem Spielfeld.

Ein recht bekanntes Chunk-Format ist IFF. Von Microsoft kopiert, wurde u.a. WAVE draus. Chunk-Formate sind in der Regel Containerformate, das heißt, Du kannst reinpacken, was Du willst. Grafik, Ton, Text... Wenn Du mit einem Grafikprogramm eine Ton-Datei liest, überspringt das Programm einfach die Chunks, die es nicht versteht: Den Ton zum Beispiel.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: Dateiformat für Mapfiles und andere Spielinhalte

Beitrag von Glocke » Mi Jan 23, 2013 8:56 am

Ich habe jetzt einige Zeit herum überlegt und werde erst einmal die Variante fahren, dass ich meine Struktur von INI- und Bild-Dateien weiterfahre, aber den Vorschlag mit den "umbenannten Zip-Archiven" (s.o.) umsetze.

Dazu habe ich noch eine Frage: Gehen wir mal davon aus, dass sich bei mir eine Masse von Kartenobjekten ansammelt. Darunter diverse Skelett-Arten (Skelettkrieger, Skelettmagier usw.) die als Gegner dienen sollen. Nun verwenden sie gemeinsam den gleichen Soundeffekt bei der Bewegung (z.B. ein knochiges Klappern). Prinzipiell gibt es ja zwei Möglichkeiten:
  • Jedes Skelett-Archiv (das Frames und Konfiguration enthält) bekommt den Soundeffekt dazu. Damit besteht zwar ein gewisses Maß an Redundanz, jedes Skelett an sich ist aber individuell modifizierbar (z.B. könnte beim Skelettkrieger noch ein Rüstungsklappern bei der Bewegung dazukommen, welches beim ~magier nicht nötig ist).
  • Alle "gemeinsam" genutzen Sounds werden in einem separaten Archiv gesammelt, so dass die Skelette gemeinsam auf ein und die gleiche Datei zugreifen können. Hier fällt klar die Redudanz weg (ist ja prinzipiell auch nicht nötig) und der Skelett-Bewegungs-Sound lässt sich an einer Stelle (im SFX-Archiv) ersetzen, so dass alle Skelette den gleichen Sound haben.
Die erstere Variante würde ich bisher bevorzugen. Da ist für mich klar, "was das Skelett alles beinhaltet" (Frames, Sounds, Konfiguration). Außerdem kann ich die Sounds dann individuell auf die genauen Objekte anpassen (und muss keinen Einheitssound für alle Skelette verwenden). Dagegen spricht die Redundanz. Allerdings frage ich mich, ob es bei einem Bewegungssound, der im OGG-Format vielleicht 10-15kb groß ist, so wichtig ist, dass man die Sounds zentral sammelt.
Was sagt ihr dazu?

LG Glocke

Benutzeravatar
Yoghurt
Beiträge: 79
Registriert: Fr Nov 16, 2012 8:01 am
Wohnort: Niederbayern

Re: Dateiformat für Mapfiles und andere Spielinhalte

Beitrag von Yoghurt » Mi Jan 23, 2013 9:30 am

Also ich würde alle Sounds zusammen packen und die verschiedenen Einheiten über eine andere Datei definieren, wo nur so Sachen wie
  • verwendete Sounds
  • verwendete Grafiken
  • Eigenschaften (Lebenspunkte, Schaden, Level, etc.)
festgelegt sind.
Vielleicht sogar als kleines Skript-File.

Dann hast du deine Assets beisammen und kannst die wirklichen Spielobjekte individuell gestalten. Eventuell lohnt es sich da sogar einen kleinen Editor zu schreiben, mit dem du die Objekte erstellen/ändern kannst und der dir die oben genannten Dateien(/Skripte) erstellt.
"Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why."

Glocke
Beiträge: 332
Registriert: Fr Okt 26, 2012 8:39 am

Re: Dateiformat für Mapfiles und andere Spielinhalte

Beitrag von Glocke » Mi Jan 23, 2013 9:46 am

Yoghurt hat geschrieben:Eventuell lohnt es sich da sogar einen kleinen Editor zu schreiben, mit dem du die Objekte erstellen/ändern kannst und der dir die oben genannten Dateien(/Skripte) erstellt.
Über so einen Editor habe ich auch schon nachgedacht :) Wenn ich das doch mit Binärdateien mache (Konfiguration, Bilder und Sounds in eine Binärdatei gespeichert), würde sich ein Editor vermutlich richtig lohnen.
Yoghurt hat geschrieben:Also ich würde alle Sounds zusammen packen und die verschiedenen Einheiten über eine andere Datei definieren.
Alle Einheiten in eine Datei zu packen erscheint mir etwas ... keine Ahnung :D
Ich hab da vor Augen, ich will später eine weitere Einheit hinzufügen und muss dann dir große Einheiten-Datei laden, das Zeug anfügen und so :lol:
Wenn alle Einheiten in einer Datei wären, würde sich das aber für die Sounds in einer separaten Datei anbieten, da gebe ich dir recht 8-)

LG Glocke

Benutzeravatar
Yoghurt
Beiträge: 79
Registriert: Fr Nov 16, 2012 8:01 am
Wohnort: Niederbayern

Re: Dateiformat für Mapfiles und andere Spielinhalte

Beitrag von Yoghurt » Mi Jan 23, 2013 10:33 am

Glocke hat geschrieben:
Yoghurt hat geschrieben:Eventuell lohnt es sich da sogar einen kleinen Editor zu schreiben, mit dem du die Objekte erstellen/ändern kannst und der dir die oben genannten Dateien(/Skripte) erstellt.
Über so einen Editor habe ich auch schon nachgedacht :) Wenn ich das doch mit Binärdateien mache (Konfiguration, Bilder und Sounds in eine Binärdatei gespeichert), würde sich ein Editor vermutlich richtig lohnen.
Ich denke das lohnt sich genau so für Archive oder sonst was (zumindest ab einem mittelgroßen Projekt), weil du dann nicht mehr die Dateien bearbeiten musst sondern das schön im Editor (nicht im Texteditor :P ) machen kannst. :)
Glocke hat geschrieben:
Yoghurt hat geschrieben:Also ich würde alle Sounds zusammen packen und die verschiedenen Einheiten über eine andere Datei definieren.
Alle Einheiten in eine Datei zu packen erscheint mir etwas ... keine Ahnung :D
Ich hab da vor Augen, ich will später eine weitere Einheit hinzufügen und muss dann dir große Einheiten-Datei laden, das Zeug anfügen und so :lol:
Wenn alle Einheiten in einer Datei wären, würde sich das aber für die Sounds in einer separaten Datei anbieten, da gebe ich dir recht 8-)
Ich glaube du hast mich etwas missverstanden. :D
Was ich meinte ist, dass du die Assets bündeln sollst. Zum Beispiel alle Einheiten-Sounds zusammen oder wenns sowieso nicht so viele Sounds sind, alle Sounds in ein Archiv.

Die Einheiten natürlich alle in einer seperaten Datei definieren, wie ich bei meinem letzten Post schon beschrieben habe.
Dann hättest du zum Beispiel zwei Dateien "skeleton_warrior.dat" und "skeleton_mage.dat". Darin sind dann die Eigenschaften der beiden Einheiten und die verwendeten Sounds definiert.
Willst du eine neue Einheit brauchst du nur eine neue Datei "skeleton_berserk.dat" erstellen und kannst darin die neue Einheit definieren und natürlich auch die Assets die schon da sind verwenden. So hast du nichts redundant gespeichert.
"Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why."

Antworten