Format de fichier extensible personnalisé pour les cartes en mosaïque 2D


8

J'ai implémenté une grande partie de ma logique de jeu en ce moment, mais je crée toujours mes cartes avec de mauvaises boucles for-on à la volée pour pouvoir travailler avec quelque chose. Maintenant, je voulais continuer et faire des recherches sur la façon de (dé) sérialiser ces données. (Je ne recherche pas d'éditeur de carte - je parle du fichier de carte lui-même)

Pour l'instant, je recherche des suggestions et des ressources, comment implémenter un format de fichier personnalisé pour mes cartes qui devrait fournir les fonctionnalités suivantes (basées sur la méthode MoSCoW):

  • Doit avoir
    • Extensibilité et compatibilité descendante
    • Manipulation de différentes couches
    • Métadonnées indiquant si une tuile est solide ou peut être traversée
    • Sérialisation spéciale d'entités / déclencheurs avec propriétés / métadonnées associées
  • Pourrais avoir
    • Une sorte d'inclusion de l'ensemble de tuiles pour éviter d'avoir des fichiers / ensembles de tuiles dispersés

Je développe avec C ++ (en utilisant SDL) et je cible uniquement Windows. Toute aide utile, astuces, suggestions, ... serait appréciée!


Résultat de la discussion ci-dessous

J'ai conçu mon format de fichier de carte ces dernières heures et j'ai trouvé un squelette (ne contient que des couches pour l'instant - je laisse le reste à tout le monde qui conçoit son propre format) que je voulais partager avec toutes les personnes intéressées - si vous avez les mêmes intentions que vous pouvez obtenir une sorte d'inspiration. La capture d'écran en taille réelle peut être téléchargée sur Imgur .

Format de fichier de carte Kore


2
XML est un format formidable pour commencer, son extensible, rétrocompatible, vous pouvez ajouter toutes les informations et métadonnées que vous souhaitez. Il existe un large support pour la lecture, la création et l'édition XML. La prise en charge de la sérialisation vers et depuis XML existe pour à peu près toutes les langues. L'inconvénient est qu'il est assez peu efficace en espace, cela peut être amélioré en utilisant une version binaire ou en utilisant la compression zip sur le fichier lui-même. Néanmoins, c'est un bon point de départ pour créer vos propres formats de fichiers
Daniel Carlsson

@DanielCarlsson: Comme mentionné dans la réponse acceptée ci-dessous, je vais m'en tenir au XML au début pour avoir quelque chose de pratique à déboguer et à travailler avec. Plus tard, je passerai à un format binaire personnalisé. Néanmoins voté parce que XML est génial en combinaison avec les bibliothèques RapidXML en C ++.
Christian Ivicevic

Réponses:


6

Personnellement, je suis plus fan des formats binaires avec des sections (comme Windows PE, juste beaucoup plus simple). Ils sont également plus faciles à analyser (mais c'est juste mon opinion ... J'ai suffisamment travaillé avec XML pour me donner des maux de tête, vérifier si getElementByName a retourné une seule valeur ou une liste de valeurs ... ugh). Donc, si j'étais vous, je ferais quelque chose comme ça:

".MMF\0" // magic value at the start, null-terminated string. stands for My Map Format :)
    char header_length // useful when parsing. char is a byte, of course, an unsigned one
    char version // version of the map file. (you don't really need ints here, because you probably won't be needing more than 255 versions for example, but you can also use them)
    char* map_name // null terminated string describing the name of the level/map
    char* author_name // if you are going to have a map editor for the general public, it would be nice to credit the person who made the map
    int width // it's probably wise to plan ahead and expect an int here when you're parsing the file
    int height
    ".layer\0" // we begin another subsection
        char header_length
        char type // type of the layer. for example, you can put 1 there if you want this to be a layer describing different tiles/block in a Terraria like game
        ".data\0" // yet another subsection. this will hold the data for the tiles
                  // in a hypothetical terraria 2d game, you would lay down tiles from
                  // the top-right corner (0,0) and then begin writing row after row
                  // write(1,0); write(2,0); write(3,0); ... then write(0,1); write(1,1);
                  // write(2,1); write(3,1); and so on..
            char t1 // tile at (0,0). for example, value 0 is empty, or passable tile
            char t2 // tile at (1,0). this might be a dirt block - value 1
            char t3 // tile at (2,0). a rock, perhaps? value 3
            (...)
            char tn // tile at (width-1, height-1) or the bottom-left tile
    ".layer\0" // another layer.
        char header_length    
        char type // let this on be of value 2, and let it describe portals.
                  // putting portals in a game makes it instantly 20% cooler
        ".data\0"
            char t1  // 0, no portal here at tile (0,0)
            char t2  // still nothing
            char t3  // nope, try again
            (...)
            char t47 // at some location, you made a red portal. let's put 1 here so we can read it in our engine
            (...)
            char t86 // looke here, another 1! you can exit here from location corresponding to t47
            (...)
            char t99 // value 2. hm, a green portal?
            (...)
            char tn  // bottom-left tile, at (width-1, height-1)
    ".layer\0" // another layer
        char header_length
        char type // value 3, player&enemies spawn points
        char something // you don't have to have header len fixed. you can add stuff later
                       // and because you were smart enough to put header length 
                       // older versions can know where the stuff of interest lays
                       // i.e. version one of the parser can read only the type of layer
                       // in version two, you add more meta-data  and the old parser
                       // just skips it, and goes straight to the .data section
            ".data\0"
                char t1  // zero
                char t2  // zero
                char t3  // zero
                (...)
                char t42 // a 1 - maybe the player spawn point. 5 tiles to the right
                         // there's a red portal
                (...)
                char t77 // a 2: some enemy spawn point
                (...)
                char tn  // last tile

,

Avantages:

  • Ça a l'air cool.
  • Vous fait penser que vous savez quelque chose sur la programmation, faire des choses à l'ancienne.
  • Vous pouvez écrire manuellement vos niveaux dans un éditeur hexadécimal:
  • Généralement plus rapide que les INI et les XML, tant du point de vue de l'écriture que de la lecture
  • C'est vraiment un long flux de données d'octets. Pas besoin de passer du temps à le rendre joli, indenté (comme ce que vous voudriez faire avec XML).
  • Il est facile d'ajouter des éléments dans les en-têtes. Si un élément de données apparaît en bas de l'en-tête, les anciennes versions des analyseurs peuvent être invitées à l'éviter et à accéder à la partie du fichier qu'elles comprennent.

Désavantages:

  • Vous devez prendre bien soin du placement des données.
    • Les champs de données doivent être commandés.
    • Vous devez connaître leur type dans l'analyseur - comme je l'ai dit, c'est juste un long flux d'octets.
    • Déplacer des données d'un emplacement (par exemple, vous oubliez d'écrire le type de la couche; l'analyseur attend un octet là et il trouve la valeur de '.' - ce n'est pas bon) gâche tout le tableau de données à partir de ce point.
  • Plus difficile à franchir - il n'y a pas d'API, pas de fonction comme getLayerWidth () - vous devez implémenter tout cela vous-même.
  • Il y a potentiellement beaucoup d'espace perdu. Prenez la troisième couche par exemple. Il sera certainement rempli de nombreux zéros. Cela peut être contourné si vous utilisez une sorte de compression. Mais encore une fois, cela dérange encore une fois avec des trucs de bas niveau ...

