DevSecOps

1 mar, 2017

Desenvolvimento de jogos em rede – Parte 02: arquitetura cliente-servidor

Publicidade

Olá, pessoas! No último artigo começamos a ver a arquitetura P2P (Peer-to-Peer). Neste tipo de arquitetura, todas as suas ações são enviadas para todos os jogadores e cada computador processa os comandos na própria máquina. No artigo de hoje, vamos conhecer a arquitetura Cliente-Servidor.

Depois da era dos primeiros RTS como Age of Empires, os jogos multiplayers começaram a se expandir para outros gêneros, e chegou em um FPS muito famoso na época: DOOM.

No DOOM, as limitações do modelo P2P começaram a mostrar as suas limitações. No jogo, cada entrada que o jogador executava (como apertar o botão para avançar, entre outras ações) era enviada para os outros jogadores. Assim, a simulação só ocorria no computador quando todos os outros comandos chegavam, para poder passar de turno. Essa estratégia funcionou quando estava em uma Rede LAN, mas falhou miseravelmente na Internet da época, a época da Internet discada.

Você não está só enviando pela Internet com baixa velocidade 1 pacote, mas N-1 pacotes e recebendo N-1 dos outros jogadores. Era muito tráfego para a velocidade da época. Como nas conexões P2P, a velocidade do jogo é sempre sincronizada com aqueles que tem a maior latência, isso prejudicava o jogo de todos. Para evitar isso, os desenvolvedores de Quake resolveram utilizar uma arquitetura Cliente-Servidor ao invés do P2P.

A arquitetura

Então, ao invés de enviar os comandos para todo mundo e cada computador realizar a simulação, agora temos um computador central. Ele será responsável por receber os dados de todos os jogadores, realizar as simulações e então devolver a eles o resultado da simulação.

No modelo puro, os computadores dos jogadores seriam terminais burros, terminais onde não possuem processamento, senão as atualizações enviadas do servidor. Isso reduz o tráfego gerado: agora cada jogador só se comunica com o servidor. Logo, o único computador que precisa ser robusto é o servidor.

Outra vantagem em relação ao P2P é que, como a conexão é feita somente com o servidor, o jogo não vai ser executado no passo do jogador com maior latência. Portanto, qualquer lag que ocorrer na experiência está relacionado apenas com a conexão do usuário e o servidor. Outra vantagem é que diferente dos jogos P2P, que necessitam de um lobby para reunir os jogadores antes da partida, a arquitetura Cliente-Servidor permite facilmente conectar um jogador a qualquer momento, sendo perfeito para os MMOs.

Entretanto, o modelo tem um ponto fraco: na percepção do usuário, é possível perceber um atraso entre o comando e o movimento do avatar do jogador. Isso ocorre porque quando o usuário entra com um comando, ele é enviado para o computador. Ou seja temos a latência de envio (vamos chamar de “le”). Então o comando é processado, no que pode levar um tempo “ex”, e logo o servidor manda a resposta, que leva um tempo “lr”. Logo, a diferença de quando o evento de comando ocorreu e sua atualização no computador do jogador tem a duração de (le+ex+lr). Já em uma conexão P2P levará apenas o tempo dele para para ser atualizado. Entretanto, algumas medidas podem ser tomadas para evitar isso.

Predição do estado de jogo no cliente

Para se ter melhor fluxo nas atualizações, podemos criar um artifício chamado de predição: dando um pouco de autonomia para o cliente para prever o resultado final do comando. Ou seja, se o jogador deu o comando para seguir em frente, o jogo fará o jogador seguir em frente imediatamente, prevendo que o mesmo ocorrerá no servidor.

Enquanto isso, o comando é processado no servidor e retorna o resultado para o cliente. Aí é que entra o pulo do gato. O cliente vai utilizar do resultado do servidor para validar sua previsão. Se a previsão for validada, o jogo simplesmente continua, entretanto se a previsão for diferente do que ocorreu no servidor, o cliente vai corrigir a situação do jogo para estar conforme o servidor.

Essa é uma situação interessante, pois quando o cliente e o servidor não concordam entre si, o servidor sempre terá a razão. Você deve estar pensando agora: e se fizéssemos o cliente ter autonomia total sobre o personagem e mandássemos apenas a atualização? Esse realmente seria um método mais simples, mas também é mais vulnerável. Permitindo esse nível de autonomia no cliente facilitaria a criação de programas de trapaças, pois basta alterar os dados antes de ser enviado por pacote para o servidor. Com um modelo onde o servidor tem autoridade, fica muito mais difícil trapacear, pois se a alteração irregular do estado de jogo no cliente não condizer com o estado do jogo do servidor, o cliente vai ser resetado para o estado do servidor.

Conclusão

Então é isso, pessoal. Hoje vimos como funcionam os jogos que utilizam o modelo Cliente-servidor. Pelas comparações que temos junto ao artigo do P2P, podemos dizer que ambos tem suas vantagens e desvantagem e valem a pena conhecê-los e aprender sobre ele. P2P pode não ter a capacidade de um modelo cliente-servidor, mas é muito fácil desenvolver esse modelo. Já o cliente-servidor permite maior número de conexões, mas a dificuldade de desenvolvimento é muito maior.

Nos próximos artigos vou explicar os tipos de conexões (UDP e TCP) e como eles afetam o desenvolvimento. Até lá!