Tutorial Multiplayer 3 Pong Este Tutorial Assume Que Você Já Leu Tanto Multiplayer Tutorial 1

12
Este tutorial assume que você já leu tanto Multiplayer tutorial 1: concepts quanto Multiplayer tutorial 2: chat room . O primeiro tutorial cobriu a teoria de como os jogos multiplayer funcionam e a maneira como eles devem ser concebidos, usando técnicas como a previsão de entrada local e compensação de lag. O segundo tutorial cobriu um exemplo prático de uma sala de bate-papo, que lidava com uso prático de sinalização, de conectividade e envio de mensagens. Este tutorial vai agora cobrir um caso simples de sincronização de objetos em tempo real para um jogo multiplayer, estilo pong, entre 2 jogadores. Este é um tutorial avançado; se você já não está confortável com o seu conhecimento, pondere fazer uma revisão dos tutoriais anteriores. Para começar, abra Exemple: Multiplayer - pong que vem com Construct 2. Isto pode ser encontrado na caixa de diálogo Select template or example que se abre quando pressionando File - New. Tal como no tutorial anterior, o projeto será descrito evento-a-evento com mais detalhes do que os comentários já existentes no projeto. Rodando e testando Como com o exemplo de chat, o exemplo do jogo em tempo real também deve ser executado a partir do primeiro layout (F4), uma vez que necessita de um nome válido inserido a partir do layout de Login. Este exemplo usa salas de auto-joining. Quando os jogadores entram no jogo eles são emparelhados nos jogos, uma vez que ele só funciona com dois jogadores por jogo. Isto será descrito com mais detalhe posteriormente. Se você entrar no jogo, você poderá encontrar outra pessoa executando o tutorial por acaso, ao mesmo tempo; se não, ou caso você não possa se conectar a ela, tente testar com um amigo ou apenas abra duas janelas do navegador, lado-a-lado. Layout Login Este layout é praticamente idêntico ao do layout de login da sala de chat do tutorial anterior. Ela simplesmente serve para permitir que o usuário digite um nome em uma caixa de texto. O nome de usuário é armazenado em uma variável global e usado para fazer login no servidor de sinalização no próximo layout. Layout Game O layout Game agora tem um objeto para o "paddle" (raquete) do "host" à esquerda e a bola. Quando um cliente (adversário) se junta, seu "paddle"

description

ddddddd

Transcript of Tutorial Multiplayer 3 Pong Este Tutorial Assume Que Você Já Leu Tanto Multiplayer Tutorial 1

Page 1: Tutorial Multiplayer 3 Pong Este Tutorial Assume Que Você Já Leu Tanto Multiplayer Tutorial 1

Este tutorial assume que você já leu tanto Multiplayer tutorial 1: concepts quanto Multiplayer tutorial 2: chat room.

O primeiro tutorial cobriu a teoria de como os jogos multiplayer funcionam e a maneira como eles devem ser concebidos, usando técnicas como a previsão de entrada local e compensação de lag. O segundo tutorial cobriu um exemplo prático de uma sala de bate-papo, que lidava com uso prático de sinalização, de conectividade e envio de mensagens. Este tutorial vai agora cobrir um caso simples de sincronização de objetos em tempo real para um jogo multiplayer, estilo pong, entre 2 jogadores. Este é um tutorial avançado; se você já não está confortável com o seu conhecimento, pondere fazer uma revisão dos tutoriais anteriores.

Para começar, abra Exemple: Multiplayer - pong que vem com Construct 2. Isto pode ser encontrado na caixa de diálogo Select template or example que se abre quando pressionando File - New. Tal como no tutorial anterior, o projeto será descrito evento-a-evento com mais detalhes do que os comentários já existentes no projeto.

Rodando e testando

Como com o exemplo de chat, o exemplo do jogo em tempo real também deve ser executado a partir do primeiro layout (F4), uma vez que necessita de um nome válido inserido a partir do layout de Login.

