[Tens de ter uma conta e sessão iniciada para poderes visualizar esta imagem]

Classes e Objetos


As palavras "classe" e "objeto" são tão usadas na programação orientada a objeto que fica fácil misturar esses termos. Em termos gerais, uma classe é uma representação abstrata de algo, enquanto que um objeto é um exemplo utilizável daquilo que a classe representa. Então classes é a definição de um objeto, tudo que um determinado objeto tem em comum é listado na classe, o papel da classe é simplesmente dizer tudo que um determinado tipo de objeto pode fazer. E quais são os seus atributos (propriedades) e suas ações (métodos).

Por exemplo, imagine um carro, os carros são todos parecidos mudando apenas alguns aspectos como potência do motor, marca do veículo, cor, etc… No nosso caso, vamos chamar esses aspectos de atributos (nossas variáveis). Então, veja que todos os carros são iguais, podendo mudar esses atributos. Mas uma classe não tem só atributos, ela tem métodos também, ou seja, o que essa classe pode fazer, no nosso exemplo de carro o que o carro pode fazer? Acelerar, freiar, trocar marcha, etc… essas funções ou ações do carro seriam nossos métodos.

É claro que não é só isso, tem muito mais, mas para nosso tutorial isso já é suficiente. Como sugestão, seria interessante vocês pesquisarem um pouco mais sobre programação orientada a objetos.

Criando as Classes Ball (Bola) e Bat (Bastão)


Por se tratar de um jogo simples, e ser o primeiro jogo da maioria que esta acompanhando este tutorial, nossas classes serão simples só para vocês poderem acompanhar o raciocínio. Então vamos Lá, vamos criar nossas classes. Clique com o botão direito do mouse no nome do projeto, depois “Add –> Class”

[Tens de ter uma conta e sessão iniciada para poderes visualizar esta imagem]

Agora na janela que se abriu, deixei selecionado o tipo Class e mude a propriedade Name para Ball e clique em Add.

[Tens de ter uma conta e sessão iniciada para poderes visualizar esta imagem]

Um arquivo irá abrir, que é a nossa classe Ball que acabamos de criar. Repita o mesmo processo e crie a classe Bat.

Codificando a classe Ball

Agora abra a classe Ball, e vamos adicionar algumas atributos. Uma bola no nosso jogo de Pong, possui uma textura (imagem que representa a bola), possui também uma vetor de posição, assim como um vetor de deslocamento (direção) e uma velocidade. também.

No código vocês verão uma acrescimo de duas usings que são a Microsoft.Xna. Framework e Microsoft.Xna. Framework.Graphics, elas servem respectivamente para usarmos o tipo Vector2 e Texture2D. Não se reocupe com a palavra public e private no momento, a palavra public deixa uma propriedade a vista para os outros objetos, enquanto a palavra private esconde essas propriedades.

O public Ball() é nosso construtor ou seja, toda vez que instanciamos um objeto a primeira coisa a ser feita é construir, e para fazer isso no nosso objeto bola, precisamos saber sua posição inicial na tela. Então note, que como parâmetro do construtor passamos a posição (position). Pronto nosso objeto bola já pode ser usado pelo nosso jogo.

Logo em seguida criamos um método para atualizar a posição da bola e um método para desenhar a bola na tela. Veja como esta classe ficaria no final.

Código:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
 
namespace TutorialPong
{
    public class Ball
    {
        /// <summary>
        /// Imagem da bola
        /// </summary>
        public Texture2D Texture { get; set; }
 
        /// <summary>
        /// Posição da bola na tela
        /// </summary>
        public Vector2 Position { get; set; }
 
        /// <summary>
        /// Direção de movimento da bola
        /// </summary>
        public Vector2 Direction { get; set; }
 
        /// <summary>
        /// Velocidade de deslocamento da bola
        /// </summary>
        public float velocity;
 
        /// <summary>
        /// Construtor da classe bola
        /// </summary>
        /// <param name="game">Jogo que instânciou a bola
        /// <param name="position">Posição de inicio da bola
        public Ball(Game game, Vector2 position)
        {
            Texture = game.Content.Load<Texture2D>(@"Textures\ball");
            Position = position;
            Direction = new Vector2(0.0f, 0.0f);
            velocity = 150.0f;
        }
 
        /// <summary>
        /// Atualiza a posição da bola
        /// </summary>
        /// <param name="gameTime">Tempo de jogo
        public void Update(GameTime gameTime)
        {
            Position += Direction * Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
        }
 
        /// <summary>
        /// Desenha a bola na tela
        /// </summary>
        /// <param name="spriteBatch">Spritebatch para desenho
        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(Texture, Position, Color.White);
        }
    }
}


Codificando a classe Bat

A classe Bat no nosso exemplo é muito parecida com a classe Ball. A unica diferença é a textura que carregamos. Veja abaixo o código.

Código:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
 
namespace TutorialPong
{
    public class Bat
    {
        /// <summary>
        /// Imagem do bastão
        /// </summary>
        public Texture2D Texture { get; set; }
 
        /// <summary>
        /// Posição do bastão na tela
        /// </summary>
        public Vector2 Position { get; set; }
 
        /// <summary>
        /// Direção de movimento do bastão
        /// </summary>
        public Vector2 Direction { get; set; }
 
        /// <summary>
        /// Velocidade de deslocamento do bastão
        /// </summary>
        private float velocity;
 
