Tratamento de erro com XNA no Windows Phone 7
Em nosso artigo anterior falamos sobre Velocidade e abstração com XNA no Windows Phone 7 e utilizando o mesmo Game1.cs continuaremos nossos estudos. Agora falaremos sobre tratamento de erros!
O método Sprite.Load() possui um meio de tratarmos erros via try/catch , você deve ter reparado nisto.
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);
}
}
Dentro deste bloco chamamos o Content.Load() , este que por sua vez tem a responsabilidade de colocar em memória um asset específico .
No momento que o XNA passar através desta chamada e não encontrar o asset que estamos declarando, teremos uma exceção, certo?
Faça esta pequena alteração no nosso código e carregue um asset que não existe no projeto Sprite DemoContent
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.image = Content.Load<Texture2D>("cave1");
//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;
}
F5 no projeto e vamos encarar nossa exceção:
Obviamente não desejamos que o usuário final veja um erro de exceção, e em projetos, renomear arquivos, principalmente de imagem e áudio que são atualizados com frequência, pode gerar a você este tipo de contra tempo.
Mas isto tudo faz parte e reclamar não é o caminho. Ao invés disso, vamos trabalhar em nosso projeto para minimizar as chances de uma ruim experiência para o usuário. Neste caso, o player ou então o testador (nosso fiel amigo!)
Nosso public bool Load(string assetName) retorna false se o asset não é encontrado. O problema é: nós não podemos sair do erro a partir do LoadContent() . Precisamos trabalhar no tratamento do erro após o LoadContent() terminar sua execução.
Vamos fazer um tratamento de erro mais apropriado, minimizando a frustração do nosso amigo testador e pelo menos deixando-o ciente da falha que aconteceu. Do motivo do erro. Assim ficará bem mais simples reporta-lo e consequentemente concerta-lo.
Mão na massa
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;
bool errorState;
string errorMessage;
SpriteFont ErrorFont;
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);
errorMessage = "";
errorState = false;
}
/// <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);
if (!cave.Load("cave"))
{
ErrorFont = Content.Load<SpriteFont>("SpriteFont1");
errorState = true;
errorMessage = "o arquivo de imagem nao foi encontrado.";
return;
}
cave.image = Content.Load<Texture2D>("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();
if (errorState)
{
spriteBatch.DrawString(ErrorFont, "ERRO CRITICO C4VE 001", Vector2.Zero, Color.White);
spriteBatch.DrawString(ErrorFont, errorMessage, new Vector2(0, 100), Color.White);
}
else
{
cave.Draw();
}
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Você reparou que utilizamos como asset um Sprite Fonte? Preciso fazer o passo a passo ou você se lembra como utilizar? Vimos em Crie seu primeiro projeto XNA 4.0 para Windows Phone 7 confere lá!
E o resultado será..
Como já vimos, erros não são bons, porem fazem parte do desenvolvimento.
Trata-los com inteligência é a melhor forma de evitar frustrações ao usuário. E deste modo, rastreando nosso código onde falhas podem ser frequentes, conseguimos concertar o bug rapidamente, facilitando a vida do suporte, do desenvolvedor e de toda equipe
Pronto, chega de falar de erros! O assunto é importante e não pude passar despercebido.
Mas no nosso próximo post voltaremos a falar de velocidade e movimento ok? Assuntos bem mais interessantes que bugs, eu sei
Forte abraço!!
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
Transformando Sprites com XNA no Windows Phone 7
Velocidade e abstração com XNA no Windows Phone 7
*Se você ainda não baixou o Windows Phone 7 SDK, clique aqui para o donwload