Estou pensando em criar um jogo isométrico simples com o HTML5 Canvas e me perguntando qual é a maneira mais rápida de renderizar os blocos.
Como os ladrilhos são em forma de diamante, mas o drawImage desenha retângulos, tenho que deixar de fora os cantos (as partes pretas a seguir):
Eu acho que isso me deixa com três opções:
- Use objetos de imagem com canais alfa (.png). Receio que isso possa prejudicar o desempenho.
- Use um traçado de recorte. Se o renderizador for otimizado, isso pode ser bem rápido.
- Pré-renderização de blocos quadrados, assim:
Eu teria o quadrado preto como um ladrilho real na memória e desenharia esse ladrilho para o campo verde e todos os campos próximos a ele, ou acima e abaixo. Os campos diagonais (azuis) seriam constituídos pelos cantos dos ladrilhos retangulares. Isso evitaria os canais alfa ou de recorte, mas eu teria que pré-renderizar todas as combinações possíveis de blocos, e isso pareceria um exagero.
Qual é a melhor ou mais rápida maneira de fazer blocos isométricos? O que outros jogos, como FarmVille, usam?
Respostas:
Usar a transparência (canal alfa) é o caminho a seguir, eu recomendo.
Isso significa que quando você deseja um objeto vertical no bloco como este:
Você poderá fazer isso facilmente se o seu renderizador desenhar os ladrilhos de trás para frente, ou seja, algoritmo de pintores.
CRÉDITO DE IMAGEM: tileset de Reiner.
fonte
Embora o método descrito por sws e MarkR também seja o que eu prefiro, gostaria de apresentar uma abordagem alternativa.
Uma opção imprudente para criar uma aparência isométrica com o mínimo esforço é realmente usar blocos ortogonais e context.transform para definir uma matriz de projeção que faz o mapa parecer isométrico (ou uma combinação de context.rotate e context.scale quando você não ' não sei como funcionam as matrizes de projeção).
Consulte a especificação para métodos de transformação de tela para obter detalhes.
Imagem lado a lado:
Código de desenho:
Resultado antes da aplicação da matriz:
O mesmo código com a mesma imagem de bloco após a aplicação desta matriz de transformação:
Com a grade tracejada removida da imagem do bloco e alterando o deslocamento do bloco no código do desenho para
img.width - 1
eimg.height - 1
para eliminar as lacunas causadas pela transformação. De repente, o ladrilho parece meio feio:A principal desvantagem desse método é que, quando você cria seus blocos em um editor gráfico, eles não serão realmente o que você vê. Você também encontrará problemas quando quiser desenhar objetos que não estejam no chão, mas que estejam em pé. Para isso, você pode desativar a matriz de transformação antes de desenhá-la, mas precisará calcular a posição. Você pode usar estas fórmulas para isso:
(observe como os números da matriz de transformação reaparecem nessas fórmulas - você está fazendo a multiplicação de matrizes aqui).
Então, por que eu deveria fazer isso?
Este método é bom quando você:
Outra característica interessante é que, quando você conhece o cálculo da matriz, é possível modificar a matriz de projeção entre os quadros para aumentar o zoom, inclinar e girar o mapa em tempo real para obter alguns bons efeitos 3D falsos (tente fazer ISSO com ladrilhos isométricos) .
Mas quando você sabe como lidar com ladrilhos isométricos, tanto artística quanto tecnicamente, e não precisa de nenhum truque de perspectiva falsa, prefiro sugerir que você escolha ladrilhos em forma de diamante com transparência.
fonte
Você está usando context.drawImage para copiar dados de pixel de uma origem (imagem ou tela fora da tela) para outra (tela fora da tela ou na tela), que lida com o alfa normalmente fora da caixa. O Canvas é acelerado por hardware, portanto, o teste permitirá determinar se há uma diferença discernível nas velocidades de renderização em pixels alfa ou opacos.
O recorte exigirá que você pressione / pop o estado do contexto ao definir um caminho de recorte uma vez por bloco, o que pode ser uma operação dispendiosa, considerando o excesso de isometria.
Ladrilhos pré-renderizados exigiriam, como você declara, um número imenso de ladrilhos 'conectores' para serem desenhados, o que pode ou não ser viável. (Estou me inclinando mais para "talvez não").
Uma quarta solução seria adotar um "bloco" pré-renderizado (PRC) de blocos, gerado uma vez para telas fora da tela e depois cobrir a tela com os PRCs uma vez por quadro. Ainda haveria excesso, mas construir a RPC uma vez e renderizá-la com um deslocamento determinado pela posição do personagem do jogador (ou da câmera de visualização) em relação à RPC deve ser uma operação relativamente simples. Isso permitiria combinar a renderização com a opção 1, que é a melhor opção para IMO se o desempenho não fosse considerado (já que é mais simples de implementar).
fonte
Um pequeno canal alfa não dói muito, mas se você quiser evitá-lo, considere o uso de dois quartos, também oferece espaço para fazer boas transições de lado a lado sem fazer uma infinidade de imagens diferentes, essa é provavelmente a maior vantagem:
fonte