Domanda

Quindi sto cercando di lavorare sul mio piccolo gioco 3D. Ora sto più o meno facendo questo per imparare C #. Mi chiedevo, qual è la migliore metodologia per imballare risorse come trame / script?

Generalmente quello che stavo pensando di fare era questo:

[header]
[number of records]
[Offset to Record 1 from End of header]
[Offset to Record 2 from end of Record 1]
.
.
[Offset to record N from Record N-1]
[record 1]
[256 bytes represent the filename]
[32 byte size]
[binary data]
[record 2]
.
.

In questo momento voglio solo che memorizzi, semplici immagini e file di testo. Mi sono guardato intorno e la cosa migliore che ho davvero trovato è un vecchio esempio di come sono archiviati i doom wad.

Qualcuno ha qualche esperienza?

È stato utile?

Soluzione

Va ??bene. Se puoi caricare tutto nella memoria virtuale e lasciare che lo scambio lo gestisca, puoi davvero usare qualsiasi formato. Se desideri un accesso casuale a un solo record (quindi ad esempio puoi caricare pigramente, anche se memmap non compresso è anche pigro), probabilmente vorrai mantenere l'indice in memoria.

La maggior parte delle persone utilizza una libreria che consente di accedere a un formato di archivio .zip, .jar, .pak (formato di terremoto) o altro (simile o compresso), come se facesse parte del filesystem (ovvero i record sono accessibili tramite chiavi stringa). Farei sicuramente così se riesci a trovare una libreria già realizzata, ad es. truezip per Java. Apache Commons ne ha uno, ma non so quanto sia facile integrare w / .NET (credo sia una grande base di codice C). ZipFS sembra un vero montatore di file zip .NET che contiene solo le intestazioni in memoria.

Oppure, con probabilmente solo un po 'meno di praticità, potresti usare DotNetZip direttamente

Altri suggerimenti

Non perdere tempo a inventare il tuo formato di archiviazione.

È possibile utilizzare SharpZipLib o un'altra libreria di compressione gratuita per .net. Con esso puoi anche comprimere più file in un archivio ed estrarre i file che desideri separatamente su richiesta.

Il tuo design mi sembra buono, anche se presumo che tu intendessi 32 bit per dimensione anziché 32 byte !

Penso che il tuo design sia il migliore per le situazioni in cui vuoi caricare tutte le tue risorse in una volta, perché è una specie di design sequenziale. Se vuoi caricare solo poche risorse alla volta (forse perché ogni livello di gioco utilizza solo un sottoinsieme delle risorse), sarebbe un po 'meno efficiente, perché dovresti leggere ogni risorsa a turno per trovare quelle che vuoi.

In tal caso potresti voler provare un design più indicizzato, forse qualcosa del genere:

[HEADER]
[Miscellaneous header stuff]
[Offset to index from start of file]
[Number of entries in index]
[RECORD 1]
[Asset data]
[RECORD 2]
[Asset data]
.
.
[RECORD N]
[Asset data]
[INDEX]
[ID or filename of asset 1]
[Size of asset 1]
[Offset to asset 1 from start of file]
[Other asset 1 flags or whatever]
[ID or filename of asset 2]
[Size of asset 2]
[Offset to asset 2 from start of file]
[Other asset 2 flags or whatever]
.
.

Ciò consentirebbe un migliore accesso casuale alle risorse, perché ora devi solo cercare attraverso il tuo indice (che caricheresti in memoria) piuttosto che attraverso l'intero file (che potrebbe non adattarsi alla memoria). Se vuoi divertirti, puoi usare un albero o una tabella hash per l'indice.

Il motivo per mettere l'indice alla fine del file piuttosto che in primo piano è che rende più semplice aggiungere un'altra risorsa al file del pacchetto senza dover ricostruire il tutto. Altrimenti, la voce aggiuntiva nel tuo indice eliminerebbe tutti i tuoi offset.


MODIFICA: per rispondere ai commenti ...

Quello che avevo in mente era che avresti avuto accesso agli asset solo tramite l'indice, quindi spero che non scapperesti mai alla fine degli asset quando li leggi. Forse sarebbe utile un esempio di un tipico caso d'uso.

Supponi di voler leggere la trama chiamata " TankTexture.png " ;. Ecco come penso che faresti al riguardo:

  1. Apri il file del pacchetto.
  2. Leggi nell'intestazione a dimensione fissa.
  3. Estrai l'offset dell'indice e il numero di voci dall'intestazione.
  4. Cerca all'inizio dell'indice.
  5. Leggi l'indice in un array (dimensioni della voce dell'indice fisse per numero di voci).
  6. Cerca nell'indice l'asset chiamato " TankTexture.png " ;.
  7. Estrai l'offset e la dimensione dell'asset dalla voce dell'indice.
  8. Cerca l'inizio dell'asset.
  9. Leggi il numero di byte indicato dalla dimensione dell'asset.

Ovviamente, per le risorse successive sono necessari solo i passaggi 6-9.

Spero che aiuti a spiegare cosa stavo pensando. Fammi sapere se hai altre domande.

Se vuoi farlo a fini di apprendimento, il formato WAD è un buon punto di partenza. Tuttavia, proporrei di utilizzare un formato di file grosso.
Quindi seguirebbe sostanzialmente il formato proposto (ad es. Intestazione, TOC ecc.) Ma per ogni voce di dati avresti un ID blocco che identifica il tipo di dati che è.
Questo ha molti vantaggi, principalmente che puoi variare il tuo formato dati rispetto al tuo formato di codice impostando il tuo codice per saltare blocchi che non capisce - questo permette allo sviluppo dei tuoi strumenti di procedere mantenendo la retrocompatibilità dei tuoi dati nel gioco.

Vorrei anche raccomandare di avere una voce aggiuntiva "flag" a 32 bit nel tuo sommario che ti consentirebbe di utilizzare un campo bit per abilitare opzioni come il tipo di compressione, la crittografia ecc.

Spero che aiuti

Dico che il tuo formato è una buona scelta. Idealmente, vuoi inserire tutte le tue risorse in una sola lettura. Ad esempio, vorrai tutti i tuoi dati per il livello 3 nello stesso pacchetto, in questo modo puoi caricare tutti i tuoi dati di livello in una lettura senza cercare. È davvero ok avere una singola risorsa in più di un pacchetto. Devi solo gestire il caso in cui un asset sia già caricato e ignorarlo.

Il modo in cui dividi i tuoi dati dovrebbe dipendere dalle dipendenze tra i tuoi dati (cioè se uno script ha bisogno di un certo modello, dovrebbero essere entrambi nello stesso pacchetto) e quanto devi fare granulare le tue letture (es. hai letto tutti i tuoi dati di livello in una volta sola? Quindi puoi mettere i tuoi nemici nel pacchetto di livelli. Ma se il tuo gioco scorre nel mondo, forse hai bisogno di pacchetti separati per i nemici.)

In realtà, tenere traccia delle dipendenze dei dati è la parte difficile. Al momento della creazione, si desidera conoscere le dipendenze di ogni dato che si inserisce. In fase di esecuzione, è sufficiente leggere nel pacchetto e visualizzare le risorse in memoria. Devi anche tenere traccia delle dipendenze in fase di esecuzione perché dovrai sapere cosa è sicuro SCARICARE in qualsiasi momento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top