Desenvolvimento - Javascript

HTML e Javascript: Desenhando um mapa 2D

Veja neste artigo como desenhar um mapa de duas dimensões em uma página HTML, utilizando para isso apenas recursos básicos da linguagem Javascript e o elemento Canvas da HTML5. Serão apresentados os principais conceitos sobre posicionamento de elementos em sistemas de coordenadas de duas dimensões e desenho de mapas baseados em tiles.

por Joel Rodrigues



Introdução

Com o rápido avanço da web, boa parte das aplicações que antes eram restritas ao desktop pôde ser migrada ou atualizada para se adequar ao novo perfil de mercado que observamos atualmente.

Uma das principais categorias de aplicações que seguiu esse avanço foi a de JOGOS. Hoje encontramos games bastante complexos, com ótimos gráficos, sons e recursos para garantir uma boa jogabilidade.

Em constante desenvolvimento, as grandes atualizações sofridas pelas web standards (HTML, CSS e Javascript) permitiram a existência, hoje, de jogos desenvolvidos praticamente só com Javascript, dinamizando uma página HTML. Utilizando o elemento CANVAS da HTML5 juntamente com Javascript, é possível desenhar vários gráficos na tela, de forma simples com um resultado “leve”, de bom desempenho.

Com base nesse contexto, esse artigo busca apresentar uma técnica simples e de fácil compreensão para se desenhar um mapa em duas dimensões em uma página HTML. Para isso serão utilizados unicamente HTML, CSS e Javascript, contidos em um único arquivo para deixar ainda mais visível a simplicidade dos códigos desenvolvidos.

A escolha desse tema se deu devido a uma ordem lógica que geralmente é seguida pelos desenvolvedores de jogos iniciantes. Primeiramente desenvolve-se protótipos em duas dimensões e, em algumas categorias de jogos, um dos primeiros elementos a ser produzido é o mapa.

Sistema de coordenadas em duas dimensões

Para se desenhar um mapa e até mesmo programar a movimentação de elementos em um game 2D, é preciso entender como funciona o sistema de coordenadas, utilizado como base do posicionamento de pontos em uma superfície (duas dimensões).

Eixos ordenados de duas dimensões

Figura 1: Eixos ordenados de duas dimensões

No sistema 2D padrão, a posição de um elemento qualquer é dada com base em dois eixos, um vertical (X) e um horizontal (Y). Havendo um objeto localizado em algum ponto do mapa, sua posição é composta por dois valores (coordenadas x e y) referentes à sua distância vertical e horizontal do canto inferior esquerdo do mapa, ponto chamado de ORIGEM (coordenadas x=0 e y=0, em vermelho na imagem).

Na Figura 2 estão dispostos alguns pontos sobre uma superfície e suas posições teóricas são mostradas em destaque.

Pontos localizados sobre a superfície 2D

Figura 2: Pontos localizados sobre a superfície 2D

Os pontos, da esquerda para a direita, encontram-se distantes verticalmente da origem de 25, 20 e 15 unidades, e horizontal de 5, 10 e 30 unidades.

Observação: a unidade de medida depende do contexto. Por exemplo, em um campo de futebol pode-se usar o metro como unidade padrão, enquanto que sobre uma mesa, o centímetro seria mais adequado. No caso de programas gráficos de computador, a unidade mais utilizada é o PIXEL, que usaremos nesse artigo.

Como já foi dito, a chamada ORIGEM do mapa está localizada no ponto inferior esquerdo. Porém, em páginas web e em alguns outros programas com interface gráfica, essa estrutura é alterada. Nesses casos, a origem está no canto superior esquerdo da tela, ou seja, ali é o ponto de coordenadas x=0 e y=0. O eixo X passa então a crescer para baixo, como ilustra a Figura 3.

Sistema de eixos em uma página web

Figura 3: Sistema de eixos em uma página web

O entendimento desses conceitos é fundamental para qualquer um que precise posicionar objetos sobre superfícies, como objetos em jogos 2D ou elementos gráficos em formulários de aplicações desktop.

Montagem do mapa

A maioria dos mapas em games 2D é montado a partir de TILES, imagens que representam uma parte de uma estrutura maior, como a grama ou um piso de madeira ou concreto. Esses tiles geralmente são pequenos para que se possa obter mais detalhes com a repetição vertical e horizontal deles.

O tile utilizado nesse artigo é mostrado na Figura 4, possui dimensões 64x64 e se chama “grama.png”.

Tile grama.png

Figura 4: Tile grama.png

Os tiles são repetidos vertical e horizontalmente até cobrir todo o mapa, ou a parte que se desejar. O primeiro tile é desenhado junto a uma das laterais e do topo ou da parte inferior. Como nesse caso desenharemos da esquerda pra direita e de cima para baixo, o primeiro ficará colado na lateral esquerda e no topo, ou seja, na origem do mapa. O segundo tile é posicionado logo após o primeiro, na mesma altura e a uma distância horizontal da lateral esquerda igual a largura da imagem. O terceiro tile, estará também na mesma altura, mas em uma distância horizontal da lateral esquerda igual a duas vezes sua largura. Esse processo é repetido até se completar a primeira linha de tiles, na parte superior do mapa.

Em seguida, inicia-se a segunda linha, onde os tiles estarão distantes do topo de uma distância igual a altura da imagem. Já o posicionamento horizontal segue a mesma sequência que na primeira linha. A Figura 5 busca ilustrar parte do processo de desenho dos tiles, tendo como base a imagem utilizada como exemplo.

Esquema de posicionamento dos tiiles

