Estou escrevendo um jogo que tem muitos aspectos baseados em tempo. Uso o tempo para ajudar a estimar as posições dos jogadores quando a rede está parada e os pacotes não estão passando (e o tempo entre o recebimento e não do pacote). É um jogo do tipo pacman, no sentido em que um jogador escolhe uma direção e não consegue parar de se mover, de modo que o sistema faz sentido (ou pelo menos eu acho que sim).
Portanto, tenho duas perguntas: 1) Como sincronizo os relógios dos jogos desde o início, pois há um atraso na rede. 2) Não há problema em sincronizá-los e apenas assumir que eles são os mesmos (meu código é independente do fuso horário). Não é um jogo super competitivo, onde as pessoas mudam seus relógios para enganar, mas ainda assim.
O jogo está sendo programado em Java e Python (desenvolvimento paralelo como um projeto)
Respostas:
Eu acho que definitivamente não é bom sincronizar o relógio no sistema . O usuário não espera que você toque nas configurações do sistema e muitos sistemas nem permitem.
Tudo o que você precisa é ter uma correlação para converter o registro de data e hora do relógio de um lado para o relógio do outro lado. Por outro lado, você precisa que essa correlação seja bastante precisa, digamos pelo menos até um centésimo de segundo, se você quiser usá-la para prever as posições dos jogadores. O relógio do sistema nunca estará tão bem correlacionado entre máquinas aleatórias. Portanto, você mesmo deve estabelecer a correlação, usando alguma variação no tema NTP , provavelmente incorporado em outras mensagens para economizar a largura de banda da rede.
A idéia básica pode ser que, em cada pacote enviado, você tenha enviado o carimbo de data / hora, o número de sequência e o carimbo de data e hora quando recebeu o último pacote do outro lado. A partir disso, você calcula a viagem de ida e volta: por exemplo, se o pacote Q diz que foi enviado em 1000 e o pacote P foi recebido em 500, então, se você enviou o pacote P em 0 e está recebendo Q em 800, a viagem de ida e volta é (800 - 0 ) - (1000 - 500) = 300. Não há como saber a assimetria, portanto, você assume que o pacote leva metade (150) tiques em qualquer direção. E esse timestamp remoto está à frente do local em 1000 - (800 - 150) = 350 ticks. A viagem de ida e volta varia. Se você presumir que o relógio é razoavelmente preciso, use uma média de longo prazo da correlação.
Observe que você também não deseja usar o relógio do sistema. Eles podem ser ressincronizados no meio do caminho, tirando você dos trilhos. Você deve usar
clock(CLOCK_MONOTONIC)
no Unix ouGetTickCount
no Windows (não tenho certeza de como essas APIs estão agrupadas em Java ou Python agora).Nota: A
SO_TIMESTAMP
opção socket (consulte o socket (7) mencionado por ott-- no comentário sobre a pergunta) seria útil para separar o efeito da latência do loop de eventos que recebe os pacotes. Se vale a pena o esforço depende de quão boa precisão você precisa.fonte
Como você sabe qual relógio do jogador está correto? Você não precisa, então use um relógio de referência .
O NTP é um exagero aqui - você só precisa de ~ 1 segundo de precisão - então use rdate ou escolha algo de um dos muitos algoritmos de sincronização de relógio.
Quando você escolher um método, faça com que a máquina de cada jogador pegue o tempo por esse método (sem alterar o relógio do sistema). Qualquer diferença entre a hora UTC de referência e a hora UTC do relógio do sistema dos jogadores é o seu deslocamento efetivo. Sempre que você faz cálculos relacionados ao tempo para, por exemplo, extrapolar movimentos de bots ou marcadores de rastreamento de raios, você considera esse deslocamento após obter a hora do sistema. O uso do UTC eliminará os fatores de fuso horário.
fonte
Eu segundas afirmações de que você não deve usar o NTP ou aproximar-se do relógio do sistema para isso. Se você realmente examinar esse requisito, descobrirá que possui as seguintes necessidades:
Este é um esboço simplificado - não tento lidar com questões como latência / pacotes descartados / etc - mas é a estrutura básica na qual tudo deve se basear.
Nada disso precisa se aproximar do relógio do sistema ou se preocupar com assuntos como fusos horários diferentes, embora o último item possa usar um fuso horário, se desejado. O importante é que os tempos reais passados sejam medidos usando um timer baseado em zero de alta resolução, para que sejam completamente independentes das diferenças de fuso horário. Deseja encontrar a hora atual real no servidor? Basta adicionar o tempo decorrido ao tempo base de referência e você terá. Da mesma forma para o cliente.
fonte