




















Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Uma análise do código de introdução ao desenvolvimento de jogos usando a plataforma xna da microsoft. O texto abrange as transformações 3d da nave, a execução de sons, e a criação de classes para representar a lógica da nave no jogo. Além disso, são discutidos conceitos básicos da plataforma xna, como a matriz de transformação padrão, a posição e rotação dos modelos, e a aceleração da nave.
Tipologia: Notas de estudo
1 / 28
Esta página não é visível na pré-visualização
Não perca as partes importantes!





















Fortaleza
Sobre este material
Este material é baseado nos tutoriais disponíveis no site XNA Creators Club (MICROSOFT, 2007a, 2007b) e no XNA Developer Center (MICROSOFT, 2007c). Os vídeos tutoriais disponibilizados no site XNA Creators Club estão disponíveis na integra no CD do curso na pasta \VIDEO. Os códigos fontes dos respectivos tutoriais estão disponíveis na pasta \PROJETOS. A pasta \STARTERKITS apresenta os instaladores dos projetos de dois jogos completos: “Marbles” (estilo “tetris”) e “Racing Game” (estilo “corrida”).
Todos os pacotes necessários ao desenvolvimento na plataforma XNA estão disponíveis na pasta \PACOTES do mesmo CD, destacando o Visual C# Express 2005, Visual C# Express 2005 SP1 e o framework XNA (instalação mínima).
Como forma de entendimento, recomenda-se fortemente a leitura dos comentários dos códigos fontes apresentados pois a explicação de seu funcionamento via de regra se encontra nestes.
2.5. Na classe Game1, substitua o método LoadGraphicsContent pelo código abaixo:
// Modelo 3D para visualização. private Model _ModeloNave;
// O proporção da tela determina como manter a propoção da tela para os objetos 2D e 3D. private float _AspectRatio;
protected override void LoadGraphicsContent( bool loadAllContent ) { if (loadAllContent) { // Carrega o modelo da nave a partir do arquivo \Content\Models\p1_wedge.fdx _ModeloNave = content.Load
// Determina a proporção da tela pela razao entre a lagura e o comprimento da tela _AspectRatio = (float) GraphicsDeviceManager.DefaultBackBufferWidth / GraphicsDeviceManager.DefaultBackBufferHeight;; }
2.6. Na classe Game1, substitua o método Draw pelo código abaixo:
// Inicia a posição inicial do modelo 3D na origem e sua rotação em 0 radianos. private Vector3 _PosicaoNave = Vector3.Zero; private float _RotacaoNave = 0.0f;
// Inicia a posição da camera no espaço para a matriz de visualização. private Vector3 _PosicaoCamera = new Vector3( 0.0f, 50.0f, 5000.0f );
protected override void Draw( GameTime gameTime ) { // Limpa a tela com um fundo azul graphics.GraphicsDevice.Clear( Color.CornflowerBlue );
// Copia a referencia das transformações para o modelo 3D da nave. Matrix[] transforms = new Matrix[_ModeloNave.Bones.Count]; _ModeloNave.CopyAbsoluteBoneTransformsTo( transforms );
// Desenha o modelo. O modelo pode possuir múltiplos Meshes. foreach (ModelMesh mesh in _ModeloNave.Meshes) { // Inicia a orientação do Mesh no espaço assim como a posição da câmera, // e da projeção do mesmo. foreach (BasicEffect effect in mesh.Effects) { // Define iluminação padrão effect.EnableDefaultLighting();
// Define a posição do modelo 3D da nave pela matriz de rotação no eixo Y // (a nave vai girar na horizontal) e a matriz de translação da posição //da nave. effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateRotationY( _RotacaoNave ) * Matrix.CreateTranslation( _PosicaoNave );
// Define a posição da câmera no espaço, assim como sua direção e //seu o eixo de rotação effect.View = Matrix.CreateLookAt( _PosicaoCamera, Vector3.Zero, Vector3.Up );
// Define os planos de projeção (discutido em detalhes na Parte 5.1) effect.Projection = Matrix.CreatePerspectiveFieldOfView( MathHelper.ToRadians( 45.0f ), _AspectRatio, 1.0f, 10000.0f ); } // Desenha o mesh. mesh.Draw(); } }}
2.7. Para fazer a nave girar em torno do próprio eixo, substitua o método Update pelo código abaixo:
protected override void Update( GameTime gameTime ) { // Para cada milisegundo, a rotação da nave é incrementando em 0,1 graus _RotacaoNave += (float)gameTime.ElapsedGameTime.TotalMilliseconds
base.Update( gameTime ); }
2.8. Execute o debug com o botão F5. O resultado deverá ser uma nave rodando no próprio eixo conforme ilustrado abaixo:
Figura 3: Apresentação do modelo 3D (.fbx). Exercícios:
Exercícios:
NOTA: Para controle via joysticks e gamepads veja o Adentro 1.
Parte 4: Fundamentos: Adicionando Som
4.1 Pressione o botão direito do mouse na janela “Solution Explorer” (Add Æ New Folder) para adicionar o diretório “Content\Audio” e o subdiretórios “Content\Audio\Waves”. 4.2 Selecione com o botão direito do mouse a pasta “Content\Audio\Waves” e selecione Add Æ Existing Item... Selecione os arquivos engine_2.wav e hyperspace_activate.wav (disponível no CD do curso na pasta
\AULA1\Content\Audio\Waves). Selecione novamente o botão direito na pasta “Content\Audio” e adicione o arquivo MyGameAudio.xap (disponível no CD do curso na pasta \AULA1\Content\Audio).
NOTA: Para informações sobre a criação do arquivo xap, veja o Adentro 2
4.3. Substitua o método Initialize() pelo código abaixo:
private AudioEngine _AudioEngine; private WaveBank _WaveBank; private SoundBank _SoundBank; protected override void Initialize() { // Carrega o arquivo de definição de sons (.xap) gerado com a ferramenta XACT _AudioEngine = new AudioEngine( "Content\Audio\MyGameAudio.xgs" ); _WaveBank = new WaveBank( _AudioEngine, "Content\Audio\Wave Bank.xwb" ); _SoundBank = new SoundBank( _AudioEngine, "Content\Audio\Sound Bank.xsb" ); base.Initialize(); }
3.1. Substitua o método UpdateKeyboardInput() pelo código abaixo:
private Cue _SomMotorNave; protected void UpdateKeyboardInput() { // Para cada tecla pressiona (podem ser pressionadas mais de uma tecla) foreach (Keys key in Keyboard.GetState().GetPressedKeys()) { // Rotação para esquerda (0,1 rad) quando pressiona a tecla esquerda if (key == Keys.Left) _RotacaoNave += 0.1f; // Rotação para direita (0,1 rad) quando pressiona a tecla direita if (key == Keys.Right) _RotacaoNave -= 0.1f;
// Se pressiona a tecla “para cima”, acelera a nave. // O vetor de aceleração tem a mesma direção da nave. Vector3 aceleracao = Vector3.Zero; if (key == Keys.Up) { aceleracao.X = -(float)Math.Sin(_RotacaoNave); eceleracao.Z = -(float)Math.Cos(_RotacaoNave);
// Se o som do motor da nave não foi criado, cria o mesmo e toca. if (_SomMotorNave == null) { _SomMotorNave = soundBank.GetCue( "engine_2" ); _SomMotorNave.Play(); } // Se o som do motor da nave já foi criado e está pausado, libera o “pause” else if (_SomMotorNave.IsPaused) { _SomMotorNave.Resume(); } } else { // NAVE NÃO ESTÁ ACELERANDO!!! // Se o som do motor da nave existe e está tocando, pausa o mesmo. if (_SomMotorNave != null && _SomMotorNave.IsPlaying) { _SomMotorNave.Pause(); } }
// Incrementa a velocidade da nave através da aceleração _VelocidadeNave += aceleracao;
// Encerra jogo se pressiona “Escape” if (key == Keys.Escape) this.Exit();
// Move a nave para a origem se pressiona “Enter” if (key == Keys.Enter) { _PosicaoNave = Vector3.Zero; _VelocidadeNave = Vector3.Zero; _RotacaoNave = 0.0f;
// Executa som do “hiper-espaço”. _SoundBank.PlayCue( "hyperspace_activate" ); } } }
Exercícios:
No entanto, podem-se abstrair outras generalizações deste modelo. Observa-se que a lógica de execução dos sons não pertence necessariamente à lógica da nave. A lógica de execução do som pode ser entendida como uma funcionalidade a parte consumida pela nave. Desta forma, a execução dos sons é de responsabilidade de um terceira classe “SoundPlayer”, associada por composição com a classe nave. Desta forma, a lógica de execução de som empregada pela nave pode ser reaproveitada em outros cenários. Novamente, a divisão de responsabilidades e o encapsulamento do código favorece o entendimento, manutenção e extensão do código do jogo.
Ademais, uma nova generalização pode ser proposta, na medida em que a nave é , em última estância, um elemento gráfico do jogo. Assim como a nave, outros elementos gráficos teriam comportamentos em comum. Todos os elementos gráficos que possamos vir a criar no futuro teriam um modelo “mesh” (propriedade “Model”), uma posição no espaço (propriedades “Posicao”) e matrizes de transformação (propriedade “Transforms”). Desta forma, classe “Ship” é definida por herança a partir da classe “Element”.
A classe “Element” encapsula as responsabilidades de desenhar o elemento gráfico na tela, empregando as propriedades de modelo e posição.
Por sua vez a classe “Ship” especializa a classe “Element”, extendendo a representação do movimento da próprios da nave, tais como: modelo físico de velocidade e rotação, assim como de manipulação deste modelo pelo teclado e joystick. Portanto a classe “Ship” disporia de uma interface mínima contanto apenas de sua rotação (propriedade “Rotacao”) e um método de atualização (método “Update”), recebendo por parâmetros a entrada do teclado/joystick e representando o comportamento do seu movimento em resposta a esta entrada.
Como forma, de facilitar futuras extensões ao código proposto são ainda extraídas as interfaces das classes “SoundPlayer” e “Element” (figura abaixo), dando o primeiro passo para estruturação de fábricas de produtos concretos ao jogo, parametrizando diversos aspectos de seu comportamento.
Figura 5 – Interfaces propostas para a refatoração do código da Parte 4.
Parte 5.1.1: Modelando as interfaces
lógicas (“namespaces”), conforme ilustrado na figura abaixo. Dica: Sobre o “Solution Explorer”, pressione o botão direito do mouse e selecione AddÆNew Folder...
Figura 6 – Criando estrutura de diretórios da solução proposta.
Interface ISoundPlayer (ISoundPlayer.cs)
using Microsoft.Xna.Framework.Audio;
namespace MyFirstGame.Sound {
///
///
///
///
Classe SoundPlayer (SoundPlayer.cs)
using Microsoft.Xna.Framework.Audio;
namespace MyFirstGame.Sound { ///
///
//
///
///
///
///
// Copia as transformações padrões do modelo para // um vetor de matrizes de transformação _Transforms = new Matrix[_Model.Bones.Count]; _Model.CopyAbsoluteBoneTransformsTo(_Transforms);
// Um elemento é constituído de vários meshes foreach (ModelMesh mesh in _Model.Meshes) { // Cada mesh pode ter vários efeitos aplicados foreach (BasicEffect effect in mesh.Effects) { // Para cada mesh aplica os efeitos de iluminação padrão, e as // matrizes de projeção e visualização effect.EnableDefaultLighting(); effect.Projection = projectionMatrix; effect.View = viewMatrix; } } }
///
///
// Um modelo é constituído de vários mesh, // desenha-se o modelo desenhando seus meshs foreach (ModelMesh mesh in _Model.Meshes) { // Antes de desenhar, é preciso definir a orientação do mesh foreach (BasicEffect effect in mesh.Effects) { // Ajusta a orientação de cada mesh segundo a matriz de transformação effect.World = _Transforms[mesh.ParentBone.Index] * modelTransform; } // Desenha o mesh, empregando os efeitos (matriz de transformação) acima. mesh.Draw(); } } } }
Classe Ship (Ship.cs)
using System; using System.Text; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Audio; using MyFirstGame.Sound;
namespace MyFirstGame.Elements { ///
///
///
// Reduz a velocidade em 5% a cada quadro (reproduz o efeito de "atrito") _Velocidade *= 0.95f; }
// Constante: aceleração private const float _AceleracaoStep = 3.0f; // Calcula a aceleração (variação da velocidade da nave) protected Vector3 GetAceleracao() { Vector3 aceleracao = Vector3.Zero; // A aceleração tem a mesma direção da rotação da nave aceleracao.X = -(float)Math.Sin(_Rotacao); aceleracao.Z = -(float)Math.Cos(_Rotacao);
// A intensidade da aceleração é dada pela constante _AceleracaoStep return _AceleracaoStep * aceleracao; }
// Constante: velocidade da rotação da nave em radianos private const float _RotacaoStep = 0.1f; ///
// Atualiza o modelo físico da nave Update();
// Aciona o hiper-espaço se pressionada a tecla "Enter" if (key == Keys.Enter) HyperSpace(); } }
///
// A rotação da nave é dada pela direção X do // direcional do polegar (thumbstick direito) Rotacao -= controllerState.ThumbSticks.Left.X * 0.10f;
// Finalmente, a matriz de rotação é adicionada ao // vetor de velocidade se controle estiver para frente. _Velocidade += _MatrizRotacao.Forward * _AceleracaoStep * controllerState.Triggers.Right;
// Se o controle está para frente, executa o som do motor, // caso contrario, pausa o mesmo if (controllerState.Triggers.Right > 0) PlayEngine(); else PauseEngine();
// Atualiza o modelo físico da nave Update();
// Aciona o hiper-espaço se pressionado o botão "A" if (controllerState.Buttons.A == ButtonState.Pressed) HyperSpace(); }
///