Wie kann man alle Bilder eines Spiels in eine Datei packen?

67

Ich habe gerade ein einfaches RPG-Spiel fertiggestellt, das in C ++ SFML geschrieben wurde, ich habe viel Mühe in das Spiel gesteckt und ich möchte es weitergeben, aber ich bin auf eine kleine Ausgabe gestoßen.

Das Problem ist, dass ich weit über 200 Bilder und Kartendateien (das sind TXT-Dateien, die Kartencodes enthalten) im selben Ordner wie die ausführbare Datei habe. Wenn ich in den Ordner schaue, möchte ich ein wenig weinen So viele Ressourcen, ich habe noch nie ein Spiel gesehen, in dem alle Ressourcen direkt angezeigt werden, stattdessen glaube ich, dass sie die Ressourcen in eine bestimmte Datei packen.

Nun, das ist, was ich versuche zu erreichen: Ich hoffe, alle Bilder in eine Datei zu packen (möglicherweise auch die TXT-Dateien) und dann in der Lage zu sein, diese Datei zu lesen oder einfach zu ergänzen.

Bugster
quelle
Ich habe Code gesehen, in dem alle Bilder in eine Zeichenfolge im Code gepackt wurden. Dies geschah jedoch aufgrund von Anforderungen. (Es war ein 64KB Java-Wettbewerb)
Omar Kooheji
Entschuldigung, es war ein 4Kb Java-Wettbewerb. Kein 64Kb großer.
Omar Kooheji

Antworten:

62

Spielprogrammierer haben sich auf eine von zwei Hauptmethoden der Datenspeicherung verlassen:

  • Speichern Sie jede Datendatei als separate Datei
  • Speichern Sie jede Datendatei in einem benutzerdefinierten Archivformat

Der Nachteil der ersten Lösung ist das Problem der Verschwendung von Speicherplatz sowie das Problem langsamerer Installationen.

Die zweite Lösung bietet ihre eigenen Fallstricke. Erstens müssen Sie Ihr ganzes Bild / Ton / etc. Schreiben. Laden von Routinen, die eine benutzerdefinierte API für den Zugriff auf die archivierten Daten verwenden. Ein weiterer Nachteil ist, dass Sie Ihr eigenes Archivierungsdienstprogramm schreiben müssen, um die Archive überhaupt zu erstellen.

Wenn Sie nicht immer alle Dateien aus dem Archiv laden, ist TAR / GZ möglicherweise keine gute Idee, da Sie bestimmte Dateien nicht bei Bedarf extrahieren können. Aus diesem Grund verwenden viele Spiele ZIP-Archive, mit denen Sie einzelne Dateien nach Bedarf extrahieren können (ein gutes Beispiel ist Quake 3, dessen PK3-Dateien nur ZIP-Dateien mit einer anderen Erweiterung sind).

BEARBEITEN: "Verstecke" die Ordnerstruktur des Spiels und "Behalte" nur die ausführbaren Dateien

Eine andere Lösung wird oft verwendet, um die Spieledateien in der Ordnerstruktur zu "verstecken". Behalten Sie nur Ihre ausführbaren Dateien und möglicherweise eine Readme-Datei im Hauptverzeichnis und verschieben Sie die Spieledateien in einen Unterordner mit dem Namen "data" oder in einen anderen zugehörigen Ordner.

EDIT: Gamedev Tuts Plus haben eine schöne Ressource

EDIT: libarchive

Eine mögliche Lösung ist libarchive, eine Archivierungsbibliothek, die das Extrahieren von Dateien aus einem Archiv wie einer ZIP-Datei übernimmt. Sie können die extrahierte Datei sogar einem Standard-FILE-Zeiger zuweisen, wodurch die Anbindung an andere Bibliotheken möglicherweise einfacher wird.

BEARBEITEN: ZIP-Format Dateien mit alternativer Erweiterung

Hier gefällt mir @Joachim Sauers Kommentar

Die Verwendung von ZIP-Dateien mit alternativen Erweiterungen hat auch außerhalb von Spielen eine große Tradition: Java , das OpenDocument-Format (auch bekannt als OpenOffice / LibreOffice-Format) und Office Open XML (auch bekannt als "neues" Microsoft Office-Format). macht es .

