Arquivos

Archive for dezembro \28\UTC 2010

Boas Festas (Feliz 2011)

Olá galera que frequenta este blog !

Ainda não entrei de férias, como sempre fico fazendo meus trabalhos até o último minuto do ano. Mas o fim do ano vem chegando e muito já estão de férias descansando e não querem nem saber de programar ou fazer outra atividade relacionada ao computador.

Vou fazer um rápido review deste ano  (2010), já que foi um ano bem divertido e interessante. Neste ano o blog começou a ter muitos acessos, comentários, sugestões entre outras movimentos no que fez o número de acesso chegar ao 108mil. Também foi um ano no qual ministrei diversas palestras, cursos de jogos e fiz também algumas viagens por conta disso, duas delas a Campo Grande – MS no qual conheci muitas pessoas legais desde alunos a professores que troquei experiências e mantenho contato até hoje. Este ano também consegui finalmente ir a SBGames apresentar o trabalho do grupo de participo dentro da USP. No laboratório de Robótica Móvel (LabRoM) foi um ano muito produtivo no qual desencadeou diversos trabalhos e artigos e estamos trabalhando o máximo que podemos e logo acabarei o mestrado também. Alias, passei no doutorado, só falta acabar o mestrado para começar mais uma etapa da vida acadêmica.

Novidades para o próximo ano: provavelmente irei comprar um domínio para poder organizar melhor o blog e até mesmo convidar mais pessoas interessadas a escrever e montar um forum de discussão. Alguns artigos estão para serem escritos uma vez que estamos acabando de falar sobre os jogos 2D. Então irei escrever um artigo agora sobre câmeras, montagem de mapas para jogos de plataforma, física e colisão, tudo isso para montarmos um jogo de plataforma básico. Logo após, irei começar a falar sobre Inteligência Artificial, mas tudo isso no decorrer do ano.

Agradeço então aqui a todos os meus amigos que colaboraram diretamente e indiretamente com este blog  que mantenho para tentar ensinar de maneira mais fácil possível como desenvolver jogos. Agradeço também a todo minha família, a minha namorada que amo tanto e  a todos os leitores deste blog. Pra fechar este tópico, desejo a todos um Feliz Natal e um Próspero Ano Novo e que 2011 seja ótimo para todos. Fiquem aqui mais um ano com o vídeo do Chiron Beta Prime (acho que é um dos melhores, quem souber outro me mande para mudar no próximo ano).

CategoriasDiversos

