Eu estava meio curioso sobre como a repetição pode ser implementada em um jogo.
Inicialmente, pensei que haveria apenas uma lista de comandos de todas as ações de jogador / ai que foram executadas no jogo e, em seguida, 'reproduz' o jogo e deixa o mecanismo renderizar como de costume. No entanto, eu olhei para replays em FPS / RTS jogos, e após uma inspeção cuidadosa até mesmo coisas como as partículas e / falhas audíveis gráficas são consistentes (e as falhas são geralmente em consistente).
Então, como isso acontece? Nos jogos com ângulo fixo da câmera, acho que ele pode gravar todos os quadros da cena inteira em um fluxo que é armazenado e depois apenas repassa o fluxo de volta, mas isso não parece suficiente para jogos que permitem pausar e mover a câmera por aí. Você teria que armazenar os locais de tudo na cena em todos os momentos (não?). Então, para coisas como partículas, são muitos os dados a serem enviados, o que parece ser um atrativo significativo no desempenho do jogo durante o jogo.
fonte
Respostas:
Eu acho que seu pensamento inicial estava correto. Para criar uma reprodução, você armazena toda a entrada recebida do usuário (junto com o número do quadro no qual foi recebida) junto com as sementes iniciais de qualquer gerador de números aleatórios. Para reproduzir o jogo, você redefine seus PRNGs usando as sementes salvas e alimenta o mecanismo de jogo com a mesma sequência de entrada (sincronizada com os números de quadro). Como muitos jogos atualizam o estado do jogo com base na quantidade de tempo que passa entre os quadros, também pode ser necessário armazenar a duração de cada quadro.
fonte
Starcraft e Starcraft: Brood War tiveram um recurso de repetição. Após a conclusão de uma partida, você pode salvar a reprodução para visualizá-la mais tarde. Durante a reprodução, você pode rolar pelo mapa e clicar em unidades e edifícios, mas não alterar seus comportamentos.
Lembro-me de uma vez assistindo a uma repetição de uma partida que havia sido disputada no jogo original, mas a repetição estava sendo vista em Brood War. Para quem não conhece, Brood War contém todas as unidades e edifícios originais, bem como uma variedade de novos. No jogo original, o jogador havia derrotado o computador, criando unidades que o computador não poderia facilmente combater. Quando reproduzi o jogo em Brood War, o computador tinha acesso a diferentes unidades, criadas e usadas para derrotar o jogador. Portanto, o mesmo arquivo de reprodução resultou em um vencedor diferente, dependendo de qual versão do Starcraft estava sendo reproduzida.
Eu sempre achei o conceito fascinante. Parece que o recurso de reprodução funcionou gravando todas as entradas do player e assumiu que o computador responderia a esses estímulos exatamente da mesma maneira a cada vez. Quando as entradas do jogador foram inseridas no replayer original de Starcraft, o jogo se desenrolou exatamente como na partida original. Quando a mesma informação exata foi inserida no replayer da Guerra da Ninhada, o computador reagiu de maneira diferente, criou unidades mais fortes e venceu o jogo.
Algo a ter em mente se você estiver escrevendo um mecanismo de repetição.
fonte
Existem dois métodos principais:
Depende do que você quer fazer. Às vezes, armazenar eventos é melhor, porque geralmente é necessário muito menos memória. Por outro lado, se você deseja fornecer replays que podem ser reproduzidos em velocidades diferentes e em diferentes pontos de partida, é melhor armazenar os estados. Ao armazenar estados, você também pode decidir se os armazena após cada evento ou por apenas 12 ou 25 vezes por segundo - isso pode reduzir o tamanho da sua reprodução e facilitar o retrocesso / avanço rápido.
Observe que "estado" não significa estado gráfico. Mais algo como posições de unidade, estado de recursos e assim por diante. Coisas como gráficos, sistemas de partículas e assim por diante geralmente são determinísticas e podem ser armazenadas como "animação X, tempo Y: Z".
Às vezes, os replays são usados como esquema de anti-aquecimento. Então, armazenar eventos é provavelmente o melhor aqui.
fonte
Tecnicamente, você deve escrever seu mecanismo para ser determinístico, isso não é aleatório. Assumindo que um personagem no jogo está mirando o braço de um oponente e dispara uma arma, a mesma quantidade de dano deve ser aplicada ao oponente em todos os casos.
Assumindo que uma bomba detona no local X, as partículas produzidas por essa explosão sempre devem resultar no mesmo resultado visual. Se você precisar de aleatoriedade, crie um conjunto de números aleatórios, selecione um valor inicial quando o jogo for jogado e salve esse valor inicial na repetição.
Em geral, ter aleatoriedade em um jogo é uma má ideia. Mesmo para coisas como multiplayer, você não pode ter metade dos seus jogadores capazes de ver em torno de uma explosão, enquanto os outros não podem simplesmente porque não obtiveram o valor aleatório certo.
Faça tudo determinístico, e você deve ficar bem.
fonte
Dado o estado inicial e uma série de ações com registro de data e hora , basta percorrer a sequência, pois as ações gravadas devem ter uma repetição.
Para que eventos aleatórios ocorram exatamente da mesma forma, use números pseudo-aleatórios semeados e salve a semente no arquivo de reprodução.
Contanto que você use o mesmo algoritmo para gerar os números aleatórios a partir da semente, poderá recriar todos os eventos da mesma forma que ocorreram no jogo ao vivo, sem a necessidade de capturas instantâneas completas do estado do jogo.
Isso exigirá que os replays sejam assistidos sequencialmente , mas isso é bastante normal para replays de jogos (consulte Starcraft 2). Se você deseja permitir acesso aleatório à linha do tempo, pode tirar instantâneos de estado completo em intervalos definidos (digamos a cada minuto), para pular a linha do tempo com uma granularidade definida.
fonte
O NVidia PhysX (um mecanismo de simulação física frequentemente usado em jogos) é capaz de gravar o estado completo da cena física ao longo do tempo. Isso incorpora quaisquer informações de direção do mecanismo de jogo, o que significa que você não precisa rastrear sementes de números aleatórios, como sugeriram outros. Se você fizer esse despejo de cena, poderá reproduzi-lo em uma ferramenta externa (fornecida pela NVidia), que é muito útil para rastrear problemas com seus modelos físicos. No entanto, você também pode usar o mesmo fluxo físico para acionar seu mecanismo gráfico, o que permitiria um controle normal da câmera, uma vez que apenas a física que conduz os gráficos foi gravada. Em muitos jogos, isso inclui os efeitos das partículas (o PhysX inclui alguns sistemas de partículas muito sofisticados.) Quanto ao som, suponho que isso seja gravado literalmente (como um fluxo de som), mas eu '
fonte
Sua idéia original está certa e, para os efeitos realmente complexos, eles não são lembrados exclusivamente. Por exemplo, o sistema de repetição do Warcraft 3 não armazena o estado das animações ou efeitos de partículas no caso de efeitos aleatórios, etc. Além disso, a MAIORIA das coisas pode ser computada computacionalmente a partir de um ponto de partida de maneira determinística, assim como na maioria dos sistemas que usam variáveis aleatórias (uma explosão de partículas que fornece um deslocamento aleatório, por exemplo), tudo o que você precisa é o tempo do efeito e a semente aleatória. Em seguida, você poderá gerar novamente o efeito sem realmente saber como ele será .. sabendo que ele está passando por um caminho de código determinístico.
Pensando nisso de maneira conceitual, para reproduzir uma linha do tempo de eventos, tudo o que você precisa são as ações do usuário. O programa reagirá exatamente da mesma maneira, exceto no caso de variáveis aleatórias. Nesse cenário, você pode ignorar a aleatoriedade (isso realmente importa se os efeitos parecem EXATAMENTE iguais, ou podem ser gerados aleatoriamente), ou armazenar o valor da semente e falsificar a aleatoriedade.
fonte
Jogue minhas duas moedas.
Depende do que você deseja, a reprodução pode ser realizada via
Na maioria das vezes, as pessoas querem um replay interativo, então 2. é o caminho a percorrer. Então, dependendo de suas restrições, existem várias maneiras de otimizar esse processo
É realmente um tópico fascinante. Lembro que um título de lançamento do Xbox Wreckless original tinha um bom recurso de reprodução. Infelizmente, em mais de uma ocasião, o replay estragou tudo;)
oh sim, como alguém poderia esquecer o Blinx Time Sweeper ! ótimo replay interativo que foi incorporado à mecânica do jogo!
* = parece que existem alguns comentários sobre o intervalo de tempo. Eu estou usando "simulação" aqui para capturar esse recurso. No núcleo, seu mecanismo precisa ser capaz de produzir períodos discretos de tempo. mesmo que um quadro de reprodução demore mais ou menos para ser processado do que o original, o sistema deve perceber que o mesmo delta já passou. isso significa gravar o intervalo de tempo do quadro com cada entrada gravada e fornecer esse delta ao relógio do seu motor.
fonte
Talvez você possa simplesmente salvar uma pilha de comandos enviados por cada jogador. Então, em vez de salvar que uma bomba detonar em um determinado ponto e tempo, ou que um determinado carro seja destruído, basta salvar as teclas pressionadas por cada jogador. Então, no replay, você simplesmente simula o jogo como teria acontecido com essas impressoras. Sinto que isso tem potencial para ocupar menos espaço, mas nunca trabalhei em um sistema de repetição como esse.
Pergunta interessante, no entanto. Eu estaria interessado em como isso é feito em jogos profissionais.
fonte
Dan Bryant
Foi exatamente o que pensei no começo, quando estava tentando descobrir como eles conseguiam, para que o jogo fosse sempre sempre o mesmo. Com Doom, pensei em quão aleatórios eram os tiros: D. Armazenar qualquer número aleatório se acostumou, eu descobri que poderia ser uma solução. Isso foi antes de me deparar com um documento em PDF sobre a tecnologia Crysis. Algumas texturas barulham lá e a disposição da grama ou da árvore, parecia estar usando a pseudo-randomização com sementes reversíveis fixas para torná-lo assim que você não via disposição alterada de ruído, árvores e grama sempre que olhava!
Evitando, ao mesmo tempo, armazenar milhões de árvores e posição das árvores. Aparentemente, a sequência pseudo-aleatória pode repetir o mesmo a qualquer momento, conforme a lógica é fixa, para criar uma sequência estatisticamente aleatória falsa de números.
fonte
O problema de ter um replay consistente é o mesmo (bem, mais fácil) do que ter um jogo multiplayer consistente.
Como mencionado anteriormente, os replays nos jogos RTS são armazenados gravando todas as entradas (isso tem um efeito. A rolagem não tem efeito.) O multiplayer também transmite todas as entradas
A gravação de todas as entradas e não apenas um palpite - há uma biblioteca para ler replays do Warcraft3 com isso.
A entrada inclui registros de data e hora para esta resposta.
fonte
Eu acreditaria que em certos incrementos o jogo tiraria um instantâneo do estado de tudo (TUDO). Então, quando a reprodução estiver ocorrendo, o uso simples de interpolação linear pode ser usado para preencher os "buracos". Pelo menos é assim que eu acho que seria feito.
Você está certo de que gravar as entradas não seria confiável / não garantiria a mesma saída. O jogo definitivamente precisa acompanhar o estado de todos os objetos (ou pelo menos os importantes)
fonte