Networking Pong Clone

10

Eu tenho os fundamentos dos soquetes TCP, comunicação UDP etc., mas não consigo encontrar muito sobre como aplicá-los a um ambiente de jogo em tempo real.

Eu tenho um clone Pong, com 4 jogadores, e preciso sincronizar as posições de remo entre os três clientes e o servidor (o servidor é o quarto jogador). Atualmente, uso o UDP para enviar atualizações em tempo real (movimentos de remo) e o TCP para configurar o lobby do jogo etc.

É uma coisa ruim estar enviando spam enormes quantidades de tráfego UDP? Devo procurar algo como o DCCP por seus recursos de congestionamento? Ou isso não é realmente um problema com um projeto de pequena escala como esse?

Quando as mensagens de sincronização devem ser enviadas entre cliente / servidor? Atualmente, o servidor está enviando spam pacotes UDP com o estado atual do jogo o mais rápido possível, e os clientes enviam sua posição de remo para o servidor o mais rápido possível. Esse é o melhor jeito de fazer isso? Há algum tipo de atraso que devo adicionar para que as mensagens sejam enviadas uma vez a cada X milissegundos ou devo enviar apenas mensagens à medida que os eventos acontecem? (por exemplo, velocidade da pá alterada devido à entrada do usuário)

Seria melhor fazer com que os clientes comuniquem suas posições de remo entre si, ponto a ponto?

Estou fazendo essas perguntas no contexto de Pong, mas também estou interessado em saber como esses problemas seriam superados em outros jogos ou soluções generalizadas.

elwyn
fonte
Preocupe-se, logo após postar eu vi isso: gamedev.stackexchange.com/questions/249/…
elwyn
Outra pergunta vagamente relacionada: gamedev.stackexchange.com/questions/552/…
Smashery

Respostas:

5

Tenha um intervalo de atualização configurável (para que você possa ajustar 5 pacotes por segundo ou 20) e cada quadro verifique se é hora de enviar uma atualização. Você pode concordar com um jogo simples enviando pacotes para cada evento, mas em um jogo mais complexo isso não é prático. Lembre-se também de que há um overhead de pacotes; portanto, se você estiver enviando vários pacotes pequenos, desperdiçará largura de banda.

Cada intervalo de atualização faz com que cada cliente envie sua posição de remo para o servidor ou para cada cliente (ponto a ponto). Peça ao servidor que também envie a posição da bola e um vetor de velocidade. Cada cliente pode executar o mesmo código de desenho da tela do modo single player, para que o movimento da bola seja suave. No modo multiplayer, embora você tenha apenas o servidor, envie as atualizações de posição / velocidade para a bola em um intervalo regular (e se você quiser cada vez que ela acertar alguma coisa).

Faça com que as atualizações de posição da bola façam referência a um tempo de jogo em todos os clientes, para que você possa descartar pacotes fora de ordem e até tornar a interpolação da posição das bolas mais precisa (você sabe a posição e a velocidade em um horário específico no passado, para poder interpolar o novo posição).

Com este modelo com um jogo lento, você pode ver a bola se mover para trás algumas vezes ou pular um pouco. Mas com uma conexão decente, deve ser bem suave.

kevin42
fonte
5

Em relação às preocupações com o tráfego - você deseja evitar o envio de mais de 20 a 30 pacotes por segundo por ponto. No caso geral, se você enviar pacotes menores e com menos pacotes, experimentará (ligeiramente) menos latência e uma chance menor de pacotes descartados.

Definitivamente, você não deseja enviar atualizações a uma velocidade mais rápida que a taxa de quadros, pois os jogadores não poderão dizer a diferença - na verdade, se você enviar pacotes apenas 10 vezes por segundo e interpolar / extrapolar os resultados no final de recebimento , a maioria dos jogadores não notará diferença.

Blair Holloway
fonte
4

Essa é uma pergunta bastante ampla, mas tentarei resumir os aspectos importantes.

A primeira decisão a ser tomada no código de rede para o seu jogo é se você deseja uma configuração de cliente / servidor de uma organização ponto a ponto. A maioria dos jogos, com o RTS provavelmente sendo a única exceção notável, provavelmente está usando uma arquitetura cliente / servidor. A principal vantagem é que esse arranjo é mais tolerante a falhas e fornece mais controle sobre os dados que cada cliente recebe. Ponto a ponto permite enviar muito menos dados, mas exige que cada ponto simule completamente o mundo exatamente como qualquer outro ponto. Se um dos pares atrasar ou dessincronizar, todos deverão esperar que eles se recuperem ou eles simplesmente estarão perdidos.