Este exemplo usa salas de auto-joining. Quando os jogadores entram no jogo eles são emparelhados nos jogos, uma vez que ele só funciona com dois jogadores por jogo. Isto será descrito com mais detalhe posteriormente. Se você entrar no jogo, você poderá encontrar outra pessoa executando o tutorial por acaso, ao mesmo tempo; se não, ou caso você não possa se conectar a ela, tente testar com um amigo ou apenas abra duas janelas do navegador, lado-a-lado.

Layout Login

Este layout é praticamente idêntico ao do layout de login da sala de chat do tutorial anterior. Ela simplesmente serve para permitir que o usuário digite um nome em uma caixa de texto. O nome de usuário é armazenado em uma variável global e usado para fazer login no servidor de sinalização no próximo layout.

Layout Game

O layout Game agora tem um objeto para o "paddle" (raquete) do "host" à esquerda e a bola. Quando um cliente (adversário) se junta, seu "paddle" será criado no lado direito. Ambos os jogadores sempre verão o "host" do lado esquerdo e o cliente (o segundo jogador a juntar-se) à direita.

A área de texto ChatLog foi substituída por um objeto Text comum, de modo que os objetos possam ser vistos abaixo dele. Uma matriz (array) é usada para simular o rolamento das mensagens para cima, que será descrito em mais detalhe brevemente.

Os eventos para este layout lidam com os mesmos eventos de sinalização que o exemplo anterior de chat fez. No entanto, acima disso ele também lida com a sincronização dos "paddles" e da bola em tempo real. Para simplificar este exemplo não incluímos um chat, portanto, o jogador apenas entra com as posições do seu "paddle", controlado pelo mouse. Também para simplificar, não há compensação lag. Se houver alta latência, o jogador à direita pode perder a bola, mesmo que ele a veja rebater, porque somente o "host" testa as colisões e ele estará vendo a conexão com um longo atraso. Uma vez que o assunto compensação de lag pode ser um pouco complicado, não vamos lidar com ele neste tutorial - o quarto tutorial (jogo em tempo real) lidará. O jogo deve funcionar bem em conexões de baixa latência, como LANs.

Este é um exemplo relativamente complexo, com um total de 40 eventos. Nós vamos começar a olhar para estes eventos na próxima página.

Page 2: Tutorial Multiplayer 3 Pong Este Tutorial Assume Que Você Já Leu Tanto Multiplayer Tutorial 1

Eventos do Jogo

Como no exemplo de chat temos constantes globais para o jogo, instância e nome da sala. Estes nos permitem mudar convenientemente os nomes no servidor de sinalização sem ter que pesquisá-los através de nossos eventos. No entanto, também temos uma nova global para o estado do jogo. O primeiro jogador a ingressar na sala precisa esperar até que alguém com quem jogar também se junte. Então o jogo vai dizer "get ready" e depois "GO!". Esta variável global contém o estado atual.

Grupo Message Log

O exemplo de chat anterior usou um objeto Text Box definido em modo textarea como a base para o chat e o log de informações. No entanto, é um objeto opaco que iria obscurecer o layout se usado neste exemplo. Em vez disso, usamos um objeto de texto comum chamado LogText para mostrar mensagens de log. No entanto objetos de texto normais não suportam rolagem. Para que tenhamos segurança de que as mensagens continuam a ser exibida mesmo quando elas saem para fora da parte inferior do objeto, vamos implementar o nosso próprio sistema de rolagem. Isso é feito usando uma matriz para armazenar uma linha de texto em cada índice da matriz, e em seguida, deletando o primeiro item ao deslocá-lo para cima. Este não é especificamente relacionado com jogos multiplayer, mas é uma técnica útil de aprender de qualquer maneira.

A função AddLog acrescenta uma nova linha, adicionando-a no final da matriz ("push back"). Se houver mais de 20 linhas, ele exclui a primeira linha ("pop front ") - então a primeira linha irá desaparecer da vista. Depois disso, repomos totalmente o conteúdo do objeto LogText: primeiro ele é limpo até esvaziar, então interagimos com a matriz e adicionamos em ordem cada linha no objeto. O resultado final é que cada vez que chamamos AddLog, uma nova linha é adicionada ao final do objeto LogText, e ele rolará para cima quando atingir 20 linhas.

Open full size image

