stato del gioco di salvataggio / caricamento?


12

qual è il metodo o l'algoritmo più utilizzato per salvare lo stato del gioco (profili), i file di testo dei database come va la crittografia e le cose relative.

Ho visto Cesare IV usato mySQL.

eventuali suggerimenti.

Risposte:


20

Sono abbastanza sicuro che il più delle volte sia fatto in un formato proprietario (binario), semplicemente scrivendo ogni variabile da qualunque struttura di stato del gioco usi in un file o rileggendolo in un'istanza della struttura. In C ++, ad esempio, puoi trattare un oggetto come un array di byte e semplicemente scriverlo () in un file o fread () dal file e ricondurlo nella sua forma oggetto.

Se si utilizza Java o un'altra lingua, è possibile scegliere di utilizzare la serializzazione per rendere l'attività davvero semplice. La spiegazione di Java è in fondo a questa risposta; altri linguaggi (di livello superiore a C ++) hanno sicuramente le loro librerie di serializzazione o funzioni integrate, che dovresti scegliere di usare. Non importa quanto inefficiente potrebbe essere la routine di serializzazione, lo spazio su disco rigido al giorno d'oggi è economico, specialmente quando lo stato del gioco non dovrebbe essere molto grande e ti impedisce di scrivere e mantenere tue routine di serializzazione.

Si dovrebbe assolutamente non utilizzare MySQL (basta leggere la prima frase di questa recensione ). Se hai davvero bisogno di un database relazionale per qualche motivo, usa SQLite ; è un sistema di database leggero ed esiste in un singolo file di database. Ma per la maggior parte dei giochi, i database relazionali non sono la strada da percorrere e le aziende che cercano di usarli finiscono per usarli come una tabella di ricerca di valori-chiave piuttosto che come un vero database relazionale.

Qualsiasi tipo di crittografia dei file del disco locale è solo offuscamento ; qualsiasi hacker annuserà i dati subito dopo che il tuo programma li decifrerà. Personalmente sono contrario a quel genere di cose, in particolare con le partite a un giocatore. La mia opinione è che i proprietari del gioco (pagando i clienti, intendiamoci) dovrebbero poter hackerare il gioco se lo desiderano. In alcuni casi può creare un maggiore senso di comunità e possono essere sviluppate "mod" per il tuo gioco che portano più clienti a te. L'esempio più recente che mi viene in mente è il portale in mod di Minecraft che è stato recentemente rilasciato. È pubblicato nei siti di notizie dei giocatori su Internet e puoi scommettere che ha spinto le vendite di Minecraft.


Se per qualche motivo sei abbastanza pazzo da usare Java per lo sviluppo di giochi come me, ecco una breve spiegazione della serializzazione in Java:

Conserva tutti i dati sullo stato del gioco in una classe, rendi la classe serializzabile implementando Serializable, usa la transientparola chiave se mescoli speciali variabili istanziate nella classe (gli oggetti transitori non sono serializzati) e semplicemente usa ObjectOutputStreamper scrivere su file e ObjectInputStreamleggere da file . Questo è tutto.


2
Hehe, The Witcher non ha crittografato i loro dati. Molto facile aprire il file di gioco salvato in un editor esadecimale, pasticciare un po 'con esso e ottenere tutte le carte del pulcino nudo ... oh dio, mi dispiace così tanto!
Anthony,

Ho usato la serializzazione binaria .NET per salvare i giochi e C # è forse una piattaforma leggermente più ragionevole di Java su cui sviluppare i giochi. Mi piace come salva automaticamente un intero grafico di oggetti automaticamente. Questo era molto più difficile. Naturalmente ora c'è la sfida di escludere pezzi non necessari come le trame, ma non è un grosso problema da realizzare.
BlueMonkMN,

Non sono in disaccordo sul fatto che C # sia leggermente più popolare di Java per sviluppare giochi. Più ragionevole implica un po 'di soggettività e, come sviluppatore di XNA e Java, preferisco Java. Sentiti libero di elencare le istruzioni sulla serializzazione anche in C # se vuoi, non l'ho mai fatto ma posso modificarlo nella mia risposta. La serializzazione di Java salva l'intero grafico degli oggetti e la parola chiave "transitoria" sulle variabili esclude pezzi non necessari come le trame; tutti i membri non transitori devono essere serializzabili oppure è possibile scrivere un metodo writeObject personalizzato per aggirare il problema.
Ricket,

Il sottaceto di Python salverà anche un intero oggetto grafico ed è facile da usare. Quando arriva il momento di deserializzare ti vengono restituiti oggetti completamente idratati, facili come una torta: docs.python.org/library/pickle.html
drhayes

Quando si utilizza il formattatore binario incorporato, escludere determinati campi dalla serializzazione in C # /. NET è semplice come adornarli con l'attributo [Non serializzato]. La cosa facile da trascurare, tuttavia, è che gli eventi generati dal compilatore (ovvero qualsiasi evento senza operatori di aggiunta / rimozione personalizzati) creano un campo di supporto per archiviare i propri abbonati. Pertanto, è facile includere accidentalmente (e inconsapevolmente) i gestori di eventi in un grafico a oggetti serializzato. Per ovviare a questo, è necessario aggiungere l'attributo Non serializzato alla dichiarazione dell'evento, ma è necessario aggiungere il qualificatore "field:":[field: NonSerialized]
Mike Strobel

