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 Smiley

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 Smiley

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 conceito Metro

Visão geral do SDK do Windows Phone

Visão geral das ferramentas de desenvolvimento para Windows Phone

Visão geral do Emulador

Testando sua app no device

Criando Protótipos

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

Marketplace Test Kit

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