Figura 5: Esquema de posicionamento dos tiiles

Observação: apesar de na figura ser possível ver um espaço em branco entre as imagens, isso não ocorrerá na prática, onde os tiles estarão “colados” uns nos outros.

Tendo entendido como os tiles são posicionados, podemos pensar em um algoritmo que permita desenhá-los de forma iterativa, ou seja, utilizando laços de repetição, e que permita utilizar imagens de quais quer dimensões para montar um mapa de tamanho qualquer. Chegamos então ao modelo teórico apresentado na Listagem 1.

Listagem 1: Algoritmo de desenho do mapa

PARA x DE 0 ATÉ qtd_tiles_vertical
	PARA y DE 0 ATÉ qtd_tiles_horizontal
		DESENHAR TILE NA POSIÇÃO (x*altura_tile, y*largura_tile)
	FIM_PARA
FIM_PARA

A quantidade de tiles que serão utilizados na vertical e horizontal depende das dimensões do mapa e da imagem do tile. Assim, a quantidade de colunas do mapa será a razão entre a largura do mapa e a largura do tile. De forma análoga, a quantidade de linhas será a razão entre a altura do mapa e a altura do tile.

Já a posição de cada tile depende diretamente do seu “índice” vertical e horizontal, pois suas coordenadas serão múltiplos inteiros de suas dimensões.

Desenhando o mapa na prática

Tendo compreendido todos os conceitos apresentados até este ponto, é possível implementar o desenho do mapa em uma página HTML utilizando Javascript.

Todo o código utilizado encontra-se na Listagem 2, que pode ser copiada e salva como um arquivo de extensão .html. A imagem “grama.png” deve estar localizada no mesmo diretório que o arquivo HTML, ou seu caminho completo deve ser indicado na parte do código responsável pelo seu carregamento.

Listagem 2: Código completo de desenho do mapa

<DOCTYPE html>
<html>
<head>
	<style type="text/css">
	body{margin:0; padding:0}
	#canvasMapa{width:100%; height:100%; border: solid 1px}
	</style>
	<script type="text/javascript">
	window.onload = function(){
		var canvas = document.getElementById("canvasMapa");
		var context = canvas.getContext("2d");             
		var tile = new Image();
		tile.onload = function(){
			var i, j;                      
			for(i=0; i < canvas.height/tile.height; i++){
				for(j = 0; j < canvas.width/tile.width; j++){    
					context.drawImage(tile, i*tile.height, j*tile.width);
				}
			}                  
		};
	        grama.src = "grama.png";
	};
	</script>
</head>
<body>
<canvas id="canvasMapa"></canvas>
</body>
</html>

O único elemento HTML criado foi o CANVAS, área sobre a qual serão desenhados os tiles que irão compor o mapa.

O código CSS serve apenas para fazer com que a canvas ocupe toda a página, definindo suas dimensões como 100% e removendo as margens do elemento body.

Entre as tags script encontra-se o código responsável por montar o mapa. Como se vê, tudo ocorre dentro do evento onload do documento, momento em que a imagem deve ser carregada e desenhada sobre a canvas.

Primeiramente é identificada a canvas, armazenando uma referência a ela na variável “canvas”. Em seguida, utilizando o método getContext, captura-se a região (chamado contexto) da canvas onde serão desenhados os gráficos em duas dimensões (podem ser feitos desenhos em 3D). Logo após, é criado um objeto do tipo Image, nomeado de “grama” (nome sugestivo para o tile).

Então, dentro do evento onload do tile (Image) são feitos os loops conforme o modelo da Listagem 1, mas utilizando a sintaxe da linguagem Javascript. O método drawImage do contexto da canvas permite desenhar uma imagem, passando como parâmetro o objeto Image e as coordenadas em que deve ser desenhada.

Já fora do evento onload do tile, define-se o caminho da imagem a ser carregada (nesse momento o evento onload é disparado, desenhando o mapa).

O código é bem simples e dispensa explicações mais aprofundadas, uma vez que apenas foram aplicados, na linguagem Javascript, os conceitos vistos anteriormente.

Abrindo o arquivo no browser, o resultado que se obtém é este mostrado a seguir, na Figura 6.

Mapa desenhado

Figura 6: Mapa desenhado

Como a imagem utilizada para o tile não tem nenhum tipo de borda, o resultado foi uma superfície quase uniforme. A imagem a seguir mostra um segundo teste, feito com outro tile.

Mapa utilizando outro tile

Figura 7: Mapa utilizando outro tile

Conclusão

Neste artigo foram apresentados inicialmente os principais conceitos relacionados ao posicionamento de elementos em superfícies coordenadas, ou seja, em duas dimensões, bem como a lógica utilizada para se desenhar um mapa com base em tiles.

Ao final foi apresentado um código que permite montar um mapa, preenchendo uma página HTML com uma imagem pré-definida, repetindo-a vertical e horizontalmente.

O código apresentado é simples e não utiliza nenhum recurso mais avançado de programação de jogos ou das web standards, facilitando o entendimento e implementação.

Surgindo dúvidas a respeito do conteúdo aqui apresentados, encontro-me a disposição para tentar saná-las através da seção de comentários logo abaixo.

Até a próxima oportunidade.

Joel Rodrigues

Joel Rodrigues - Técnico em Informática - IFRN Cursando Bacharelado em Ciências e Tecnologia - UFRN Programador .NET/C# e Delphi há quase 3 anos, já tendo trabalhado com Webservices, WPF, Windows Phone 7 e ASP.NET, possui ainda conhecimentos em HTML, CSS e Javascript (JQuery).