JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.php?sid=044c2c75526120d67c7c6a1278e01a3dMedaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Wie man Dateiformate aufbaut

 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Tutorials
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Jonathan_Klein
Living Legend


Alter: 36
Anmeldedatum: 17.02.2003
Beiträge: 3431
Wohnort: Siegerland
Medaillen: Keine

BeitragVerfasst am: 01.03.2007, 18:18    Titel: Wie man Dateiformate aufbaut Antworten mit Zitat

Es gibt sicherlich Menschen, die mehr Ahnung von Dateien haben als ich.
Daher ist das auch kein richtiges Tutorial, eher eine Sammlung hoffentlich wertvoller Hinweise. ich werde mich bemühen alles gut zu begründen, was der Leser dann macht, ist sein Problem Smile
Das größte Problem bei Dateien ist, dass man sie nur laden kann, wenn man ihre genaue Struktur kennt. Außerdem muss man sie genauso laden, wie man sie geschrieben hat. Auf der Festplatte sind nur Bytes, der Programmierer muss diese interpretieren. Dadurch können einfach Fehler entstehen.


Vor dem Laden: Löschen!
Man stelle sich vor, man hat eine Liste von Adressen. Lädt man jetzt eine Datei und hängt jede Adresse an die Liste an, wird man schnell merken, dass die alten noch da sind.
Daher muss vor dem Laden ALLES zurückgesetzt werden.



Binär- oder Textdatei?
Tja, eigentlich ist das gar kein richtiger Unterschied. Denn beide sind im Prinzip gleich. Im Prinzip nur eine Ansammlung von Bytes. Wenn man Textdateien lädt bekommt man das Ergebnis eben in Form eines Strings und geht meist Zeilenweise vor. Es werden also Zeichen wie "NeueZeile" direkt interpretiert, eben um zum Beispiel genau eine Zeile zu laden.
Man kann also auch eine Datei im Binärmodus schreiben und damit eine gültige Textdatei erzeugen.
So gesehen sind Textdateien genau wie Bilddateien nur ein Untertyp von Binärdateien, allerdings gibt es wohl kaum etwas einfacheres als Textdateien.

Damit muss man also unterscheiden, ob man alle Werte als String oder so wie sie im Rechner liegen abspeichern möchte. In Textdateien muss man wohl alles als String speichern, oder man bekommt nur lustige Zeichen.
Nun muss man bei Textdateien aber alle Zahlen in Strings umwandeln um sie zu speichern und zum laden wieder zurückkonvertieren. Das kostet Rechenzeit. Und im Binärformat wären sie obendrein kleiner.
Der Vorteil ist natürlich, dass man alles direkt als Textdatei im Notepad bearbeiten kann. Z.B. ini-Dateien kann man so recht einfach benutzen oder halt XML.
Will man jedoch komplexe Daten speichern und auch einen Editor dazu entwickeln, sollte man eine Binärdatei nutzen. Diese ist einfach schneller und kleiner. Auch wenn XML-Dateien sehr flexibel sein können, bin ich mit einfachen Binärdateien bis her sehr gut zurecht gekommen. Es kommt letztendlich darauf an, einen Aufbau zu finden, der alles kann was man braucht.


Größe speichern
Man muss sehr oft die Größe mitspeichern. Hat man z.B. eine Adressliste, in der jede Adresse mehrere Telefonnummern haben kann stößt man schnell auf ein Problem. Man kann nicht einfach die Adresse laden, sondern muss die unterschiedliche Anzahl von Telefonnummern berücksichtigen. Dazu muss man VOR den Telefonnummern deren Anzahl schreiben, weil eof bei dieser Aufgabe einfach nur versagt (da nach den x-Nummern ja neue Adressen kommen könnten).
Eigentlich sehr einfach.


Signatur
Es ist gut ganz am Anfang der Datei einen Wert zu schreiben, mit dem man Überprüfen kann, was es für eine Datei ist. Das kann man entweder als String oder als Zahl machen. Je größer dieser Wert ist, desto besser, denn so kann es nicht zufällig eine andere Datei sein. Allerdings ist man sich ja in den meisten Fällen seiner Sache sicher, also ist das jedem selber überlassen, wie hoch die Gefahr ist, eine andere Datei zu laden.
Bitmaps (*.bmp) z.B. haben ganz am Anfang immer ein "BM" in der Datei stehen. Das sind immerhin 16bit, soo zufällig können die nicht diesen Wert annehmen, es sei den jemand benutzt die selbe Signatur...
Die Signatur dient eigentlich nur dazu, das Laden abzubrechen. Den wenn man eine falsche Datei öffnet, wird der Ladealgorithmus praktisch immer Fehlschlagen und oft das Programm abstürzen lassen.