[C#] Laços de Repetição (WHILE)

Galera novo artigo sobre laços de repetição, complementar ao antigo porém escrito pelo novo colaborador do blog o Diego Correa Gomes Ferreira. Este artigo será voltado para falar de repetição While. Que nada mais é do que uma repetição controlada por contador, possuindo quatro aspectos importantes:

  1. Uma variável de controle (ou contador de loop).
  2. Um valor inicial para controlar a variável.
  3. O incrementador e o decrementador, através da qual a variável de controle é modificada a cada passagem pelo loop.
  4. A condição para continuação do loop que determina se o looping deve continuar.

Para ver esses aspectos de repetição controlada por contador, considere a aplicação que usa um loop para mostrar números de 1 até 10. Veja no exemplo abaixo:

Using System;

Public class RepeticaoWhile
{
      Public static void Main ( string[] args )
      {
            int contador = 1;           // Declaração e inicialização da variável de
                                                // controle
	 while ( contador <= 10 )  // Condição de continuação do loop
	 {
	       Console.Write (“ {0} “, contador );
 	       contador++;    // Incrementa a variável de controle
	 }

           Console.WriteLine();     //Escreve uma nova linha em branco
       }
 }

A variável de controle (contador) foi declara como sendo Int, pois nós usaremos apenas valores de 1 até 10. Para uma estrutura de repetição é desnecessário declarar a variável como sendo Double ou Float, pois o contador só funciona com números inteiros, o que não descartaria a hipótese de você utilizá-la com os operadores em uma divisão ou resto, nesse caso basta colocar em parênteses (float) ou (double) para que o seu resultado não saia como sendo um número inteiro, e sim um número decimal. Porém jamais armazene esse valor decimal na variável contador, pois se o loop continuar isso resultará em um erro no seu programa.

Note que o contador é inicializado com o valor 1, logo após é declarada a estrutura de repetição while, que verifica se o valor do contador é menor ou igual a 10. Se ele for menor ou igual a 10, ele é escrito na tela pelo comando Console.Write, e logo em seguida ele implementa mais 1 ao valor do contador. A expressão contador++ nada mais é do que uma forma reduzida e prática de (contador = contador + 1), que primeiramente pode ser simplicada por (contador += 1), mas isso fica a cargo das preferências do programador.

Logo após chegar ao final da estrutura de repetição, ele retorna ao início do while e começa tudo novamente, isso é chamado de loop, quando um número fica retornando inúmeras vezes ao começo da estrutura de repetição.

 

[XNA] Animação de Sprites – Parte 3

Eai galera, esta é a penúltima parte do tutorial, mas já com esta etapa você já poderão construir seus objetos ou personagens animados. Neste tutorial iremos criar uma classe chamada AnimatedSprite que irá gerenciar objetos animados, ou seja objetos criados com aquela classe do tutorial passado.

O que está classe realmente faz então, esta classe armazena um dicionário de nomes para chamar cada animação que poderá ser adicionada a ele. O método Update navega entre os quadros da animação atual conforme um intervalo de tempo determinado por cada animação. E o método Draw desenha o objeto.

A classe que gerencia as animações (AnimatedSprite) pode ser vista abaixo.

public class AnimatedSprite
{
    #region [ Fields ]

    /// <summary>
    /// Sprite sheet da imagem animada
    /// </summary>
    protected Texture2D texture;

    /// <summary>
    /// Posição do objeto animado no mundo
    /// </summary>
    public Vector2 Position { get; set; }

    /// <summary>
    /// Dicionário contendo as animações do personagem
    /// </summary>
    public Dictionary<string, Animation> Animations
    {
        get { return this.animations; }
    }
    private Dictionary<string, Animation> animations = new Dictionary<string, Animation>();

    /// <summary>
    /// Indice do frame da animação em execução
    /// </summary>
    public int FrameIndex
    {
        get { return this.frameIndex; }
    }
    private int frameIndex = 0;

    /// <summary>
    /// Nome da animação
    /// </summary>
    private string animationKey;
    public string AnimationKey
    {
        get { return this.animationKey; }
    }

    /// <summary>
    /// Cor de desenho da imagem
    /// </summary>
    protected Color color = Color.White;

    /// <summary>
    /// Rotação da imagem
    /// </summary>
    protected float rotation = 0.0f;

    /// <summary>
    /// Origem do desenho
    /// </summary>
    protected Vector2 origin;

    /// <summary>
    /// Escala da imagem
    /// </summary>
    protected float scale = 1.0f;

    /// <summary>
    /// Efeitos de imagem
    /// </summary>
    public SpriteEffects Flip
    {
        get { return this.flip; }
        set { this.flip = value; }
    }
    protected SpriteEffects flip = SpriteEffects.None;

    /// <summary>
    /// Layer de desenho
    /// </summary>
    protected float layerDepth = 0.0f;

    /// <summary>
    /// Tempo decorrido do frame atual da animação
    /// </summary>
    private float timeElapsed = 0.0f;

    /// <summary>
    /// Lista com os quadros do sprite sheet
    /// </summary>
    public List<Rectangle> Frames
    {
        get { return this.frames; }
    }
    private List<Rectangle> frames = new List<Rectangle>();

    /// <summary>
    /// Largura do quadro
    /// </summary>
    private int frameWidth = 0;

    /// <summary>
    /// Altura do quadro
    /// </summary>
    private int frameHeight = 0;

    /// <summary>
    /// Tamanho do frame
    /// </summary>
    public Vector2 Size
    {
        get { return new Vector2(frameWidth, frameHeight); }
    }

    #endregion

    #region [ Constructor ]

    /// <summary>
    /// Construtor do objeto animado
    /// </summary>
    /// <param name="texture">Imagem (Sprite Sheet)</param>
    /// <param name="columns">Quantidade de colunas</param>
    /// <param name="rows">Quantidade de linhas</param>
    public AnimatedSprite(Texture2D texture, int columns, int rows)
    {
        this.texture = texture;
        this.Position = new Vector2();
        this.frameWidth = texture.Width / columns;
        this.frameHeight = texture.Height / rows;

        // Cria todos os quadros da imagem
        for (int i = 0; i < rows; i++)
            for (int j = 0; j < columns; j++)
                frames.Add(new Rectangle(j * frameWidth,
                    i * frameHeight, frameWidth, frameHeight));

        this.origin = new Vector2(frameWidth / 2, frameHeight / 2);
    }

    #endregion

    #region [ Update ]

    /// <summary>
    /// Atualiza a animação do objeto
    /// </summary>
    /// <param name="gameTime">Tempo de jogo</param>
    public void Update(GameTime gameTime)
    {
        timeElapsed += (float)gameTime.ElapsedGameTime.TotalSeconds;

        if (timeElapsed > animations[AnimationKey].Interval)
        {
            if (animations[AnimationKey].IsLooping)
            {
                frameIndex = (frameIndex + 1) % animations[AnimationKey].FramesCount;
            }
            else
            {
                frameIndex = (int)MathHelper.Min(frameIndex + 1, animations[AnimationKey].FramesCount - 1);
            }
            timeElapsed = 0.0f;
        }
    }

    #endregion

    #region [ Draw ]

    /// <summary>
    /// Desnha o objeto animado
    /// </summary>
    /// <param name="spriteBatch"></param>
    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(texture,
            Position,
            Animations[AnimationKey].Frames[frameIndex],
            color,
            rotation,
            origin,
            scale,
            flip,
            layerDepth);
    }

    #endregion

    #region [ Add Animations ]

    /// <summary>
    /// Adiciona novas animações
    /// </summary>
    /// <param name="name">Nome chave da animação</param>
    /// <param name="newAnimation">Animação definida</param>
    public void AddAnimation(string name, Animation newAnimation)
    {
        animations.Add(name, newAnimation);
    }

    #endregion

    #region [ Play Animation ]

    /// <summary>
    /// Inicia ou continua uma animação.
    /// </summary>
    public void PlayAnimation(string name)
    {
        // Se a animação for a mesma em execução, não reinicia a animação
        if (name == AnimationKey)
            return;

        // Inicia uma nova animação
        this.animationKey = name;
        this.frameIndex = 0;
        this.timeElapsed = 0.0f;
    }

    #endregion
}