Mahbubur R Aaman
quelle
2
Ja, Thief / SystemShock2 hat .zip-Dateien verwendet und auch etwas anderes umbenannt. In Java können Sie so etwas wie TrueZip verwenden, um auf Dateien in ZIPs zuzugreifen, als wären sie Dateien in Ordnern. Ich stelle mir vor, es gibt ähnliche Bibliotheken für C ++.
Nick
18
Die Verwendung von ZIP-Dateien mit alternativen Erweiterungen hat auch außerhalb von Spielen eine große Tradition: Java , das OpenDocument-Format (auch bekannt als OpenOffice / LibreOffice-Format) und Office Open XML (auch bekannt als "neues" Microsoft Office-Format). tut es , ...
Joachim Sauer
5
@Svish. Abhängig von der Plattform kann der von vielen kleinen Dateien belegte Speicherplatz erheblich größer sein als der von einer großen Datei belegte Speicherplatz, selbst wenn diese große Datei überhaupt nicht komprimiert ist ( .tarz. B.). Dies hängt damit zusammen, wie Daten physisch auf der Festplatte gespeichert werden.
TRiG
1
Ah, das stimmt. Sollte zwar nicht viel sein, es sei denn, es gibt viel , aber in diesem Fall kann es in der Tat aufbauen. Ich kann mir vorstellen, dass die Installation und Deinstallation auch bei vielen kleinen Dateien einen Hit macht.
Svish
2
In geringem Zusammenhang mit Kylotans Kommentar finden Sie hier einen Beitrag von Jonathan Blow im Dev-Blog von The Witness über die Verwendung von Archiven und deren Interaktion mit dem Patching-Mechanismus von Steam. "The Witness packt die meisten seiner Daten in eine einzelne 2-Gigabyte-Datei, die im ZIP-Format gespeichert ist. Vor dem Hochladen der ursprünglichen Version auf Steam habe ich mich sicher gestellt, um die Patch-Größe zu minimieren, oder so dachte ich [...] (Imagine die dateien werden in zufälliger reihenfolge gespeichert: wahrscheinlich muss jeder spieler bei jedem patch das ganze spiel neu herunterladen!) "
Eric
39

Eine andere Lösung, die häufig zum "Verstecken" der Spieledateien verwendet wird, ist die Ordnerstruktur. Behalten Sie nur Ihre ausführbaren Dateien und möglicherweise eine Infodatei im Hauptverzeichnis und verschieben Sie die Spieledateien in einen Unterordner "data". Ich denke nicht, dass es sehr ungewöhnlich ist, dies zu tun. Viele Spiele, die ich kenne, speichern ihren Inhalt so.

Tom van Green
quelle
8
+1 Wenn Speicherplatz oder Schutz kein Problem ist, ist dies die einfachste Lösung.
Laurent Couvidou
1
+1, weil der andere Typ +1 sagte. Kann doch nicht falsch sein, oder? (Scherz beiseite, tolle Antwort.)
Jcora
Dies ist meiner Meinung nach die ideale Wahl. Wenn das Dateisystem nicht effizient damit umgehen kann, ist das Dateisystem kaputt und Sie sollten sich auf den OS Maker stützen, um es zu verbessern.
Omnifarious
3
@Omnifarious Das ist nicht immer der Fall, zB beim Lesen von einer optischen Disk, selbst bei einem perfekten Dateisystem, ist es üblich, Dateien in Ladereihenfolge zu packen, um übermäßiges Suchen zu verhindern (die Geschwindigkeit kann tatsächlich ziemlich überraschend sein). Aber das ist eine ganz andere Geschichte für Festplatten, und ich neige dazu, das OP in diesem Fall zu denken.
Laurent Couvidou
3
@ Mr.Beast Du hast meinen Standpunkt verpasst. Ich spreche von optischen Datenträgern. Ich habe für ein Studio gearbeitet, in dem ein einzelner Programmierer Vollzeitarbeit geleistet hat, um sicherzustellen, dass die Dateien so effizient wie möglich auf eine DVD gepackt werden, um die bestmögliche Ladezeit zu erzielen. Ich bin sicher, er wäre froh zu erfahren, dass er sich einfach auf das DVD-Dateisystem hätte verlassen können;)
Laurent Couvidou
22

