Como construir um jogo de realidade virtual multijogador em tempo real (parte 1)

Publicados: 2022-03-10
Resumo rápido ↬ A realidade virtual é um novo meio imersivo para explorar conteúdo, seja esse conteúdo um filme ( Life of Pi ), ​​um jogo ( Beat Saber ) ou uma experiência social (conforme descrito em Ready Player One ). Apesar de sua novidade, a RV não requer um conjunto de ferramentas drasticamente diferente para projetar - as mesmas ferramentas que usamos para desenvolvimento de jogos na web, modelagem 3D e outras ainda são aplicáveis. Este tutorial aproveita sua familiaridade com desenvolvimento web para começar a desenvolver VR.

Nesta série de tutoriais, construiremos um jogo de realidade virtual multijogador baseado na web no qual os jogadores precisarão colaborar para resolver um quebra-cabeça. Usaremos A-Frame para modelagem VR, MirrorVR para sincronização em tempo real entre dispositivos e A-Frame Low Poly para estética low-poly. No final deste tutorial, você terá uma demonstração online totalmente funcional que qualquer pessoa pode jogar.

Cada par de jogadores recebe um anel de orbes. O objetivo é “ligar” todos os orbes, onde um orbe está “ligado” se estiver elevado e brilhante. Um orbe está “desligado” se estiver mais baixo e escuro. No entanto, certos orbes “dominantes” afetam seus vizinhos: se ele mudar de estado, seus vizinhos também mudarão de estado. Apenas o jogador 2 pode controlar os orbes dominantes, enquanto apenas o jogador 1 pode controlar os orbes não dominantes. Isso força os dois jogadores a colaborar para resolver o quebra-cabeça. Nesta primeira parte do tutorial, construiremos o ambiente e adicionaremos os elementos de design para nosso jogo de RV.

As sete etapas neste tutorial são agrupadas em três seções:

  1. Configurando a cena (etapas 1–2)
  2. Criando os Orbes (Passos 3–5)
  3. Tornando os orbes interativos (etapas 6 a 7)
Mais depois do salto! Continue lendo abaixo ↓

Esta primeira parte será concluída com um orbe clicável que liga e desliga (como na foto abaixo). Você usará A-Frame VR e várias extensões A-Frame.

(Visualização grande)

Configurando a cena

1. Vamos com uma cena básica

Para começar, vamos dar uma olhada em como podemos configurar uma cena simples com um terreno:

Criando uma cena simples
Criando uma cena simples (visualização grande)

As três primeiras instruções abaixo são extraídas do meu artigo anterior. Você começará configurando um site com uma única página HTML estática. Isso permite que você codifique a partir de sua área de trabalho e implante automaticamente na web. O site implantado pode ser carregado em seu telefone celular e colocado dentro de um headset de RV. Como alternativa, o site implantado pode ser carregado por um headset VR autônomo.

Comece navegando até glitch.com. Então, faça o seguinte:

  1. Clique em “Novo Projeto” no canto superior direito,
  2. Clique em “hello-webpage” no menu suspenso,
  3. Em seguida, clique em index.html na barra lateral esquerda. Vamos nos referir a isso como seu “editor”.

Agora você deve ver a seguinte tela Glitch com um arquivo HTML padrão.

Projeto Glitch: o arquivo index.html
Projeto Glitch: o arquivo index.html (visualização grande)

Assim como no tutorial vinculado acima, comece excluindo todo o código existente no arquivo index.html atual. Em seguida, digite o seguinte para um projeto básico de webVR, usando A-Frame VR. Isso cria uma cena vazia usando a iluminação e a câmera padrão do A-Frame.

 <!DOCTYPE html> <html> <head> <title>Lightful</title> <script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script> </head> <body> <a-scene> </a-scene> </body> </html>

Levante a câmera até a altura de pé. De acordo com as recomendações do A-Frame VR (problema do Github), envolva a câmera com uma nova entidade e mova a entidade pai em vez da câmera diretamente. Entre suas tags a-scene nas linhas 8 e 9, adicione o seguinte.

 <!-- Camera! --> <a-entity position="0 3 0"> <a-camera wasd-controls look-controls></a-camera> </a-entity>

Em seguida, adicione uma caixa grande para indicar o solo, usando a-box . Coloque-o diretamente abaixo de sua câmera da instrução anterior.

 <!-- Action! --> <a-box shadow width="75" height="0.1" depth="75" position="0 -1 0" color="#222"></a-box>

