Artigo
Criando Efeitos atraves de SpriteBatch com XNA

Uma abordagem sobre enumenração SpriteBlendMode

Enviado por Luciano José em 21/4/2008 0:00:00

Introdução
 
Será assumido que você tenha algum conhecimento sobre SpriteBatch.
Mais informações neste artigo: Um Panorama sobre o objeto SpriteBatch do XNA
Este artigo vai tratar especificamente da enumeração: SpriteBlendMode.
 
A enumeração SpriteBlendMode provê 3 valores:
 
  • SpriteBlendMode.None
  • SpriteBlendMode.AlphaBlend
  • SpriteBlendMode.Additive
 
 
Modos de mistura de Sprites
 
SpriteBlendMode.None
 
Indica que nenhum modo de “blending” será utilizado.
 
Nesse modo, por exemplo, não é possível modificar a opacidade da textura.
 

Demonstração:

 

Suponha que você tenha feito sua arte em uma ferramenta de edição de imagem que permita alterar a opacidade da imagem. E, ao finalizar a sua arte, você coloque a opção de “opacity” menor que 100% com o objetivo de obter uma imagem “transparente” em seu jogo. Nesse caso, para este modo de “blending”(SpriteBlendMode.None), você não obterá o resultado desejado - que é uma imagem transparente em seu jogo. O resultado obtido será uma imagem totalmente opaca.

Foto1
 
A imagem acima contém apenas 10% de opacidade.

 

Foto2 - Por exemplo: Na ferramente MS Expression Design você pode “regular” a opacidade, alterando os valores nas barras ao lado do nome “Opacity”.
 
Se você tentar renderizar a imagem(Foto1) utilizando SpriteBlendMode.None. Você, certamente, obterá algum resultado visual com uma imagem totalmente opaca - como mostrado abaixo:

 

Foto3 - Imagem com sua propriedade de opacidadade em 10%. Essa Imagem foi renderizada no modo SpriteBlendMode.None. Essa imagem está ocopuando toda a janela(800x600).

 

Foto4 – Imagem com 20% de opacidade
 
 
 
Foto5 – Imagem com 20% de opacidade sendo renderizada no modo
SpriteBlendMode.None.
 
Observe que tanto nas fotos 3 e 5, o texel´s com o seus valores RGBA – (0, 0, 0, 0) estão vísiveis neste modo(SpriteBlendMode.None).
 
 
 
 
SpriteBlendMode.AlphaBlend
 
Quando esse é escolhido, é abilitado o efeito de Alpha Blending. No XNA, por padrão, este modo é utilizado para qualquer imagem renderizada com o spriteBatch.
 
Isso ocorre para o bloco de código a seguir:
 
this.spriteBatch.Begin();
...
this.spriteBatch.End();
 
O bloco acima, tem “o mesmo efeito” que o bloco de código abaixo:
 
this.spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
...
this.spriteBatch.End();
 
Esse padrão do XNA, mencionado anteriormente, pode ser quebrado quando o SpriteBlendMode é explicitamente indicado com outro valor diferente de SpriteBlendMode.AlphaBlend - isso só pode ser verdade a partir da 2º sobrecarga do método SpriteBatch.Begin.
 
Abaixo uma lista das sobrecargas do método SpriteBatch.Begin:
SpriteBatch.Begin ()
SpriteBatch.Begin (SpriteBlendMode)
SpriteBatch.Begin (SpriteBlendMode, SpriteSortMode, SaveStateMode)
SpriteBatch.Begin (SpriteBlendMode, SpriteSortMode, SaveStateMode, Matrix)
Observe que a partir da 2º sobrecarga do método em questão, é que pode-se modificar o SpriteBlendMode.
 
Quando este modo(SpriteBlendMode.AlphaBlend) é escolhido, a textura tem a capacidade de
 
Ter o seu valor do alpha modificado; a textura pode “ficar transparente” – a opacidade da textura pode ser alterada.
 

Diferentemente do ocorrido com o modo SpriteBlendMode.None, se você tentar renderizar a imagem da Foto1 neste modo - o resultado visual obtido será uma imagem transparente, como mostrado na foto abaixo:

 
Foto6 - Imagem com 10% de opacidade. Renderizada no modo SpriteBlendMode.AlphaBlend.
 

Tome Cuidado!

 
Imagine que esteja desenhando sua arte em alguma das ferramentas de edição de imagem apresentadas a seguir, e você queira o seu arquivo de textura com o fundo com transparência abilitada - ao final, você deve tomar alguns cuidados, se você estiver utilizando a ferramenta:
 