3

Se stai scrivendo il tuo codice, diciamo in C ++, puoi usare file binari. I file binari ti danno una forma di crittografia attraverso l'offuscamento. Ma come documentato in tutti gli Internet, questa è una forma molto debole di sicurezza.

O, puoi usare qualcosa come RapidXML se vuoi una soluzione leggibile dall'uomo.

Se stai usando un qualche tipo di framework, guarda le sue funzioni di supporto ai file. HTH


0

La maggior parte dei giochi che ho visto usa solo codice scritto a mano per leggere / scrivere da file binari. Spesso, il formato su disco sarà una replica esatta del layout di memoria di un oggetto, quindi il caricamento è solo:

  1. Leggi il file in memoria.
  2. Trasmetti il ​​puntatore al buffer sul tipo di oggetto.

È veloce, ma è un lavoro ingrato da mantenere, specifico per la piattaforma e poco flessibile.

Ultimamente, ho visto un paio di giochi usare SQLite. Alla gente con cui ho parlato sembra piacere.


0

La serializzazione è menzionata in alcune delle altre risposte e sono d'accordo che sia una soluzione ragionevole. Un modo in cui fallisce è il controllo delle versioni.

Supponiamo che tu rilasci il tuo gioco e che la gente lo giochi e crei alcuni salvataggi. Quindi in una patch successiva si desidera correggere un bug o aggiungere alcune funzionalità. Se usi un semplice metodo di serializzazione binaria e aggiungi un membro alle tue classi, la serializzazione potrebbe non essere compatibile con i vecchi giochi di salvataggio quando i clienti installano la tua patch.

Quindi, qualunque sia l'approccio che usi, assicurati di pensare a questo problema prima di rilasciare il gioco la prima volta! I clienti non saranno felici se dovranno ricominciare da capo dopo aver applicato una patch.

Un modo per evitarlo è che ogni tipo di dati di base implementi i metodi Salva (versione) e Carica (versione) che siano abbastanza intelligenti da sapere quali dati salvare e caricare per ogni versione del gioco. In questo modo puoi supportare la retrocompatibilità dei tuoi salvataggi e fallire con grazia se un utente prova a caricare un salvataggi da una versione più recente di quella in esecuzione.


1
Come nota veloce: l'implementazione delle funzioni "salva" e "carica" ​​per ogni versione del gioco si trasforma rapidamente in un incubo di manutenzione. Ho trovato una soluzione migliore è incorporare un numero di versione, scrivere le funzioni "salva / carica" ​​per la versione corrente del gioco e scrivere una funzione di "conversione" dalla versione non corrente più recente alla versione corrente. Quindi mantieni tutte le tue funzioni di conversione in giro. Tentare di caricare un gioco vecchio di dieci versioni eseguirà dieci funzioni di conversione in serie, quindi la funzione nativa "carica la versione corrente del gioco".
ZorbaTHut,

Molto più facile da mantenere a lungo termine: mantenere una serie di funzioni "carica tutti i file di gioco precedenti" si trasforma rapidamente in un'operazione polinomiale.
ZorbaTHut

Nei giochi su cui ho lavorato non è così complesso - piuttosto che conservare più copie dei metodi load / save, l'unico metodo utilizza il numero di versione per determinare quali byte leggere e scrivere. Ciò è ancora più semplice se non si scrivono solo strutture, ma si implementano operazioni di caricamento e salvataggio come operazioni a livello di tipo di dati primitivo (ad esempio ReadByte / ReadFload / etc). Quindi se aggiungi un nuovo membro puoi fare qualcosa come if (versione> 10) {someNewByte = ReadByte (); } L'implementazione in questo modo semplifica anche il supporto di diverse piattaforme endian.
Kevin Aug42

Un altro modo per evitare il supporto del controllo delle versioni è quello di evitare che i metodi di serializzazione / deserializzazione dei tuoi oggetti scrivano / leggano i singoli valori direttamente da uno stream. Invece, gli oggetti potrebbero scrivere i loro dati di proprietà in un bag di proprietà usando coppie chiave / valore e quindi scrivere il bag nel flusso. Durante la deserializzazione, gli oggetti possono leggere i valori dal sacchetto per nome. Ma invece di avere controlli di numeri di versione specifici come suggerito da kevin42, potresti semplicemente avere delle regole su come gestire i valori mancanti (cioè usare un valore predefinito standard quando il valore richiesto non è nel sacchetto).
Mike Strobel,

0

Se puoi usare lo stesso formato che usi per memorizzare i tuoi livelli, è un bonus.

Ad esempio, un gioco come Peggle potrebbe avere una disposizione iniziale della tavola, il numero di palline, il punteggio attuale (0 per la tavola iniziale), ecc. Quindi una partita salvata può usare esattamente lo stesso formato.

Se usi lo stesso formato, il gioco di salvataggio e il caricamento del livello possono condividere il codice rendendo il tuo lavoro più semplice!

Per un gioco con file di mappe molto grandi, il gioco di salvataggio può includere il file di mappa come riferimento. I file di livello iniziale potrebbero anche fare la stessa cosa, il che rende anche più facile il ritorno su quella mappa se per qualche motivo la storia ha il personaggio tornato nello stesso posto, tranne per il fatto che alcuni degli NPC sono morti e ci sono corpi morti che giacciono tutti al di sopra di.

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.