Estou codificando minha final para um curso de Programação de videogame e quero saber como criar um arquivo salvo para o meu jogo, para que um usuário possa jogar e depois voltar mais tarde. Qualquer idéia de como isso é feito, tudo que eu fiz antes foi em programas de execução única.
c++
savegame
serialization
Tucker Morgan
fonte
fonte
Respostas:
Você precisa usar a serialização para salvar suas variáveis na memória no disco rígido. Existem muitos tipos de serialização. O .NET XML é um formato comum, embora haja serializadores binários e JSON disponíveis. Não sou muito programador em C ++, mas uma pesquisa rápida mostrou um exemplo de serialização em C ++:
Existem bibliotecas que oferecem funcionalidades de serialização. Alguns são mencionados em outras respostas.
As variáveis nas quais você estará interessado provavelmente estarão relacionadas ao estado do jogo. Por exemplo, você provavelmente desejará conhecer esse tipo de informação
Você realmente não se importa com as texturas que estão sendo usadas (a menos que seu jogador possa mudar sua aparência, esse é um caso especial), porque elas geralmente são as mesmas. Você precisa se concentrar em salvar dados importantes do estado do jogo.
Ao iniciar o jogo, você inicia normalmente um jogo "novo" (isso carrega suas texturas, modelos etc.), mas no momento apropriado você carrega os valores do seu arquivo salvo no objeto de estado do jogo, substituindo o novo "padrão" estado do jogo. Em seguida, você permite que o player continue a jogar.
Simplifiquei bastante aqui, mas você deve ter uma ideia geral. Se você tiver uma pergunta mais específica, faça uma nova pergunta aqui e podemos tentar ajudá-lo.
fonte
Normalmente, isso é específico para o seu jogo. Tenho certeza que você aprendeu a escrever e ler arquivos de suas aulas até agora. A ideia básica é:
O que você escreve depende de você, depende do seu jogo. Uma maneira de escrever é escrever as variáveis que você deseja em uma ordem específica como um fluxo de bytes. Em seguida, ao carregar, leia-os no seu programa na mesma ordem.
Por exemplo (no pseudo-código rápido):
fonte
Provavelmente, existe um grande número de maneiras de fazer isso, mas a mais simples que sempre achei e usei tanto pessoal quanto profissionalmente é criar uma estrutura que contenha todos os valores que desejo salvar.
Depois, escrevo / lemos os dados de e para um arquivo usando os valores básicos de IO do arquivo. O inventárioCont é o número de estruturas de itens que são salvas após a estrutura principal SaveGameData no arquivo, para que eu saiba quantas delas serão lidas após a busca desses dados. A chave aqui é que, quando eu quero salvar algo novo, a menos que seja uma lista de itens ou algo parecido, tudo o que tenho que fazer é adicionar um valor à estrutura em algum lugar. Se for uma lista de itens, terei que adicionar um passe de leitura, como já impliquei para os objetos Item, um contador no cabeçalho principal e depois as entradas.
Isso tem a desvantagem de tornar incompatíveis versões diferentes de um arquivo salvo sem tratamento especial (mesmo que sejam apenas valores padrão para cada entrada na estrutura principal). Mas, no geral, isso facilita a extensão do sistema, apenas adicionando um novo valor de dados e colocando um valor quando necessário.
Novamente, algumas maneiras de fazer isso e isso podem levar mais ao C do que ao C ++, mas ele já fez o trabalho!
fonte
Primeiro, você precisa decidir quais dados precisam ser salvos. Por exemplo, pode ser a localização do personagem, sua pontuação e o número de moedas. Obviamente, seu jogo provavelmente será muito mais complexo e, portanto, você precisará salvar dados adicionais, como o número do nível e a lista de inimigos.
Em seguida, escreva o código para salvá-lo em um arquivo (use ofstream). Um formato relativamente simples que você pode usar é o seguinte:
E assim o arquivo ficaria assim:
O que significa que ele estava na posição (14, 96) com uma pontuação de 4200 e 100 moedas.
Você também precisa escrever um código para carregar este arquivo (use ifstream).
É possível salvar os inimigos incluindo sua posição no arquivo. Podemos usar este formato:
Primeiro,
number_of_enemies
é lido e, em seguida, cada posição é lida com um loop simples.fonte
Uma adição / sugestão seria adicionar um nível de criptografia à sua serialização para que os usuários não possam editar seus valores em texto para "9999999999999999999". Uma boa razão para fazer isso seria evitar estouros de número inteiro (por exemplo).
fonte
Eu acho que sua melhor aposta é boost :: serialization porque é fácil de propagar na sua hierarquia. Você só precisa chamar a função de salvar / carregar do objeto superior e todas as suas classes são criadas facilmente.
Consulte: http://www.boost.org/doc/libs/1_49_0/libs/serialization/doc/index.html
fonte
Por uma questão de completude, quero mencionar uma biblioteca de serialização c ++, que eu pessoalmente uso e ainda não foi mencionada: cereal .
É fácil de usar e possui uma sintaxe agradável e limpa para serialização. Ele também oferece vários tipos de formatos nos quais você pode salvar (XML, Json, Binário (incluindo uma versão portátil com os respectivos aspectos endianess)). Ele suporta herança e é somente cabeçalho,
fonte
Seu jogo comprometerá as estruturas de dados (espero?) Que você precisa transformar em bytes (serializar) para poder armazená-las. Em um futuro, você poderá carregar esses bytes de volta e transformá-los novamente em sua estrutura original (desserialização). Em C ++, não é tão complicado, pois a reflexão é muito limitada. Mas ainda assim, algumas bibliotecas podem ajudá-lo aqui. Eu escrevi um artigo sobre isso: https://rubentorresbonet.wordpress.com/2014/08/25/an-overview-of-data-serialization-techniques-in-c/ Basicamente, eu sugiro que você dê uma olhada biblioteca de cereais se você tiver como alvo os compiladores C ++ 11. Não é necessário criar arquivos intermediários, como o protobuf, para que você economize algum tempo se desejar resultados rápidos. Você também pode escolher entre binário e JSON, para ajudar bastante na depuração aqui.
Além disso, se a segurança for uma preocupação, convém criptografar / descriptografar os dados que você está armazenando, especialmente se você estiver usando formatos legíveis por humanos, como JSON. Algoritmos como o AES são úteis aqui.
fonte
Você precisa usar
fstream
para arquivos de entrada / saída. A sintaxe é simples EX:Ou
Outras ações são possíveis no seu arquivo: append , binário , trunc etc. Você usaria a mesma sintaxe acima, em vez de colocarmos std :: ios: :( flags), por exemplo:
ios::out
para operação de saídaios::in
para operação de entradaios::binary
para operação IO binária (byte bruto), em vez de baseada em caracteresios::app
para começar a escrever no final do arquivoios::trunc
pois se o arquivo já existir, substitua, exclua o conteúdo antigo e substitua por novoios::ate
- posicione o ponteiro do arquivo "no final" para entrada / saídaEx:
Aqui está um exemplo mais completo, mas simples.
fonte
goto
s, você será linchado no local público. Não usegoto
s.