xna game studio expressagomes/tjv/praticas/xnagamestudioexpress...se for manual, os recursos...

Post on 10-Mar-2020

26 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

XNA Game Studio ExpressXNA Game Studio ExpressAula 2Aula 2

DesenhoDesenho emem 2D2D

Alexandre Santos LobãoAlexandre Santos Lobãocontatocontato@@AlexandreLobaoAlexandreLobao.com.com

PPóós em Desenvolvimento s em Desenvolvimento de de Jogos EletrônicosJogos Eletrônicos -- IESB IESB

2

Agenda: Aula 2Agenda: Aula 2

RevisãoRevisão

Arquitetura Arquitetura de um de um programa programa XNAXNA

DesenhoDesenho emem 2D2D

““ComponentsComponents”” de um gamede um game

Tratamento Tratamento de input do de input do usuusuááriorio

Divisão Divisão dos dos grupos para grupos para o o projeto da matprojeto da matéériaria

3

XNA FrameworkXNA Framework

RevisãoRevisão -- XNA Game Studio ExpressXNA Game Studio Express

XNA Game Studio XNA Game Studio ExpressExpress

XNA Game Studio ExpressXNA Game Studio Express

Extends C# Express to Extends C# Express to support XNA Framework, support XNA Framework, building game content and building game content and targetingtargeting XboxXbox 360360

XNA FrameworkXNA Framework

.NET Game Framework.NET Game Framework

.NET Framework for 360.NET Framework for 360

Customized .NET Compact Customized .NET Compact Framework Framework

XNA FrameworkXNA Framework

4

RevisãoRevisão: XNA Framework: XNA Framework

PlataformaPlataforma

CoreCore

FrameworkFramework

ExtendedExtended

FrameworkFramework

GamesGames

XACTXACT XINPUTXINPUT XContentXContentDirect3DDirect3D

GraphicsGraphics AudioAudio InputInput MathMath StorageStorage

Application ModelApplication Model Content PipelineContent Pipeline

Starter KitsStarter Kits CCóódigodigo ConteConteúúdodo ComponentesComponentes

Legenda XNA ProvidesXNA Provides NNóós criamoss criamos ComunidadeComunidade

5

ArquiteturaArquitetura de umde um programaprograma XNAXNA

Ao Ao se se criar criar um um projetoprojeto, , são gerados dois arquivossão gerados dois arquivos::

Program.cs

Game1.cs

6

ArquiteturaArquitetura de umde um programaprograma XNAXNA

Program.cs

static void Main(string[] args)

{

using (Game1 game = new Game1())

{

game.Run(); -> Executa o Game Loop

}

}

7

Classe“Game”

É a central da arquitetura XNA

Tem, internamente, um game loop chamado a cada 1/60 de segundo (default)

Propriedade TargetElapsedTime pode mudar esta velocidade

is 1/60th of a second.

8

Arquitetura Arquitetura de umde um programa programa XNAXNA

Game1.csConstrutor – cria os objetos Graphics e Content

public Game1()

{

graphics = new GraphicsDeviceManager(this);

content = new ContentManager(Services);

}

Métodos chamados pela classe Game (“Eventos” do jogo)Initialize()

LoadGraphicsContent(bool loadAllContent)

UnloadGraphicsContent(bool unloadAllContent)

Update(GameTime gameTime)

Draw(GameTime gameTime)

9

ArquiteturaArquitetura de umde um programaprograma XNAXNA

Métodos chamados pela classe Game (1/2)Initialize()

Chamado quando o jogo carrega

Onde se inicializam os recursos não gráficos

Por exemplo, Mousehelper, Som, etc

LoadGraphicsContent(bool loadAllContent)

Chamado sempre que é necessário carregar os recursos (conteúdos) gráficos

Isso pode acontecer no início do jogo, ou quando a janela (no Windows) sai de trás de outra janela, ou quando por algum erro se perde a referência ao dispositivo (device) de video

