Salvando o estado do jogo roguelike?

11

Estou trabalhando em um roguelike básico usando HTML5 e jQuery e me deparei com um problema.

Do jeito que o jogo está atualmente, o sistema só salva o estado do jogo toda vez que o usuário se move entre os andares - para minimizar a sobrecarga. O perigo disso é que, se o usuário tiver problemas, ele poderá simplesmente fechar a janela e retornar ao jogo no início do andar atual. Isso reduz drasticamente a dificuldade do jogo (e quase derrota o objetivo de um roguelike) - mas não é razoável salvar o estado do jogo a cada movimento ou ataque de um único jogador.

Eu pesquisei maneiras de salvar o estado do jogo na janela do navegador, mas não estou feliz com elas. Minha pergunta é a seguinte: assumindo que "salvar um estado de jogo" significa uma solicitação ajax / pós moderadamente pesada, como faço para impedir esse comportamento de trapaça? Existe uma metodologia conhecida para quantificar alterações incrementais / processuais em um mapa 2D, em vez de salvar todo o estado do mapa? Observe que não estou pedindo "a maneira mais eficiente" - estou procurando metodologias existentes para corrigir minha inexperiência.

CodeMoose
fonte
Pergunta de programação JavaScript muito genérica e geral. Votei negativamente, mas depois repensei, já que é interessante se você considerar como faria se não pudesse desencadear um evento durante a descarga.
Tim Tim Holt
Talvez eu reformulá-la para resolver esse problema diretamente =)
CodeMoose
@ TimHolt - editado por sua sugestão
CodeMoose

Respostas:

8

A solução óbvia é enviar todos os comandos do jogador para o servidor conforme ele é feito e fazer com que o servidor os registre; dessa forma, se o jogo for abortado por qualquer motivo, os comandos registrados poderão ser repetidos para restaurar o jogo no ponto em que parou.

Obviamente, quando um salvamento adequado é feito, o log de comandos antigo pode ser descartado (embora você também possa salvá-lo para permitir repetições de jogos antigos; se você fizer isso, inclua carimbos de data e hora no log para reprodução em tempo real. ) Você também pode fazer um salvamento completo automaticamente depois que n comandos foram feitos desde o último salvamento (onde, digamos, n = 1000) para evitar repetições excessivamente longas se o jogador permanecer no mesmo nível por muito tempo antes de fechar ou travar o jogo .

Se o seu jogo envolver números aleatórios (e, sendo um roguel, provavelmente o envolve), você também precisará garantir que eles possam ser recriados corretamente durante uma repetição. Uma solução é incluir todos os números aleatórios no log de repetição; outro é usar um gerador de números pseudo-aleatórios determinísticos e salvar a semente quando o jogo for salvo.

Observe que todos esses métodos podem ser explorados adulterando o cliente, mas isso é realmente inevitável sempre que você tiver lógica de jogo no cliente. Como alternativa à prova de trapaça, você pode executar o jogo real no servidor e apenas fazer com que o cliente envie todos os comandos do jogador para o servidor e receba as atualizações de exibição de volta. Para um roguelike, isso pode muito bem ser possível. Obviamente, isso também resolveria seu problema de economia de estado (embora você ainda possa implementar alguma forma de log de comando no servidor, tanto para a funcionalidade de reprodução quanto para permitir a recuperação de falhas do servidor). A desvantagem é que isso impossibilitaria a execução off-line (a menos, é claro, que você também disponibilize o código do servidor para os jogadores executarem localmente, se assim o desejarem).

Ilmari Karonen
fonte
1
AFAIK todos os RGNs são pseudo-aleatórios. Você precisa de hardware especializado para obter valores aleatórios verdadeiramente (não-semeados).
9139 bobobobo
1
@bobobobo há pseudo-aleatório (semeado) e há números aleatórios criptograficamente seguros (sem-semente) na plataforma .Net. Pode ou não ser aleatório por hardware, mas está perto o suficiente para não poder armazenar apenas uma semente.
Rangoric
2

Consulte /programming/3888902/javascript-detect-browser-close-tab-close-browser para obter uma pergunta mais genérica da mesma pergunta.

Considere também salvar o jogo completo nas mudanças de piso e deltas incrementais a cada movimento. Depois, você pode repetir o jogo até o ponto da última jogada.

Supondo que haja algum uso de geradores de números aleatórios, você pode gerar e re-propagar o gerador de números aleatórios no início de cada novo andar e, em seguida, salvá-lo junto com o andar. Em seguida, você pode repetir o carregamento com a carga e deve poder reproduzir os movimentos com a mesma sequência até a última feita.

Tim Holt
fonte
Obrigado Tim - uma vez que entro na mentalidade do desenvolvedor de jogos, é realmente fácil encontrar tudo o que o toca no desenvolvedor de jogos. Props por fornecer uma resposta de qualquer maneira.
CodeMoose
Não se preocupe - ver meu comentário revista em questão também :)
Tim Holt
Eu teria dito deltas incrementais em cada movimento também.
9133 bobobobo
2

Aborda, não as economias incrementais, mas encontra tempo para uma economia completa:

  • onunload, Como mencionado anteriormente. Eu achei isso confiável (mas usando localStorage, não a rede, o que pode mudar as coisas).
  • Salve quando sua janela perder o foco.
  • Salvar periodicamente: quando o último salvamento não ocorre em n minutos e o usuário não faz nenhuma entrada em m segundos.
Kevin Reid
fonte