Ich mag PhysFS wirklich dafür. Sie können mit demselben Code auf Ordner oder ZIP-Archive zugreifen. Es funktioniert gut für alle Phasen eines Spiellebens.

  1. Während der Entwicklung : Greifen Sie direkt über eine Ordnerhierarchie auf die Ressourcen zu. Auf diese Weise werden komprimierte Archive nicht behindert und Sie können schnell iterieren.
  2. Erstbereitstellung : Komprimieren Sie Ihre Ressourcen für eine einfache Bereitstellung / schnelle Installation. Es muss sich kein Code ändern. Zeigen Sie einfach mit PhysFS auf die Zip-Datei anstelle des Ordners.
  3. Updates / Modding : PhysFS kann mehrere Zip-Archive laden, bei denen die Ressourcen eines den anderen überschreiben. Aktualisierungen können so einfach wie eine neue ZIP-Datei mit nur den geänderten Dateien sein. Ähnliches gilt für das Modden.

aktualisieren:

Ich habe das mit der Quelle gelieferte Tutorial und die Doxygen-Dokumentation verwendet , um PhysFS zu lernen. Die API ist wirklich recht einfach. Sie werden mehr Zeit damit verbringen, das Laden von Bildern in SFML über Speicherpuffer anstatt über den Dateipfad zu erlernen.

deft_code
quelle
4
Ich benutze PhysFS für mein aktuelles Projekt und ich liebe es. Ich muss meine Inhaltsarchivdatei nicht immer neu generieren. Ich kann einfach eine aktualisierte Version in den Suchpfad und die BAM einfügen! Es klappt.
Zack The Human
Nach einigen Antworten habe ich mich für physFS entschieden. Würden Sie gerne ein nettes Tutorial empfehlen? :)
Bugster
12

Ich würde vorschlagen, eine ZIP-Datei zu verwenden. Es ist ein allgegenwärtiges Format und es gibt vorgefertigte Bibliotheken, mit denen Sie Dateien aus einer ZIP-Datei laden können. Eine schnelle Google-Suche ergab sogar einen Zip-Loader für sfml .

Blödmann
quelle
3

Nun, Sie könnten schummeln, wie sie es erwähnt haben :) Sie können aus den Bildern ein Sprite-Sheet erstellen. Es ist heutzutage nicht mehr nötig, es zu zippen, es sei denn, es spart eine Menge Platz. Nachdem Sie ein Sprite-Sheet oder mehrere Sprite-Sheets aus den Bildern erstellt haben, können Sie deren Erweiterungen einfach umbenennen. Die meisten Spieler werden sich nicht die Mühe machen, dies zu überprüfen. Überlassen Sie diese Option den Künstlern, die Ihr Spiel in Zukunft möglicherweise modifizieren möchten. Auf diese Weise können sie auch ein Sprite-Sheet erstellen, dessen Erweiterung umbenennen und loslegen.

Mit den Textdateien würde ich demütig vorschlagen, dass Sie diese Daten in binäre Form konvertieren. Ich bin mir ziemlich sicher, dass Sie einen einfachen Weg finden werden, dies zu tun. Wenn Sie beispielsweise nur AZ, az und 0-9 verwenden, können Sie 6 Bits verwenden, um jedes Zeichen darzustellen, das Ihr urheberrechtlich geschütztes Material in gewisser Weise schützt verhindert auch, dass andere Karten bearbeiten. Sie können jederzeit einen Karten-Konverter hinzufügen, wenn Sie möchten. Das Komprimieren von Texten ist jedoch völlig in Ordnung.

