Existem muitos fãs de jogos antigos. E eles não são avessos a deixar escapar uma lágrima nostálgica mesquinha e não, não, mas tocando "Arkanoid", "Pakman" ou "Prince of Persia" como vinte, trinta, quarenta ou - substituam o número desejado - anos atrás. Caixa DOS e emuladores - para ajudá-los. Sim, o que está aí, recentemente assisti a uma transmissão do primeiro "Prince of Persia" em 2D no YouTube, onde uma serpentina bastante jovem, depois de passar por outro obstáculo mortal, acenando suor da testa com a mão, disse: "Eu nunca fiquei tão assustado em um jogo de computador" " Ou seja, até os jovens são capazes de apreciar o hardcore e o frescor dos jogos antigos.

Eu pensei, por que não criar um novo jogo em um estilo semelhante? Sim, existem vários remakes e clones. Além disso, jogos modernos no estilo de pixel art deliciam. No entanto, todos eles, em regra, repetem missões, mecânicas e, às vezes, até projetam completamente os jogos antigos, com base nos quais eles foram feitos. Bem, ou, inversamente, eles oferecem um enredo e locais completamente novos, que são simplesmente uma estilização visual de "antiguidade". Mas e se você imaginar qual seria a nova parte do jogo antigo se seguisse o último da série? Eu decidi criar um.
Peguei um jogo de plataformas 2D e adicionei gráficos 3D lá, mantendo a vista lateral clássica. Ele construiu novos labirintos, criou novas missões, introduziu tarefas e implementou espaços de inventário. Diversificou levemente a sensação de espaço, adicionando curvas de 90 graus. Talvez, nos tempos antigos, antes da transição total de jogos em 3D com três graus de liberdade, algo assim pudesse sair.
Como gosto de escrever jogos para navegadores, decidi fazer um jogo para o navegador. Devido à sua especificidade, ele não possui nenhum número louco de polígonos, pelo menos exibido na tela ao mesmo tempo, não há mundo aberto. Portanto, tudo isso não carregará muito o navegador. Para exibir gráficos 3D, escolhi minha biblioteca Three.js favorita (WebGL) com meu próprio wrapper. Nenhuma outra biblioteca é usada e o código é escrito em javascript puro.
Three.js e os problemas que encontrei
Os desenvolvedores de mecanismos gráficos 3D periodicamente, aproximadamente uma vez a cada dois anos, lançam novas versões de suas criações. No caso da biblioteca de scripts Three.js., os desenvolvedores adoram atualizações com uma frequência frenética - cerca de uma vez por mês. No momento da redação deste artigo, a versão mais recente tinha o número 106. Parece que isso está bom. (No.)
Por que ninguém sequer pensa em compatibilidade com versões anteriores? Quando os desenvolvedores do Three.js renomearam o ambiente da propriedade do material, percebi:
"Houston, temos problemas" . Ok, digamos que não foi difícil para mim em todo o meu código alterar a palavra "ambiente" para "cor" com uma substituição de pesquisa. Mas quando eles descartaram a possibilidade de uma fonte de luz criar uma sombra sem iluminação, percebi que agora o pouso da
Águia está em perigo real e a base
Calma está lentamente começando a se transformar na base da
Raiva . No entanto, como se viu depois, não foi tão ruim ...
O fato é que, no meu jogo, além da luz assada, a iluminação dinâmica também é usada. O número de fontes dinâmicas em uma cena 3D afeta muito o desempenho.
Eu escolhi o número de fontes nas configurações do jogo - de 1 a 7. E, dependendo do poder da placa de vídeo, você pode tentar valores diferentes.Há também uma matriz que contém as coordenadas e características de cada fonte - intensidade, cor e assim por diante. Funciona assim. Ao se mover pelo mundo do jogo em um determinado quadrado ao redor do jogador, o número de fontes de luz especificadas nas configurações com as características especificadas é aceso. Ou seja, as fontes de luz parecem seguir o jogador (à sua volta) pela nuvem.
Então, Houston, quais são nossos problemas? Eu relato.Problema número 1: sombras
As fontes de luz criam sombras. Percebi que as sombras das fontes de luz pontuais consomem muito mais recursos do que as sombras direcionadas (luz pontual). E isso é compreensível: no caso de uma fonte pontual, as sombras são projetadas em todas as direções e direcionais - apenas em um determinado cone. No entanto, sugeri que quando as sombras em todas as direções não são necessárias, duas fontes podem ser usadas ao mesmo tempo: um ponto criará apenas iluminação e um direcional criará sombras apenas em uma determinada direção. Isso é perfeito para o meu jogo e, como se viu, realmente economiza significativamente o poder da computação.
A pirâmide limita a área em que as sombras podem aparecer.Mas aqui está o problema: a partir da versão three.js r73, uma fonte de luz direcional não pode mais apenas projetar uma sombra; agora também sempre fornece iluminação. E a luz dela se espalha dentro da área, bem como a sombra. É impossível remover uma fonte pontual e deixar apenas uma fonte direcional: preciso de iluminação em todas as direções. E usar as duas fontes, ajustando-as com o brilho desejado, também não funciona: os objetos dentro do cone serão iluminados com muito mais brilho. O uso de iluminação "honesta" com sombras em todas as direções afeta o desempenho do jogo fatalmente.
E eles removeram a propriedade necessária de uma fonte de luz direcional .onlyShadow, apenas porque o autor do mecanismo queria isso.
Problema número 2: nomes de propriedades
Eu decidi que preferia ficar na versão r71, onde a propriedade de iluminação de que eu preciso ainda está presente. Por que não r72 então? Afinal, a propriedade desapareceu apenas na versão r73. Porque eu já escrevi bastante código para carregar modelos 3D, animações e física para a versão r71. E na versão r72, um grande número de nomes de propriedades foi alterado: type - shadowMap se tornou shadow.map, etc. Em geral, eu também não queria renomear tudo isso. E a diferença entre uma versão é pequena. Portanto, continuamos na versão r71.
Problema número 3: assar sombras
A luz de cozimento em diferentes versões do mecanismo também parece diferente. Não sei o que eles estão fazendo com ele lá, mas ao aplicar um mapa de sombras à textura, o brilho e até a cor mudam drasticamente. De maneira geral, resolvi esse problema digitando o mecanismo no código GLSL e definindo a correção automática de cores no carregador de modelos 3D nos locais em que os mapas de sombra são usados. Obviamente, isso funciona apenas para a versão r71. Para outras versões, você precisará usar outros parâmetros. Esse é outro motivo para permanecer na versão r71.
Na verdade, não faz sentido mudar para as versões mais recentes, pois o resultado do trabalho, em comparação com o antigo, não difere fundamentalmente em termos de desempenho.Bom Uma fonte de luz direcional cria apenas uma sombra. Posso assar e carregar sombras na montagem na versão r71. E agora - a emboscada mais importante. Personagens.
Edição 4: animação esquelética
Foi por isso que lutei por muito tempo. No total, passei algumas semanas tentando encontrar algum tipo de algoritmo de trabalho para transferir um personagem com um conjunto de animações para o jogo.

Versões recentes do Three.js não têm esse problema. Lá, criei com sucesso um modelo de personagem animado em um conhecido serviço online, converti-o para o popular formato gltf e enviei-o para a cena de teste. No entanto, se as novas versões do Three.js usarem o formato gltf 2.0, o meu suportará apenas a versão 1.0. Parece, qual é o problema, bem, converta para 1.0 e faça o download. Acabou não sendo tão simples. Aparentemente, existem várias variações do formato gltf 1.0. Eu precisava de um em que, além do arquivo principal do modelo, mais dois arquivos com a extensão * .glsl estivessem presentes. Mas, nesse caso, o formato do arquivo principal pode variar ... Em geral, não consegui encontrar um conversor que satisfizesse todos os parâmetros, principalmente porque ele também foi convertido do novo formato para o antigo. Também não consegui concluir a versão antiga do three.js para o suporte ao gltf 2.0: esse suporte é muito profundo no código, enraizado na matemática, implementado de maneira diferente em diferentes versões do mecanismo ... Em geral, de alguma forma, não funcionou com o gltf.
Tentei usar o formato .dae para modelos 3D. Como resultado, o próprio modelo estava carregando, mas não consegui que as animações de personagens funcionassem corretamente. Também houve problemas com texturas.
Acabou bem com o formato .md2. O personagem foi exibido imediatamente e todas as animações funcionaram corretamente. Mas, pelo que entendi, o md2 é um formato de modelo para o Quake 2 e alguém implementou seu suporte no Three.js apenas por diversão. E onde conseguir modelos nesse formato, e mais ainda, para projetar e salvar meu próprio personagem nele, eu não encontrei.
Eu tentei mais alguns formatos. Mas, sob eles, não havia gerenciador de inicialização para o three.js, não havia programas para criar a preservação de seu personagem neles, então eles não suportavam animação esquelética.
A base "Raiva" estava certa em renomear a base "Desespero".Já quase desesperado e pensando em mudar para uma nova versão do mecanismo em detrimento do desempenho (a história de uma fonte de luz direcional), decidi pela última vez atormentar o formato json, com o qual realmente comecei. Mas, pela primeira vez, não consegui repetir o processo de conversão de um caractere de um arquivo de exemplo que veio no pacote Three.js. do formato .blend original para .json no editor 3D do Blender. As animações estragaram e se comportaram de alguma maneira aleatória, e com uma dúzia de variações do exportador do Blender para o json, cada uma delas funcionou incorretamente. Além disso, eu também tentei em várias versões do Blender. O próprio JSONLoader, ou seja, um carregador de modelo no formato json, agora foi removido do three.js. Eu decidi olhar para qual versão seu suporte havia cessado, a fim de levá-lo e uma amostra do modelo 3D não da minha versão, mas daquela em que ele ainda estava. Ela acabou por ser r88. E eis! Consegui reproduzir a exportação do modelo de teste em r71 e tudo, incluindo animações de personagens, funcionou bem no jogo!
"Eagle" pousou em segurança.Decidi editar uma das animações do personagem de teste no Blender para ver se eu poderia fazer as minhas. Uma chatice estava me esperando aqui. A animação que editei não queria funcionar no jogo. O personagem congelou na posição inicial. Embora outras animações funcionassem sem problemas. Mas isso é alguma coisa. Ou seja, agora o problema é o meu desconhecimento de algumas nuances da edição da animação.
Então pensei - e se eu perguntar ao autor deste exemplo como ele fez isso? Mas não foi fácil chegar ao autor. Ele não tem contatos pessoais no Github. Uma busca por um apelido e mais alguns parâmetros trazidos para o Twitter, no entanto, as mensagens privadas foram fechadas. Mas a partir daí soube que ele era professor de alguma universidade americana e foi ao site dessa instituição educacional. Verificou-se que o professor estava envolvido em gráficos 3D com seus alunos, usando seu exemplo como material metodológico. Depois voltei ao Github e examinei todos os seus repositórios. Aqui eu estava esperando pelo sucesso. Como eu esperava, o exemplo dele foi armazenado em um repositório separado. E não apenas uma cópia do que eu já vi nos exemplos do three.js, mas um exemplo cuidadosamente fornecido com instruções (aparentemente, para os alunos). Baixei o arquivo e, seguindo as instruções, repeti tudo. Viva!
Este é um pequeno passo para a humanidade, mas um grande salto para uma pessoa e seu jogo!Não tem problema, Houston!
Agora entendo que, se seguir esse formato, essas instruções e versões do Three.js, JSONLoader e Blender e fizer tudo da mesma maneira, posso criar e carregar qualquer um dos meus personagens no jogo do navegador. A boa notícia foi que, apesar de usar a versão antiga do mecanismo, você pode usar a versão mais recente do editor do 3D Blender e criar qualquer personagem com animação. Nesse momento, você precisa exportá-los de acordo com um esquema estritamente definido usando este kit de ferramentas específico.
Sim, notei mais um problema com a nova versão do Three.js: durante o jogo, ao rolar a tela, por algum motivo, frisos constantes são observados. E isso não se deve ao aumento do consumo de recursos - o processador e a placa de vídeo não carregam 100%. E no velho r71 não existe tal desgraça.
Agora resta apenas fazer o jogo no editor de personagens 3D com animação. E, claro, a geometria dos níveis. Não sei quanto tempo vai demorar. Mas até agora eu apenas coletei uma versão demo gratuita no Webkit e a enviei para lojas de aplicativos populares.
Um pouco sobre o jogo
Name. Eu chamei o jogo Percy Lancaster. Tudo é óbvio aqui: "Eu sou um artista, e vejo isso".
Como os gráficos foram criados . Criei dois planos no editor 3D, organizei-os à distância um do outro, de modo que o mais distante estivesse escondido atrás do mais próximo, puxei uma textura de pedra sobre eles, fiz buracos no mais próximo e depois removi as peças desnecessárias, ou seja, invisíveis. Então ele modelou os aviões para pisos e tetos. Então, acabou sendo um corredor para o jogador andar. Diversifiquei locais com várias texturas.
No jogo em si não existe esse tipo, existe apenas uma vista lateral e nenhum espaço em preto é perceptível. Esta é apenas uma visão geral do corredor.Eu decidi criar corredores que se cruzam. Durante a curva, uma parede do outro corredor é concluída, toda a estrutura gira e, em seguida, a parede do primeiro corredor é removida. Com base nessa mecânica, também planejo criar torres dentro das quais você pode subir a escada em espiral.
Com gráficos estáticos, na verdade, não há problemas, é facilmente exportado para o json a partir de qualquer editor 3D. As dificuldades, como eu já mencionei, surgiram apenas com sombras assombrosas e animação de personagens.
Performance. Na resolução de tela HD, ou seja, 1280x720, minha placa de vídeo GT-730 não tão poderosa é carregada em cerca de 35-40%, e o processador Xeon E5440 está em cerca de 30%. Eu acho que isso é mais do que um resultado aceitável.
OS Até o momento, a demonstração está disponível apenas no Windows como um assembly no Webkit. No futuro, pretendo lançar uma versão do navegador. Me deparei com o fato de que nem todos os navegadores rolam a tela sem problemas. Ainda preciso trabalhar no gerenciamento e na chamada da função de saída gráfica. Enquanto isso, eu decidi pelo Webkit versão 26.0. Ela pesa pouco e tudo funciona bem nela.
O som Os sons são parcialmente extraídos de bibliotecas gratuitas, parcialmente geradas. Em geral, eles foram feitos até agora, "ser". Enquanto eu não me incomodava muito com eles.
Vídeo Nível de demonstração de passagem completa.
Planos
Eu pretendo ir ao crowdfunding e contratar um modelador 3D com o dinheiro levantado, o que criará um personagem e animações normais para ele. Ainda assim, os gráficos não são meus. Mas agora eu sei como introduzir um personagem no meu jogo.
Além disso, pretendo lançar uma versão do navegador para as versões mais recentes do Chrome e Firefox. Deixe-me contar um segredo: eu até consegui rodar o jogo no MS Edge, mas, por algum motivo, não havia objetos nos quais as texturas das sombras sobrepostas se sobrepunham, ainda não descobri. Em seguida, depurarei os navegadores para Linux e Android e, se eu conseguir dispositivos da Apple para alguém testar, também os navegadores no iOS e no MacOS.
A longo prazo - escrevendo sua própria biblioteca para trabalhar com o WebGL, como Three.js: não gosto que eles renomeiem abruptamente propriedades e removem a funcionalidade necessária. Por outro lado, a maior parte do grande número de oportunidades oferecidas pelo Three.js não são necessárias.
Acho que mais tarde, quando descobrir o funcionamento correto do jogo para todos os navegadores em diferentes sistemas operacionais, escreverei um artigo sobre isso com alguns detalhes técnicos.