Introdução
Scrolling ocorre quando se está “deslizando” sobre o conteúdo(texels) de uma imagem.
Para efetuar scrolling, com o SpriteBatch provido pelo XNA, em sprites, é necessário utilizar algum método a partir da 3º sobrecarga do Método SpriteBatch.Draw; são aquelas sobrecargas que possibilitam a especificação de uma seção da textura. Este artigo do André Furtado trata mais a fundo esse assunto.
O protótipo que será criado mais adiante, vai usar a 4º sobrecarga do método SpriteBatch.Draw.
Observe a assinatura da sobrecarga escolhida:
public void Draw (
Texture2D texture,
Vector2 position,
Nullable<Rectangle> sourceRectangle,
Color color
)
texture – a textura a ser renderizada.
position – a posição da textura na tela.
sourceRectangle – determina uma região(interna) retangular, da textura, a ser renderizada na tela. Se o valor passado for null a textura será renderizada por completa.
color – cor de tingimento.
sourceRectangle.X e sourceRectangle.Y -especificam o local de origem da região(interna). sourceRectangle.Width e sourceRectangle.Height determinam as dimensões da região interna.
Scrolling
O XNA utiliza como padrão, para o mapeamento de textura, o valor TextureAddressMode.Clamp. Nesse tipo de mapeamento, se o limite(tanto da largura ou altura) da textura for extrapolado, na proporção que o scrolling for acontecendo, o sprite vai sendo “borrado” com os texels da borda da textura aonde houve o extrapolamento.
Para obter um comportamento compatível com o objetivo do Scrolling,
é preciso utilizar o mapeamento TextureAddressMode.Wrap. Nesse tipo de mapeamento, a textura é repetida após:
- os valores de Rectangle.X ou Rectangle.Y ultrapassarem os valores de largura ou altura da textura.
- o retângulo usado para definir as dimensões(largura e altura) da textura, tem sua largura ou altura maior que a largura ou altura da textura. Essa 2º situação é útil para “ladrilhar” algum sprite. No link passado ao final do artigo, você pode encontrar um exemplo aonde um sprite é “ladrilhado”. A idéia e código utilizado é bem semelhante que o apresentado no protótipo mais adiante.
A modificação de mapeamento deve ser feita após a chamada do método SpriteBatch.Begin, no modo SpriteSortMode.Immediate
Criando um protótipo para demonstrar o que foi abordado acima

Foto 1
Este protótipo consiste em fazer scrolling com a imagem(Foto 1) mostrada acima.
Com o teclado, utilizando as setas, o player poderá deslizar sobre a imagem em qualquer direção. Tal comportamento é interessante, por exemplo, para se ter a sensação de um mapa infinito. Nesse caso, a idéia obtido será de um “céu infinito”.
public class Game1 : Microsoft.Xna.Framework.Game
{
...
Texture2D nuvens;
/*Os campos abaixo, u e v, irão determinar o ponto de
* origem do retangulo na textura
* */
///<summary>
/// Vai determinar o Rectangle.X
///</summary>
int u = 0;
///<summary>
/// Vai determinar o Rectangle.Y
///</summary>
int v = 0;
No método Update, será oferecido ao player, o direito de efetuar o scrolling na imagem das nuvens(Foto 1). Veja como ficou o método Update:
protected override void Update(GameTime gameTime)
{
KeyboardState keyboard = Keyboard.GetState();
if (keyboard.IsKeyDown(Keys.Up))
{
v -= 2;
}
if (keyboard.IsKeyDown(Keys.Down))
{
v += 2;
}
if (keyboard.IsKeyDown(Keys.Left))
{
u -= 2;
}
if (keyboard.IsKeyDown(Keys.Right))
{
u += 2;
}
base.Update(gameTime);
}
O valor 2 foi escolhido aleatoriamente(não faça isso em um jogo real) para que o scrolling seja apreciado nem muito rápido, nem muito lento!!!
Lembre-se, em um “jogo real”, não atribua valores aleatoriamente no codigo de seu jogo!!!
Tome cuidado com os valores de u e v que crescerão rapidamente. Desenvolva algum algoritmo para que esses valores por exemplo, não extrapole o limite dos inteiros ou do tipo escolhido para as variáveis(u e v);
Será sugerida 2 formas(algoritmos) para controlar esses valores de u e v, preservando o scrolling para qualquer direção:
/*
* Sugestão 1
*
* Para controlar os valores de u e v, obtendo um resultado
* visual satisfatorio e que não comprometa o desempenho do jogo.
*
* O algoritmo abaixo, garante que u esteja entre a largura
* da textura negativa ou a largura da textura positiva.
* O mesmo vale para v com a altura...
u %= this.nuvens.Width;
v %= this.nuvens.Height;
* */
/*
* Sugestão 2
*
* Para controlar os valores de u e v, obtendo um resultado
* visual satisfatorio e que não comprometa o desempenho do jogo.
*
* O algoritmo abaixo, garante que u esteja entre a largura
* da textura negativa ou a largura da textura positiva.
* O mesmo vale para v com a altura...
if (u > this.nuvens.Width || u < -this.nuvens.Width)
{
u = 0;
}
if (v > this.nuvens.Height || v < -this.nuvens.Height)
{
v = 0;
}
* */
Tudo que foi abordado anteriormente, será concretizado no método Draw:
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.Snow);
this.spriteBatch.Begin(SpriteBlendMode.AlphaBlend,
SpriteSortMode.Immediate, SaveStateMode.None);
this.GraphicsDevice.SamplerStates[0].AddressU = TextureAddressMode.Wrap;
this.GraphicsDevice.SamplerStates[0].AddressV = TextureAddressMode.Wrap;
this.spriteBatch.Draw(this.nuvens, Vector2.Zero,
new Rectangle(u, v, this.GraphicsDevice.Viewport.Width,
this.GraphicsDevice.Viewport.Height),
Color.White);
this.spriteBatch.End();
base.Draw(gameTime);
}
Abaixo, uma imagem com o resultado final:

Foto 2
Agora você pode baixar o protótipo e realizar o scrolling com as setas do teclado: Projeto - Scrolling
Dúvidas, Críticas e Sugestões são bem-vindas.
Obrigado!
|