O UDP também é geralmente a escolha correta, certamente para qualquer modelo de cliente / servidor. O TCP pode ser prático para um jogo ponto a ponto, mas mesmo assim o UDP pode ser uma escolha melhor. Basicamente, o UDP lida menos com você, o que significa mais esforço, mas também mais controle sobre como você lida com falhas.

Para Pong, a escolha que eu faria é cliente / servidor, sendo um jogo orientado à ação. Uma coisa a ser observada aqui, mesmo que você diga que um jogador "é o servidor", é melhor estruturar seu código de modo que eles estejam executando um servidor local e se conectando a ele como cliente.

Você definitivamente não quer receber atualizações de "spam" em nenhuma direção. Uma atualização do servidor por quadro é tudo o que é necessário e o servidor deve estar executando a uma taxa de quadros fixa. Depende de você, mas não há necessidade de exagerar. Um quadro de 50ms (20 FPS) é suficiente para obter um bom jogo. Para manter as coisas tranqüilas no cliente, você deseja fazer uso da interpolação. O cliente deve estar constantemente em transição entre os instantâneos de quadro do servidor, embora isso possa ser facilmente o tópico de uma pergunta separada.

As atualizações do cliente também devem ser limitadas, embora uma por quadro provavelmente seja demais se o seu cliente estiver executando a uma taxa de quadros decente.

Jason Morales
fonte
1

Você se importa com trapaça?

Caso contrário, ir ponto a ponto reduzirá pela metade o atraso, pois é A <-> C em vez de A <-> B <-> C. Em caso afirmativo, para ser justo na sincronização, você pode querer tornar a resposta um tanto demorada para o jogador local, ou o que a maioria dos jogos faz - deixe o jogador fazer o que quer localmente e depois retroceda se o resultado do servidor divergir do simulado localmente.

Um clone de pong é na verdade um pouco complicado, porque, diferentemente da maioria dos jogos, você não pode (como desenvolvedor) trapacear fazendo com que um lado veja um sucesso e o outro não.

Quanto a algo generalizado, uma técnica que eu ouvi falar, mas que não achei necessária (pode ser para jogos de ação) é manter as ações com seus carimbos de data / hora verdadeiros (tempo de recebimento - ping / 2) e fazer o servidor reverter ( snap) se um evento anterior ocorrer e reaplicar ações posteriores. Dessa forma, todos são consistentes localmente, a menos que haja algum conflito devido às interações dos diferentes jogadores. O único perigo é a capacidade de "reverter o tempo" se eles falsificarem uma conexão atrasada.

James Bellinger
fonte
1

Cálculo morto do Google. Enviar atualizações para 4 jogadores não será significativo. A quantidade de dados enviados será da ordem de bytes. Portanto, isso significa que atualizações freqüentes devem estar ok. Com o acerto de contas morto, você move o player no cliente e no servidor. O servidor é a autoridade. Quando a posição do cliente fica muito fora de sincronia do servidor, ela precisa voltar ao alinhamento. http://trac.bookofhook.com/bookofhook/trac.cgi/wiki/Quake3Networking O uso do UDP é o caminho a percorrer. Bupdates serão enviados com frequência para que os dados perdidos sejam substituídos em breve pelos dados recebidos. A retransmissão de pacotes do TCP não vale a pena para a posição do jogador. Consulte este artigo para obter mais informações sobre como manter o cliente e o servidor sincronizados.

zooropa
fonte
-1, conteúdo baixo e atualmente incorreto. É acerto de contas morto .
Tetrad
Removido meu voto negativo.
Tetrad
0

Programei um jogo de pong em rede local para 2 jogadores há algumas semanas, eis como eu o fiz:

- Um lado abre um servidor, o outro se conecta automaticamente - ambos estão enviando as pás x posição um para o outro a 60fps ou menos [UDP] - se um lado bate na bola, eles decidem sobre a nova velocidade e posição das bolas e enviam isso para o outro [TCP] - se a bola passa por uma raquete, o jogador que errou entra em contato com o outro com uma mensagem de aumento de pontuação e a bola é redefinida [TCP] - a bola está sendo simulada independentemente o tempo todo, o que combina com a física simples das bolas de pong

Isso cria aproximadamente 0,3 a 0,5 KByte / s de tráfego a 60fps e os jogadores não têm atraso em sua percepção, mas apenas se o ping estiver abaixo de um determinado limite, porque a nova posição das bolas precisa ser transmitida.

Também é fácil trapacear com este sistema e há uma grande possibilidade de ficar fora de sincronia com uma conexão muito perdida, mas quem se importa em trapacear no pong ?!

VaTTeRGeR
fonte