Seu arquivo index.html agora deve corresponder exatamente ao seguinte. Você pode encontrar o código-fonte completo aqui, no Github.

 <html> <head> <title>Lightful</title> <script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script> </head> <body> <a-scene> <!-- Camera! --> <a-entity position="0 3 0"> <a-camera wasd-controls look-controls></a-camera> </a-entity> <!-- Action! --> <a-box shadow width="75" height="0.1" depth="75" position="0 -1 0" color="#222"></a-box> </a-scene> </body> </html>

Isso conclui a configuração. Em seguida, personalizaremos a iluminação para uma atmosfera mais misteriosa.

2. Adicione Atmosfera

Nesta etapa, vamos configurar a neblina e a iluminação personalizada.

Uma prévia de uma cena simples com um clima sombrio
Uma prévia de uma cena simples com um clima sombrio (Pré-visualização grande)

Adicione um nevoeiro, que obscurecerá objetos distantes para nós. Modifique a tag a-scene na linha 8. Aqui, adicionaremos uma névoa escura que rapidamente obscurece as bordas do solo, dando o efeito de um horizonte distante.

 <a-scene fog="type: linear; color: #111; near:10; far:15"></a-scene>

O cinza escuro #111 aparece linearmente de uma distância de 10 a uma distância de 15. Todos os objetos a mais de 15 unidades de distância são completamente obscurecidos e todos os objetos a menos de 10 unidades são completamente visíveis. Qualquer objeto no meio é parcialmente obscurecido.

Adicione uma luz ambiente para iluminar os objetos do jogo e uma luz unidirecional para acentuar as superfícies reflexivas que você adicionará mais tarde. Coloque-o diretamente após a tag a-scene que você modificou na instrução anterior.

 <!-- Lights! --> <a-light type="directional" castshadow="true" intensity="0.5" color="#FFF" position="2 5 0"></a-light> <a-light intensity="0.1" type="ambient" position="1 1 1" color="#FFF"></a-light>

Diretamente abaixo das luzes da instrução anterior, adicione um céu escuro. Observe que o cinza escuro #111 combina com o nevoeiro distante.

 <a-sky color="#111"></a-sky>

Isso conclui as modificações básicas no clima e, mais amplamente, na configuração da cena. Verifique se seu código corresponde exatamente ao código-fonte da Etapa 2 no Github. Em seguida, adicionaremos um orbe de baixo poli e começaremos a personalizar a estética do orbe.

Criando os orbes

3. Crie um Orbe Low-Poly

Nesta etapa, criaremos um orbe giratório e reflexivo, conforme ilustrado abaixo. O orbe é composto por duas esferas estilizadas de baixo poli com alguns truques para sugerir material refletivo.

Orbe rotativa e reflexiva
(Visualização grande)

Comece importando a biblioteca low-poly em sua tag head . Insira o seguinte entre as linhas 4 e 5.

 <script src="https://cdn.jsdelivr.net/gh/alvinwan/[email protected]/dist/aframe-low-poly.min.js"></script>

Crie um carrossel, um wrapper e um contêiner orb. O carousel conterá vários orbes, o wrapper nos permitirá girar todos os orbes em torno de um eixo central sem girar cada orbe individualmente, e o container conterá - como o nome sugere - todos os componentes do orbe.

 <a-entity> <a-entity rotation="0 90 0" class="wrapper" position="0 0 0"> <a-entity class="container" position="8 3 0" scale="1 1 1"> <!-- place orb here --> </a-entity> </a-entity> </a-entity>

Dentro do recipiente do orbe, adicione o próprio orbe: uma esfera é levemente translúcida e deslocada, e a outra é completamente sólida. As duas superfícies refletivas combinadas imitam.

 <a-entity class="orb" data-> <lp-sphere seed="0" shadow max-amplitude="1 1 1" position="-0.5 0 -0.5"></lp-sphere> <lp-sphere seed="0" shadow max-amplitude="1 1 1" rotation="0 45 45" opacity="0.5" position="-0.5 0 -0.5"></lp-sphere> </a-entity>

Finalmente, gire a esfera indefinidamente adicionando a seguinte tag a-animation imediatamente após a lp-sphere dentro da entidade .orb na última instrução.

 <a-animation attribute="rotation" repeat="indefinite" from="0 0 0" to="0 360 0" dur="5000"></a-animation>