Versionsnummern
Ich würde jedem raten, an Anfang einer Datei, direkt hinter die Signatur, eine Versionsnummer zu schreiben. Denn wenn man das Format erweitert, wird man alte Dateien nicht mehr gebrauchen können. Den zum laden muss man ja den genauen Aufbau kennen. Die Lösung mit der Versionsnummer ist folgende:
Man lässt den alten Ladealgorithmus bestehen und schreibt "daneben" einen neuen. Nun kann man Anhand der Versionsnummer entscheiden, welche genutzt werden soll (switch oder ähnliches). Werte, die im alten Format noch nicht gespeichert wurden, wird man auf Standardwerte setzen müssen, Werte die nicht mehr benötigt werden wird man löschen müssen.
Natürlich muss man abschätzen in wie weit das Sinn macht. Manche alten Dateien sind einfach nicht mehr zu gebrauchen, nicht nur wegen ihrer Struktur sondern weil fundamental Dinge fehlen. Aber mit Versionsnummern hat man wenigstens die Chance einen Fehler auszugeben.


Header
Header sind quasi Köpfe die die wichtigsten Informationen der Datei speichern. Ein Header ist meistens eine Struktur, die immer dne selben Aufbau hat. Z.B. würde man die Signatur und die Versionsnummer in den Header aufnehmen. In Bilddateien steht dann meistens noch die Größe und Farbtiefe, d.h. Informationen wie die folgenden Daten zu interpretieren sind. In einem Savegameheader könnte z.B. das aktuelle Level stehen, und hinter dem Header nur noch die Position von Spieler und Gegner, sowie welche Gegenstände aufgesammelt wurden.


Chunks
Auch wenn sich das Wort sehr komisch anhört (dt. Brocken...). Chunks sind ein sehr cooles System. Im Prinzip teilt man die Datei in mehrere kleinere Dateien auf.
In einem Spiel hat man ja oft Dinge wie das Level, den Spieler, die Gegner, die Gegenstände usw. Jeder dieser Typen bekommt einen eigenen Chunk. Jeder Chunk hat einen Header, der dessen Typ und dessen Größe angibt. Zusätzlich können natürlich noch mehr Informationen darin stehen, z.B. die Versionsnummer (die Signatur ist im Prinzip der Typ).
Beim Laden geht man jetzt folgendermaßen vor: Man lädt den Chunk Header, und je nach Typ (ein Fall für switch) lädt man diesen dann. In einem default-Zweig kann dank der Größenangabe der komplette Chunk übersprungen werden (z.B. mit fseekf, falls man FILEs benutzt).
Das System ist deshalb so gut, weil man beliebig Informationen hinzufügen oder weglassen kann. Hat man z.B. keine Gegenstände mehr im Level liegen kann man diesen Chunk beim Speichern weglassen. Da beim Laden die Chunkreihenfolge egal ist, gibt es auch keine Probleme, wenn ein Chunk nicht existiert. Da ja vorher alle Gegenstände gelöscht wurden funktioniert also alles perfekt.
Bei dem Laden sollte man darauf achten, das genau so viel geladen wurde, wie der Chunk groß sein soll. Das ist dann schon mal ein guter Hinweis, dass das Laden einigermaßen geklappt hat.
Um fürs Speichern die Chunk-Größe zu bestimmen, Kann man sich im Prinzip alle Schreibbefehle anschauen und deren Größe zusammenrechnen. Hat man eine Adresse mit 7 Telefonnummern, braucht man 4 byte für den Integer der die Anzahl angibt, und 7 mal 10 Byte (wenn die Telefonnummer als 10 chars gespeichert wird). Das ganze ist nicht ganz einfach aber dennoch machbar. Und die Vorteile sollten für den Aufwand wirklich entschädigen.


Problembehandlung
Wenn nach dem Speichern und anschließenden Laden nichts mehr wie vorher ist, ist entweder der Speicher oder der Ladealgorithmus kaputt. Dumm nur, dass man diese recht schwer debuggen kann. Hat man ein Chunk-System kann man natürlich Chunk für Chunk testen. Man kann auch wenn man möchte immer wieder Kontrollwerte Schreiben. z.B. nach einer kompletten Adresse "ende der Adresse" (als String speichern, den man weiß, je länger der Wert, desto unwahrscheinlicher ist, dass er zufällig entsteht). Damit kann man kontrollieren, wie viele Adressen korrekt geladen werden konnten. So kann man sich Stück für Stück vortasten.




So, dass war es fürs erste, sind ja eigentlich nur ein paar Techniken und Hinweise. Wenn noch was unklar ist, kann ich ja manches noch näher erläutern, wenn jemand noch mehr Ideen hat, kann er sie mir ja sagen^^.
_________________
https://jonathank.de/games/
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Tutorials Alle Zeiten sind GMT
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de

Impressum