Agora nós podemos chamar AddLog no objeto Function de qualquer outro lugar na folha de eventos para adicionar convenientemente mensagens com rolagem em LogText.

Page 3: Tutorial Multiplayer 3 Pong Este Tutorial Assume Que Você Já Leu Tanto Multiplayer Tutorial 1

Grupo Signalling

Este grupo é semelhante ao exemplo de chat anterior, em que se trata da conexão ao servidor de sinalização, login, ingresso em uma sala e determinar se é o "host". No entanto, existem algumas diferenças fundamentais, agora que estamos lidando com objetos e sincronização em tempo real.

Primeiro de tudo, em On start of layout devemos configurar os objetos e dados que vão ser transmitidos. A primeira ação configura as entradas que os clientes enviam para o anfitrião. Para evitar fraudes (cheat), os clientes só enviam suas entradas para o host, que realiza os testes de colisão reais com os "paddles" e a bola. A única entrada que o cliente tem é a posição vertical (Y) do seu "paddle".

Open full size image

As entradas que os clientes enviam para o host são chamadas client input values. Neste caso, usamos uma entrada que nós nomeamos "y", para a posição Y do "paddle". Ele usa um inteiro de 16 bits, uma vez que só usa dois bytes e posições sub-pixels não importam. O valor de entrada também utiliza interpolação Linear. Isso significa que mesmo que as atualizações estejam vindo para o "host" com pouca frequência, o motor multiplayer pressupõe um valor intermediário assumindo que o "paddle" está se movendo de forma linear. Isso garante que o movimento da raquete seja suave. Se nós escolhermos None para a interpolação, o movimento de remo poderia muitas vezes parecer agitado.

A próxima parte do evento configura quais objetos e quais de suas variáveis de instância são sincronizados.

A primeira ação usa o objeto Multiplayer Sync object. Esta é a ação chave para indicar quais objetos devem ser enviados através da rede. Sincronizar um objeto é Uma Via de Mão Única: isso significa que o Host Informa aos Clientes quantos desses objetos existem e onde eles estão. Clientes só recebem esses dados e quaisquer alterações que os clientes fazem a estes objetos será ignorada e substituído! Os valores de entrada do cliente são as únicas maneiras que os clientes têm de afetar o jogo, e os únicos dados do jogo são os enviados a partir dos clientes para o host.

O "host" tem a versão oficial do jogo, e os clientes estão fazendo o seu melhor para mostrar o que o "host" tem. O "host" é o único responsável por criar, mover e destruir estes objetos; assim que ele faça isso, Sync object também fará com que os objetos sejam criados, movidos e destruídos pelos clientes conectados. Tudo isso acontece internamente no motor multiplayer, como conseqUência dessa ação.

Uma vez que Sync object moverá os objetos por si só, e somente o "host" está "realmente" executando o jogo, os clientes também desativam todos os comportamentos nos objetos. Por exemplo, a esfera tem o comportamento de bala (Bullet behavior). Apenas o "host" deve ter o comportamento habilitado. O comportamento da bala deve ser desativado quando atua como um cliente, uma vez que Sync object já estará movendo-o como ele se move no "host", e ter o comportamento ativado no cliente poderia fazer com que o comportamento entre em conflito com o que Sync object estiver tentando fazer. Neste exemplo, o comportamento de bala inicialmente está desativado, e ele estará habilitado nos eventos quando atuando na qualidade de "host".

"Sync object" pode atualizar a posição ou ângulo do objeto, ambos, ou nenhum. Neste caso, estamos interessados apenas na posição, uma vez que o ângulo do objeto não é importante para a jogabilidade e seria

Page 4: Tutorial Multiplayer 3 Pong Este Tutorial Assume Que Você Já Leu Tanto Multiplayer Tutorial 1

um desperdício de largura de banda enviar dados sobre ângulos de objetos. O parâmetro "Bandwidth" (largura de banda) permite que a taxa máxima de atualização do "host" possa ser reduzida. Isto normalmente não é necessário - consulte o manual para saber mais sobre a opção.

