Velocidade e abstração com XNA no Windows Phone 7
A velocidade pode ser calculada pela distancia ao longo do tempo. Pela matemática (ou "matematicamente" , pois acredite, a palavra existe) a formula é V = D / T
Este cálculo é mais útil a partir de certa distância percorrida e por certo período de tempo (o que está relativamente conectado) para calcular a média de velocidade. Isto pelo simples fato de aceleração e desaceleração que objetos sofrem na vida real. Até mesmo a Ferrari mais potente que você conhece sofre do mesmo mal, além de pontos como resistência, inércia e demais fatores que podem ou não ser relevantes para nós. Aí, o que depende é o nível de realidade que desejamos empregar em nossa física para o deslocamento de objetos.
Agora definiremos uma certa velocidade a frente do tempo pois distancia e tempo ainda não nos interessam. Nosso exercício não exigirá tal precisão.
Está confuso? Não se preocupe, exercícios práticos sempre tornam o conceito mais simples.
"Velocity " ,sendo uma propriedade pública, podemos utiliza-la fora da nossa classe. Mas para testarmos, vamos adicionar um novo método na classe que criamos para mover um Sprite baseando-nos em velocidade
Sabe de que classe estamos falando? Se você disse "nossa querida Sprite class!" parabéns! Se não, sugiro a leitura do post Criando uma simples classe Sprite com XNA no Windows Phone 7
Para acompanhar este lab/post, vá ao post anterior e crie esta classe ok? Estaremos esperando você bem aqui
Para dar continuidade, vamos falar um pouco mais sobre "escrever código reutilizável" e "abstração" antes de continuar falando de velocidade. Se formos rápido demais na construção de games, nos perderemos em importantes conceitos de programação.
Abstrair o código XNA é importante para construir a base de um jogo, ou pelo menos parte dele.
Agora, se o game fosse feito para outras plataformas como Windows e XBOX, aí meu amigo, seria essencial, mas não vamos complicar nosso exemplo (pois sei que o assunto não é tão simples para quem está começando) mas para você ter uma boa visão do que estamos falando, você teria que ter a necessidade de reescrever seu código algumas vezes, adaptando-o para diferentes plataformas (e linguagens , acredite ou não!!) para começar a identificar as similaridades e então entender onde você deveria "desacoplar responsabilidades" do seu código.
Na nossa classe Sprite queremos abstrair duas coisas. A primeira é o Loading da imagem. Isto acontece no LoadContent() . A segunda é o Drawing , que é executado do Draw() .
Para abstrair no XNA estes dois aspectos, precisamos ter nossos próprios Load() e Draw() na própria Sprite class certo? (se não estiver entendendo muito bem, não se preocupe, apenas continue a leitura, exercícios, e se necessário releia o artigo quantas vezes achar que pode facilitar seu entendimento)
Para cumprir nosso objetivo, nossa classe precisa ter acesso ao ContentManager e SpriteBatch.
Podemos fazer isto passando os objetos necessários para o construtor da classe Sprite.
Mão no código
using System;
using System.Collections.Generic;
using System.Linq;
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.Input.Touch;
using Microsoft.Xna.Framework.Media;
namespace Sprite_Demo
{
/// <summary>
/// This is the main type for your game
/// </summary>
///
public class Sprite
{
private ContentManager p_content;
private SpriteBatch p_spriteBatch;
public Texture2D image;
public Vector2 position;
public Color color;
public Sprite(ContentManager content, SpriteBatch spriteBatch)
{
p_content = content;
p_spriteBatch = spriteBatch;
image = null;
position = Vector2.Zero;
color = Color.White;
}
public bool Load(string assetName)
{
try
{
image = p_content.Load<Texture2D>(assetName);
}
catch (Exception) { return false; }
return true;
}
public void Draw()
{
p_spriteBatch.Draw(image, position, color);
}
}
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Viewport viewport;
Sprite cave;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
// Frame rate is 30 fps by default for Windows Phone.
TargetElapsedTime = TimeSpan.FromTicks(333333);
// Extend battery life under lock.
InactiveSleepTime = TimeSpan.FromSeconds(1);
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
//get screen dimensions
viewport = GraphicsDevice.Viewport;
//creating a Sprite
cave = new Sprite(Content, spriteBatch);
cave.Load("cave");
//center the cave sprite on screen
float x = (viewport.Width - cave.image.Width) / 2;
float y = (viewport.Height - cave.image.Width) / 2;
cave.position = new Vector2(x, y);
//set color
cave.color = Color.White;
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
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
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
spriteBatch.Begin();
//draw the cave
cave.Draw();
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Mesmo conceito de exemplos anteriores. Estamos fazendo pequenas otimizações que a primeira vista parecem que nos trazem poucos benefícios. Mas pegue os conceitos e tente empregá-los em projetos maiores e mais complexos, inclusive, nesta caso, portando nosso game para outras plataformas compatíveis com o XNA.
Otimização de código é um tema muito rico e com o tempo, o que você acredita ser uma boa prática, verá que não é tão boa assim, e irá melhorar sua lógica a cada novo projeto.
Nos próximos posts continuaremos a falar sobre velocidade e também sobre temas importantes e básicos no mundo do desenvolvimento, como tratamentos de erro por exemplo.
Até mais!
Posts anteriores
Visão geral do MVA - entendendo o roteiro de Windows Phone
O Windows Mobile e o Windows Phone
Visão geral do Windows Phone 7.5 (codinome Mango)
Visão geral do SDK do Windows Phone
Visão geral das ferramentas de desenvolvimento para Windows Phone
O que é o Windows Phone Marketplace parte 1 - Publicando sua app no Marketplace
O que é o Windows Phone Marketplace parte 2 - Publicando sua app no Marketplace
Crie seu primeiro projeto XNA 4.0 para Windows Phone 7
Entendendo o User Input no Windows Phone 7 com XNA
Utilizando gestos no Windows Phone 7
Desenhando Bitmaps com XNA no Windows Phone 7
Tratando Bitmaps como Sprites utilizando XNA no Windows Phone 7
Desenhando muitos bitmaps com XNA no Windows Phone 7
Desenhando muitos bitmaps com XNA no Windows Phone 7 - parte 2
Criando uma simples classe Sprite com XNA no Windows Phone 7