Quando LoadAllContent é true, é necessário recarregar todo o conteúdo (jncluindo os marcados como “modo de gerenciamento de recursos”automático).

Mais sobre o “modo de gerenciamento de recursos” no próximo slide

10

ArquiteturaArquitetura de umde um programaprograma XNAXNA

O Modo de gerenciamento de recursos É usado nos métodos LoadGraphicsContent e UnloadGraphicsContent

É passado como parâmetro ao carregar vertex buffers, index buffers, textures, e surfaces) pode ser manual ou automático

Se for Manual, os recursos precisam ser recarregados sempre que se perder a referência ao device

Se for Automático, serão automaticamente gerenciados pelo sistema, “existindo” para a aplicação quase sempre (o XNA carrega para a memória caso necessário e já não esteja carregado)

No gerenciamento automático, o XNA fica livre para liberar os recursos na memória da placa caso precise deles, recarregandoquando a aplicação necessitar.

O Gerenciamento Automático é o default, e o usado pela maioria das aplicações.

11

ArquiteturaArquitetura de umde um programaprograma XNAXNA

Métodos chamados pela classe Game (2/2)UnloadGraphicsContent(bool unloadAllContent)

Chamado sempre que é necessário liberar os recursos (conteúdos) gráficos

Quando LoadAllContent é true, é necessário descarregar todo o conteúdo

Update(GameTime gameTime)

Chamado a cada game loop

Onde se coloca a lógica principal do jogo (cálculos)

Recebe um objeto (gameTime) com uma “foto” com informações sobre o tempo no instante da chamada do método

Mais sobre gameTime no próximo slide

Draw(GameTime gameTime)

Chamado a cada game loop

Onde se colocam as rotinas de desenho do jogo

12

ArquiteturaArquitetura de umde um programaprograma XNAXNA

GameTime

Passado como parâmetro para os métodos Update e Draw

Tem propriedades que permitem ler o tempo transcorrido desde a última chamada e desde o início do jogo

Propriedade IsRunningSlowly indica se o TargetElapsedTime não estásendo atingido

O tempo pode se lido em:“Real Time”: tempo em segundos reais (relógio)

É o usado por quase todas as aplicações

“Game Time”: número de passos fixos executados conforme o clock da máquina.

Como não reflete o tempo “de relógio”, a performance de um jogo que se baseie em “Game Time” pode variar conforme a performance da máquina, caso não se tenha cuidado.

Pode ser usado para criar jogos com performance controlável via programa (possivelmente maior), setando-se a propriedade IsFixedTimeStep do objeto Game para false (executa jogo em full speed, ignorando a propriedade TargetElapsedTime)

Exemplos: gameTime.ElapsedRealTime; gameTime.TotalGameTime;

13

DesenhoDesenho dede objetosobjetos 2D2D

14

DesenhoDesenho dede objetosobjetos 2D2D

Na classe game 1:private Texture2D textura;

private SpriteBatch Renderizador2D;

No Método LoadGraphicsContent:override void LoadGraphicsContent(bool loadAllContent)

{

if (loadAllContent)

{ // Para escolher tamanho da janela ou modo fullscreen:

//graphics.PreferredBackBufferWidth = 400;

//graphics.PreferredBackBufferHeight = 400;

//graphics.IsFullScreen = true;

//graphics.ApplyChanges();

textura = content.Load<Texture2D>("xna_thumbnail");

Renderizador2D = new SpriteBatch(graphics.GraphicsDevice);

}

}

15

DesenhoDesenho dede objetosobjetos 2D2D

No Método UnloadGraphicsContent:override void UnloadGraphicsContent(bool unloadAllContent)

{

if (unloadAllContent)

{

textura.Dispose();

Renderizador2D.Dispose();

content.Unload();

}

}

16

DesenhoDesenho dede objetosobjetos 2D2D

No Método Draw:

override void Draw(GameTime gameTime)

