Jogos em HTML5: Criando um jogo 2D com Canvas – Parte 1
Na primeira parte deste artigo nós abordamos conceitos iniciais acerca do desenvolvimento do jogo usando Canvas, atrelado à HTML5, JavaScript e CSS3. Essa introdução foi muito importante para que o leitor consiga se adaptar à forma como o Canvas não só impõe sua arquitetura de camadas, mas também a como ele lida com as funções de script para expor o conteúdo e gerenciar o “desenho” gráfico das diversas formas do jogo.
Até o momento criamos três atores principais: o plano de fundo (e seu efeito de movimento, dando a ideia de cenário infinito), o player e os combos de ataque. Além disso, alguns conceitos físicos foram aplicados, muitos deles abstraídos pela própria linguagem, e continuarão sendo abordados até o fim da implementação, haja vista a necessidade de incutir tais efeitos em quase todos os personagens.
Na segunda parte do artigo focaremos no restante do desenvolvimento, que consiste em criar os inimigos e adicionar os efeitos de animação, identificar a colisão dos combos de ataque entre ambos os atores, adicionar sonorização, implementar as funções que irão randomizar a exibição dos inimigos e players, etc. A partir de agora, faremos referência às figuras do pool de objetos e repositórios de forma mais frequente, uma vez que quanto mais objetos precisarem ser criados, maior o processamento que ocorrerá na instanciação desse tipo de estrutura de dados.
Criando os inimigos
A primeira mudança significativa para criar os inimigos, assim como fizemos para os demais objetos Image, é inserir as referências aos objetos e instanciá-los. Lembre-se que o objeto repositorio funciona como uma espécie de contêiner em memória que pré-carrega as variáveis e objetos antes que eles sejam requisitados pelas respectivas funções e exibidos na tela. Isso alivia o processamento e impede que travamentos e lentidão aconteçam em tempo de jogo. Veja na Listagem 1 o código que usaremos para efetuar essa mudança.
Listagem 1. Adicionando os objetos de inimigo e combo no objeto repositorio.
01 /**
02 * Define um objeto para manter todas as nossas imagens do jogo para
03 * evitar que elas sejam criadas mais de uma vez.
04 */
05 var repositorio = new function() {
06 // Define os objetos de imagens
07 this.planofundo = new Image();
08 this.player = new Image();
09 this.combo = new Image();
10 this.inimigo = new Image();
11 this.comboInimigo = new Image();
12
13 var numImagens = 5;
14 var numCarregados = 0;
15 function imgCarregada() {
16 numCarregados++;
17 if (numCarregados === numImagens) {
18 window.iniciar();
19 }
20 }
21 this.planofundo.onload = function() {
22 imgCarregada();
23 }
24 this.player.onload = function() {
25 imgCarregada();
26 }
27 this.combo.onload = function() {
28 imgCarregada();
29 }
30 this.inimigo.onload = function() {
31 imgCarregada();
32 }
33 this.comboInimigo.onload = function() {
34 imgCarregada();
35 }
36
37 // Configura os caminhos (src) das imagens
38 this.planofundo.src = "imgs/pf.png";
39 this.player.src = "imgs/player1.png";
40 this.combo.src = "imgs/combo1.png";
41 this.inimigo.src = "imgs/enemy1.png";
42 this.comboInimigo.src = "imgs/combo2.png";
43 }
As configurações previstas inicialmente para os demais objetos permanecem. Nas linhas 10 e 11 declaramos e instanciamos os objetos inimigo e comboInimigo, respectivamente, que servirão para guardar a referência à imagem física de cada um deles. Posteriormente, estes objetos serão usados para receber o valor randômico que implementaremos. A linha 13 traz a variável numImagens que já havia sido criada e é incrementada de acordo com a quantidade de objetos que foram carregados no pool repositorio. Caso a informação não case exatamente com a quantidade de objetos criados dentro dessa classe, você receberá um erro na tela do console JavaScript.
Da linha 30 à 35 temos a adição das funções que efetuarão o pré-carregamento de fato. Veja como o reaproveitamento de código é feito a partir do uso da função imgCarregada() que irá lidar com quaisquer tipos de objetos desenháveis. Por último temos a configuração dos atributos src dos mesmos objetos que apontam o caminho relativo das imagens. As imagens informadas podem ser encontradas no arquivo de download do código fonte deste artigo, mas o leitor pode ficar à vontade para usar suas próprias imagens de jogadores e inimigos e ver como o jogo se adapta às mesmas. Não esqueça de verificar sempre os tamanhos de cada arquivo para que os personagens não apareçam cortados.
Esse código ainda não surtirá nenhum efeito, porque precisamos que as demais configurações dos objetos sejam criadas em suas respectivas funções. Para isso, atualizemos a classe Combo, como mostra a Listagem 2.
Listagem 2. Atualizando as funções na classe Combo.
01 function Combo(objeto) {
02 this.vivo = false; // Será marcado como true se o combo estiver em uso
03 var self = objeto;
04
05 /*
06 * Valores dos combos
07 */
08 this.configurar = function(x, y, velocidade) {
09 this.x = x;
10 this.y = y;
11 this.velocidade = velocidade;
12 this.vivo = true;
13 };
14
15 /*
16 * Função que desenha os combos
17 */
18 this.desenhar = function() {
19 this.context.clearRect(this.x-1, this.y-1, this.largura+1, this.largura+1);
20 //this.context.clearRect(this.x, this.y, this.largura, this.altura);
21 this.x += this.velocidade;
22 if (self == "combo" && this.x <= 0 - this.largura) {
23 return true;
24 } else if (self === "comboInimigo" && this.y >= this.alturaCanvas) {
25 return true;
26 } else {
27 if (self === "combo") {
28 this.context.drawImage(repositorio.combo, this.x, this.y);
29 } else if (self === "comboInimigo") {
30 this.context.drawImage(repositorio.comboInimigo, this.x, this.y);
31 }
32 return false;
33 }
34 };
35
36 /*
37 * Reinicia as propriedades do combo
38 */
39 this.limpar = function() {
40 this.x = 0;
41 this.y = 0;
42 this.velocidade = 0;
43 this.vivo = false;
44 };
45 }
46 Combo.prototype = new Desenhavel();
Nessa listagem podemos observar dois comportamentos que serão distintos dos combos que já criamos antes:
• Primeiro, os inimigos irão lançar combos diferentes em relação aos do player, e esses mesmos combos também têm comportamentos diferentes ...
Confira outros conteúdos:
Perguntas frequentes
Nossos casos de sucesso
Eu sabia pouquíssimas coisas de programação antes de começar a estudar com vocês, fui me especializando em várias áreas e ferramentas que tinham na plataforma, e com essa bagagem consegui um estágio logo no início do meu primeiro período na faculdade.
Estudo aqui na Dev desde o meio do ano passado!
Nesse período a Dev me ajudou a crescer muito aqui no trampo.
Fui o primeiro desenvolvedor contratado pela minha
empresa. Hoje eu lidero um time de desenvolvimento!
Minha meta é continuar estudando e praticando para ser um
Full-Stack Dev!
Economizei 3 meses para assinar a plataforma e sendo sincero valeu muito a pena, pois a plataforma é bem intuitiva e muuuuito didática a metodologia de ensino. Sinto que estou EVOLUINDO a cada dia. Muito obrigado!
Nossa! Plataforma maravilhosa. To amando o curso de desenvolvimento front-end, tinha coisas que eu ainda não tinha visto. A didática é do jeito que qualquer pessoa consegue aprender. Sério, to apaixonado, adorando demais.
Adquiri o curso de vocês e logo percebi que são os melhores do Brasil. É um passo a passo incrível. Só não aprende quem não quer. Foi o melhor investimento da minha vida!
Foi um dos melhores investimentos que já fiz na vida e tenho aprendido bastante com a plataforma. Vocês estão fazendo parte da minha jornada nesse mundo da programação, irei assinar meu contrato como programador graças a plataforma.
Wanderson Oliveira
Comprei a assinatura tem uma semana, aprendi mais do que 4 meses estudando outros cursos. Exercícios práticos que não tem como não aprender, estão de parabéns!
Obrigado DevMedia, nunca presenciei uma plataforma de ensino tão presente na vida acadêmica de seus alunos, parabéns!
Eduardo Dorneles
Aprendi React na plataforma da DevMedia há cerca de 1 ano e meio... Hoje estou há 1 ano empregado trabalhando 100% com React!
Adauto Junior
Já fiz alguns cursos na área e nenhum é tão bom quanto o de vocês. Estou aprendendo muito, muito obrigado por existirem. Estão de parabéns... Espero um dia conseguir um emprego na área.