 | | |
|
| | | | Usando Tiles para criar Mapas |  | | A utilização de tiles otimiza o desenho de mapas. É possível criar mapas grandes a partir de imagens pequenas ou construir mapas diferetes usando uma mesma imagem. |  | Enviado por Denis Martins em 18/11/2009 0:00:00
| Por que usar Tiles? Carregar grandes imagens pode deixar seu jogo bastante lento. Através do uso de Tiles, podemos construir mapas grandes a apartir de imagens pequenas e montar mapas diferentes utilizando uma mesma imagem. Para esse exemplo, vamos utilizar a seguinte imagem:  A Classe Tile Um tile é representado por um retângulo. Cada tile possui um tipo e um atributo que define se ele pode ser atravessado, ou seja, se é possível se movimentar sobre ele. public class Tile { private Rectangle retangulo; private int tipo; private bool andavel; public Rectangle Retangulo { get { return this.retangulo; } set { this.retangulo = value; } } public int Tipo { get { return this.tipo; } set { this.tipo = value; } } public bool Andavel { get { return this.andavel; } set { this.andavel = value; } } public Tile(int tipo, bool andavel, int x, int y, int larguraTile, int alturaTile) { this.Tipo = tipo; this.Andavel = andavel; this.retangulo = new Rectangle(x, y, larguraTile, alturaTile); } public bool Collide(Rectangle box) { return this.retangulo.Intersects(box); } } Criando o Mapa Um mapa de tiles pode ser representado por uma matriz: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | public class Mapa { //imagem dos tiles private Texture2D imagemTiles; //conjunto de recortes da imagem dos tiles private Rectangle[] tileFrames; //matriz de tiles private Tile[,] tiles; //número de linhas da matriz de tiles private int linhas; //número de colunas da matriz de tiles private int colunas; //altura do tile private int tileAltura; //largura do tile private int tileLargura; //define o tipo de tile não andavel private const int TIPO_NAO_ANDAVEL = 0; O mapa é formado por uma matriz de tiles. Por isso, devemos definir o número de linhas e colunas dessa matriz. O mapa também possui uma imagem que representa o conjunto de tiles pelo qual ele é formado (tileset). Note que os tiles não possuem imagem, eles só definem a área da tela onde a imagem do mapa (tileset) será desenhada. Essa imagem é carregada através do método LoadContent. public Mapa(int linhas, int colunas, int tileLargura, int tileAltura) { this.linhas = linhas; this.colunas = colunas; this.tileLargura = tileLargura; this.tileAltura = tileAltura; this.tiles = new Tile[linhas, colunas]; } public void LoadContent(ContentManager content, string filename) { this.imagemTiles = content.Load<Texture2D>(filename); } O atributo tileFrames representa um conjunto de recortes da imagem de tiles. Cada tipo de tile tem um recorte diferente. //gera os recortes da imagem de tiles public void GerarTileFrames() { //quantidade de tiles na imagem int tileSprites = (this.imagemTiles.Width / this.tileLargura) * (this.imagemTiles.Height / this.tileAltura); this.tileFrames = new Rectangle[tileSprites]; //indice do array de frames int indice = 0; //largura da imagem de tiles int width = this.imagemTiles.Width; //altura da imagem de tiles int height = this.imagemTiles.Height; for (int i = 0; i < width; i += this.tileLargura) { for (int j = 0; j < height; j += this.tileAltura) { //cria os frames correspondentes a cada tipo de tile this.tileFrames[indice] = new Rectangle(i, j, this.tileLargura, this.tileAltura); indice++; } } } Calculamos o número de tiles diferentes contidos na imagem. Percorremos a imagem criando os recortes correspondentes a cada tipo de tile. Para carregar o mapa, passamos como parâmetro uma matriz de inteiros. Cada valor da matriz representa um tipo diferente de tile. public void CarregarMapa(int[,] matriz) { /* testa se a matriz parâmetro tem * dimensões diferentes da matriz de tiles */ if (matriz.GetLength(0) != this.tiles.GetLength(0) || matriz.GetLength(1) != this.tiles.GetLength(1)) { throw new Exception("Matriz não possui a mesma dimensão do Mapa"); } //testa se a imagem dos tiles foi carregada if (this.imagemTiles == null) { throw new Exception("Imagem do mapa não foi carregada"); } //gera os frames dos tiles this.GerarTileFrames(); //posição x do tile int x = 0; //posição y do tile int y = 0; //tipo do tile que vai ser lido da matriz int tipo = -1; //indica se o tile pode ser atravessado bool andavel = true; for (int i = 0; i < this.linhas; i++) { for (int j = 0; j < this.colunas; j++) { tipo = matriz[i, j]; if (tipo < 0 || tipo > this.tileFrames.Length) { throw new Exception("Tipo de tile inválido"); } else { //testa se o tipo lido é não-andável if (tipo == TIPO_NAO_ANDAVEL) andavel = false; //cria o tile na posição x y this.tiles[i, j] = new Tile(tipo, andavel, x, y, this.tileLargura, this.tileAltura); } x += this.tileLargura; } x = 0; y += this.tileAltura; } } Definimos a posição x,y da tela onde cada tile será desenhado. Para desenhar o mapa na tela, é só percorrer a matriz de tiles desenhando um tile de cada vez. //desenha os tiles na tela public void Draw(SpriteBatch batch) { for (int i = 0; i < this.linhas; i++) { for (int j = 0; j < this.colunas; j++) { Rectangle destino = new Rectangle( this.tiles[i, j].Retangulo.X, this.tiles[i, j].Retangulo.Y, this.tileLargura, this.tileAltura); int frame = this.tiles[i, j].Tipo; batch.Draw(this.imagemTiles, destino, this.tileFrames[frame], Color.White); } } } } Usamos o método Draw() do SpriteBatch para definirmos como cada tile será desenhado na tela. O primeiro parâmetro representa a imagem dos tiles e o segundo, a área onde a imagem será desenhada. O terceiro parâmetro é o mais importante, porque define a área da imagem (recorte) que será usada na impressão. Usamos o frame correspondente ao tipo de tile que está sendo desenhado. Usando o Mapa Na Classe Game, adicione: Mapa mapa; //estrutura do mapa int[,] matrizMapa = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 0}, {0, 1, 1, 0, 1, 1, 0, 1, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 0}, {0, 1, 1, 0, 1, 1, 0, 1, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 0}, {0, 1, 1, 1, 1, 1, 1, 1, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; //largura do tile const int LARGURA_TILE = 32; //altura do tile const int ALTURA_TILE = 32; Definimos as dimensões dos tiles e criamos a matriz de construção do mapa. protected override void Initialize() { //cria o mapa this.mapa = new Mapa(matrizMapa.GetLength(0), matrizMapa.GetLength(1), LARGURA_TILE, ALTURA_TILE); base.Initialize(); } protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); //carrega a imagem de tiles do mapa this.mapa.LoadContent(this.Content, "tiles"); //carrega o mapa this.mapa.CarregarMapa(this.matrizMapa); } protected override void UnloadContent() { // TODO: Unload any non ContentManager content here } protected override void Update(GameTime gameTime) { base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); this.spriteBatch.Begin(); //desenha o mapa na tela this.mapa.Draw(this.spriteBatch); this.spriteBatch.End(); base.Draw(gameTime); } | Arquivos Anexados
|
Clique para avaliar: |
| Comentários
|
" Denis, verifique seu cadastro aqui no portal e seu perfil no fórum. Se nada aparecer estranho, mande um e-mail para mim. jalf@sharpgames.net ok?" | |
Enviado por Jose Antonio Farias em 19/11/2009 8:49:43: |
|
|
" Submeti esse artigo, mas meu nome não apareceu. Como sou novo aqui o que eu faço?" | |
Enviado por Denis Martins em 18/11/2009 17:08:56: |
|
| Adicione seu Comentário
Voltar |
|
 |

|
| | |
|
|
|  |