Blog Post

Velocidade e abstração com XNA no Windows Phone 7

Description

A velocidade média pode ser calculada pela distância percorrida ao longo do tempo. Pela matemática, 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 da 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 Smiley

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.

Reutilização de código e abstração são conceitos importantes da POO - Programação Orientada a Objetos, nós já estamos implementado alguns desses conceitos sem notar. Nos artigos anteriores, expliquei o conceito de Sprite e finalmente no último artigo criamos a classe Sprite. Pois bem, a classe Sprite é a abstração do conceito de Sprite, é a forma para construirmos objetos do tipo Sprite.

Ao instanciarmos uma classe, estamos reutilizando o código do seu construtor, e de seus métodos o que nos dá maior agilidade na hora de fazer uma alteração (mudamos em um único lugar, na forma).

Outro termo importante é o desacoplamento, com o desacoplamento aumentamos a flexibilidade para desenvolver o código. Uma das práticas para aumentar o desacoplamento em POO, é a programação com interfaces.

Interface é um contrato que define o que a classe deve fazer, mas não como fazer. Padrões em POO é um assunto vasto e muito interessante, existem vários livros que tratam esse assunto o meu preferido é "Design Patterns: Elements of Reusable Object-Oriented Software".

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 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 do XNA estes dois aspectos, precisamos ter nossos próprios métodos 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. Este é o mesmo nas três plataformas (como framework) que citamos, mas cada uma delas possui peculiaridades, e é por isso que é interessante pensar na portabilidade do seu código para fazer o melhor uso possível do hardware que está disponivel, seja em um PC, um console ou um smarthphone.

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.

Este post foi um pouco mais denso, eu sei. Mas não se preocupe, procuraremos sempre tratar com muita simplicidade os conteúdos trabalhados aqui, e sempre que possível, com bom humor também.

Outro ponto, por mais que pareça dificil, não desista. Continue lendo sobre o tema, fazendo testes, errando, errando, errando.. e as vezes acertando. O velho lema, a prática leva a perfeição.

Não espere entender 100% do que falamos aqui para continuar seus estudos. As vezes é preciso avançar mesmo sem enxergar com total clareza o caminho a sua frente.

Com o seu caminhar, o que era escuridão total irá se revelar aos poucos, e tudo irá ficará cada vez mais simples ok?

Empenho e persistência!

 

Forte abraço

caverna

 

 

 

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

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

 

*Se você ainda não baixou o Windows Phone 7 SDK, clique aqui para o donwload

The Discussion

  • User profile image
    terra

    Muito legal Diego e Caverna (até parece nome de dupla sertaneja, kkk), eu já estou elaborando minhas classes, para facilitar o desenvolvimento e principalmente evitar códigos repetitivos, ao invés de Criar os Vectors, etc. Também usando diversos Sprites (um para cada situação) e muitos assets. Seguindo seus conselhos estou fazendo uma classes de utilitários que eu apenas informo o objeto e ela automaticamente faz todo o resto! Acredito que esse seja o caminho, assim evitamos ficar criando diversos objetos como os Vectors, Textures, etc.

    Muito interessante esse roteiro do MVA, espero que tenha um próximo (mais avançado)!
    Onde por exemplo demonstre a criação de um game simples com poucos elementos, mas com movimentações, sons, etc!

    Sou novo no desenvolvimento pra Games, mas experiente com Desktop, Web, e pelo pouco que aprendi já consegui muita coisa, peguei umas imagens na net (personagens andando) e to tentando fazer algo aqui, já consigo fazer as animações usando apenas o conceito aplicado até agora!
    Isso indica que este curso anda muito bem.

    Parabéns a todos! 

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.