"Sync object", por padrão, não transmite quaisquer outros dados, e variáveis de instância não são atualizadas. Seria um desperdício atualizar automaticamente cada variável de instância, uma vez que algumas delas só podem ser usadas localmente. Após o uso de Sync object, nós podemos, opcionalmente, usar qualquer número de ações Sync instance variable para adicionar variáveis de instância para o "host" enviar também a seus clientes (e assim como "Sync Object", as variáveis de instância são atualizados automaticamente). É importante notar que Sync instance variable só pode ser usada depois de Sync Object. Por si só ele não faz nada; a ação significa "sincronize também esta variável para os objetos já sincronizados".

A única variável que sincronizar neste caso é points, variável do objeto "Paddle". Esta é uma maneira simples para que todos saibam pontuação de cada jogador.

A tag com o valor do cliente é usada se a variável de instância também corresponde a um valor de entrada do cliente. Isso não é necessário neste exemplo, mas é tratado no próximo tutorial.

O objeto bola também deve ser sincronizado, de modo que o jogador possa ver onde ela está! No entanto, não há necessidade de sincronizar outra coisa senão a sua posição.

Agora que todas as entradas do cliente e objetos sincronizados foram ajustados, a última ação em On start of layout é conectar-se ao servidor de sinalização.

O restante do grupo Signalling é similar ao exemplo de chat; no entanto ainda existem mais algumas diferenças para vir. Primeiramente como antes, uma vez conectados, ingressamos com nosso nome de usuário.

Open full size image

Para entrar no jogo, uma diferença é que usamos Auto-join room em vez de Join room. Se nós só usamos Join room, então todos acabam no mesmo jogo. 30 jogadores em um jogo que suporta apenas dois jogadores não é muito útil! Ao usar Auto-join room, uma vez que um quarto está cheio, os próximos jogadores a se juntar são enviados para uma nova sala. Neste caso, 30 jogadores agrupados serão designados para 15 jogos de 2 jogadores separados. Bloquear a sala quando cheia, também previne clientes atrasados; isso significa que uma vez que a sala está cheia, mesmo que alguns jogadores saiam, ninguém mais será adicionado ao jogo. Se a sala ficou desbloqueada um cliente recém logado pode ser enviado para a mesma sala, para preenchê-la novamente, mas como isso significa ter que lidar com clientes atrasados, vamos ficar com a simplicidade.

Page 5: Tutorial Multiplayer 3 Pong Este Tutorial Assume Que Você Já Leu Tanto Multiplayer Tutorial 1

Open full size image

Uma vez dentro, estabelecemos se somos o "host". Fazemos o mesmo que no exemplo de chat: ou o grupo Host ou o Peer é ativado. No entanto, também precisamos lidar com o "paddle" e a bola existentes no layout, dependendo se nos tornamos "host". Se nós somos um cliente (peer), é fácil: nós apenas destruímos os objetos existentes no layout. O objeto "Sync" irá automaticamente criar, mover e destruir quaisquer objetos que estão presentes no host, incluindo o objeto que representa o nosso próprio jogador. O jogo também será iniciado apenas depois de nós nos juntarmos como um cliente, uma vez que o "host" já está lá, portanto, nós imediatamente definiremos o estado do jogo para "getready".

No entanto, quando formos o "host", adotamos o objeto "paddle" existente no layout como o nosso próprio objeto que controlamos. O objeto "paddle" tem uma variável de instância peerid. Esta armazena o ID atribuído ao cliente, e nos permite escolher qualquer instância do "paddle" e saber qual jogador que ela representa. Deve ser uma variável de texto, uma vez que IDs de clientes são curtas sequências de caracteres aleatórios. Nossa própria ID de cliente é atribuída a este objeto para indicar que representa a nós mesmos.

A ação Associate object with peer também é necessária para indicar ao "engine" multiplayer que esta instância representa um jogador na sala. Por padrão Sync object trata objetos como neutros, como objetos de cenário ou inimigos controlados por IA, e simplesmente certifica-se que todos vejam o mesmo número de objetos nos mesmos lugares. Usando Associate object significa que o objeto não é neutro e está associada a um cliente conectado na mesma sala, e lhe permite fazer mais automaticamente (tais como destruir o objeto quando o peer folhas). Neste caso, estamos adotando o objeto já no layout, por isso, associá-lo com a nossa própria identidade.

