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! |