{

graphics.GraphicsDevice.Clear(Color.White);

Renderizador2D.Begin(SpriteBlendMode.AlphaBlend);

Renderizador2D.Draw(textura, Vector2.One, Color.White);

Renderizador2D.End();

base.Draw(gameTime);

}

17

““ComponentsComponents”” de um gamede um game

18

““ComponentsComponents”” de um gamede um game

Coleção Components da Classe Game

Informa ao XNA quais os componentes do jogo

Passos para criar um componente:

1. Criar uma classe derivada de GameComponent

2. Criar um objeto desta classe

3. Adicionar o objeto ao Game usando:this.Components.Add( objeto );

O XNA automaticamente chama os métodos Update e Draw do objeto, se existirem

19

““ComponentsComponents”” de um gamede um game

1. Criar uma classe derivada de GameComponent (1/2)

class clsSprite : GameComponent

{

public Texture2D textura; // sprite texture

public Vector2 posicao; // sprite posicao on screen

public Vector2 velocidade; // velocidade in pixels

public clsSprite(Game game, Texture2D Textura, Vector2 Posicao)

: base(game)

{

textura = Textura;

posicao = Posicao;

}

}

20

““ComponentsComponents”” de um gamede um game1. Criar uma classe derivada de GameComponent (2/2)

public override void Update(GameTime gameTime)

{

// ajusta a velocidade para não sair pelas bordas da tela

if(posicao.X + textura.Width + velocidade.X > this.Game.Window.ClientBounds.Width)

velocidade.X = -velocidade.X; // direita

if (posicao.Y + textura.Height + velocidade.Y > this.Game.Window.ClientBounds.Height)

velocidade.Y = -velocidade.Y; // de baixo

if (posicao.X + velocidade.X < 0)

velocidade.X = -velocidade.X; // esquerda

if (posicao.Y + velocidade.Y < 0)

velocidade.Y = -velocidade.Y; // de cima

// Atualiza a posição

posicao += velocidade;

}

21

““ComponentsComponents”” de um gamede um game

2. Criar um objeto desta classe

3. Adicionar o objeto ao Game

private clsSprite Desenho2D;

...

protected override void LoadGraphicsContent(bool loadAllContent)

{

...

// Load a 2D texture sprite

Desenho2D = new clsSprite(this,

content.Load<Texture2D>("xna_thumbnail"), Vector2.One);

Desenho2D.velocidade = new Vector2(1, 2);

this.Components.Add(Desenho2D);

}

22

““ComponentsComponents”” de um gamede um game

Como não fizemos override do Draw, precisamos atualizar o método Draw da classe Game

protected override void Draw(GameTime gameTime)

{

graphics.GraphicsDevice.Clear(Color.White);

Renderizador2D.Begin(SpriteBlendMode.AlphaBlend);

Renderizador2D.Draw(Desenho2D.textura, Desenho2D.posicao,

Color.White);

Renderizador2D.End();

base.Draw(gameTime);

}

23

TratamentoTratamento de input do de input do usuusuááriorio

24

TratamentoTratamento de input do de input do usuusuááriorio

Vamos adaptar o demo anterior para incluir um novo objeto, controlado pelo usuário via teclado, gamePad e mouse, através dos seguintes passos:

1. Copiar a classe clsSprite e renomeá-la para clsPlayer

2. Alterar o método Update para tratar o input do usuário

3. Alterar os métodos do objeto principal (game1) para incluir o novo componente e desenhá-lo

25

TratamentoTratamento de input do de input do usuusuááriorio

1. Copiar a classe clsSprite para clsPlayer

Dica: use Copy e Paste direto na janela de “Solution Explorer” do C# Express

Além de renomear, vamos incluir na classe:using Microsoft.Xna.Framework.Input;

26

TratamentoTratamento de input do de input do usuusuááriorio

2. Alterar o método Update para tratar o input do usuário - GamePad

public override void Update(GameTime gameTime)

{

Vector2 novaPosicao = posicao;

bool podeMover = true; // será usado para teste das bordas da janela

// Muda a posição usando o thumbstick da esquerda

GamePadState gamePad = GamePad.GetState(PlayerIndex.One);

novaPosicao.X += gamePad.ThumbSticks.Left.X;

novaPosicao.Y -= gamePad.ThumbSticks.Left.Y;

// Atualiza a posição

if(podeMover)

posicao = novaPosicao;

}

27

TratamentoTratamento de input do de input do usuusuááriorio

2. Alterar o método Update para tratar o input do usuário - Teclado

public override void Update(GameTime gameTime)

{

...

// muda a posição usando o teclado

KeyboardState keyboardState = Keyboard.GetState();

if (keyboardState.IsKeyDown(Keys.Up))

novaPosicao.Y -= 1;

if (keyboardState.IsKeyDown(Keys.Down))

novaPosicao.Y += 1;

if (keyboardState.IsKeyDown(Keys.Left))

novaPosicao.X -= 1;

if (keyboardState.IsKeyDown(Keys.Right))

novaPosicao.X += 1;

...

}

28

TratamentoTratamento de input do de input do usuusuááriorio

2. Alterar o método Update para tratar o input do usuário – Mouse

public override void Update(GameTime gameTime)

{

...

// muda a posição usando o mouse

MouseState mouse = Mouse.GetState();

novaPosicao.X = mouse.X;

novaPosicao.Y = mouse.Y;

...

}

29

TratamentoTratamento de input do de input do usuusuááriorio

2. Alterar o método Update para tratar o input do usuário – Testando as bordas da janela

public override void Update(GameTime gameTime)

{

Vector2 novaPosicao = posicao;

bool podeMover = true;

...

// testa a nova posição para não sair pelas bordas da tela

if(novaPosicao.X + textura.Width > this.Game.Window.ClientBounds.Width)

podeMover = false; // direita

if (novaPosicao.Y + textura.Height > this.Game.Window.ClientBounds.Height)

podeMover = false; // de baixo

if (novaPosicao.X < 0)

podeMover = false; // esquerda

if (novaPosicao.Y < 0)

podeMover = false; // de cima

// Atualiza a posição

if(podeMover)

posicao = novaPosicao;

}

30

TratamentoTratamento de input dode input do usuusuááriorio

3. Adicionar o objeto Player ao Game

private clsPlayer jogador;

...

protected override void LoadGraphicsContent(bool loadAllContent)