Seu código-fonte para os wrappers orb e o próprio orb devem corresponder exatamente ao seguinte.

 <a-entity> <a-entity rotation="0 90 0" class="wrapper" position="0 0 0"> <a-entity class="container" position="8 3 0" scale="1 1 1"> <a-entity class="orb" data-> <lp-sphere seed="0" shadow max-amplitude="1 1 1" position="-0.5 0 -0.5"></lp-sphere> <lp-sphere seed="0" shadow max-amplitude="1 1 1" rotation="0 45 45" opacity="0.5" position="-0.5 0 -0.5"></lp-sphere> <a-animation attribute="rotation" repeat="indefinite" from="0 0 0" to="0 360 0" dur="5000"></a-animation> </a-entity> </a-entity> </a-entity> </a-entity>

Verifique se seu código-fonte corresponde ao código-fonte completo da etapa 3 no Github. Sua visualização agora deve corresponder ao seguinte.

Orbe rotativa e reflexiva
(Visualização grande)

Em seguida, adicionaremos mais iluminação ao orbe para obter um tom dourado.

4. Acenda o Orbe

Nesta etapa, adicionaremos duas luzes, uma colorida e outra branca. Isso produz o seguinte efeito.

Orbe iluminado com luzes pontuais
(Visualização grande)

Comece adicionando a luz branca para iluminar o objeto por baixo. Usaremos uma luz pontual. Diretamente antes #orb0 mas dentro de #container-orb0 , adicione a seguinte luz de ponto de deslocamento.

 <a-entity position="-2 -1 0"> <a-light distance="8" type="point" color="#FFF" intensity="0.8"></a-light> </a-entity>

Em sua visualização, você verá o seguinte.

Orbe iluminado com luz de ponto branco
(Visualização grande)

Por padrão, as luzes não diminuem com a distância. Ao adicionar distance="8" , garantimos que a luz decaia totalmente com uma distância de 8 unidades, para evitar que a luz pontual ilumine toda a cena. Em seguida, adicione a luz dourada. Adicione o seguinte diretamente acima da última luz.

 <a-light class="light-orb" distance="8" type="point" color="#f90" intensity="1"></a-light>

Verifique se seu código corresponde exatamente ao código-fonte da etapa 4. Sua visualização agora corresponderá ao seguinte.

Orbe iluminado com luzes pontuais
(Visualização grande)

Em seguida, você fará sua modificação estética final no orbe e adicionará anéis rotativos.

5. Adicionar anéis

Nesta etapa, você produzirá o orbe final, conforme ilustrado abaixo.

Orbe dourado com vários anéis
(Visualização grande)

Adicione um anel em #container-orb0 diretamente antes #orb0 .

 <a-ring color="#fff" material="side:double" position="0 0.5 0" radius-inner="1.9" radius-outer="2" opacity="0.25"></a-ring>

Observe que o anel em si não contém cor, pois a cor será impregnada pela luz pontual na etapa anterior. Além disso, o material="side:double" é importante porque, sem ele, a parte de trás do anel não seria renderizada; isso significa que o anel desapareceria na metade de sua rotação.

No entanto, a visualização apenas com o código acima não será diferente. Isso ocorre porque o anel está atualmente perpendicular à tela. Assim, apenas o “lado” do anel (que tem espessura 0) é visível. Coloque a seguinte animação entre as tags a-ring na instrução anterior.

 <a-animation attribute="rotation" easing="linear" repeat="indefinite" from="0 0 0" to="0 360 0" dur="8000"></a-animation>

Sua visualização agora deve corresponder ao seguinte:

Orbe dourado com anel
(Visualização grande)

Crie um número variável de anéis com diferentes eixos de rotação, velocidades e tamanhos. Você pode usar os seguintes anéis de exemplo. Quaisquer novos anéis devem ser colocados embaixo do último a-ring

 <a-ring color="#fff" material="side:double" position="0 0.5 0" radius-inner="2.4" radius-outer="2.5" opacity="0.25"> <a-animation attribute="rotation" easing="linear" repeat="indefinite" from="0 45 0" to="360 45 0" dur="8000"></a-animation> </a-ring> <a-ring color="#fff" material="side:double" position="0 0.5 0" radius-inner="1.4" radius-outer="1.5" opacity="0.25"> <a-animation attribute="rotation" easing="linear" repeat="indefinite" from="0 -60 0" to="-360 -60 0" dur="3000"></a-animation> </a-ring>

Sua visualização agora corresponderá ao seguinte.

Orbe dourado com vários anéis
(Visualização grande)

Verifique se seu código corresponde ao código-fonte da etapa 5 no Github. Isso conclui a decoração do orbe. Com o orbe concluído, adicionaremos interatividade ao orbe. Na próxima etapa, adicionaremos especificamente um cursor visível com uma animação de clique quando apontado para objetos clicáveis.

Tornando os orbes interativos

6. Adicione um cursor

