Qual è un buon formato di file flat per l'archiviazione di una mappa di tessere 2D che può crescere all'infinito in qualsiasi direzione?


9

Sto creando un semplice motore di mappe che si espanderà automaticamente in qualsiasi direzione con contenuti generati proceduralmente secondo necessità.

Qual è un buon modo per memorizzare i dati della mappa, ancorati a un'origine 0,0 in modo che un sottoinsieme rettangolare di dati della mappa possa essere caricato in modo rapido ed efficiente da qualsiasi punto della mappa?

Ho un'idea che forse dovrei dividere la mappa in settori distinti e quindi utilizzare una sorta di formato di intestazione per identificare dove è archiviato un determinato settore nel file. È una buona tecnica o ci sono tecniche migliori, più efficienti che posso osservare?

Risposte:


7

Vorrei sconsigliare l'utilizzo di un singolo file flat per quantità teoricamente infinite di dati.

Se si dispone di una quantità teoricamente infinita di dati, è necessario un accesso casuale , ovvero più file o un database, oppure un formato di file flat indicizzato, che implica la risoluzione dei problemi di indicizzazione già risolti dai file system o da un database.

Se distribuisci i tuoi blocchi su più file, ottenere il blocco in (-110, 5000) è solo una questione di dire "% APPDATA% / game / map / -110 / 5000.dat" (o qualche altro nome file se vuoi iniziare a comprimerli). I database hanno solo bisogno di una query. Se un blocco non ha dati, non puoi semplicemente archiviare nulla. Un singolo file flat non offre la velocità e la praticità dell'accesso casuale fin dall'inizio.

In un singolo file di dimensioni arbitrarie, per un accesso casuale rapido devi avere una garanzia per la posizione di qualsiasi blocco di dati, il che significa utilizzare un indice (poiché una ricerca binaria non elaborata attraverso i tuoi blocchi di dati danneggia le prestazioni e la creazione di una griglia nel tuo file con punti "vuoti" ti dà il problema di Byte56 ). Una volta sviluppato un sistema di indicizzazione, assicurandogli efficienza e scrivendo un'API, hai ricreato qualcosa come il file system o un database. A meno che non si ottenga effettivamente qualcosa dal farlo, probabilmente non vale l'investimento. Ad esempio, Steam beneficia enormemente dei loro formati di file GCF / NCF.

Se vuoi un po 'di sicurezza sui tuoi salvataggi, è ancora possibile farlo. Ad esempio, puoi crittografare ogni singolo blocco. Per evitare che vengano cancellati, potresti avere un hash centrale basato sui dati salvati esistenti. Se i dati salvati non corrispondono all'hash (e il tuo programma non ha causato la modifica), un blocco è stato eliminato.


4

La soluzione utilizzata più spesso sembra essere quella di suddividere in molti file, tuttavia la tua domanda implica solo un singolo file. L'unica opzione sensata per questo (secondo me) è emulare un file system molto semplice all'interno di quel singolo file. In realtà non è terribilmente difficile da fare, ma dovresti davvero considerare l'utilizzo di più file se puoi.

Se devi attenersi a un solo file, potresti trovare ispirazione per la tua implementazione da ext2 fs. http://it.wikipedia.org/wiki/Ext2 So che mi ha aiutato a prendere alcune buone decisioni quando ho dovuto implementare un semplice FS per un gioco.

Ma in realtà, per qualsiasi mappa in crescita, di solito è meglio usare solo un file per ogni blocco "accessibile".


4

Ho implementato un sistema di chunking per il mio gioco quando stavo giocherellando con mondi infiniti (non sono sicuro se li terrò o no). Per l'uso con un singolo file, all'inizio ho usato la posizione mondiale del blocco per calcolare un offset di byte nel file. Ciò presuppone una dimensione del blocco statico o almeno un massimo statico. Tuttavia, se l'utente dovesse andare avanti in una direzione per un po ', questo file diventerebbe piuttosto scarso per le sue dimensioni, poiché c'erano grandi aree di terra che non erano state ancora generate e quindi c'erano spazi vuoti nel file.

Ho anche provato un file system a due. Un file contiene una mappa di "posizione pezzo" a coppie "offset file pezzo". Il secondo contiene tutti i pezzi. Quando viene generato un nuovo blocco, esso va semplicemente alla fine del file di blocco e il suo offset viene memorizzato nel file position-> offset. Questo era un problema quando avevi MOLTO pezzi e trovare l'offset nel file position-> offset ha richiesto un po 'di tempo. Se lo ritieni fattibile, puoi caricare i dati di posizione> offset in una mappa hash al caricamento, per avere un accesso rapido.

Sto usando la seconda opzione per ora, ma posso passare a qualcos'altro se trovo che le prestazioni siano carenti. Forse con queste informazioni sarai in grado di creare qualcosa che funzioni per te. In bocca al lupo!


Suggerirei di esaminare sqlite sqlite.org . È molto autonomo, indicizzato, gestisce BLOB, ecc. Ciò contribuirebbe a "buchi" di prestazioni e indirizzi nel file.
Daniel Blezek,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.