Olá, caros leitores, vamos continuar aqui nossa série sobre XNA. Como o título sugere, hoje veremos um pouco de como manipular o dispositivo de entrada padrão, o teclado, para executar ações em nossos games, como por exemplo o movimento dos personagens.
Recomendo que se você for acompanhar post a post, como um tutorial, salve o projeto para abri-lo e continuá-lo a cada novo post. Nesse segundo post, vou partir do que tínhamos ao final do primeiro. Nossa classe principal, Game1
, estava assim:
public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D avatar; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } protected override void Initialize() { base.Initialize(); } protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); avatar = Content.Load<Texture2D>("avatar"); } protected override void UnloadContent() { } protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); spriteBatch.Draw(avatar, new Vector2(300, 200), Color.White); spriteBatch.End(); base.Draw(gameTime); } }
Vamos dar um pouco de atenção a essa parte do código:
protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); base.Update(gameTime); }
Como eu havia comentado no primeiro post. Essas linhas têm o efeito de finalizar o jogo caso o jogador aperte backspace no seu teclado ou o botão Back do joystick do XBOX. Mas como estamos desenvolvendo para Windows, não é interessante obter a entrada do GamePad, e sim do teclado. No caso acima, existe uma “correspondência” entre o botão “Back” e a tecla backspace. Mas, por uma simples questão de quantidade, não haverá correspondentes no controle de XBOX suficientes para todas as teclas do teclado.
Assim, queremos controlar a entrada pelo teclado propriamente dito. Na verdade o processo é semelhante ao usado para o controle de XBOX. Em vez da classe estática GamePad
, utilizaremos a também estática Keyboard
, que oferece também um método GetState()
, que retorna o estado do teclado em vez do estado do GamePad. Vamos apagar a parte do GamePad e atribuir o objeto KeyboardState
, retornado pelo método GetState()
, a uma variável para poder utilizá-lo várias vezes:
protected override void Update(GameTime gameTime) { KeyboardState state = Keyboard.GetState(); base.Update(gameTime); }
Pronto, agora essa variável state
nos dará acesso ao estado de todas as teclas do teclado, através dos métodos IsKeyDown
e IsKeyUp
, que recebem como parâmetro um item da enumeração Keys
, representando alguma tecla, e retornam true
ou false
dependendo do estado da tecla.
Por exemplo, se quiséssemos executar uma ação quando a tecla space estivesse apertada, usaríamos o seguinte código:
protected override void Update(GameTime gameTime) { KeyboardState state = Keyboard.GetState(); if (state.IsKeyDown(Keys.Space)) { // ações aqui! } base.Update(gameTime); }
Visto isso, que tal tornar um pouco mais dinâmico nosso jogo? Seria interessante, por exemplo, movimentar o nosso avatar utilizando as teclas direcionais. Primeiramente, observemos o seguinte:
protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); spriteBatch.Draw(avatar, new Vector2(300, 200), Color.White); spriteBatch.End(); base.Draw(gameTime); }
O posicionamento de nossa imagem é determinado pelo objeto Vector2
enviado ao método Draw
de spriteBatch
. Ou seja, para movimentarmos a imagem, esse posicionamento tem que ser modificado em tempo de execução. Portanto, obviamente não podemos enviar valores constantes para o construtor do Vector2
. Poderíamos usar variáveis numéricas que modificaríamos conforme ações no teclado, ou melhor ainda, utilizar uma variável do tipo Vector2
, da qual modificaríamos os atributos X e Y.
Façamos assim:
public class Game1 : Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D avatar; Vector2 posicao; . . .
Agora, ao desenhar a imagem do avatar, enviaremos esse Vector2
chamado “posicao” como parâmetro. Dessa forma, poderemos mudar suas coordenadas X e Y para “movimentar” a imagem. Como havíamos proposto, vamos fazer isso usando o teclado. Voltando ao método Update
:
protected override void Update(GameTime gameTime) { KeyboardState state = Keyboard.GetState(); if (state.IsKeyDown(Keys.Up)) { posicao.Y -= 5; } if (state.IsKeyDown(Keys.Down)) { posicao.Y += 5; } if (state.IsKeyDown(Keys.Left)) { posicao.X -= 5; } if (state.IsKeyDown(Keys.Right)) { posicao.X += 5; } base.Update(gameTime); }
Mas ainda é preciso fazer uma pequena mudança no método Draw
, que é enviar o Vector2 posicao
como parâmetro:
protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); spriteBatch.Draw(avatar, posicao, Color.White); spriteBatch.End(); base.Draw(gameTime); }
Experimente executar o jogo agora. Sim, a imagem se movimenta com as teclas direcionais! Está se movendo muito rápido? Basta mudar o valor que é acrescentado ou subtraído de posicao.X
e posicao.Y
. E por que agora a imagem começa no canto da tela? Porque nosso querido Vector2 posicao
não foi inicializado, e portanto seus atributos X e Y terão o valor padrão de float
, que é zero. Os “eixos” x e y têm sua origem no canto superior esquerdo da tela, que é onde nossa imagem ficará inicialmente posicionada, portanto.
Visto isso, amigo, você já é capaz de fazer coisas mais divertidas e diferentes ações para as inúmeras teclas do teclado. Mas o jogo ainda não está muito visualmente atraente, não é? Bom, esse incoveniente eu te ajudarei a resolver no próximo post, que focará o método Draw
. Até lá!
olha só, sei que é massante manter um blog, já tive um e eu mesmo me cansei, mas o conteúdo deste é ótimo, um material tão detalhado e simples assim sobre xna é raro de se ver, e olha que já li muita coisa gringa sobre o assunto
parabéns e continuem os posts e o bom trabalho
Valeu pelos comentários! É muito importante este feedback pra sabermos se nosso “trabalho” aqui no blog está sendo bem feito.
Em relação aos posts sobre XNA, tenho certeza que, assim que o Victor se aliviar um pouco do trabalho + faculdade, ele vai continuar com seus posts.
Muito bom.
Estou voltando a mexer com XNA
quero voltar com tudo.
e estou relembrando.