Nesta etapa, adicionaremos um cursor branco que pode acionar objetos clicáveis. O cursor é mostrado abaixo.

clicando no orbe
(Visualização grande)

Em sua tag a-camera , adicione a seguinte entidade. O atributo fuse permite que essa entidade acione eventos de clique. O atributo raycaster determina com que frequência e até que ponto verificar objetos clicáveis. O atributo objects aceita um seletor para determinar quais entidades são clicáveis. Nesse caso, todos os objetos da classe clickable são clicáveis.

 <a-entity cursor="fuse: true; fuseTimeout: 250" position="0 0 -1" geometry="primitive: ring; radiusInner: 0.03; radiusOuter: 0.04" material="color: white; shader: flat; opacity: 0.5" scale="0.5 0.5 0.5" raycaster="far: 20; interval: 1000; objects: .clickable"> <!-- Place cursor animation here --> </a-entity>

Em seguida, adicione animação de cursor e um anel extra para estética. Coloque o seguinte dentro do objeto cursor de entidade acima. Isso adiciona animação ao objeto cursor para que os cliques fiquem visíveis.

 <a-circle radius="0.01" color="#FFF" opacity="0.5" material="shader: flat"></a-circle> <a-animation begin="fusing" easing="ease-in" attribute="scale" fill="backwards" from="1 1 1" to="0.2 0.2 0.2" dur="250"></a-animation>

Em seguida, adicione a classe clickable ao #orb0 para corresponder ao seguinte.

 <a-entity class="orb clickable" data->

Verifique se seu código corresponde ao código-fonte da Etapa 6 no Github. Na sua visualização, arraste o cursor deles para o orbe para ver a animação do clique em ação. Isso é retratado abaixo.

clicando no orbe
(Visualização grande)

Observe que o atributo clicável foi adicionado ao próprio orbe e não ao contêiner do orbe. Isso é para evitar que os anéis se tornem objetos clicáveis. Dessa forma, o usuário deve clicar nas esferas que compõem o próprio orbe.

Em nossa etapa final para esta parte, você adicionará animação para controlar os estados ligado e desligado do orbe.

7. Adicione Estados Orbes

Nesta etapa, você animará o orbe dentro e fora de um estado desligado ao clicar. Isso é retratado abaixo.

Orbe interativo respondendo a cliques
(Visualização grande)

Para começar, você encolherá e abaixará o orbe até o chão. Adicione tags a-animation ao #container-orb0 logo após #orb0 . Ambas as animações são acionadas por um clique e compartilham a mesma função ease-elastic para um leve salto.

 <a-animation class="animation-scale" easing="ease-elastic" begin="click" attribute="scale" from="0.5 0.5 0.5" to="1 1 1" direction="alternate" dur="2000"></a-animation> <a-animation class="animation-position" easing="ease-elastic" begin="click" attribute="position" from="8 0.5 0" to="8 3 0" direction="alternate" dur="2000"></a-animation>

Para enfatizar ainda mais o estado desligado, removeremos a luz do ponto dourado quando o orbe estiver desligado. No entanto, as luzes do orbe são colocadas fora do objeto orbe. Assim, o evento click não é passado para as luzes quando o orbe é clicado. Para contornar esse problema, usaremos algum Javascript leve para passar o evento click para a luz. Coloque a seguinte tag de animação em #light-orb0 . A luz é acionada por um evento de switch personalizado.

 <a-animation class="animation-intensity" begin="switch" attribute="intensity" from="0" to="1" direction="alternate"></a-animation>

Em seguida, adicione o seguinte ouvinte de evento de clique ao #container-orb0 . Isso retransmitirá os cliques para as luzes do orbe.

 <a-entity ...>

Verifique se seu código corresponde ao código-fonte da Etapa 7 no Github. Por fim, abra sua visualização e mova o cursor para dentro e para fora do orbe para alternar entre os estados desligado e ligado. Isso é retratado abaixo.

Orbe interativo respondendo a cliques
(Visualização grande)

Isso conclui a interatividade do orbe. O jogador agora pode ligar e desligar os orbes à vontade, com estados ligados e desligados autoexplicativos.

Conclusão

Neste tutorial, você construiu um orbe simples com estados ligado e desligado, que pode ser alternado por um clique de cursor compatível com fone de ouvido VR. Com várias técnicas de iluminação e animações diferentes, você conseguiu distinguir entre os dois estados. Isso conclui os elementos de design de realidade virtual para os orbes. Na próxima parte do tutorial, preencheremos os orbes dinamicamente, adicionaremos mecânicas de jogo e configuraremos um protocolo de comunicação entre um par de jogadores.