        /// <summary>
        /// Construtor da classe bastão
        /// </summary>
        /// <param name="game">Jogo que instânciou o bastão
        /// <param name="position">Posição de inicio do bastão
        public Bat(Game game, Vector2 position)
        {
            Texture = game.Content.Load<Texture2D>(@"Textures\bat");
            Position = position;
            Direction = new Vector2(0.0f, 0.0f);
            velocity = 150.0f;
        }
 
        /// <summary>
        /// Atualiza a posição do bastão
        /// </summary>
        /// <param name="gameTime">Tempo de jogo
        public void Update(GameTime gameTime)
        {
            Position += Direction * velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
        }
 
        /// <summary>
        /// Desenha o bastão na tela
        /// </summary>
        /// <param name="spriteBatch">Spritebatch para desenho
        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(Texture, Position, Color.White);
        }
    }
}


Adicionando os objetos ao jogo

Declare um objeto do tipo Ball e dois do tipo Bat, para isso vou fazer desta forma.

Código:


// Declara uma variavel do tipo bola (objeto)
Ball ball;
// Declara duas variaveis do tipo bastão (objetos)
Bat bat1, bat2;


Kleber, onde você colocou isso? essas variáveis eu declarei acima do construtor e debaixo do background que declaramos no tutorial passado.

Agora, precisamos instânciar estes objetos para que eles possam deixar de ser abstratos e se tornem concretos. Para fazer isso, é necessário usar a palavra new e passar os parametros para conforme o construtor do objeto pede. Faremos isso no método LoadContent, veja como ficará nosso método.

Código:

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);
    // Carrega a imagem de fundo do jogo
    background = Content.Load<Texture2D>(@"Textures\gameplay");
    // Instância a bola
    ball = new Ball(this, new Vector2(386.0f, 310.0f));
    // Instância o primeiro bastão
    bat1 = new Bat(this, new Vector2(10.0f, 290.0f));
    // Instância o segundo jogador
    bat2 = new Bat(this, new Vector2(765.0f, 290.0f));
}


Desenhando os objetos

Para desenharmos a bola e os bastões, precisamos no método Draw do nosso jogo, chamar os métodos de desenho do bastão e da bola. Veja como isso ficaria abaixo

Código:


protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);
    spriteBatch.Begin();
    // Desenha a imagem de fundo
    spriteBatch.Draw(background, Vector2.Zero, Color.White);
    // Desenha a bola
    ball.Draw(spriteBatch);
    // Desenha o bastão do jogador 1
    bat1.Draw(spriteBatch);
    // Desenha o bastão do jogador 2
    bat2.Draw(spriteBatch);
    spriteBatch.End();
    base.Draw(gameTime);
}


Movimentando os Bastões e atualizando as posições dos objetos

Legal, já instanciamos a bola e os bastões no jogo, e ja desenhamos na tela, agora só faltar colocar movimento nas raquetes para concluirmos esta parte do tutorial. Então vamos ao método protected override void Update(GameTime gameTime) que é o método que atualiza a lógica do jogo, vamos fazer o seguinte:

Vamos declarar uma variável do tipo KeyboardState que será responsável por armazenar as infõrmações do teclado

  • Entradas do Jogador 1:
  • Tecla W faz o bastão 1 subir (ou seja, posição Y é decrementada)
  • Tecla S faz o bastão 1 descer (ou seja, posição Y é incrementada)
    Entradas do Jogador 2:
  • Tecla seta para cima faz o bastão 2 subir (ou seja, posição Y é decrementada)
  • Tecla seta para baixo faz o bastão 2 descer (ou seja, posição Y é incrementada)

É isso que temos que fazer, veja como deve ficar no código abaixo.

Código:


protected override void Update(GameTime gameTime)
{
    // Recebe o estado do teclado
    KeyboardState keyState = Keyboard.GetState();
    // Se pressionar a tecla ESC encerra o jogo
    if (keyState.IsKeyDown(Keys.Escape))
        Exit();
    // Entradas do jogador 1 (bastão do lado esquerdo)
    if (keyState.IsKeyDown(Keys.W))
        bat1.Direction = new Vector2(0.0f, -1.0f);
    else if (keyState.IsKeyDown(Keys.S))
        bat1.Direction = new Vector2(0.0f, 1.0f);
    else
        bat1.Direction = Vector2.Zero;
    // Atualiza a posição do bastão 1
    bat1.Update(gameTime);
    // Entradas do jogador 2 (bastão do lado direito)
    if (keyState.IsKeyDown(Keys.Up))
        bat2.Direction = new Vector2(0.0f, -1.0f);
    else if (keyState.IsKeyDown(Keys.Down))
        bat2.Direction = new Vector2(0.0f, 1.0f);
    else
        bat2.Direction = Vector2.Zero;
    // Atualiza a posição do bastão 2
    bat2.Update(gameTime);
    // Atualiza a posiação da bola
    ball.Update(gameTime);
    base.Update(gameTime);
}


A chamada do método Update de cada bastão, faz com que a posição dele incremente conforme informações do vetor direção.

Resultado do tutorial

É isso pessoal, se não nos esquecemos de nada, podemos rodar nossa aplicação e ver o resultado conforme a imagem abaixo.

[Tens de ter uma conta e sessão iniciada para poderes visualizar esta imagem]