{

...

// carrega o jogador

jogador = new clsPlayer(this,

content.Load<Texture2D>(“player_xna_thumbnail"),

new Vector2(300, 100));

this.Components.Add(jogador );

}

31

TratamentoTratamento de input dode input do usuusuááriorio

...e finalmente atualizar o método Draw da classe Game

protected override void Draw(GameTime gameTime)

{

graphics.GraphicsDevice.Clear(Color.White);

Renderizador2D.Begin(SpriteBlendMode.AlphaBlend);

Renderizador2D.Draw(Desenho2D.textura, Desenho2D.posicao,

Color.White);

Renderizador2D.Draw(jogador.textura, jogador.posicao, Color.White);

Renderizador2D.End();

base.Draw(gameTime);

}

32

TratamentoTratamento de input dode input do usuusuááriorio

Toque final: Incluindo detecção de colisão

1. Incluir código na classe Player que testa colisão com objetos Sprite

2. Chamar código na classe principal (game1)

Incluir vibração no GamePad

33

TratamentoTratamento de input dode input do usuusuááriorio

1. Incluir código na classe Player que testa colisão com objetos Sprite

public bool Colidiu(clsSprite sprite)

{

// Verifica se colidiu com a sprite

if (this.posicao.X + this.textura.Width > sprite.posicao.X &&

this.posicao.X < sprite.posicao.X + sprite.textura.Width &&

this.posicao.Y + this.textura.Height > sprite.posicao.Y &&

this.posicao.Y < sprite.posicao.Y + sprite.textura.Height)

return true;

else

return false;

}

34

TratamentoTratamento de input dode input do usuusuááriorio

2. Chamar código na classe principal (game1)

protected override void Update(GameTime gameTime)

{

...

// Testa se houve colisão

if (jogador.Colidiu(Desenho2D))

{

Desenho2D.velocidade *= -1;

GamePad.SetVibration(PlayerIndex.One, 1.0f, 1.0f);

}

else

GamePad.SetVibration(PlayerIndex.One, 0f, 0f);

...

}

35

Desafio 1: Navegação entre telas

Criar uma lista de telas

Navegar pela lista de telas

36

Criando uma classe “Tela”A tela é fácil – mais simples que uma sprite!

class Tela

{

private Texture2D fundo; // Textura da tela

public Tela(Texture2D Textura)

{

fundo = Textura;

}

public void Draw(SpriteBatch Renderizador2D)

{

Renderizador2D.Draw(fundo, Vector2.Zero, Color.White);

}

public void Unload()

{

fundo.Dispose();

}

}

37

Navegando entre telasTambém é fácil – basta desenhar uma tela em vez da outra!

...

private Tela tela1; private Tela tela2; private Tela telaAtual;

...

protected override void Initialize()...

Tela1 = new Tela(content.Load<Texture2D>("Tela_Inicial"));

Tela2 = new Tela(content.Load<Texture2D>("Tela_GameOver"));

telaAtual = Tela1;

...

protected override void Update(GameTime gameTime)...

if

(GamePad.GetState(PlayerIndex.One).Buttons.A==ButtonState.Pressed)

telaAtual = Tela2;

...

protected override void Draw(GameTime gameTime)

...

telaAtual.Draw(Renderizador2D);

38

Dica: E a lista de telas?

No C#, podemos criar listas de objetos com ListEstas listas podem ser acessadas como arrays ou via foreach. Por exemplo:

List<string> palavras = new List<string>();

palavras.Add("Teste1");

palavras.Add("Teste2");

foreach (string palavra in palavras)

{

MessageBox.Show(palavra);

}

for(int i = 0; i < palavras.Count;i++ )

{

MessageBox.Show(palavras[i]);

}

39

Desafio 2: Criar uma lista de botões

Duas imagens: selecionado / não selecionado

Com evento que é disparado ao executar o botão

Criar lista que gerencia navegação entre botões

40

DicaDica: Input : Input não não tem tem ““memmemóóriaria””

Os objetos de input (Mouse, Keyboard, GamePad) tiram uma “foto” do estado atual!

Não dá para saber se o mouse “está se movendo”, só sua posição

Não dá para saber se o usuário acabou de apertar uma tecla, ou se ela já estava apertada.

Não dá para saber a última direção em que o usuário moveu o Mouse ou gamePad

=> Uso de classes de apoio (“helpers”)

41

DicaDica: Input : Input não não tem tem ““memmemóóriaria””

Exemplo de uso de Helpers (classes do Abi, do livro “Professional XNA game...”:

1. Incluir Input.cs (modificada) no projeto

2. Chamar Input.Update no update do jogoInput.Update(gameTime);

3. Usar os métodos (exemplos)if (Input.KeyboardUpJustPressed)

incremento = -1;

...

if(Input.GamePadLeftShoulderJustPressed)

incremento = -1;

...

if (Input.MouseLeftButtonJustPressed)

{

if (Input.MouseInBox(this[BotaoAtivo].retangulo))

this[BotaoAtivo].Executa();

}

42

Dica: Organizar Projeto!Atual Organizado

content.Load<Texture2D>(@"Texturas\Botoes\blackBall“)

content.Load<Texture2D>(@"Texturas\Telas\Tela_Inicial")

content.Load<Texture2D>(@"blackBall“)

content.Load<Texture2D>(@"Tela_Inicial")

43

DivisãoDivisão dosdos grupos paragrupos para oo projeto da projeto da matmatéériaria

Mini-GDD em duas semanas

44

Perguntas?Perguntas?

top related