wolfdawn
quelle
Die Konvertierung in eine Binärdatei ist ein guter Rat, aber kein Schutz. Sie wird einfacher zu analysieren und schneller zu laden sein. Ich würde es als Vorverarbeitungsschritt vorschlagen, aber das wird für die Frage nicht zum Thema.
Maximus Minimus
Nun, ich vermute, wenn er es effektiver schützen möchte, könnte er versuchen, es in RSA oder einem ähnlichen Algorithmus zu verschlüsseln (es besteht keine Notwendigkeit). Ich bezweifle, dass jemand die Map-Dateien eines Indie-Spiels unbefugt verwenden wird, wenn sie sich in einer Binärdatei befinden. Es scheint einfach nicht wert zu sein, die Zeit in das Analysieren zu investieren. Textdateien sind einfach völlig anfällig und, wie Sie vorgeschlagen haben, unwirksam für das Speichern von Daten.
Wolfdawn
3
Auf Festplatten ist das Laden einer einzelnen Zip-Datei schneller als das Laden vieler kleiner Dateien, da die physische Festplatte kostengünstiger nach dem Zufallsprinzip durchsucht wird. Eine Binärdatei für ein kleines Spiel kann in den Speicher gemappt werden und "magisch" funktionieren, fast ohne dass ein Parsing erforderlich ist.
Liosan
@Liosan Du hättest falsch interpretieren können, was ich meinte, oder ich habe dich falsch verstanden. Ich sagte, dass Binärdateien besser zum Speichern von Daten geeignet sind und dass andere Spieleentwickler wahrscheinlich nicht lernen möchten, wie man einen binären Kartencode parst, es sei denn, er ist dokumentiert und für Modifikationen empfohlen Zwecke. Daher bietet es einen rudimentären Schutz gegenüber Textdateien.
Wolfdawn
2

Es geht nicht nur um die Anzahl der Ressourcen oder den Speicherplatz.
Da Sie SFML verwenden, das mit OpenGL gerendert wird, muss OpenGL bei jedem Rendern einer Textur die nächste Textur an die Grafikkarte binden (überprüfen Sie glBindTexture ()) eine wirklich teure Aufgabe.
In diesem Sinne können Sie erkennen, warum Spiele in der Regel eine Reihe von Sprites in der gleichen Textur platzieren, die so genannten Spritesheets, entsprechend Ihren Menüs / Ebenen / Karten des Spiels.
Das Ergebnis ist ein enormer Leistungszuwachs, da Sie viele Sprites mit demselben Bind-Textur-Aufruf rendern.

Edmo Freitas
quelle
Nachdem ich einige Hinweise zum Erstellen eines Spritesheets erhalten hatte, habe ich einige Umgestaltungen in Betracht gezogen, um die Anzahl der Bilder zu verringern. Vielen Dank
Bugster
2

Ich persönlich würde die Route für benutzerdefinierte Binärdateien nach unten gehen. Dies ist etwas, das ich die ganze Zeit selbst mache, es ist nicht so schwierig, wie es sich anhört, und es bietet auch ein Maß an Verschleierung für Ihre Spielressourcendateien. Ich habe vor nicht allzu langer Zeit einen kleinen Einführungsartikel über dieses Spiel geschrieben:

http://gamedev.tutsplus.com/tutorials/implementation/create-custom-binary-file-formats-for-your-games-data/

Sprite-Sheets sind ein völlig anderes Thema, aber sie sind die Norm für die meisten Spiele :)

Si Robertson
quelle
1

Eine andere Methode, die Sie verwenden können:

Die kostenlose Version von XnView bietet eine Funktion namens " Strip of Images" (UMSCHALT + A), mit der Sie erstellen können sprite-collections.

Dies minimiert den Dateizugriff und ist besonders wichtig für Webanwendungen / Spiele, um die Anzahl der zu minimieren HTTP-roundtrips.

Der Zugriff auf einzelne Bilder erfolgt dann über Koordinatenkarten (z. B. CSS-Definitionen).

Lorenz Lo Sauer
quelle
0

Zuerst müssen Sie Ihr ganzes eigenes Bild / Ton / etc. schreiben. Laden von Routinen, die eine benutzerdefinierte API für den Zugriff auf die archivierten Daten verwenden. Ein weiterer Nachteil ist, dass Sie Ihr eigenes Archivierungsdienstprogramm schreiben müssen, um die Archive überhaupt zu erstellen. Wenn Sie nicht immer alle Dateien aus dem Archiv laden, ist TAR / GZ möglicherweise keine gute Idee, da Sie bestimmte Dateien nicht bei Bedarf extrahieren können. Aus diesem Grund verwenden viele Spiele ZIP-Archive, mit denen Sie einzelne Dateien nach Bedarf extrahieren können (ein gutes Beispiel ist Quake 3, dessen PK3-Dateien nur ZIP-Dateien mit einer anderen Erweiterung sind). http://zpp-library.sourceforge.net/


quelle