Para começar, eu tenho uma boa experiência em redes (hardware, roteadores, ex.), Mas muito pouco conhecimento além dos conceitos básicos de programação de rede. Isso pode parecer uma pergunta estúpida, mas eu quero saber no que estou me metendo enquanto estuda a implementação do multiplayer no meu jogo.
Estou criando um mundo baseado em blocos, que é gerado através de uma simples matriz 2D. Digamos algo como Mundo [100] [100], por uma questão de simplicidade.
Atualmente, o método de renderização processa apenas os blocos com base na resolução da janela, além de um bloco (para renderização suave durante o movimento.) Não importa o tamanho do mundo, (10x10, 1 milhão x 1 milhão), a renderização é perfeita no desempenho.
A jogabilidade precisa de nada mais do que saber o que está atualmente visível (renderizado na tela +1) e, possivelmente, ALGUMAS informações de peças em uma área ao redor do jogador.
Portanto, qualquer coisa mais enviada pelo servidor não seria a informação completa do bloco. Ex. Itens colocados no chão, tipo de terreno, árvores, etc. não seriam importantes na área fora da vista do jogador, mas seriam apenas o que o Cliente / Jogador precisa saber nesses ladrilhos. (Por exemplo, os "nomes recebidos" de Ultima Online, onde os jogadores podiam conhecer um personagem [jogador ou monstro], estavam além dos ladrilhos em sua exibição renderizada.)
Eu não sei muito sobre redes, então talvez, ao descobrir isso, possa responder à minha pergunta. No entanto, estou curioso para saber se essa é uma solução viável ou se a idéia é simplesmente risível.
As informações enviadas seriam sobre uma área de 10x15 de blocos e cada bloco contém informações sobre o que está no bloco. Mais eficientemente, tudo seria um Objeto, onde o bloco contém todos os Objetos no bloco. Ex. Lado a lado [4] [4] contém Espada # 23452, Pedra2, Árvore5, Jogador3, Monstro4.
Ladrilhos vazios não enviariam nada além do tipo de terreno [Grama, Areia, Água] se ainda não estiver carregado durante a Inicialização / Carregamento. Algumas peças teriam um punhado de objetos [Árvore2, Espada # 924, Ouro, Cadáver, Rocha3].
Portanto, não consigo imaginar que um bloco tenha muitas informações para enviar ao cliente do servidor, pois o cliente precisa conhecer apenas a textura que precisa ser carregada e a posição para colocá-lo na tela. Posicione sendo apenas dois números inteiros e Texture sendo um número inteiro para uma lista de arquivos a serem solicitados ao cliente para renderização.
Na pior das hipóteses, o Servidor teria que enviar 150 blocos com informações de apenas um punhado de Objetos OnLOAD e, a partir de então, atualizar apenas alterações em blocos (se houver) e novos blocos (10 a 15 sempre que um jogador se mover em uma direção) ) e a direção do movimento dos caracteres na tela (para que o cliente possa simular movimentos suaves entre peças).
Suponho que estou certo ao pensar que se trata de uma quantidade incrivelmente baixa de informações enviadas pela Internet ou entre colegas, por isso deve ter pequenos problemas de desempenho, mesmo em conexões atrasadas? Ou sou tão ignorante em relação a redes que minha mente ficará abalada quando finalmente abrir meu livro sobre redes para vários jogadores?
Se houver uma quantidade muito baixa de informações sendo enviadas entre Cliente / Servidor, faria mais sentido simplesmente carregar o mundo inteiro na inicialização? Ou 'Mapa' se o mundo for excessivamente grande. E depois de LOAD, envie apenas blocos que são atualizados?
Ainda estou pensando em como devo lidar especificamente com dados. O livro que estou usando como referência deseja que eu tenha uma Lista Vinculada, onde adiciono e removo objetos, para que tudo seja booleano. "Existe um personagem? Existe uma árvore?"
Eu estava pensando em uma abordagem diferente, como um contêiner que contém objetos e a lógica do servidor que envia apenas o necessário para informar ao cliente o que renderizar. Possivelmente com objetos que contêm informações de rede em si, que são enviadas quando solicitadas pelo servidor.
Respostas:
Você está no caminho certo.
Considere o Minecraft. O Minecraft carrega apenas as áreas (também chamadas de pedaços) imediatamente ao redor dos jogadores. É assim que o servidor pode executar sem ficar sem memória e por que os clientes não ficam atolados no tráfego de rede.
É exatamente isso que você deve fazer. Envie apenas os dados que você precisa enviar.
Se você está apenas enviando uma matriz 2D de IDS de bloco, o tamanho dos dados pode ser muito baixo, especialmente se você tiver menos de 256 tipos diferentes de bloco. Nesse caso, você pode usar um único byte (ou caractere não assinado). Então, se você estiver enviando 100x100 blocos para o jogador, e cada bloco consiste apenas em um único byte ... Você entendeu. Não são muitos dados.
A comunidade Minecraft fez um trabalho maravilhoso ao documentar seu protocolo: http://mc.kev009.com/Protocol
http://www.minecraftwiki.net/wiki/Classic_server_protocol
fonte
Geralmente, é uma boa idéia enviar apenas as informações para o cliente, que devem ser mostradas ao jogador. Seguir esse princípio reduz o tráfego na rede e evita trapaças.
Mas lembre-se de que quando o jogador move seu personagem, você certamente deseja iniciar a jogada no lado do cliente antes de receber a confirmação do servidor para fazer com que o jogo pareça menos lento e mais responsivo. Isso provavelmente significa que você também deseja começar a rolar a tela para uma área que ainda não foi carregada. Isso força você a deixar esta parte do mapa em branco e substituí-la pelo mundo real quando estiver carregado. Isso seria um grande quebra-imersão. Por esse motivo, você deve pré-carregar a área em um determinado raio ao redor da tela dos jogadores.
O tamanho da área pré-carregada depende da rapidez com que seus jogadores podem se mover e de quanto tempo será a latência média.
fonte
A quantidade de dados que você está enviando do servidor para o cliente pode ser incrivelmente insignificante. Se isso é tudo o que você precisa enviar, sugiro veementemente carregar o máximo possível no Load, portanto, são necessários menos dados ainda. A quantidade enviada no carregamento será pequena o suficiente para justificar o tempo de carregamento, o uso da memória será quase inexistente, a menos que seu mundo seja ridiculamente superdimensionado e você precise atualizar quase nenhum dado.
Eu imagino que você também possa fazer alguns truques para otimizar a previsão de atraso, o que compensa o atraso médio que um usuário experimenta, permitindo movimentos previsíveis com os personagens.
Também a priorização de dados insignificantes, com movimentos e ações / reações de personagens com maior prioridade, pode ajudar a garantir que até jogadores atrasados sintam muito pouco atraso.
fonte