Open full size image

Os restantes eventos no grupo Signalling cobrem os erros de tratamento da mesma forma que a sala de chat fez. No entanto, há um evento extra que simplesmente exibe algumas estatísticas de conexão, incluindo o número de mensagens enviadas e recebidas enviados por segundo, a largura de banda resultante em kilobytes por segundo e a latência e PDV para o "host" (Estes irão mostrar como 0 para o "host", uma vez que eles não precisam se conectar a eles mesmos!).

Grupo Peer

Page 6: Tutorial Multiplayer 3 Pong Este Tutorial Assume Que Você Já Leu Tanto Multiplayer Tutorial 1

Como com o exemplo de chat, o grupo de eventos Peer é um pouco mais simples do que o do "host". Lembre-se que Sync object cria, move e destrói objetos automaticamente para os clientes, dependendo do que acontece no "host", por isso, não precisamos nos preocupar com isso aqui. O grupo Host entretanto, terá que lidar com a lógica de como os objetos se movem e interagem, o que neste caso é principalmente detectar o ricocheteio da bola nos "paddles", e manter a contagem.

No entanto, há uma coisa que precisamos fazer ao criar objetos como um cliente. Sync object automaticamente criará e destruirá objetos, mas quando eles são criados precisamos definir sua variável de instância peerid para que possamos mais tarde saber qual cliente o objeto representa. Quando Sync object cria um objeto, os eventos do objeto On created disparam e a expressão Multiplayer.PeerID é definida para o ID do cliente para o qual o objeto está sendo criado. Isto permite-nos lembrar quem o cliente é. Além disso, como com todos os objetos que representam clientes, usamos a ação Associate object with peer para indicar que este objeto representa um cliente conectado (Isso deve ser sempre feito em ambos os lados, tanto do "host" quanto dos clientes.).

Open full size image

Em seguida, o cliente precisa enviar suas entradas para o "host". On client update dispara para os clientes quando o "engine multiplayer" está prestes a enviar as entradas para o "host", por isso, devemos dizer ao objeto Multiplayer os valores mais recentes. Tudo o que precisamos fazer é dizer ao "host" a coordenada Y do nosso "paddle". O "paddle" é movido pelo nosso cursor do mouse, por isso apenas definimos o valor de entrada "y" (que nós adicionamos no início do layout) para a posição Y do mouse.

Open full size image

Finalmente, o "host" está no controle do jogo, e decide quando passamos do "get ready" para "go!". A fim de manter o nossa variável global GameState sincronizada com o "host", sempre que recebermos uma mensagem "gamestate-changed" nós atualizamos esta variável global.

Open full size image

Isso é tudo para os eventos específicos de clientes!

Grupo Host

O "host" é responsável por realmente executar o jogo. Sync Object faz a maioria do trabalho mantendo os clientes atualizados. O "host" lida com a lógica real do jogo, então os eventos do Host são um pouco mais complicados do que para os clientes.

Primeiramente, quando formos o "host", estaremos apenas à espera que outro jogador se junte. Portanto, na primeira vez que On peer connected disparar, podemos começar o jogo. Quando um cliente conecta, primeiro criamos um "paddle" para ele à direita da tela e o associamos ao cliente que está entrando. O jogo

Page 7: Tutorial Multiplayer 3 Pong Este Tutorial Assume Que Você Já Leu Tanto Multiplayer Tutorial 1

deve dizer "Get ready...", aguardar 3 segundos, dizer "Go!" durante 1 segundo, em seguida, mudar para a visualização do resultado (que é o estado do jogo "started"). Quando o jogo começa também habilitamos o movimento de bala da bola e o definimos em um ângulo randômico. Lembre-se que apenas o "host" realmente move o objeto; Sync object acompanha-o e atualiza-o para os clientes, e o comportamento também só deve ser habilitado no "host", pois caso contrário, poderá entrar em conflito com Sync object no cliente.

Open full size image