A classe Game1.cs deve ficar da seguinte forma para testar nosso exemplo.

public class Game1 : Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    /// <summary>
    /// Entrada atual do teclado
    /// </summary>
    ///
    KeyboardState keyState = Keyboard.GetState();
    /// <summary>
    /// Entrada antiga do teclado
    /// </summary>
    KeyboardState oldKeyState = Keyboard.GetState();

    /// <summary>
    /// Personagem animado
    /// </summary>
    AnimatedSprite player;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    protected override void Initialize()
    {
        base.Initialize();
    }

    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);

        // Cria o personagem
        player = new AnimatedSprite(Content.Load<Texture2D>("claudius"), 6, 4);
        // Posiciona o personagem na tela
        player.Position = new Vector2(100, 100);

        // Baixo
        // Cria as animações para baixo
        Animation stopedDownAnimation = new Animation(player.Frames, 0, 2);
        player.AddAnimation("StopedDown", stopedDownAnimation);
        // Cria as animações para baixo andando
        Animation walkingDownAnimation = new Animation(player.Frames, 2, 4);
        walkingDownAnimation.IsLooping = true;
        player.AddAnimation("WalkingDown", walkingDownAnimation);

        // Esquerda
        // Cria as animações para esquerda
        Animation stopeLeftAnimation = new Animation(player.Frames, 6, 2);
        player.AddAnimation("StopedLeft", stopeLeftAnimation);
        // Cria as animações para esquerda andando
        Animation walkingLeftAnimation = new Animation(player.Frames, 8, 4);
        walkingLeftAnimation.IsLooping = true;
        player.AddAnimation("WalkingLeft", walkingLeftAnimation);

        // Cima
        // Cria as animações para cima parado
        Animation stopedUpAnimation = new Animation(player.Frames, 12, 2);
        player.AddAnimation("StopedUp", stopedUpAnimation);
        // Cria as animações para cima andando
        Animation walkingUpAnimation = new Animation(player.Frames, 14, 4);
        walkingUpAnimation.IsLooping = true;
        player.AddAnimation("WalkingUp", walkingUpAnimation);

        // Direita
        // Cria as animações para direita parado
        Animation stopedRightAnimation = new Animation(player.Frames, 18, 2);
        player.AddAnimation("StopedRight", stopedRightAnimation);
        // Cria as animações para direita andando
        Animation walkingRightAnimation = new Animation(player.Frames, 20, 4);
        walkingRightAnimation.IsLooping = true;
        player.AddAnimation("WalkingRight", walkingRightAnimation);

        // Inicializa a animação do personagem parado a direita
        player.PlayAnimation("StopedRight");
    }

    protected override void Update(GameTime gameTime)
    {
        oldKeyState = keyState;
        keyState = Keyboard.GetState();

        if (keyState.IsKeyDown(Keys.Right))
        {
            player.PlayAnimation("WalkingRight");
            player.Position += new Vector2(60.0f, 0.0f) * (float)gameTime.ElapsedGameTime.TotalSeconds;
        }
        else if (keyState.IsKeyUp(Keys.Right) && oldKeyState.IsKeyDown(Keys.Right))
        {
            player.PlayAnimation("StopedRight");
        }
        else if (keyState.IsKeyDown(Keys.Left))
        {
            player.PlayAnimation("WalkingLeft");
            player.Position += new Vector2(-60.0f, 0.0f) * (float)gameTime.ElapsedGameTime.TotalSeconds;
        }
        else if (keyState.IsKeyUp(Keys.Left) && oldKeyState.IsKeyDown(Keys.Left))
        {
            player.PlayAnimation("StopedLeft");
        }
        else if (keyState.IsKeyDown(Keys.Up))
        {
            player.PlayAnimation("WalkingUp");
            player.Position += new Vector2(0.0f, -60.0f) * (float)gameTime.ElapsedGameTime.TotalSeconds;
        }
        else if (keyState.IsKeyUp(Keys.Up) && oldKeyState.IsKeyDown(Keys.Up))
        {
            player.PlayAnimation("StopedUp");
        }
        else if (keyState.IsKeyDown(Keys.Down))
        {
            player.PlayAnimation("WalkingDown");
            player.Position += new Vector2(0.0f, 60.0f) * (float)gameTime.ElapsedGameTime.TotalSeconds;
        }
        else if (keyState.IsKeyUp(Keys.Down) && oldKeyState.IsKeyDown(Keys.Down))
        {
            player.PlayAnimation("StopedDown");
        }
        // Atualiza o personagem
        player.Update(gameTime);

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin();
        // Desenha o personagem
        player.Draw(spriteBatch);
        spriteBatch.End();

        base.Draw(gameTime);
    }
}