-Gimp
 
Na barra de opções, vá em Layer-> Transparency-> Add Alpha Channel.
 
Agora, vá para a janela de Ferramentas do Gimp, e escolha a ferramenta “Fuzzy Select Tool”. Clique com essa ferramenta no funda da sua artBoard e aperte a tecla do teclado Delete.
 
-Adobe Photoshop
 
Assegure-se que a sua layer que vem criada pelo Photoshop, denominada BackGround, está desbloqueada. Ao estar desbloqueada,
escolha a ferramenta Magic Wand(W) e clique no fundo de sua artBoard e aperte a tecla Delete.
 
-Paint.Net
 
Escolha a ferramenta Magic Wand, clique no fundo da ArtBoard e aperte delete.
 
-Microsoft Expression Design 2 beta e Adobe Illustrator
 
Quando você for exportar sua arte, por padrão, a opção de transparência já vem marcada e você não precisa se preocupar!
 
 
SpriteBlendMode.Additive
 
Esse modo é usado para “reluzir” objetos; tal efeito pode ser usado em explosões, efeitos mágicos, etc.
 
 
Demonstração
 

Para demonstrar este modo, será utilizado a imagem abaixo:

 
 
Foto7
 
Quando, no jogo, essa imagem for renderizada utilizando o modo  SpriteBlendMode.Additive, ela tomará um aspecto “transparente” e com algumas caracteristicas:
 
Quando essa imagem transpõe(passa por cima) de outra textura, ela vai “reluzir” a outra textura de acordo com as cores envolvidas na transposição.
 
Você observará, na demonstração disponivel mais adiante, que nas regiões mais escuras em que houve a transposição, a região da textura transposta tende a ficar mais próxima ao aspecto normal. O efeito contrário acontece quando a região da textura está sendo transposta por alguma coloração que tende ao Branco.
 

A foto abaixo, mostra o que acontece com a textura transposta quando uma textura com o modo SpriteBlendMode.Additive transpõe essa textura:

 
 
Foto8- na região entre o branco e o preto, está a escala cinza, mas para obter algum efeito reluzente, a cor deve estar entre o branco(RGB – 255, 255, 255) e o preto(RGB – 255, 255, 255). Alguns exemplos: o vermelho(RGB – 255, 0, 0), o verde(RGB – 0, 255, 0) são cores que estão entre o branco e o preto.
 
 

Adimitamos a textura abaixo:

Foto9 – um retangulo totalmente preto
 

Se a Foto9 for renderizada com o modo SpriteBlendMode.Additive, e, posteriormente, essa textura(Foto9) “passe por cima” da maça. O resultado obtido será a propria maça:

Foto10
 
 
Em contra partida, se a textura(Foto9) utilizada para obter o efeito acima, for um retângulo totalmente branco, o resultado obtido será o próprio retangulo branco 100% opaco.
 
Fica, então, sendo possivel obter algum resultado reluzente com qualquer cor sendo diferente e estando entre o preto(RGB – 0, 0, 0) e o branco(RGB – 255, 255, 255) - como mostrado na Foto8.
 
Nesta demonstração, o efeito luminoso obtido se resumi a este bloco de código localizado no método Draw:
 
this.spriteBatch.Begin(SpriteBlendMode.Additive);           
            this.spriteBatch.Draw(this.luz, posicaoDaLuz, Color.Yellow);
            this.spriteBatch.End();
 
Observe o 3º parametro do método spriteBatch.Draw, aonde foi indicado a cor amarela. Nas fotos da demonstração mostradas mais adiante, você reparará um efeito luminoso que sai da lanterna será amarelo; tal efeito foi acançado através da imagem da Foto7.
 
Quando você for criar seus efeitos, quando possível, tenha em mente a criação deles com as tonalidades da textura estando em Branco e Preto.
 
 
Abaixo, é exposto a a fórmula que causa indepêndencia entre o programador e o designer:
 
Cor Branca(RGB – 255, 255, 255) + Cor X(RGB – Y, W, Z) = Cor X(RGB – Y, W, Z)
 
No método Draw do spriteBatch, foi indicado que a cor de tingimento é Color.Yellow, dai quando a Foto5 for renderizada na tela, temos um resultado visual obtido a partir da fórmula:
 
Branco + Amarelo = Amarelo
 