O "host" utiliza uma função para definir o estado do jogo. Isso ocorre porque mudando simplesmente a variável GameState afetaria apenas o "host", e os cientes nunca descobririam. Esta função permite-nos tanto mudar a variável quanto enviar uma mensagem para o cliente indicando que o estado do jogo mudou. O cliente recebe isto e atualiza sua própria variável GameState. Isso mantém a variável atualizada para todos no jogo.

Open full size image

Cada variável peerid dos "paddles" é definida para o ID do jogador correspondente, e podemos usar isso para separar o objeto dos jogadores individualmente. Uma vez que este é um jogo para dois jogadores, o ID dos clientes ou é MyID e é nosso próprio "paddle", ou é diferente e é o "paddle" do outro jogador. Precisamos avançar o "paddle" do outro jogador para onde eles o posicionam, portanto, escolhemos seu "paddle" e definimos para seu valor "y" de entrada. O valor de entrada mais recente para um cliente é obtido com a expressão PeerState.

Open full size image

Apenas o "host" cuida da lógica do jogo, como lidar com colisões. Neste caso, o "host" é responsável pelo rebate da bola pelos "paddles"; isso acontece automaticamente porque os "paddles" são sólidos e o comportamento Bala está definido para ricochetear em sólidos (lembre-se o cliente tem o comportamento de bala desativado então isso acontece somente no host). Cada vez que ela ricocheteia, nós também aumentamos sua velocidade, assim o jogo fica mais difícil.

Page 8: Tutorial Multiplayer 3 Pong Este Tutorial Assume Que Você Já Leu Tanto Multiplayer Tutorial 1

Open full size image

Eventos 29 e 30 rastreiam o placar. Se a bola vai para fora do lado esquerdo da tela (X <0), adiciona 1 a pontuação do cliente (o jogador à direita), e repõe a bola. Se a bola vai para fora da direita da tela (X> LayoutWidth), adicionar 1 a pontuação do "host" (o jogador à esquerda), e repõe a bola.

Open full size image

Isso é tudo para os eventos específicos do "host".

Grupo Common

O grupo Common tem eventos que são usados tanto para o "host" quanto para clientes.

Quando clientes se conectam e desconectam, nós adicionamos um log assim como no tutorial do chat.

Open full size image

Independentemente de se somos o "host" ou o cliente, nós sempre mostraremos nosso próprio "paddle" pelo nosso próprio mouse.

Sync object não transmite em qual camada (layer) os objetos estão, para economizar largura de banda. Isso nunca muda neste jogo de qualquer maneira, mas este evento garante que eles sempre apareçam na camada correta.

Page 9: Tutorial Multiplayer 3 Pong Este Tutorial Assume Que Você Já Leu Tanto Multiplayer Tutorial 1

O "host" e o cliente atualizam suas variáveis *GameState" de forma diferente, mas podemos fazer com o mesmo com seu conteúdo: se estamos no estado "getready" ou "go", mostramos algum texto no visor do placar.

Finalmente, quando o jogo está em estado de "started", exibimos a pontuação nas variáveis points de cada "paddle". Ambos os jogadores veem a pontuação do "host" à esquerda e a pontuação do cliente à direita, correspondente à posição dos "paddles". O "paddle" do "host" pode ser selecionado se seu "peerid" corresponder à ID do "host", e a "paddle" do cliente pode ser escolhido verificando se seu "peerid" não é o ID do "host".

Open full size image

Conclusão

O modelo geral de um jogo multiplayer em tempo real é:- O "host" tem comportamentos habilitados e realmente executa a lógica do jogo. - Clientes têm comportamentos desativados e apenas usa "sync object" para assistir passivamente o que acontece. No entanto, eles podem influenciar o jogo através de seus valores de entrada, que o host lê e usa para influenciar a jogabilidade.

Pong é um exemplo simples, mas ainda assim envolveu 40 eventos. Este exemplo também não cobriu previsão de entrada local ou compensação de lag. Projetar jogos multiplayer pode ser um desafio e pode levar algum tempo para aprender. Para passar para os conceitos finais em um jogo um pouco mais complexo, vá para Multiplayer tutorial 4: jogo em tempo real.