Je développe un jeu de plateforme 2D avec des amis uni. Nous l'avons basé sur le kit de démarrage XNA Platformer qui utilise des fichiers .txt pour stocker la carte des tuiles. Bien que cela soit simple, cela ne nous donne pas assez de contrôle et de flexibilité avec la conception de niveau. Quelques exemples: pour plusieurs couches de contenu, plusieurs fichiers sont requis, chaque objet est fixé sur la grille, ne permet pas la rotation des objets, un nombre limité de caractères, etc. Je fais donc des recherches sur la façon de stocker les données de niveau et fichier de carte.
Cela ne concerne que le stockage du système de fichiers des cartes de tuiles, pas la structure de données à utiliser par le jeu pendant son exécution. La carte de tuiles est chargée dans un tableau 2D, donc cette question concerne la source à partir de laquelle remplir le tableau.
Raisonnement pour la base de données: De mon point de vue, je constate moins de redondance des données à l'aide d'une base de données pour stocker les données de tuiles. Les carreaux dans la même position x, y avec les mêmes caractéristiques peuvent être réutilisés d'un niveau à l'autre. Il semble qu'il serait assez simple d'écrire une méthode pour récupérer toutes les tuiles utilisées à un niveau particulier de la base de données.
Raisonnement pour JSON / XML: fichiers visuellement modifiables, les modifications peuvent être suivies via SVN beaucoup plus facilement. Mais le contenu est répété.
L'un ou l'autre présente-t-il des inconvénients (temps de chargement, temps d'accès, mémoire, etc.) par rapport à l'autre? Et qu'est-ce qui est couramment utilisé dans l'industrie?
Actuellement, le fichier ressemble à ceci:
....................
....................
....................
....................
....................
....................
....................
.........GGG........
.........###........
....................
....GGG.......GGG...
....###.......###...
....................
.1................X.
####################
1 - Point de départ du joueur, Sortie de niveau X,. - Espace vide, # - Plateforme, G - Gemme
Réponses:
Donc, en lisant votre question mise à jour, il semble que vous soyez plus préoccupé par les "données redondantes" sur le disque, avec quelques préoccupations secondaires concernant les temps de chargement et ce que l'industrie utilise.
Tout d'abord, pourquoi vous inquiétez-vous des données redondantes? Même pour un format gonflé comme XML, il serait assez trivial d'implémenter la compression et de réduire la taille de vos niveaux. Vous êtes plus susceptible de prendre de la place avec des textures ou des sons que vos données de niveau.
Deuxièmement, un format binaire va plus que probablement se charger plus rapidement qu'un format texte que vous devez analyser. Doublement donc si vous pouvez simplement le déposer en mémoire et avoir vos structures de données juste là. Cependant, il y a quelques inconvénients à cela. D'une part, les fichiers binaires sont presque impossibles à déboguer (en particulier pour les créateurs de contenu). Vous ne pouvez pas les différencier ou les versionner. Mais ils seront plus petits et se chargeront plus rapidement.
Ce que certains moteurs font (et ce que je considère comme une situation idéale) consiste à implémenter deux chemins de chargement. Pour le développement, vous utilisez un format texte quelconque. Peu importe le format spécifique que vous utilisez, tant que vous utilisez une bibliothèque solide. Pour la publication, vous passez au chargement d'une version binaire (plus petit, plus rapide, éventuellement dépourvu d'entités de débogage). Vos outils pour éditer les niveaux crachent les deux. C'est beaucoup plus de travail qu'un seul format de fichier, mais vous pouvez en quelque sorte tirer le meilleur parti des deux mondes.
Cela étant dit, je pense que vous sautez un peu le pistolet.
La première étape de ces problèmes est de toujours décrire le problème auquel vous vous heurtez. Si vous savez de quelles données vous avez besoin, vous savez quelles données vous devez stocker. De là, c'est une question d'optimisation testable.
Si vous avez un cas d'utilisation à tester, vous pouvez tester différentes méthodes de stockage / chargement de données pour mesurer tout ce que vous considérez comme important (temps de chargement, utilisation de la mémoire, taille du disque, etc.). Sans rien savoir, il est difficile d'être plus précis.
la source
Ma recommandation est d'utiliser un format de fichier binaire personnalisé. Avec mon jeu, j'ai juste une
SaveMap
méthode qui passe et enregistre chaque champ en utilisant aBinaryWriter
. Cela vous permet également de choisir de le compresser si vous le souhaitez et vous donne plus de contrôle sur la taille du fichier. Par exemple, enregistrez unshort
au lieu d'unint
si vous savez qu'il ne sera pas supérieur à 32767. Dans une grande boucle, enregistrer quelque chose en tant queshort
au lieu d'unint
peut signifier une taille de fichier beaucoup plus petite.De plus, si vous suivez cette voie, je recommande que votre première variable dans le fichier soit un numéro de version.
Prenons par exemple une classe de carte (très simplifiée):
Maintenant, supposons que vous vouliez ajouter une nouvelle propriété à votre carte, dire un
List
desPlatform
objets. J'ai choisi cela parce que c'est un peu plus impliqué.Tout d'abord, vous incrémentez le
MapVersion
et ajoutez leList
:Ensuite, mettez à jour la méthode de sauvegarde:
Ensuite, et c'est là que vous voyez vraiment l'avantage, mettez à jour la méthode de chargement:
Comme vous pouvez le voir, la
LoadMaps
méthode peut non seulement charger la dernière version de la carte, mais aussi des versions plus anciennes! Lorsqu'il charge les anciennes cartes, vous contrôlez les valeurs par défaut qu'il utilise.la source
Histoire courte
Une alternative intéressante à ce problème consiste à stocker vos niveaux dans une image bitmap, un pixel par tuile. En utilisant RGBA, cela permet facilement de stocker quatre dimensions différentes (calques, identifiants, rotation, teinte, etc.) sur une seule image.
Longue histoire
Cette question m'a rappelé quand Notch a diffusé en direct son entrée à Ludum Dare il y a quelques mois, et j'aimerais partager au cas où vous ne savez pas ce qu'il a fait. Je pensais que c'était vraiment intéressant.
Fondamentalement, il a utilisé des bitmaps pour stocker ses niveaux. Chaque pixel de la bitmap correspondait à une "tuile" dans le monde (pas vraiment une tuile dans son cas car il s'agissait d'un jeu diffusé en streaming mais assez proche). Un exemple d'un de ses niveaux:
Donc, si vous utilisez RGBA (8 bits par canal), vous pouvez utiliser chaque canal comme une couche différente, et jusqu'à 256 types de tuiles pour chacun d'eux. Serait-ce suffisant? Ou par exemple, l'un des canaux pourrait maintenir la rotation de la tuile comme vous l'avez mentionné. En outre, la création d'un éditeur de niveau pour travailler avec ce format devrait également être assez triviale.
Et le meilleur de tous, vous n'avez même pas besoin d'un processeur de contenu personnalisé car vous pouvez simplement le charger dans XNA comme tout autre Texture2D et lire les pixels en boucle.
IIRC, il a utilisé un point rouge pur sur la carte pour signaler un ennemi, et en fonction de la valeur du canal alpha pour ce pixel, il déterminerait le type de l'ennemi (par exemple, une valeur alpha de 255 pourrait être une chauve-souris tandis que 254 serait un zombie ou autre chose).
Une autre idée serait de subdiviser vos objets de jeu en ceux qui sont fixés dans une grille et ceux qui peuvent se déplacer "finement" entre les tuiles. Conservez les tuiles fixes dans le bitmap et les objets dynamiques dans une liste.
Il pourrait même y avoir un moyen de multiplexer encore plus d'informations dans ces 4 canaux. Si quelqu'un a une idée à ce sujet, faites-le moi savoir. :)
la source
Vous pourriez probablement vous en tirer avec presque n'importe quoi. Malheureusement, les ordinateurs modernes sont si rapides que cette quantité de données probablement relativement petite ne ferait pas vraiment de différence de temps notable, même si elle est stockée dans un format de données gonflé et mal construit qui nécessite une énorme quantité de traitement à lire.
Si vous voulez faire la "bonne" chose, vous faites un format binaire comme Drackir l'a suggéré, mais si vous faites un autre choix pour une raison stupide, il ne reviendra probablement pas et ne vous mordra pas (du moins pas en termes de performances).
la source
Voir cette question: «XML binaire» pour les données de jeu? J'opterais également pour JSON ou YAML ou même XML, mais cela a beaucoup de frais généraux. Quant à SQLite, je ne l'utiliserais jamais pour stocker des niveaux. Une base de données relationnelle est pratique si vous prévoyez de stocker beaucoup de données qui sont liées (par exemple, a des liens relationnels / clés étrangères) et si vous prévoyez de poser un grand nombre de requêtes différentes, le stockage de tilemaps ne semble pas faire ce genre de les choses et ajouterait une complexité inutile.
la source
Le problème fondamental de cette question est qu'elle confond deux concepts qui n'ont rien à voir l'un avec l'autre:
Vous pouvez stocker vos fichiers en texte brut dans un format arbitraire, JSON, script Lua, XML, un format binaire arbitraire, etc. Et rien de tout cela ne nécessitera que votre représentation en mémoire de ces données prenne une forme particulière.
C'est le travail de votre code de chargement de niveau de convertir le paradigme de stockage de fichiers en votre représentation en mémoire. Par exemple, vous dites: «Je constate moins de redondance des données à l'aide d'une base de données pour stocker les données de tuiles». Si vous voulez moins de redondance, c'est quelque chose que votre code de chargement de niveau devrait rechercher. C'est quelque chose que votre représentation en mémoire devrait être capable de gérer.
Ce n'est pas quelque chose dont votre format de fichier doit se préoccuper. Et voici pourquoi: ces fichiers doivent provenir de quelque part.
Soit vous allez les écrire à la main, soit vous allez utiliser une sorte d'outil qui crée et modifie les données de niveau. Si vous les écrivez à la main, la chose la plus importante dont vous avez besoin est un format facile à lire et à modifier. La redondance des données n'est pas quelque chose que votre format doit même prendre en compte, car vous passerez la plupart de votre temps à modifier les fichiers. Voulez-vous réellement utiliser manuellement les mécanismes que vous proposez pour assurer la redondance des données? Ne serait-il pas préférable d'utiliser votre temps pour que votre chargeur de niveau s'en occupe?
Si vous disposez d'un outil qui les crée, le format réel ne compte (au mieux) que pour la lisibilité. Vous pouvez mettre n'importe quoi dans ces fichiers. Si vous souhaitez omettre des données redondantes dans le fichier, concevez simplement un format qui peut le faire et faites en sorte que votre outil utilise correctement cette capacité. Votre format de tilemap peut inclure la compression RLE (encodage de longueur), la compression de duplication, quelles que soient les techniques de compression que vous souhaitez, car c'est votre format de tilemap.
Problème résolu.
Les bases de données relationnelles (RDB) existent pour résoudre le problème de l'exécution de recherches complexes sur de grands ensembles de données qui contiennent de nombreux champs de données. Le seul type de recherche que vous effectuez sur une carte de tuiles est «obtenir la tuile à la position X, Y». N'importe quel tableau peut gérer cela. L'utilisation d'une base de données relationnelle pour stocker et maintenir des données de tilemap serait extrêmement exagérée et ne vaut vraiment rien.
Même si vous intégrez une certaine compression dans votre représentation en mémoire, vous pourrez toujours battre facilement les RDB en termes de performances et d'encombrement de la mémoire. Oui, vous devrez réellement implémenter cette compression. Mais si la taille des données en mémoire est une préoccupation telle que vous envisagez un RDB, vous souhaiterez probablement implémenter des types spécifiques de compression. Vous serez plus rapide qu'un RDB et plus faible en mémoire en même temps.
la source
Pour des données vraiment simples, je choisirais probablement la voie XML, si vous êtes déjà familier avec le chargement et l'analyse XML.
la source