Tutorial nível: Normal
Para este tutorial você precisa:
ter instalado o MS XNA GSE 2.0
Este tutorial é continuação de:
Desenhado uma Imagem na tela
Movendo e Rotacionando Imagens na tela
Agora vamos continuar nosso
tutorial adicionado movimento ao nosso carro(citado como imagem no nosso
tutorial anterior).
Abra nosso antigo projeto.
Primeira coisa que teremos que fazer e criar variáveis para armazenar a posição, ângulo e a velocidade de nosso carro quando em movimento.
Então no começo do código, abaixo da linha:
Texture2D car;
Adicionaremos nossas variaveis:
float speed = 3f;
float rotation = 0;
Vector2 position; //--> este é um vetor de duas posições X,Y
Então ficará assim:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace Race
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D car;
float speed = 3f;
float rotation = 0;
Vector2 position; //--> este é um vetor de duas posições X,Y
Agora como não podemos instaciar o
Vector2 position no inicio teremos que instacia-lo em um lugar específico, no método
protected override void Initialize(), então dentro do método Initialize abaixo da linha:
base.Initialize();
Instanciamos o
Vector2 position assim:
position = new Vector2((
float)((
int)graphics.PreferredBackBufferWidth / 2), (
float)((
int)graphics.PreferredBackBufferHeight / 2));
com a propriedade
PreferredBackBufferWidth e
PreferredBackBufferHeight do
GraphicsDeviceManager graphics estamos pegando a largura e altura da tela para depois dividirmos por dois, que nos da o centro da tela, ou seja, estaremos instanciando com a posição do centro da tela.
Então ficara assim o método Initialize:
protected override void Initialize()
{
base.Initialize();
position = new Vector2((float)((int)graphics.PreferredBackBufferWidth / 2), (float)((int)graphics.PreferredBackBufferHeight / 2));
}
Agora para podermos testar nossas mudanças só precisamos atualizar o método Draw. Então reponha o método já existente:
spriteBatch.Draw(car,new Rectangle(20,20,car.Width,car.Height),Color.White);
Por este mais complexo:
spriteBatch.Draw(car, position, null, Color.White, rotation, new Vector2(35, 22), 1, SpriteEffects.None, 0);
Repare nos novos parametros do método Draw, são 9:
1° o mesmo parametro antigo,
Textura2D texture, que será a imagem que planejamos desenhar, então nós indicamos a nossa
Texture2D chamada car
2° é o
Vector2 Position, que é a posição da imagem em um vetor, então passamos o nosso
Vector2 position.
3° é o
Rectangle? sourceRectangle, esse e o retangulo que representa a parte da sua imagem que você quer desenhar, por exemplo você tem essa como sua imagem:
E passa como parametro a um retangulo com x=210 y=110 width=70(largura) heigth=90(altura), você irá apenas desenhar essa parte da figura:

Ou seja, apenas aparecerá na tela assim:

Então como nós querenos desenhar a imagem intera e não apenas parte podemos pasar o valor do parametro como
null(nulo) pois ele e um retangulo que aceita valor nulo por isso ele é um
Rectangle? e não apenas um
Rectangle, assim o método entende que você quer desenhar a imagem inteira.
4° é o
Color color é a cor para imagem, então passamos o branco pois o branco contém todas a cores(Ex.: Se você passar o vermelho nossa imagem não possuirá tons de verde e nem de azul, ou seja só possuirá tons de vermelho, e para amarelo ele posuirá tons de verde e vermelho) então após esse método escreveremos:
5° é o
float rotation é o valor da rotação da nossa imagem
6° é o
Vector2 origin é o vetor da posição do centro da imagem, ou seja, o ponto em que sua imagem vai se rotacionar em volta, aqui nos passamos o valor x=35 y=22 que será o ponto azul e amarelo da imagem:
7° é o
float scale esse é o parametro de escala da imagem como não queremos alteração no tamanho passamos 1.
8° é o
SpriteEffects effects é um enum com uns efeitos para aplica na imagem com espelhar na horizontal ou na vertical, mas como não queremos fazer nada disso selecionamos o efeito nome, ou seja, nenhum efeito.
9° é o
float layerDepth esse eu não consegui perceber diferença então não sei para que serve.
Então ficará assim o novo método Draw:
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(car, position, null, Color.White, rotation, new Vector2(35, 22), 1, SpriteEffects.None, 0);
spriteBatch.End();
base.Draw(gameTime);
}
Agora nós podemos testar para ver a diferença, em vez do carro aparecer no canto esquerdo em cima da tela ele vai aparecer no meio da tela, lembra que quando nós instanciamos nossa variavel position nós davamos o centro da tela como posição.
Mas agora nós vamos fazer a gente comandar o carro com as setas do teclado.
Então no método
protected override void Update(GameTime gameTime) vamos adicionar após a linha:
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
1°:
KeyboardState ks = Keyboard.GetState();
Nesse comando nós estamos pegando como estará o estado do teclado, para podermos ver quais teclas estão precionadas.
2°:
if (ks.IsKeyDown(Keys.Left))
rotation -= MathHelper.ToRadians(1);
Agora nós verificaremos se a seta para a esquerda do teclado está precionada para reduzirmos da ratação do carro 1 grau mas sendo que nossa rotação está em radiano e não em grau então nós convertemos com o método ToRadians existente na classe
MathHelper.
3°:
if (ks.IsKeyDown(Keys.Right))
rotation += MathHelper.ToRadians(1);
Agora nós verificaremos se a seta para a direita do teclado está precionada para fazermo o contrário somar 1 grau a rotação do carro.
4°:
if (ks.IsKeyDown(Keys.Up))
{
position.Y += (float)Math.Sin((double)rotation) * speed;
position.X += (float)Math.Cos((double)rotation) * speed;
}
Agora nós temos que fazer o carro se mexer mas em função da sua rotação, então para o eixo Y nós damos o seno de nosso ângulo multiplicado por nossa velocidade(a variavel float speed), que por enquanto é limitada em 3. E no eixo X nós damos o cosseno da rotação multiplicado com a velocidade.
Então ficará assim o método Update:
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
KeyboardState ks = Keyboard.GetState();
if (ks.IsKeyDown(Keys.Left))
rotation -= MathHelper.ToRadians(1);
if (ks.IsKeyDown(Keys.Right))
rotation += MathHelper.ToRadians(1);
if (ks.IsKeyDown(Keys.Up))
{
position.Y += (float)Math.Sin((double)rotation) * speed;
position.X += (float)Math.Cos((double)rotation) * speed;
}
base.Update(gameTime);
}
Agora está pronto! Nós temos nosso carro comandados por nós, mas lembre que não fizemos com uma fisica realista.
Espere pelos próximos tutoriais!
Código completo:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace Race
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D car;
float speed = 3f;
float rotation = 0;
Vector2 position;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
position = new Vector2((float)((int)graphics.PreferredBackBufferWidth / 2), (float)((int)graphics.PreferredBackBufferHeight / 2));
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
car = Content.Load<Texture2D>(@"car");
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
KeyboardState ks = Keyboard.GetState();
if (ks.IsKeyDown(Keys.Left))
rotation -= MathHelper.ToRadians(1);
if (ks.IsKeyDown(Keys.Right))
rotation += MathHelper.ToRadians(1);
if (ks.IsKeyDown(Keys.Up))
{
position.Y += (float)Math.Sin((double)rotation) * speed;
position.X += (float)Math.Cos((double)rotation) * speed;
}
base.Update(gameTime);
}
protected override void Draw(
GameTime gameTime)
{
graphics.GraphicsDevice.Clear(
Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(car, position,
null,
Color.White, rotation,
new Vector2(35, 22), 1,
SpriteEffects.None, 0);
spriteBatch.End();
base.Draw(gameTime);
}
}
}