Introdução
No XNA, em geral, a responsabilidade de representar imagens(2D) é atribuída a classe Texture2D.
A classe Texture2D representa uma grade(2D) de Texels; também denominamos isso de Sprite.
Sprite é qualquer imagem atribuída a um jogo.
Visao geral sobre Texel:
-
Um Texel representa a menor parte de uma Textura.
-
Um Texel pode ser qualquer um dos formatos disponiveis representados na enumeração SurfaceFormat.
-
Um Texel é composto de 1 a 4 componentes.
O Formato de Texel mais utilizado é o RGBA(SurfaceFormat.Color).
O formato RGBA possui 4 componentes - R(vermelho), G(verde), B(azul), Alpha(canal que determina o quão opaco é o texel) - cada componente possui 8-bit´s, ou seja, cada texel usa um valor de 32-bit´s para representar a sua cor.
Formas de obtenção de uma Textura no XNA
No XNA, é muito comum obter uma textura através do código a seguir:
protected override void LoadContent()
{
...
this.myTexture = this.Content.Load<Texture2D>(“...”);
...
}
O código acima ler uma textura através do Contet Pipeline.
O Content Pipeline provê o suporte dos tipos de imagens a seguir: .bmp, .dds, .dib, .hdr, .jpg, .pfm, .png, .ppm e .tga
Você também pode instanciar um objeto Texture2D. Fazendo assim, para obter algum resultado visual proveniente dessa instância, você precisa manipular a cor de cada texel através de “código C#”.
Logo, temos 2 formas para obtenção de uma Textura:
- Através do Content Pipeline;
- Instanciando(explícitamente) uma Textura.
Existe também uma outra maneira, que é através do método Texture2D.FromFile.
Mais informações sobre o Método FromFile da classe Texture2D e aonde utilizá-lo, no artigo do Shinji abaixo:
Instanciando um objeto Texture2D
Observe o construtor da classe Texture2D:
public Texture2D (
GraphicsDevice graphicsDevice,
int width,
int height,
int numberLevels,
ResourceUsage usage,
SurfaceFormat format
)
graphicsDevice – usado para mostrar a textura na tela.
width – a largura, em pixels, da textura.
height – a altura, em pixels, da textura.
numberLevels – quantidade de pequenas versões da textura; utilizadas quando a textura é redimensionada para preencher uma área menor que o tamanho da textura original. Geralmente, o numero de níveis utilizado é 1.
usage – indica o comportamento da textura.
format – indica o formato de cada Texel.
Como abordado anteriormente, a classe Texture2D representa uma grade(2D) de Texel´s. Então, saber como manipular os Texel´s, é uma tarefa relevante quando se está instanciando(explícitamente) uma textura.
A classe Texture2D, provê 2 métodos importantes para manipulação de seus texel´s:
- Texture2D.GetData – Copia os dados da texture para um “array”.
- Texture2D.SetDate – Copia um “array” de dados para uma textura.
Para esta demonstração, não será necessário a utilização do método GetData, pelo fato da Textura, quando instanciada, estar desprovida de qualquer tipo de cor, como mostrado na foto a seguir:
Observe o local do breakpoint após o objeto ser instanciado - observação dos texel´s da texetura. Na foto, o array de cores contém 100 elementos com cada elemento composto de 4 componentes(RGBA) de valor 0.
Será criado o método criaTexturaSimples, com a seguinte assinatura:
void criaTexturaSimples(ref Texture2D textura);
Esse método será chamado dentro do método LoadContent e terá como função: criar uma textura que tenha todos os seus Texel´s de uma única cor; uma textura unicolor(que tem só uma cor). Quando isso(a textura) for renderizada na tela, você notará uma forma geometrica de quatro lados e uma única cor.
Observe o método:
void criaTexturaSimples(ref Texture2D textura)
{
//largura e altura da Textura
int width = 100;
int height = 100;
//quantidade Total de Texels que a textura vai conter
int quantidadeTotalDeTexels = width*height;
//instanciando todas as cores que
//estarão contidas nos texels da textura
Color[] coresDaTextura = new Color[quantidadeTotalDeTexels];
/*instanciando um objeto Texture2D.
* Para esta demonstração, o formato da superficie a ser usado
* será do tipo Cor */
textura = new Texture2D(this.GraphicsDevice, width, height, 0,
TextureUsage.None, SurfaceFormat.Color);
/*Já instanciada, agora a textura já contém todos os Texel´s no
* formato informado no seu construtor.
* Neste momento, para obter algum resultado visual, é necessario
* atribuir uma cor a cada Texel - o código a seguir faz isso.*/
for (int i = 0; i < quantidadeTotalDeTexels; i++)
{
coresDaTextura[i] = Color.Blue;
}
//modifica os dados atuais da textura para o array de cores processados no
//bloco de codigo anterior
textura.SetData<Color>(coresDaTextura);
//Por fim, a textura tem todos os Texel´s com cores atribuidas.
//Nesta demonstração os Texel´s contêm a cor branca
}
Entendendo o que foi feito de maneira Gráfica:
Foi criado um textura de largura e altura: 100. Fica inviável demonstrar 10.000 texel´s, portanto, imagine uma textura com altura e largura: 4. Observe a imagem:
Neste caso, cada célula da “matriz” é um Texel. Logo, temos um amontoado de Texel´s dispostos de forma Bidimensional(formado por linhas e colunas); como o proprio nome sugere – Texture2D.
Observe o código:
for (int i = 0; i < quantidadeTotalDeTexels; i++)
{
coresDaTextura[i] = Color.Blue;
}
Do ponto de vista da textura, os Texel´s da textura são acessados semelhante a foto abaixo:
A linha vermelha, juntamente com as setas preta, representa o fluxo com que o loop(for) está acessando os texels.
Se olharmos do ponto de vista do array de cores, ele está sendo acessado, conforme mostrado na figura abaixo:
Cada célula do vetor unidimensional, representa um Texel e este, recebe a cor azul.
Com o array de cores preenchidos, agora só falta atribuir as cores ao texel´s da textura, a linha de código abaixo faz isso:
textura.SetData<Color>(coresDaTextura);
Observe graficamente:
O método SetData, preenche a textura com as cores fornecidas no array de cores.
Neste momento a textura já está pronta para ser renderizada na tela e mostrar algum tipo de resultado visual. O resultado visual obtido é uma forma geométrica com 4 lados e totalmente azul.
Criando uma Bandeira
Para a criação desta bandeira, o array de cores será acessado em sua forma “nativa”; o acesso se dará através de linhas e colunas tornando possível uma melhor manipulação dos Texel´s.
Observe a bandeira pronta:
Bandeira ao lado do quadrado azul. Da esquerda para direita, as cores da bandeira: Purple, Pink and Yellow.
Observe a assinatura do método para construção da bandeira acima:
void criaBandeira(ref Texture2D bandeira);
Esse método é semelhante ao método mostrado anteriormente, nomeado: criaTexturaSimples.
void criaBandeira(ref Texture2D bandeira)
{
//variavel auxiliar para acesso aos campos do array de cores
int aux;
//largura e altura da Textura
int width = 500;
int height = 250;
//quantidade Total de Texels que a textura vai conter
int quantidadeTotalDeTexels = width * height;
//A Bandeira criada aqui(semelhante a varias existentes na vida real),
//é composta por 3 retangulos iguais e com cores diferentes
int tercaParte = width / 3;
...
/*Já instanciada, agora a textura já contém todos os Texel´s no
* formato informado no seu construtor.
* Neste momento, para obter algum resultado visual, é necessario
* atribuir uma cor a cada Texel - o código a seguir faz isso.*/
for (int i = 0; i < height/*linha*/; i++)
{
//"Prendemos" a linha, e "andamos" com as colunas
for (int j = 0; j < width/*coluna*/; j++)
{
aux = i * width + j;
if (j < tercaParte)
coresDaTextura[aux] = Color.Purple;
else if (j < (tercaParte * 2))
coresDaTextura[aux] = Color.Pink;
else
coresDaTextura[aux] = Color.Yellow;
}
}
...
}
Entendendo o Código de criação da Bandeira:
A bandeira criada e mostrada acima, tem 3 faixas de “mesmo tamanho” na vertical. A variavel tercaParte é reponsavel por guardar a largura de cada faixa. Como são 3 faixas, temos:
tercaParte + tercaParte + tercaParte = larguraTotalDaTextura;
Obs.: Nem sempre a soma das 3 partes será exatamente igual a largura total da textura, entretanto isso não afetará a textura visualmente.
Observe a linha de código do método criaBandeira:
int tercaParte = width / 3;
Representação gráfica da situação:
for (int i = 0; i < height/*linha*/; i++)
{
//"Prendemos" a linha, e "andamos" com as colunas
for (int j = 0; j < width/*coluna*/; j++)
{
aux = i * width + j;
if (j < tercaParte)
coresDaTextura[aux] = Color.Purple;
else if (j < (tercaParte * 2))
coresDaTextura[aux] = Color.Pink;
else
coresDaTextura[aux] = Color.Yellow;
}
O fluxo de acesso ao array de cores:
Sugestão de Texturas instanciadas e manipuladas
3 Sugestões("tarefa de casa") para você fazer e praticar o que foi abordado acima.
1. Criar as faixas da bandeira no formato horizontal, como mostrado na figura abaixo:
2. Criar a bandeira acima, com o fluxo de acesso aos Texel´s do array de cores mostrado na imagem abaixo:
3. Instanciar(explícitamente) um objeto Texture2D, e criar uma moldura circular conforme mostrado na figura abaixo:

Observe que a região circular da textura está desprovida de cor, ou seja, você pode ver o que "está por trás" dela.
Leia mais sobre o assunto:
Artigo do José Ferreira: http://www.sharpgames.net/Artigos/Tutorial+de+XNA+-+Parte+IV.xna
Todas as imagens utilizadas neste artigo, foram criadas e/ou editadas com a ferramenta Microsoft Expression Design 2 Beta.
Dúvidas, Críticas e Sugestões são bem vindas.
Obrigado! |