Mais la meilleure chose dans cette approche à mon avis est - vous pouvez tout faire par vous-même. Beaucoup d'essais et d'erreurs, mais à la fin, vous finissez par apprendre beaucoup.


Vous enregistrez simplement ... disons les ID des tuiles, mais qu'en est-il de leurs métadonnées? Comment dois-je économiser si les carreaux sont passables ou non? Qu'en est-il des déclencheurs et peut-être même des scripts / appels de code / fonction qui leur sont associés?
Christian Ivicevic

@ChristianIvicevic: Il y a plusieurs façons de le faire:
Vladimir Mitrovic

@ChristianIvicevic: 1. Emballez les métadonnées dans un seul octet. Vous n'avez que huit tuiles possibles? Génial, conservez les cinq autres bits pour autre chose. Dans votre cas, vous avez posé des questions sur les carreaux passables. Vous pouvez avoir le premier bit (0e bit) stocker ces informations. Un peu de manipulation de bits :) fera l'affaire ( codepad.org/Q6zfTV44 ). 2. Utilisez des calques pour cela. Ayez une couche avec un type unique et remplissez-la de zéros et de uns, de uns pour passables et de zéros pour les carreaux infranchissables. 3. Utilisez plus d'un octet par tuile. Un octet pour la valeur, l'autre pour les métadonnées.
Vladimir Mitrovic

@ChristianIvicevic: En ce qui concerne les scripts, je suppose que vous avez implémenté un analyseur de script qui fonctionne. Vous pouvez ajouter une section à votre fichier de carte et les y placer: pastebin.com/yUKncz19 OU Vous pouvez les placer dans un fichier séparé et enregistrer un nom de fichier dans la section ".scripts". Vous ajoutez ensuite une autre section ".layer" décrivant les tuiles qui déclenchent quel script: pastebin.com/BgPCR2xQ
Vladimir Mitrovic

Beaucoup d'exemples - TOP! Maintenant, je vais m'en tenir à XML pour créer des niveaux de base pour déboguer / travailler et, finalement, je passerai au format binaire que vous avez décrit pour le fichier map brut contenant les données et emballer ce fichier avec les deux ensembles de tuiles (png, etc.) et le (s) fichier (s) de script dans un zip pour que tout soit mieux structuré. Ce sera à l'écriture de code, qui lit en fait de telles données binaires - mais c'est un autre sujet dans mon histoire ... merci!
Christian Ivicevic,

9

Vous pouvez utiliser le format de carte TMX utilisé par l' éditeur de tuiles (ainsi que plusieurs autres éditeurs de cartes).

Même si vous n'utilisez pas Tiled vous-même, le format TMX prend en charge toutes les fonctionnalités que vous avez mentionnées et il dispose de plusieurs chargeurs / analyseurs existants pour une variété de langues. Il est également très facile de comprendre le format et de l'étendre à votre propre jeu.


J'aurai mon concept XML actuel basé un peu sur le format de carte TMX, puis je lirai tous les fichiers avec RapidXML - plus tard, je passerai à un format de fichier binaire personnalisé.
Christian Ivicevic
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.