Artigo
Efetuando Scrolling com XNA

Realizando scrolling atraves de SpriteBatch

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

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:
 
 
  1. os valores de Rectangle.X ou Rectangle.Y ultrapassarem os valores de largura ou altura da textura.
 
  1. 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

 

 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!

 

Sobre o Autor

lucianoJose
Luciano José
MCP, MCTS. Administrador do SharpGames. Sou de Pernambuco! Meu Blog: lucianojosefj.spaces.live.com

Clique para avaliar:

Comentários

Adicione seu Comentário  Voltar
Translator
AdSense

Amazon

Logos do XBox 360, XNA e Games For Windows
Copyright 2008 por SharpgamesPolítica de Privacidade  |  Termos de Uso