Para ver como ficou o resultado veja o vídeo abaixo.

Se quiser fazer download do código-fonte do tutorial clique aqui.

Abraços galera, os próximos tutoriais serão sobre Camera 2D para começarmos a montar um jogo de plataforma.

[XNA] Animação de Sprites – Parte 2

Pelo visto muitos leitores estavam ansiosos por mais tutoriais sobre animação de sprites, então vamos hoje falar mais um pouco. Neste tutorial basicamente falaremos sobre o sprite sheet (folha de imagens) e descreveremos uma estrutura básica que armazenará as animações que compõem este objetos 2D. Esta estrutura consiste de uma classe que definirá as animações ou seja, qual o quadro de inicio e quantidade de quadros na sequência desta uma animação, se esta animação se repete ou não, entre outras coisas que podem ser acrescentadas no futuro.

Primeiro passo para se criar uma animação é preciso ter um sprite sheet de um objeto (nosso caso um personagem de rpg) como vimos na primeira parte deste tutorial a imagem do Mario e Luigi. Nosso personagem animado que será animado neste tutorial é o Claudius.

 

A esquerda sprite sheet do personagem Claudius e a direita o sprite sheet com a marcação dos quadros (frames)

Perceba que o sprite sheet possui as imagens espaçadas igualmente tanto na vertical quanto na horizontal formando quadros de mesmo tamanho, facilitando assim o processo de animação. Este sprite sheet tem 192 x 256 pixels, então cada quadro tem 32 x 64 pixels. Se dividirmos esta imagem nos seus respectivos quadros teremos a imagem a direita marcada.

Vamos criar então uma classe que possa representar cada animação deste personagem. Daremos o nome para esta classe de Animation, veja como ela ficaria abaixo.

public class Animation
{
    #region [ Fields ]

    ///
    /// Lista contendo a sequência de quadros da animação
    ///
    public List Frames
    {
        get { return this.frames; }
    }
    private List frames = new List();

    ///
    /// Intervalo de tempo de passagem dos frames da animação
    ///
    public float Interval
    {
        get { return this.interval; }
        set { this.interval = value; }
    }
    private float interval = 0.25f;

    ///
    /// Define se existe repetição na animação
    ///
    public bool IsLooping
    {
        get { return this.isLooping; }
        set { this.isLooping = value; }
    }
    private bool isLooping = false;

    ///
    /// Quantidade de frames da aniamação
    ///
    public int FramesCount
    {
        get { return this.framesCount; }
    }
    private int framesCount = 0;

    #endregion

    #region [ Constructor ]

    ///
    /// Construtor de uma animação
    ///
    /// Nome da animação que será utilizada como chave
    /// Tamanho do quadro
    /// Quadro inicial
    /// Quantidade de quadros
    public Animation(List frames, int startFrame, int framesCount)
    {
        this.framesCount = framesCount;
        // Armazena os quadros referêntes a esta animação
        for (int i = startFrame; i < startFrame + framesCount; i++)
            Frames.Add(frames[i]);
    }

    #endregion
}

No próximo tutorial veremos então como gerenciar as animações que serão criadas utilizando esta classe que definimos hoje. Abraços, até a próxima.

100 mil acessos!

Gostaria de agradecer a todos os leitores deste blog pelos acessos e pelos comentários. Conseguimos chegar a marca dos 100 mil acessos e espero logo postar mais tutoriais e artigos para vocês sobre desenvolvimento de jogos.

Abraços,

CategoriasNotícias
Seguir

Obtenha todo post novo entregue na sua caixa de entrada.

Join 29 other followers