Ergebnis 1 bis 11 von 11

Thema: -

  1. #1

    -

    -

    Geändert von Owly (03.01.2012 um 20:52 Uhr)

  2. #2
    Das einzige, was gegen eine andere Programmiersprache als Mapeditor spricht, ist a) die fehlende Interoperabilitaet der verwendeten Sprachen und b) dass es eventuell ganz nett sein kann, wenn man InGame Editieren kann.

    a) Beim Schreiben von Dateien und uebergabe von Werten nach aussen stellen sich manche Programmiersprachen recht umstaendlich an (ich denke da z.B. an Fortran zu C Schnittstellen - gruslig). Bei C# zu C++ sollte das allerdings kein Problem sein, zumal du ein Textbasiertes Mapformat verwenden willst.

    b) Was mich z.B. beim Maker schon immer gestoert hat, ist, dass man innerhalb des Spiels nicht bestimmte Dinge editieren kann. Man spielt das Spiel, sieht einen Fehler, beendet das Spiel, editiert, startet das Spiel neu, spielt zu der selben Stelle und sieht nach, ob der Fehler behoben ist. Effektiver waere es ggf, wenn Spiel und Editor in ein und dem selben Programm stecken. Man baut die Maps und Events sozusagen, waehrend man sich darauf befindet, bzw wechselt auf Tastendruck zwischen den beiden Modi. Spiele ich das Spiel normal und sehe, dass ein Objekt unerreichbar ist, schwupps kann ich es korrigieren und einfach weiter spielen. Sehe ich einen Bug in einem Script oder einen Typo in einer Messagebox, zack, sofoert korrigiert. Das funktioniert aber natuerlich nur, wenn der Editor in der selben Sprache wie das Spiel geschrieben ist (oder du musst mit DLLs arbeiten).

    Was die Frage bzgl. Text vs. XML angeht: XML ist grauenvoll !
    Ich hab mal ein Projekt gemacht, dass auf XML Basis gearbeitet hat und muss gestehen, dass ich das Format danach nie wieder angefasst habe. XML hat einen riesigen Overhead und ist vom Format her einfach total ueberladen. Einen XML Parser zu schreiben oder auch nur einen fertigen zu finden, der ALLE Features von XML implementiert, war damals ein Ding der Unmoeglichkeit. Das System ist weder besser menschenlesbar, als ein ordentliches Plain-Text-Format, noch ist es besser maschinenlesbar. Zudem ist es durch sein starres Format sehr fehleranfaellig, was tippfehler etc angeht und beschissen zu editieren, vor allem bei groesseren Dateien.

    Ich wuerde ja zu einem ordentlich dokumentierten Binaerformat raten, in dem die entsprechenden Mapdaten nativ abgelegt sind. Ist interoperabilitaet zwischen verschiedenen Architekturen ein Problem, dann wuerde ich einfach ein Tool schreiben, dass die Binaerdaten in ein austauschfaehiges menschenlesbares Textformat umwandelt (ggf mit zlib komprimiert), welches man auf der anderen Architektur einfach wieder in deren natives Binaerformat uebersetzt. Das ist nicht nur am schnellsten, sondern auch am speichersparendsten. Und als weiterer Bonus: du brauchst keinen aufwaendigen Parser zu schreiben.

  3. #3
    Mal nur zum Dateiformat: auf keinen Fall XML für die Layerdaten. Zumindest nicht so, wie du es oben beschreibst. Mit <tile sourcex="wert" sourcey="wert"></tile> hast du pro Tile ca. 40 Bytes Overhead nur für die XML Struktur (ohne Einrückungen). Nimm dafür lieber ein Binärformat, in dem einfach nacheinander die Tiledaten als short oder int abgelegt sind. Die Reihenfolge kannst du ja als gegeben annehmen, wenn nur deine eigenen Programme mit dem Format arbeiten. Damit braucht eine 20x15 Tiles große Map grade noch 600 bzw. 1200 Bytes statt ca. 13 kB. Das ist immerhin um einen Faktor 10 bis 20 kleiner und bei großen Maps rechnet sich das. Außerdem ist es wesentlich leichter einzulesen. Lukis Argument mit der Plattformabhängigkeit versteh ich jetzt nicht so ganz. Unterschiedliche Größen von Datentypen sind unwichtig, weil du beim Lesen aus Dateien auch einfach die Anzahl der zu lesenden Bytes angeben kannst und für unterschiedliche Endigkeiten gibt es auch eine recht einfache Methode. Schreibe an den Anfang der Dateien zwei bekannte Bytes, etwa 0xFF00 und mache dann folgendes:

    Code (C):
     
    // ...
    short temp;
    bool must_swap;
    fread(&temp, 2, 1, file);
    if(temp != 0xFF00)
    {
        must_swap = true;
    }
    //...
     
    for(i = 0; i < num_tiles; i++)
    {
        fread(&tiles[i], 1, 4, file);
        if(must_swap)
        {
            tiles[i] = SWAP_SHORT(tiles[i]); // Oder wie auch immer du das Makro nennst
        }
    }


    Dann musst du nichtmal beim Schreiben auf die Endigkeit achten, nur beim Lesen. Alternativ kannst du auch alles grundsätzlich in Network Byte Order speichern. Funktionen zum Umwandeln sind htonl/ntohl, htons/ntohs, etc. liegen aber je nach Betriebssystem in unterschiedlichen Headern.

    Geändert von DFYX (30.07.2010 um 19:59 Uhr)

  4. #4
    Da hat DFYX natuerlich recht, dass man das so "schoen" machen kann.

    Ich bezog mich eigentlich eher darauf, dass du als binaerformat in den Maps direkte Dumps von Speicherbloecken etc verwenden kannst. Und da gibt es zwischen den Architekturen mehr Unterschiede als nur Endigkeit und Wordbreite, sondern auch noch so sachen wir Alignment oder Column vs. Row Ordering.

    Die Textzwischenformatmethode ist fuer sowas geeignet und erfordert nur primitive Grundkenntnisse.

  5. #5
    Wir hatten ja mal so ein Projekt hier im Forum; das ist zwar nach kurzer Zeit gescheitert, aber man kann's ja trotzdem anmerken.

    Bei uns wurden Maps zu komplex erachtet, um sie in einer einzigen Datei anzugeben. Statt dessen war jede Map ein Zip-Archiv, das in etwa Folgendes beinhaltete:

    - Eine Reihe von Tilesets
    - Eine Reihe von Layern, die als PNG-Bilder gespeichert waren. Jedes Tile wurde als ein Pixel repräsentiert; der (8-bit-)Farbwert war dann der Index auf das entsprechende Tileset
    - Eine Datei, die definiert, welche Layer in welcher Reihenfolge vorkommen, welche Eigenschaften die Layer haben, welches Tileset sie verwenden und wo die Events sind
    - Events/Skripte jeweils als einzelne Dateien

    PNG wurde gewählt, weil es ein geeignetes, effizientes Binärformat war, für das man vorgefertigte Bibliotheken verwenden konnte. Man könnte statt dessen natürlich auch ein einfaches Textformat benutzen, beispielsweise etwas in der Art von PGM.


    Ein anderer Ansatz wäre vielleicht der, den DoomRL für Usermaps nimmt: Usermaps sind da einfach Lua-Skripte. Du definierst erst, welche Arten von Tiles durch welche Zeichen dargestellt werden und gibt dann den Level in ASCII art an. Das Ganze sieht dann in etwa so aus.

    Der Vorteil ist, daß du so ein halbwegs menschenlesbares Format hast und auch noch die Skripte zusammen mit der Map gespeichert kriegst. Außerdem kannst du beliebiges Verhalten in die Map einbauen, sofern die API es zuläßt. Der Nachteil ist, daß die Datei mit mehreren Layern schnell unübersichtlich werden dürfte und daß die Anzahl der möglichen Tiles durch die Anzahl der druckbaren Zeichen beschränkt ist. Falls du auf Unicode setzt, kriegst du zwar mehr Zeichen, als du je brauchen wirst, aber die Datei wird auch entsprechend größer.


    Menschenles- und editierbare Formate haben immer den Nachteil, anderswo suboptimal zu sein. Du mußt halt sehen, ob dir eine einfache Implementierung oder kleine Mapdateien wichtiger sind als Menschenlesbarkeit.

    Auf jeden Fall solltest du von XML wegbleiben. Das Format ist wirklich grausam und du tust dir keinen Gefallen damit, wenn du es verwendest.


    Oh, und was die Programmiersprache angeht: Ich würde es zumindest so drehen, daß du die Spielengine im Editor zur Anzeige verwenden kannst. Wenn du zwei verschiedene Engines benutzt, kriegst du nur lustige Bugs, wo die Engines die Map nicht identisch rendern und der User im Editor raten muß, wie es später im Spiel aussieht.

  6. #6
    Zitat Zitat von Owly Beitrag anzeigen
    Und...was bedeutet Endigkeit?
    Endigkeit beschreibt, in welcher Reihenfolge die einzelnen Bytes in größeren Datentypen vorliegen. Nehmen wir einen 32bittigen Integer mit dem Wert 255. Liegt der jetzt im Speicher als 00 00 00 FF oder als FF 00 00 00?

    Es gibt nur zwei sinnvolle Möglichkeiten: Das Byte mit dem kleinsten Wert komt am Anfang (großendig oder big-endian) oder der Byte mit dem kleinsten Wert kommt am Ende (kleinendig oder little-endian). Was der Fall ist, hängt in der Regel von der Prozessorarchitektur ab. Die Endigkeit explizit in der Datei festzuhalten hat den Vorteil, daß die Handhabung der Datei zwischen Plattformen vereinfacht wird.


    Zitat Zitat
    Der DoomRL Weg sieht ziemlich herkömmlich aus, abgesehen davon, dass normalerweise statt ASCII- Zeichen die Koordinaten auf dem Spritesheet angegeben sind. Übersehe ich einen besonderen Kniff?
    Naja, DoomRL ist ein Roguelike; die Maps werden später im Spiel genau so angezeigt. Allerdings hat das Format zwei Vorteile:
    • Die Map ist ein Skript. Damit hast du bereits Skripte und Layer zusamengebracht, weil du die Events etc. einfach als Unterfunktionen implementieren kannst.
    • Eine Darstellung des Layers als ASCII art ist mehr oder weniger menschenlesbar; Binärdateien sind das nicht.

    Es gibt noch andere Formate, die ähnlich vorgehen; das X Pixmap-Format funktioniert beispielsweise ähnlich (jeder Farbe wird ein Zeichen zugewiesen und dann macht mal mit diesen Zeichen ASCII art).


    Zitat Zitat
    Gibt es zu dem alten Projekt noch einen Thread/Aufzeichnungen/etc.? Die Überlegungen dazu würden mich sehr interessieren.
    Such' mal im Forum nach "Yaldabaoth". Leider wurde der Großteil der Planung in einem mittlerweile verschollenen eigenen Forum gemacht.

    Geändert von Jesus_666 (31.07.2010 um 21:57 Uhr)

  7. #7
    Zitat Zitat von Owly Beitrag anzeigen
    (Übrigens, meine Unerfahrenheit erschlägt mich nahezu. Ein dreidimensionales Array mit 3x160x60 Tiles zu initialisieren ist offenbar ungesund für den Stack. Ist da malloc oder ein Vector der Weg, den man gehen sollte?)
    Eindeutig malloc bzw. falls du mit C++ arbeitest new. Das reserviert Speicher auf dem Heap statt auf dem Stack und Heap hat man üblicherweise wesentlich mehr. Von der Vector-Klasse würde ich in dem Fall dringend abraten. Die ist für Listen, deren Größe sich häufig ändert. Das Hinzufügen und Löschen von Elementen geht (je nach Implementierung) wesentlich schneller als bei Arrays, dafür ist der Zugriff langsamer und es wird mehr Platz gebraucht.

    Den Rest hat dir Jeez ja schon erklärt. Wenn du noch so unerfahren bist, empfehle ich dir, erstmal etwas kleiner anzufangen und dir möglichst ein paar Bücher durchzulesen. Für C und C++ empfehle ich "C von A bis Z" bzw. "C++ von A bis Z" von Jürgen Wolf. Ersteres gibt es als kostenloses Openbook auf www.galileocomputing.com und letzteres im Buchhandel. Für ein grundlegendes Verständnis von Algorithmen und der Abwägung von Platz vs. Geschwindigkeit habe ich mit "Algorithms and Data Structures: The Basic Toolbox" von Peter Sanders (dessen Vorlesung zu dem Thema ich genießen durfte) und Kurt Mehlhorn empfehlen. In der Zwischenzeit existiert auch eine deutsche Übersetzung und mit etwas Glück findest du die PDF (legal) im Netz. Die zugehörigen Vorlesungsfolien und Übungsblätter samt Musterlösungen findest du auf der Vorlesungswebsite zum kostenlosen Download.

  8. #8
    Zitat Zitat von DFYX Beitrag anzeigen
    Von der Vector-Klasse würde ich in dem Fall dringend abraten. Die ist für Listen, deren Größe sich häufig ändert. Das Hinzufügen und Löschen von Elementen geht (je nach Implementierung) wesentlich schneller als bei Arrays, dafür ist der Zugriff langsamer und es wird mehr Platz gebraucht.
    std::vector???


    Owly: Nach Möglichkeit/Bedarf solltest du dein Dateiformat flexibel gestalten. Flexibilität heißt hier Erweiterbarkeit ohne Kompatibilitätsverlust. Ein guter Start wäre, wenn du dich am IFF, oder seinen Derivaten orientierst.

  9. #9
    Zitat Zitat von Kyuu Beitrag anzeigen
    std::vector???
    Ja, std::vector. Wobei ich in dem Moment davon ausgegangen bin, dass der als doppelt verkettete Liste implementiert sein kann. Allerdings ist wohl tatsächlich vorgeschrieben, dass es ein dynamisches Array sein muss. Dementsprechend ist der Geschwindigkeitsunterschied noch da. Da sich die Layergröße aber zur Laufzeit nicht ändert, ist ein Array fester Größe via malloc/new trotzdem noch die bessere Wahl.

  10. #10
    Zitat Zitat von DFYX Beitrag anzeigen
    Für C und C++ empfehle ich "C von A bis Z" bzw. "C++ von A bis Z" von Jürgen Wolf. Ersteres gibt es als kostenloses Openbook auf www.galileocomputing.com und letzteres im Buchhandel.
    Wobei ich finde, dass die verketteten Listen im Buch "C von A bis Z" sehr umständlich erklärt werden. Man wird da echt mit Quellcodes erschlagen, die dann alles doppelt und dreifach ausführen.

  11. #11
    Zitat Zitat von DFYX Beitrag anzeigen
    Allerdings ist wohl tatsächlich vorgeschrieben, dass es ein dynamisches Array sein muss. Dementsprechend ist der Geschwindigkeitsunterschied nicht da. Da sich die Layergröße aber zur Laufzeit nicht ändert, ist ein Array fester Größe via malloc/new trotzdem noch die bessere Wahl.
    Es gibt durchaus Gründe gegen std::vector, diesen würde ich aber wirklich nicht dazu zählen. Zum Beispiel ist ein Layer ein zweidimensionales Feld und da würde sich die eindimensionale Struktur von std::vector als unnötig unhandlich erweisen. Persönlich würde ich hier sowieso zu einer eigenen Layer-Klasse mit RAII raten.

    Owly: Ich kann dir den Rat geben, deinen Editor in einer Skriptsprache wie beispielsweise Python oder Lua zu schreiben. Das hat viele Vorteile, wie etwa erhöhte Produktivität, bessere Wartbarkeit und Erweiterbarkeit sowie Plattformunabhängigkeit. Außerdem solltest du dich auf ein Toolkit festlegen, das deinen Anforderungen am ehesten entspricht. Falls du beispielsweise vorhast deine Software für andere Plattformen anzubieten, würde ich von .NET schonmal die Finger lassen. Meine persönliche Empfehlung wäre die Kombination Lua + Qt. Lua ist cool und Qt ist großartig, ich glaube nicht, dass du damit irgendwas verlieren würdest. Für Qt gibt es sogar mehrere Anbindungen an Lua, sodass du sofort loslegen kannst.

    Geändert von Kyuu (03.08.2010 um 11:37 Uhr)

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •