Quel est un bon format de fichier plat pour stocker une carte de tuiles 2D qui peut croître à l'infini dans n'importe quelle direction?

9

Je crée un moteur de carte simple qui se développera automatiquement dans n'importe quelle direction avec du contenu généré de manière procédurale selon les besoins.

Quelle est la bonne façon de stocker des données cartographiques, ancrées à une origine 0,0 afin qu'un sous-ensemble rectangulaire de données cartographiques puisse être chargé rapidement et efficacement à partir de n'importe quel point de la carte?

J'ai une idée que je devrais peut-être fragmenter la carte en secteurs distincts, puis utiliser une sorte de format d'en-tête pour identifier où dans le fichier un secteur spécifique est stocké. Est-ce une bonne technique ou existe-t-il des techniques meilleures et plus efficaces que je peux étudier?

Nathan Ridley
la source

Réponses:

7

Je déconseille d'utiliser un seul fichier plat pour des quantités théoriquement infinies de données.

Si vous avez une quantité de données théoriquement infinie, vous avez besoin d' un accès aléatoire , ce qui signifie plusieurs fichiers ou une base de données - ou un format de fichier plat indexé, ce qui implique de résoudre les problèmes d'indexation déjà résolus par les systèmes de fichiers ou une base de données.

Si vous répartissez vos morceaux sur plusieurs fichiers, obtenir le morceau à (-110, 5000) revient simplement à dire "% APPDATA% / game / map / -110 / 5000.dat" (ou un autre nom de fichier si vous le souhaitez). commencer à les comprimer). Les bases de données ont juste besoin d'une requête. Si un morceau n'a pas de données, vous ne pouvez tout simplement pas stocker quoi que ce soit. Un seul fichier plat n'offre pas la vitesse et la commodité d'un accès aléatoire dès le départ.

Dans un seul fichier de taille arbitraire, pour un accès aléatoire rapide, vous devez avoir une garantie pour la position de tout bloc de données, ce qui signifie utiliser un index (car une recherche binaire brute dans vos blocs de données nuit aux performances et créer une grille dans votre fichier avec des taches "vides" vous donne le problème de Byte56 ). Une fois que vous avez développé un système d'indexation, que vous lui donnez de l'efficacité et que vous écrivez vous-même une API, vous avez recréé quelque chose comme le système de fichiers ou une base de données. À moins que vous ne gagniez réellement quelque chose, cela ne vaut probablement pas l'investissement. Par exemple, Steam profite massivement de leurs formats de fichiers GCF / NCF.

Si vous voulez une certaine sécurité sur vos sauvegardes, il est toujours possible de le faire. Par exemple, vous pouvez crypter chaque bloc individuel. Afin d'éviter qu'ils ne soient supprimés, vous pouvez avoir un hachage central basé sur les données enregistrées existantes. Si les données enregistrées ne correspondent pas au hachage (et que votre programme n'a pas provoqué la modification), un morceau a été supprimé.

doppelgreener
la source
4

La solution utilisée le plus souvent semble être de diviser en de nombreux fichiers, mais votre question implique un seul fichier. La seule option raisonnable pour cela (à mon avis) est d'émuler un système de fichiers très simple à l'intérieur de ce fichier unique. Ce n'est pas vraiment difficile à faire, mais vous devriez vraiment envisager d'utiliser plusieurs fichiers si vous le pouvez.

Si vous devez vous en tenir à un seul fichier, alors vous pourriez trouver l'inspiration pour votre implémentation à partir des ext2 fs. http://en.wikipedia.org/wiki/Ext2 Je sais que cela m'a aidé à prendre de bonnes décisions lorsque j'ai dû implémenter un FS simple pour un jeu.

Mais vraiment, pour toute carte en croissance, il est généralement préférable d'utiliser simplement un fichier pour chaque bloc "accédé".

Richard Fabian
la source
4

J'ai implémenté un système de segmentation pour mon jeu quand je jouais avec des mondes infinis (je ne sais pas si je les garderai ou non). Pour une utilisation avec un seul fichier, j'ai d'abord utilisé la position mondiale du bloc pour calculer un décalage d'octet dans le fichier. Cela suppose une taille de bloc statique, ou au moins un maximum statique. Cependant, si l'utilisateur devait se diriger dans une direction pendant un certain temps, ce fichier deviendrait assez rare pour sa taille, car il y avait de grandes zones de terrain qui n'avaient pas encore été générées, il y avait donc des espaces vides dans le fichier.

J'ai également essayé un système à deux fichiers. Un fichier contient une mappe de paires "position de morceau" à "décalage de fichier de morceau". Le second contient tous les morceaux. Quand un nouveau morceau est généré, il va simplement à la fin du fichier de morceau, et son décalage est stocké dans le fichier position-> offset. Celui-ci était un problème lorsque vous aviez BEAUCOUP de morceaux et trouver le décalage dans le fichier de position-> décalage prenait un peu de temps. Si vous le trouvez réalisable, vous pouvez charger les données de position-> offset dans une carte de hachage lors du chargement, pour y accéder rapidement.

J'utilise la deuxième option pour l'instant, mais je peux passer à autre chose si je trouve que les performances font défaut. Peut-être qu'avec ces informations, vous pourrez créer quelque chose qui vous convient. Bonne chance!

MichaelHouse
la source
Je suggérerais de regarder sqlite sqlite.org . Il est très autonome, indexé, gère les blobs, etc. Cela aiderait avec les performances et résoudrait les "trous" dans votre fichier.
Daniel Blezek