[Tutorial] Renderizando objetos e movendo-os com XNA [Via Classe]
Este tutorial é uma continuação do tutorial:
Introdução
 No tutorial anterior, criamos uma imagem na tela e fizemos com que ela se movesse. No entanto, podemos encapsular este código dentro do uma classe e reutilizá-lo no futuro.
Neste artigo trataremos a criação de uma classe para o PacMan e sua utilização. Sendo assim, adicione uma nova classe no seu projeto com o nome de Sprite.cs.
Criando as variáveis
Para nossa classe Sprite, precisaremos criar algumas variáveis, sendo elas:
texture – Utilizada para manipular a textura da sprite.
size – Tamanho da sprite.
position – Posição da sprite na tela.
speed – velociade com que a sprite se movimentará.
rotation – Rotação da sprite.
effect – Efeitos da sprite.
Deste modo, teremos o seguinte código:
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; namespace XNASprites { /// /// Classe para manipulação de Sprites /// public class Sprite { #region Variáveis private Texture2D texture; private Vector2 size; private Vector2 position; private int speed = 1; private float rotation = 0; private SpriteEffects effect = SpriteEffects.None; #endregion } }
Criando as propriedades
Sabemos que na orientação à objetos, para cada variável a ser acessada externamente, temos que ter uma propriedade referente a mesma. Sendo assim, temos a adição das propriedades na nossa classe:
#region Propriedades /// /// Manipula a textura da Sprite /// public Texture2D Texture { get { return this.texture; } set { this.texture = value; } } /// /// Manipula o tamanho da Sprite. /// public Vector2 Size { get { return this.size; } set { this.size = value; } } /// /// Manipula a posição da Sprite na tela. /// public Vector2 Position { get { return this.position; } set { this.position = value; } } /// /// Manipula a velocidade na qual a Sprite se move na tela. /// public int Speed { get { return this.speed; } set { this.speed = value; } } /// /// Manipula a rotação da Sprite sobre seu eixo central. /// public float Rotation { get { return this.rotation; } set { this.rotation = value; } } /// /// Manipula os efeitos a serem aplicados sobre a Sprite. /// public SpriteEffects Effect { get { return this.effect; } set { this.effect = value; } } #endregion
Criando os métodos construtores
Basicamente teremos a criação de um construtor simples e um composto, informando os valores das propriedades.
Â
#region Métodos Construtores /// /// Método Construtor simples /// public Sprite() { // Método construtor simples } /// /// Método construtor composto /// /// Textura da Sprite /// Tamanho da Sprite /// Posição da Sprite na tela /// Velocidade com que a Sprite se moverá /// Rotação da Sprite sobre seu eixo central /// Efeitos a serem aplicados na Sprite public Sprite(Texture2D pTexture, Vector2 pSize, Vector2 pPosition, int pSpeed, float pRotation, SpriteEffects pEffect) { this.texture = pTexture; this.size = pSize; this.position = pPosition; this.speed = pSpeed; this.rotation = pRotation; this.effect = pEffect; } #endregion
Sobrescrevendo o método Draw
O método Draw() é responsável por renderizar os objetos na tela, e pode ser extendido. Neste caso, deixaremos que ele se encarregue de desenhar a sprite na tela.
#region Overridables /// /// Desenha a sprite na tela /// /// Lote de Sprites public void Draw(SpriteBatch spriteBatch) { spriteBatch.Draw(texture, new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y), null, Color.White, rotation, new Vector2((int)size.X / 2, (int)size.Y / 2), effect, 0); } #endregion
Quando chamamos o método Draw() temos 7 sobrecargas. Optei pela sobrecarga número 5, que é a mais completa, e apesar de não utilizarmos todos os seus parâmetros agora, nos próximos artigos ficará mais fácil adaptar este método ao que queremos fazer.
No método temos os seguintes parâmetros (Nesta ordem):
- Texture2D Texture – Textura da Sprite.
- Rectangle Destination – Retangulo onde a sprite será desenhada.
- Rectangle Source – Retângulo de origem da imagem. (Opcional)
- Color Color – Coloração da Sprite.
- Float Rotation – Rotação da Sprite.
- Vector2 Origin – Ponto pivot da sprite. (Usado para rotação também)
- SpriteEffects Effects – Efeitos aplicados à sprite.
- Float LayerDepth – Profundidade da Sprite. Podemos criar nÃveis de renderização de sprites utilizando esta propriedade.
Note que informamos o rectangle source como NULL, pois ele é opcional e não utilizaremos ele agora.
No parâmetro Destination, criamos um novo retângulo utilizando as posições e o tamanho da sprite, ou seja, criamos um retângulo na mesma posição e do mesmo tamanho da sprite.
No parâmetro Origin, criamos um novo vetor e informamos que ele se situa no ponto central da sprite atravéz da divisão da largura e altura da sprite por 2. Sendo assim, temos o ponto pivot sobre o meio da sprite, e quando aplicarmos a rotação na mesma, ela girará sobre seu centro.
Como não estamos trabalhando com background nem nada, atribui o LayerDepth fixo como 0.
Utilizando a classe Sprite
Bem, com a nossa classe criada, nos resta saber como podemos utiliza-la no nosso jogo.
Primeiramente, precisamo criar uma variável do tipo sprite, para armazenar nossa sprite.
Sendo assim, logo após a variável SpriteBatch, no topo do arquivo Game1.cs, crie a constante utilizada para armazenar o nome do asset a ser carregado na sprite e a variável sprite.
GraphicsDeviceManager graphics; SpriteBatch spriteBatch; public const string SPRITE_ASSET = "pacman"; Sprite minhaSprite;
Criadas as variáveis, precisamos carregar a textura e inicializá-las. No método LoadContent(), adicione a seguinte linha:
// TODO: use this.Content to load your game content here minhaSprite = new Sprite(Content.Load(SPRITE_ASSET), new Vector2(64f, 64f), new Vector2(100f, 100f), 2, 0, SpriteEffects.None);
Agora o que precisamos fazer é no método Draw() chamar a função Draw() da nossa sprite.
protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); // TODO: Add your drawing code here spriteBatch.Begin(); minhaSprite.Draw(spriteBatch); spriteBatch.End(); base.Draw(gameTime); }
Aplicando movimento à Sprite
O que iremos fazer agora é criar um método para mover, rotacionar e aplicar efeitos sobre sprite. Este método será chamado dentro do método Update(), pois será atualizado frame a frame.
#region Keyboard Handler /// /// Atualiza a posição da Sprite na tela /// /// Estado do teclado public void UpdatePacmanMovement(KeyboardState pKeyboardState) { if (pKeyboardState.IsKeyDown(Keys.Left)) { minhaSprite.Position = new Vector2(minhaSprite.Position.X - minhaSprite.Speed, minhaSprite.Position.Y); minhaSprite.Rotation = 0; minhaSprite.Effect = SpriteEffects.FlipHorizontally; } if (pKeyboardState.IsKeyDown(Keys.Right)) { minhaSprite.Position = new Vector2(minhaSprite.Position.X + minhaSprite.Speed, minhaSprite.Position.Y); minhaSprite.Rotation = 0; minhaSprite.Effect = SpriteEffects.None; } if (pKeyboardState.IsKeyDown(Keys.Up)) { minhaSprite.Position = new Vector2(minhaSprite.Position.X, minhaSprite.Position.Y - minhaSprite.Speed); minhaSprite.Rotation = -90; minhaSprite.Effect = SpriteEffects.None; } if (pKeyboardState.IsKeyDown(Keys.Down)) { minhaSprite.Position = new Vector2(minhaSprite.Position.X, minhaSprite.Position.Y + minhaSprite.Speed); minhaSprite.Rotation = 45; minhaSprite.Effect = SpriteEffects.None; } } #endregion
Note que temos um parâmetro de entrada do tipo KeyboardState, que é de onde extrairemos a informação de qual tecla está sendo pressionada.
Vamos as explicações.
Basicamente, temos um calculo de velocidade onde somamos ou subtraÃmos a velocidade que informamos à sprite (Propriedade Speed) da posição X ou Y da Sprite (Propriedade Position).
Feito isso, no caso das teclas pressionadas serem para baixo (Down) ou cima (Up), aplicamos uma rotação de -90 graus (Para Up) ou 45 graus (Para Down). As teclas pressionadas sejam direita (Right) ou esquerda (Left) aplicamos o valor 0, que significa sem rotação. Deste modo, temos o Pacman olhando para baixo e para cima.
Na terceira linha temos o efeito de espelho aplicado a sprite. Necessitamos deste efeito para quando a seta da esquerda for pressionada (Left), fazendo com que o Pacman ande para esquerda e deste modo, temos que inverter a sprite para que ela fique virada para esquerda.
Para finalizar, no método Update(), vamos chamar a função UpdatePacmanMovement().`
protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); // TODO: Add your update logic here KeyboardState ks = new KeyboardState(); ks = Keyboard.GetState(); UpdatePacmanMovement(ks); base.Update(gameTime); }
Sem muito segredo, criamos um KeyboardState e obtemos o estado das teclas através do método GetState(). Então, passamos o KeyboardState para função UpdatePacmanMovement().
O resultado pode ser conferido na imagem abaixo.
![]()
Download do Projeto
http://www.insidedotnet.com.br/andrebaltieri/Artigos/2009/11/xna_sprite_class/XNASprites.zip
Espero que tenham gostado!
Um ótimo fim de semana e até o próximo artigo, que será sobre animação de sprites =D
Abraços!
2 Comments to “[Tutorial] Renderizando objetos e movendo-os com XNA [Via Classe]”
Leave a Reply





Muito bom André, bem interessante o encapsulamento. Esta de parabéns. Depois eu vou fazer um link do seu tutorial no meu blog, se você concordar.
Abraços, t+
Cara, uma correção talvez?
Ali onde vc adiciona a linha no LoadContente()
// TODO: use this.Content to load your game content here
minhaSprite = new Sprite(Content.Load(SPRITE_ASSET), new Vector2(64f, 64f), new Vector2(100f, 100f), 2, 0, SpriteEffects.None);
não seria….
new Sprite(Content.Load(SPRITE_ASSET), new Vector2(64f, 64f), new Vector2(100f, 100f), 2, 0, SpriteEffects.None);
?