Você observará nas fotos a seguir, que nas regiões brancas foram tingidas com amarelo e o resultado obtido é amarelo. Nas regiões aonde da textura há o preto, nada acontece.
 
Quando você for construir seu jogo com sua equipe e dependendo do efeito que você vai querer obter no jogo - se você quer promover uma indepêndencia entre o designer e o programador, evitando texturas para cada tipo de situação, basta 1 única textura(geralmente, branco e preto) e via código você vai obter o resultado desejado!
 
Nesta demonstração, vários objetos foram colocados na tela para você observar o resultado obtido com este modo(SpriteBlendMode.Additive).
 

Fotos da demonstração:

Foto11

Foto12

Foto13

Foto14

 

Foto15
 
O et observado na tela foi feito pelo André Furtado.
 
 
Projeto para drownload:  spritebatchproject.zip 646528 bytes
 
 

2º Demonstração

 
Esta demonstração funciona da seguinte forma:
 
Este Mouse, da foto abaixo, será desenhado uma vez na tela. 

 

 

Foto16 - Mouse
 
Logo após, várias texturas serão desenhadas acima dele(transpondo-o; encobrindo-o). Essas texturas serão a Foto16, só que elas estarão sendo “desenhadas” no modo SpriteBlendMode.Additive. A quantidade de texturas que cobrirão o Mouse em seu estado de coloração real será determinada pela variavel:
 
int qtdEffectsMax;
 
Para esta demonstração, essa variável terá a quantidade 5.
 
Isso implica que teremos 5 texturas, dando um efeito luminoso a imagem da Foto12, sendo desenhadas a cada passagem do método Draw.
 
 
Quando aplica-se o modo Additive, a textura também afetará, com algum efeito, as cores do fundo da tela, então, para manter o efeito dado a textura em seu “estado real” – sem causar misturas indesejadas - será usado o fundo preto.

 

Foto17
 
A Foto17 tem desenhado na tela apenas 1 a textura da Foto16 em modo Additive e com tingimento – Color.Red
 
O que de fato acontece nesta demonstração é que o Mouse da Foto16, é desenhado na tela e logo após, o mouse avermelhado da Foto17 sobrepõe,gradativamente, por várias vezes o Mouse da Foto16 – a quantidade de vezes é determinada pela variavel qtdEffectsMax.
 

Isso vai resultar em alguma coisa parecida com uma “aura” tingindo o mouse de vermelho. Observe esse efeito no fluxo da foto abaixo:

 
 

Foto18


Veja o método Draw dessa demonstração:
 
protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.Black);
           
            this.spriteBatch.Begin();
            this.spriteBatch.Draw(this.mouse, this.posicaoDoMouse, Color.White);
            this.spriteBatch.End();
 
            if (turnOnEffect)
            {
                int qtdEffects = (int)(aux % qtdEffectsMax);
 
                this.spriteBatch.Begin(SpriteBlendMode.Additive,
                    SpriteSortMode.Immediate, SaveStateMode.None);
 
                for (int i = 0; i < qtdEffects; i++)
                    this.spriteBatch.Draw(this.mouse, this.posicaoDoMouse, Color.Red);
 
                this.spriteBatch.End();
            }
           
 
            base.Draw(gameTime);
        }
 
A variável turnOnEffect indica se o efeito deve acontecer ou não.
 
No método Update, essa turnOnEffect recebe true, quando o botão esquerdo do Mouse é pressionado. Quando o botão esquerdo é liberado, o efeito para de ocorrer.
 
No bloco de código:
for (int i = 0; i < qtdEffects; i++)
   this.spriteBatch.Draw(this.mouse, this.posicaoDoMouse, Color.Red);
 
Além da cor - Color.Red - uma boa sugestão é você testar com outras cores. Note que, se você colocar a cor Color.Black, nada acontece!
 

Projeto para Download: spritebatchproject2.zip 104646 bytes 

3º Demonstração

Esta demonstração tem como objetido criar um efeito de ganho e perda de luminosidade baseado no tempo e tem como base a 2º demonstração.
 

Demostrando uma Lua ganhando e perdendo Luminosidade

 

A imagem utilizada para criação do efeito será uma Lua.

Observe a lua nos variados instantes ao longo do Efeito:

 

Foto 19 – Lua no instante 0,5 segundos.

 

 

Foto 20 – Lua no instante 5,3 segundos.

 

Foto 21 – Lua no instante 9,7 segundos. 
 
 

Projeto para Download: SpriteBatchProject3_Lua.zip