sexta-feira, 10 de julho de 2015

Jogo no servidor e cliente

O servidor e o cliente do nosso jogo funcionam em cima de uma mesma estrutura básica, mas há diferenças grandes entre eles.

Para começar, nosso servidor deve ser anti-cheating. O player pode alterar sua posição de um jeito "ilegal" e mandar para o servidor e... Opa, devemos tratar isso. E se ele quiser roubar uns pontos de vida? Para evitar isso, usamos um servidor autoritário: o cliente envia inputs para o servidor e desenha na tela, além de atualizar localmente o que recebe remotamente, enquanto nós processamos tudo.


Isso impacta em diferentes componentes para os dois. Por exemplo, ambos as entidades player do servidor e cliente tem a componente Health, mas enquanto uma atualiza quando há colisões, a outra só é utilizada como get/set e para saber quando o player morre (quando é atualizada para zero).

Um problema chave quando tratamos de servidores remotos é o lag, ou seja, o atraso do cliente em relação ao servidor. Isto porque um cliente (digamos 1) executa um comando, envia para o servidor, o servidor confirma o comando, e reenvia para todos os clientes. Mas quando o cliente 1 recebe sua posição do servidor, ele já está em outro lugar. Pior para um cliente 2, que vê o jogo atrasado.

Delay entre a ação do player, o envio para o servidor e o recebimento de confirmação
Uma opção é só movimentar ao ter os movimentos confirmados, mas o cliente iria perceber um lag muito grande. Há formas de tratar isto, e você pode ler mais sobre elas aqui: (http://www.gabrielgambetta.com/fast_paced_multiplayer.html). Na versão atual do jogo, ainda tratamos de modo ruim: quando o cliente aperta inputs, ele se move localmente e envia para o servidor, que reaplica os inputs e reenvia para o cliente, que sincroniza, ainda sem predição.

JavaScript V8 (interpretador usado pelo NodeJS) tem a vantagem de ser relativamente rápida comparada a outras linguagems. Uma comparação mais completa pode ser encontrada neste link: (http://raid6.com.au/~onlyjob/posts/arena/).

Comparação entre tempo de execução de linguagens em segundos para determinada tarefa.
No entanto, uma das dificuldades que só percebemos depois está relacionada a escalabilidade: os processos em JS ocorrem em thread única. Por isso, talvez seja vantajoso migrar posteriormente para uma linguagem multi-thread como C++.

Até mais!

Nenhum comentário:

Postar um comentário