sábado, 3 de dezembro de 2011

063 - AmareloGameEngine[3]: Tornando o seu teclado útil

Nos posts anteriores, aprendemos a montar o esqueleto de nosso jogo ( e de futuros jogos que usem a AmareloGameEngine ) e adicionar assets ao jogo ( imagens de fundo, sprite do personagem...). Vamos tentar agora fazer algo aparentemente simples: mover o personagem.

5. Captura de teclado
Até aqui, não elaboramos nenhum código para captura de entrada de teclado ou mouse. Nos exemplos anteriores, possivelmente o seu jogo gerará uma exceção de referência nula caso você aperte qualquer botão do teclado como esse:



Precisamos criar dois métodos para tratar essa exceção: um método para quando o jogador apertar o botão e outro para quando soltar o mesmo botão.
  • Ao final do arquivo "Game1.cs" , crie dois novos métodos
 public void tecla (object o, KeyBoardEvent e) //chamada quando o jogador aperta o botao  
 {  
 }  


 public void teclaR (object o, KeyBoardEvent e) //chamada quando o jogador solta o botao q apertou  
 {  
 }  

  • No  initialize() adicione essas linhas:
 this.inputEngine.KeyPressed += tecla;  
 this.inputEngine.KeyReleased += teclaR;  


  • No escopo da classe, crie um array de quatro booleanos:
 bool[] teclas = { false, false, false, false };  


Cada posição do array indicará uma direção: Vamos definir:
   -- 0 como esquerda
   -- 1 como direita
   -- 2 como para cima
   -- 3 como para baixo

  • No método tecla(), faça um conjunto de if's como segue:
 if (e.Key == Keys.Left)  
 {  
   teclas[0] = true;  
 }  
 else if (e.Key == Keys.Right)  
 {  
   teclas[1] = true;  
 }  
 else if (e.Key == Keys.Up)  
 {  
   teclas[2] = true;  
 }  
 else if (e.Key == Keys.Down)  
 {  
   teclas[3] = true;  
 }  


  • E no método teclaR(), faça o mesmo conjunto de if's, retornando false ao invés de true.
 if (e.Key == Keys.Left)  
 {  
   teclas[0] = false;  
 }  
 else if (e.Key == Keys.Right)  
 {  
   teclas[1] = false;  
 }  
 else if (e.Key == Keys.Up)  
 {  
   teclas[2] = false;  
 }  
 else if (e.Key == Keys.Down)  
 {  
   teclas[3] = false;  
 }  


  • No método update(), faça outro conjunto de if's usando o estado da variável teclas:
 if (teclas[0])  
 {  
   s[CHAR1].posX--;  
 }  
 else if (teclas[1])  
 {  
   s[CHAR1].posX++;  
 }  
 else if (teclas[2])  
 {  
   s[CHAR1].posY--;  
 }  
 else if (teclas[3])  
 {  
   s[CHAR1].posY++;  
 }  


  • Esse é o nosso código até o momento
1:  using System;  
2:  using System.Collections.Generic;  
3:  using System.Linq;  
4:  using Microsoft.Xna.Framework;  
5:  using Microsoft.Xna.Framework.Audio;  
6:  using Microsoft.Xna.Framework.Content;  
7:  using Microsoft.Xna.Framework.GamerServices;  
8:  using Microsoft.Xna.Framework.Graphics;  
9:  using Microsoft.Xna.Framework.Input;  
10:  using Microsoft.Xna.Framework.Media;  
11:  using Amarelo;  
12:  using Amarelo.GameEngine;  
13:  namespace testetutorial  
14:  {  
15:    /// <summary>  
16:    /// This is the main type for your game  
17:    /// </summary>  
18:    public class testetutorial : Amarelo.AmareloGame  
19:    {  
20:      public const int BACKGROUND = 0;  
21:      public const int CHAR1 = 1;  
22:      List<Sprite> s = new List<Sprite>(); //Cria uma lista de sprites  
23:      bool[] teclas = { false, false, false, false };  
24:      public testetutorial(GameConfig cg) : base(cg)  
25:      {  
26:        Content.RootDirectory = "Content";  
27:      }  
28:      /// <summary>  
29:      /// This is called when the game should draw itself.  
30:      /// </summary>  
31:      /// <param name="gameTime">Provides a snapshot of timing values.</param>  
32:      protected override void Draw(GameTime gameTime)  
33:      {  
34:        GraphicsDevice.Clear(Color.CornflowerBlue);  
35:        // TODO: Add your drawing code here  
36:        base.Draw(gameTime);  
37:      }  
38:      protected override void initialize()  
39:      {  
40:        this.inputEngine.KeyPressed += tecla;  
41:        this.inputEngine.KeyReleased += teclaR;  
42:        //throw new NotImplementedException();  
43:      }  
44:      protected override void loadContent()  
45:      {  
46:        s.Add(new Sprite("backg", Content.Load<Texture2D>("Imagens\\background_01"), 0)); //Carrega o background na lista  
47:        s.Add(new Sprite("char1", Content.Load<Texture2D>("Sprites\\char_black"), 1)); //Carrega a sprite do personagem na lista  
48:        this.graphicsEng.addSprite(s[BACKGROUND]); //adiciona o background  
49:        this.graphicsEng.addSprite(s[CHAR1]); //adiciona a sprite  
50:      }  
51:      protected override void unloadContent()  
52:      {  
53:        //throw new NotImplementedException();  
54:      }  
55:      protected override void update(GameTime time)  
56:      {  
57:        if (teclas[0])  
58:        {  
59:          s[CHAR1].posX--;  
60:        }  
61:        else if (teclas[1])  
62:        {  
63:          s[CHAR1].posX++;  
64:        }  
65:        else if (teclas[2])  
66:        {  
67:          s[CHAR1].posY--;  
68:        }  
69:        else if (teclas[3])  
70:        {  
71:          s[CHAR1].posY++;  
72:        }  
73:      }  
74:      public void tecla(object o, KeyBoardEvent e) //chamada quando o jogador aperta o botao  
75:      {  
76:        if (e.Key == Keys.Left)  
77:        {  
78:          teclas[0] = true;  
79:        }  
80:        else if (e.Key == Keys.Right)  
81:        {  
82:          teclas[1] = true;  
83:        }  
84:        else if (e.Key == Keys.Up)  
85:        {  
86:          teclas[2] = true;  
87:        }  
88:        else if (e.Key == Keys.Down)  
89:        {  
90:          teclas[3] = true;  
91:        }  
92:      }  
93:      public void teclaR(object o, KeyBoardEvent e) //chamada quando o jogador solta o botao q apertou  
94:      {  
95:        if (e.Key == Keys.Left)  
96:        {  
97:          teclas[0] = false;  
98:        }  
99:        else if (e.Key == Keys.Right)  
100:        {  
101:          teclas[1] = false;  
102:        }  
103:        else if (e.Key == Keys.Up)  
104:        {  
105:          teclas[2] = false;  
106:        }  
107:        else if (e.Key == Keys.Down)  
108:        {  
109:          teclas[3] = false;  
110:        }  
111:      }  
112:    }  
113:  }  


  • Salve e teste
  • Agora apertando as teclas esquerda, direita, pra cima e pra baixo, o seu personagem irá se deslocar para a direção desejada sem gerar possíveis erros de referência nula.
  • A seguir, construiremos a física do nosso jogo: faremos o personagem pular, cair, andar sobre uma superfície sólida, etc...

terça-feira, 29 de novembro de 2011

062 - 4 Mundos[4]: Antes que eu me esqueça

Nos últimos dias, cometi uma burrada e perdi 90% dos arquivos de quatro mundos no processo de formatação das máquinas do indi. Agora terei de refazer o projeto quase do zero.

Parte do projeto é recuperável graças ao tutorial do AmareloGameEngine que já escrevi. Outra parte, refererente a troca de personagens, é fácil de implementar e tenho o código na cabeça. O problema está no problema do fade in, fade out (já resolvido há um bom tempo, mas esquecido) e na inserção de sons no projeto.

Antes que eu me esqueça, vou escrever tudo isso aqui e colocar logo aquilo que já tenho em uma pasta no dropbox :p

quarta-feira, 19 de outubro de 2011

061 - AmareloGameEngine[2]: Importando arquivos para o projeto

Neste post, vamos aprender um pouco sobre os métodos abstratos da engine que devem ser implementados, a sua importância e como adicionar arquivos ao projeto.

3. Importância dos métodos abstratos
Anteriormente vimos que AmareloGameEngine possui quatro métodos abstratos que precisam ser implementados no projeto. Vejamos o que cada um desses métodos faz:
  • initialize() - É usado para carregar os arquivos que mais tarde serão utilizados no jogo [audio, sprites, fontes...]. Tais arquivos precisam ser importados, como será mostrado adiante.
  • loadContent() - É usado para inserir no jogo os arquivos carregados préviamente na initialize.
  • unloadContent() - Em teoria, é usado para remover do jogo os arquivos carregados na loadContent() [particulamente, não sabemos o seu verdadeiro propósito. Vamos deixar essa função um pouco de lado].
  • update(GameTime game) - é usado para atualizar as informações do jogo em andamento (posição do personagem, tempo de jogo...). Toda a lógica do seu jogo é adicionado a função update.
4. Importando os arquivos do jogo
Todos os arquivos que serão usados em seu jogo [imagens, arquivos de audio, fontes] devem ser importados para a pasta Content de seu projeto



  • Na aba SOLUTION EXPLORER, clique com o botão direito em cima de "(***projeto***)Content (Content)" // add // Existing Item


  • Na janela que se abrirá, navegue até a pasta onde estão os itens que você deseja adicionar e selecione - os [Mais de um arquivo podem ser adicionados a vez]. Aperte ENTER [ou clique em ADD] para adiciona - los. [ Como exemplo importarei 3 arquivos: "background_01.png", "char_black.png" e "qqr.wav"]
  • Os arquivos adicionados aparecem aqui

  • Para melhor organizar os arquivos, crie pastas no Content [(***projeto***)Content (Conent) //add //new folder]. Você pode criar uma pasta para IMAGENS, uma para SPRITES e uma para SONS e arrastar os arquivos importados às suas respectivas pastas.



5. Adicionando os arquivos importados ao jogo
Após importar os arquivos, você precisa agora mandar a engine carregar tais arquivos em seu jogo usando a função loadContent()
  • No escopo da classe crie uma lista de sprites

 List \Sprite/ s = new List\Sprite/()  
 //entre sinais de maior e menor - a formatação html do blogger não me permite adicionar tais símbolos  

  • Assim como Java, C# também tem a classe List e sua utilização é similar a Java.
  • Vamos usar "background_01.png" como imagem de fundo do jogo e "char_black.png" para representar o personagem. Use a função Add para carregar na lista tais imagens.
 s.Add(new Sprite("nomeUnico", Content.Load\Texture2D/("caminho\\do\\arquivoSemExtensao"), layer));  


O construtor da classe Sprite pede:
[*] Uma string "nomeUnico" para o arquivo adicionado. Como da para perceber, essa string deve ser única em todo o projeto;
[*] O caminho de Content.Load\Texture2D/("caminho\\do\\arquivoSemExtensao") é o caminho no Solution Explorer do arquivo da sprite a ser adicionada
[*] _layer_ é um valor float entre 0 e 1 que indica a posição da sprite quanto a profundidade da tela. 0 representa o fundo do seu monitor e 1 representa a tela do monitor;

  • Em nosso caso, para carregar o background e a sprite, usaríamos as seguintes linhas:
 s.Add(new Sprite("backg", Content.Load\Texture2D/("Imagens\\background_01"), 0));  
 s.Add(new Sprite("char1", Content.Load\Texture2D/("Sprites\\char_black"), 1));  

  • Para fazer os arquivoas carregados no jogo aparecerem na tela use
 this.graphicsEng.addSprite(s[i])   


Onde:
[*] i representa o índice da lista. A engine acessará a posição s[i] e carregará qualquer arquivo que estiver lá.

  • Fique alerta a ordem de inserção dos itens na lista! Isto afeta o índice que você usará para fazer a chamada da engine e futuras alterações desses arquivos no jogo. Na ordem que inserimos, a chamada da engine seria feita da seguinte forma:
 this.graphicsEng.addSprite(s[0]); //adiciona o background  
 this.graphicsEng.addSprite(s[1]); //adiciona a sprite  

  • Se você não quiser memorizar quais são os índices que correspondem a cada arquivo, defina constantes no escopo da classe:
 public const int BACKGROUND = 0;  
 public const int CHAR1 = 1;  

  • E use - as como índice:
 this.graphicsEng.addSprite(s[BACKGROUND]); //adiciona o background  
 this.graphicsEng.addSprite(s[CHAR1]); //adiciona a sprite  
  • Neste tutorial, como usaremos poucos recursos gráficos, a definição de constantes é desprezível. Mas em jogos mais complexos, tais definições ajudam o programador a não se perder durante o processo de programação do jogo.
  • Agora o nosso código está desta forma:
1:   using System;  
2:  using System.Collections.Generic;  
3:  using System.Linq;  
4:  using Microsoft.Xna.Framework;  
5:  using Microsoft.Xna.Framework.Audio;  
6:  using Microsoft.Xna.Framework.Content;  
7:  using Microsoft.Xna.Framework.GamerServices;  
8:  using Microsoft.Xna.Framework.Graphics;  
9:  using Microsoft.Xna.Framework.Input;  
10:  using Microsoft.Xna.Framework.Media;  
11:  using Amarelo;  
12:  using Amarelo.GameEngine;  
13:  namespace testetutorial  
14:  {  
15:    ///  
16:    /// This is the main type for your game  
17:    ///  
18:    public class testetutorial : Amarelo.AmareloGame  
19:    {  
20:      public const int BACKGROUND = 0;  
21:      public const int CHAR1 = 1;  
22:      List s = new List(); //Cria uma lista de sprites  
23:      public testetutorial(GameConfig cg) : base(cg)  
24:      {  
25:        Content.RootDirectory = "Content";  
26:      }  
27:      ///  
28:      /// This is called when the game should draw itself.  
29:      ///  
30:      ///  
31:  Provides a snapshot of timing values.  
32:      protected override void Draw(GameTime gameTime)  
33:      {  
34:        GraphicsDevice.Clear(Color.CornflowerBlue);  
35:        // TODO: Add your drawing code here  
36:        base.Draw(gameTime);  
37:      }  
38:      protected override void initialize()  
39:      {  
40:        this.inputEngine.KeyPressed += tecla;  
41:        this.inputEngine.KeyReleased += teclaR;  
42:        //throw new NotImplementedException();  
43:      }  
44:      protected override void loadContent()  
45:      {  
46:        s.Add(new Sprite("backg", Content.Load("Imagens\\background_01"), 0)); //Carrega o background na lista  
47:        s.Add(new Sprite("char1", Content.Load("Sprites\\char_black"), 1)); //Carrega a sprite do personagem na lista  
48:        this.graphicsEng.addSprite(s[BACKGROUND]); //adiciona o background  
49:        this.graphicsEng.addSprite(s[CHAR1]); //adiciona a sprite  
50:      }  
51:      protected override void unloadContent()  
52:      {  
53:        //throw new NotImplementedException();  
54:      }  
55:      protected override void update(GameTime time)  
56:      {  
57:        //throw new NotImplementedException();  
58:      }  
59:    }  
60:  }  

  • Salve e teste
  • Agora essa é a nossa tela de jogo no momento: note que o seu personagem não vai cair em queda livre por enquanto. Ainda não colocamos a física do jogo, o que será feito mais adiante.


  • A seguir: captura de teclas de teclado


060 - AmareloGameEngine[1]: Esqueleto do código

Amarelo Game Engine é uma engine de desenvolvimento de jogos para XNA do grupo Interactive Digital Enterteniment [Indigente] da Universidade Federal da Bahia e pode ser baixada direto do repositório SVN do projeto [ procura no google ae... ] mediante um programa apropriado [ para usuários do Windows, recomenda - se TortoiseSVN ]. A engine é desenvolvida em C#

Todo esse tutorial será feito usando Microsoft Visual Studio 2010 Express. Lembre - se de ter instalado este programa mais o XNA.

Neste primeiro post, vamos aprender a criar um projeto no Visual Studio (a coisa mais simples do mundo) e a escrever o esqueleto do código.

1. Criando um novo projeto no Visual Studio
  • FILE // NEW PROJECT
  • VISUAL C# // WINDOWS GAME 4.0


  • No campo NAME, dê o nome do seu jogo [ "testetutorial" por exemplo ]
  • Clique em OK
  • Após tudo isso, a próxima tela deve ser similar a essa...



2. Montando o esqueleto do código
  • Baixe a engine no svn do projeto - use um programa próprio para isso [ TortoiseSVN por exemplo]
  • Na aba SOLUTION EXPLORER //SOLUTION (nome do projeto), clique com o botão direito na pasta REFENCES // ADD REFERENCE


  • Uma janela como essa se abrirá


  • Navegue até "(pasta do checkout) // AmareloGameEngine // bin // x86 // debug", selecione a dll "AmareloGameEngine.dll" e clique em OK


  • O nome AmareloGameEngine aparecerá na pasta REFERENCES



  •  Para importar outros recursos - como a engine de física ou outra engine qualquer - basta repetir os passos acima
Ao criar o projeto, o Visual Studio já gera o esqueleto do código do seu jogo. Mas para usar os recursos da AmareloGameEngine, você precisará importar duas coisas para o projeto: a engine em si e o namespace Amarelo
Agora porque importar o namespace? Sem isso, todas as funções da engine que você usar devem ser seguidas do nome Amarelo [ Amarelo.FadeInOut(), Amarelo.graphicsEngine.addSprite() ]. Com o namespace, apenas o nome da função já basta.
  • No arquivo "Game1.cs", logo nas linhas iniciais do código, existe uma lista de imports do XNA:
 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.Media;  
  • Adicione a essa lista o namespace e a engine, respectivamente:
 using Amarelo;  
 using Amarelo.GameEngine; 



  •  Troque a linha...


  •  public class Game1 : Microsoft.Xna.Framework.Game  
    

    • ...por
      public class _nome do projeto_ : Amarelo.AmareloGame  
    

    • e o nome do construtor...
     public Game1()  
    

    • por...
     public _nome do projeto_(GameConfig cg) : base(cg)
    

    • enfim apague a linha
     GraphicsDeviceManager graphics;  
    
    • Na aba SOLUTION EXPLORER // ( nome do projeto ) , clique duas vezes no arquivo "program.cs"
    • Dentro da função main adicione a linha
      Amarelo.GameConfig cg = new Amarelo.GameConfig()  
    

    • e troque a linha
      using (Game1 game = new Game1())  
    

    • ...por
      using ( _nome do projeto_ game = new _nome do projeto_(cg))   
    

    • Salve o projeto (Ctrl+S)  e teste (F5)
    • Ao tentar executar, vc deve se deparar com uma mensagem de erro similar a essa:


    • O erro reporta a não implementação dos métodos abstratos da engine. Na linha
    public class : Amarelo.AmareloGame

    • Clique com o botão direito em Amarelo.AmareloGame e selecione a opção IMPLEMENT ABSTRACT CLASS


    • Essas novas linhas aparecerão no final do código


    • Trata - se dos métodos Initialize(), LoadContent(), UnloadContent e Update(GameTime game). Elas já existem quando você cria um novo projeto no XNA. AmareloGameEngine apenas reimplementa tais métodos. Portanto as linhas de código abaixo, situadas logo após o construtor da classe são dispensáveis. Apague - as do código


         /// 
         /// 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.  
         ///   
         protected override void Initialize()  
         {  
           // TODO: Add your initialization logic here  
           base.Initialize();  
         }  
         /// 
         /// LoadContent will be called once per game and is the place to load  
         /// all of your content.  
         ///   
         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  
         }  
         /// 
         /// UnloadContent will be called once per game and is the place to unload  
         /// all content.  
         /// 
         protected override void UnloadContent()  
         {  
           // TODO: Unload any non ContentManager content here  
         }  
         ///  
         /// Allows the game to run logic such as updating the world,  
         /// checking for collisions, gathering input, and playing audio.  
         /// 
         /// 
    
    
    
    
    
    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);  
         }  
    
    •  Comente as exceções dos métodos abstratos implementados. Eles só servem para lembrar de que é você que vai implementar o código desses métodos. Essa implementação varia com o jogo.
    • Agora nós temos apenas o construtor do projeto, o método Draw(GameTime gameTime) default do projeto e os métodos abstratos da AmareloGameEngine, encerrando assim a construção do esqueleto do código
    1:  /* --- ESQUELETO Game1.cs --- */  
    2:  using System;  
    3:  using System.Collections.Generic;  
    4:  using System.Linq;  
    5:  using Microsoft.Xna.Framework;  
    6:  using Microsoft.Xna.Framework.Audio;  
    7:  using Microsoft.Xna.Framework.Content;  
    8:  using Microsoft.Xna.Framework.GamerServices;  
    9:  using Microsoft.Xna.Framework.Graphics;  
    10:  using Microsoft.Xna.Framework.Input;  
    11:  using Microsoft.Xna.Framework.Media;  
    12:  using Amarelo;  
    13:  using Amarelo.GameEngine;  
    14:  namespace <nome do projeto>  
    15:  {  
    16:    /// 
    17:    /// This is the main type for your game  
    18:    /// 
    19:    public class _nome do projeto_ : Amarelo.AmareloGame  
    20:    {  
    21:       GraphicsDeviceManager graphics;  
    22:      SpriteBatch spriteBatch;  
    23:      public <nome do projeto>(GameConfig cg) : base(cg)  
    24:      {  
    25:        Content.RootDirectory = "Content";  
    26:      }  
    27:      /// 
    28:      /// This is called when the game should draw itself.  
    29:      /// 
    30:      /// Provides a snapshot of timing values.
    31:      protected override void Draw(GameTime gameTime)  
    32:      {  
    33:        GraphicsDevice.Clear(Color.CornflowerBlue);  
    34:        // TODO: Add your drawing code here  
    35:        base.Draw(gameTime);  
    36:      }  
    37:      protected override void initialize()  
    38:      {  
    39:        //throw new NotImplementedException();  
    40:      }  
    41:      protected override void loadContent()  
    42:      {  
    43:        //throw new NotImplementedException();  
    44:      }  
    45:      protected override void unloadContent()  
    46:      {  
    47:        //throw new NotImplementedException();  
    48:      }  
    49:      protected override void update(GameTime time)  
    50:      {  
    51:        //throw new NotImplementedException();  
    52:      }  
    53:    }  
    54:  }  
    55:  /* --- ESQUELETO program.cs --- */  
    56:  using System;  
    57:  namespace __nome do projeto__
    58:  {  
    59:  #if WINDOWS || XBOX  
    60:    static class Program  
    61:    {  
    62:      /// 
    63:      /// The main entry point for the application.  
    64:      /// 
    65:      static void Main(string[] args)  
    66:      {  
    67:        Amarelo.GameConfig cg = new Amarelo.GameConfig();  
    68:        using (_nome do projeto_ game = new _nome do projeto_(cg))  
    69:        {  
    70:          game.Run();  
    71:        }  
    72:      }  
    73:    }  
    74:  #endif  
    75:  }  
    
    • Salve e teste
    • Após todos esses procedimentos, finalmente teremos uma tela azul ( não se trata da BlueScreenOfDeath ) como essa. Clique no X vermelho no canto da janela para fechar.


    quinta-feira, 13 de outubro de 2011

    059 - AmareloGameEngine

    Como já citei anteriormente, Amarelo Game Engine é a engine desenvolvida pela galera do Indigente para os jogos Amarelo e Quatro Mundos.

    Como a engine ainda está em fase de desenvolvimento, em diversos momentos encontramos dificuldades em usa - la. Quatro Mundos é praticamente um laboratório para o Amarelo: tudo aquilo que esperamos que a engine suporte mas não suporta é reportado para a equipe de desenvolvimento da engine para conserto futuro.

    Até eu tento "consertar a engine".

    Por isso como forma de documentação informal da Amarelo Game Engine, para os atuais membos do grupo e futuros indigentes, estou postando este pequeno tutorial de uso, feito com base naquilo que já deu certo.

    99% de tudo o que for postado aqui neste tutorial tem que dar certo (1% não vai dar certo porque ou está em fase de implementação ou não foi implementado).

    sexta-feira, 7 de outubro de 2011

    058 - 4 Mundos[3]: Últimas notícias da sexta

    Nessa semana, eu e Yuri travamos um combate contra o XACT, tentando usa - la no Amarelo. Basicamente tentamos fazer os efeitos de Fade In e Fade Out (aumentar/diminuir o som gradativamente). Nosso problema era acessar o volume do arquivo de audio atual e fazer esse controle. O problema já foi resolvido.

    Falta agora testar isso com os arquivos que serão usados no jogo. Fazer também que a troca de personagens gere o fade out do personagem atual simultaneamente com o fade in do personagem chamado.

    segunda-feira, 3 de outubro de 2011

    057 - SBGames2011[3] - Agora é só diversão e aprendizado

    Sabe OfeDef, uma das nossas submissões no SBGames 2011? Pois bem...

    Fail: o jogo não foi aprovado :'(

    Dessa forma, esse jogo deixa de ser conhecido do público de jogos em geral para se tornar mais uma produção no portifólio do Indigente.

    Mesmo com essa derrota [ fatality ], não vamos parar de produzir. O próprio conceito do jogo já é algo novo ( jogo de tiro com elementos do exército brasileiro, incentivo do patriotismo nacional...). Continuemos com isso até o fim!

    sexta-feira, 30 de setembro de 2011

    056 - Reabilitação + Diversão[1]: Inicio

    Há dois meses, existe no instituto de física um projeto para desenvolvimento de jogos voltados para reabilitação usando detecção de movimentos. Só um exemplo: jogar snake usando as mãos...

    Me lancei de cabeça no projeto e, ao lado de Paulo, faremos tais jogos em C++. Eu me interessei nisso porque trata - se de um projeto legal e tenho interesse em aprender C++. Só o snake já é uma realidade.

    Já comecei a instalar o básico para o projeto aqui no Indi e irei instalar isso também em casa.

    O único problema é só a demora na instalação do Qt [to escrevendo e só tem 21% de completo...]

    055 - 4 mundos[2]: Começando a programar e a tocar som

    Desde ontem [29/set] comecei a botar a mão na massa em 4 mundos usando o XNA e a GameEngine do projeto Amarelo (só para se ter uma ideia da importancia de amarelo em nosso projeto e no Indi, Amarelo já é base para alguns projetos finais aqui no grupo).

    O que consegui até o momento foi inicializar o jogo (carregar a tela de jogo, cenário, sprite do personagem) e fazer a troca de personagens. Em 4 mundos, como cada personagem possui a sua visão de mundo do cenário atual, trocar de personagem significa trocar de mundo - literalmente.

    Também fiz alguns testes com a engine de som usando XACT. Só consigo tocar um som em loop e tocar outro som a depender do cenário. Preciso relembrar como fazer isso com a engine de Amarelo. Deve ser pouca coisa para mudar.

    segunda-feira, 5 de setembro de 2011

    054 - 4 mundos: Introdução

    Desde o inicio do ano, já ha aqui no Indi alguns projetos novos de jogos: um jogo de ninja, uma dissertação sobre game design... Fui enquadrado em um jogo com uma visão de mundo diferente. Ou melhor: 4 visões de mundo diferentes.

    4 mundos - como o próprio nome diz - é uma ideia de adventure plataforma com alguns elementos de jogo. Nele, você controla um grupo de 4 estudantes: um valentão, um nerd, uma patricinha e uma espírita. Cada personagem possui uma visão diferente do mundo e o jogo se desenvolve a partir disso.

    Por exemplo: ao mesmo tempo que a patricinha ve um mundo todo cor - de - rosa, cheio de flores e criaturas fofas e insetos gigantescos ao som de Backstreet Boys, o valentão veria um mundo em chamas, com feras selvagens e insetos minúsculos (os mesmos insetos gigantes da patricinha), ao som de Metallica.

    Acho que só isso da pra dar uma ideia de como será o jogo.

    Em virtude das labutas dos membros do Indi com a UFBA, quase não dedicamos tempo para este projeto. Até agora.

    Já tivemos algumas reuniões sobre 4 mundos. Já definimos um deadline e as principais características dos personagens. O jogo será desenvolvido em C#, usando uma engine similar a de outro projeto daqui do grupo.

    053 - SBGames2011[2]: Estado atual de OfeDef

    Faltando 5 dias para a divulgação dos aprovados pela comissão do evento, a atualização de OfeDef continua de vento em popa. Vale destacar aqui o nosso progresso atual.

    Inicialmente, aproveitamos nossos projetos anteriores (em especial, Space Invaders e a modelagem da sala 136) para criar uma zona de testes para este novo projeto.

    Ja contei na postagem anterior da equipe envolvida nessa jornada: Flavio Conterato deu a ideia do jogo (fortalecida pela sua experiência no exército). Anderson Sampaio, nosso modelador de todas as horas,
    fez o terreno, o personagem principal, o tiro e um ensaio de mob (o soldadinho que você, jogador, terá de matar), alem da programação básica do jogo e da animação da logomarca do jogo. Eu venho prestando suporte em algumas partes da programação que Anderson teve algum tipo de dificuldade. Direto da Escola de Belas Artes da UFBA, Alexia Corujas já contribuiu com a logo do jogo e uma ideia inicial de interface in game.

    Também tivemos a ajuda de alguns membros do Indigente que deram as suas contribuições ao projeto - em especial Phillipe Yuri [ nossa bússola mestra nos momentos mais difíceis :) ].

    O que temos no momento:
    • Um ensaio de terreno de jogo
    • Um ensaio de pistola de prata
    • Um ensaio de mob - uma bola para ser mais específico
    • Um ensaio de gerador de mobs - um cubo voador que cospe bolinhas que andam na sua direção
    • Um ensaio de GUI (Graphic User Interface - a interface in game do jogador: o score atual, quantas balas o jogador ainda possui...)
    A meta agora é passar todos esses ensaios para o que efetivamente será OfeDef. O terreno, a pistola e a bala da pistola que realmente serão usados no jogo, isso já temos. Falta ainda aprimorar a GUI, transformar o mob em um soldado de verdade (ao invés de uma bola) e o gerador de mobs em um helicóptero, um caminhão, um avião bombardeiro (ao invés de um cubo que gera mobs like Minecraft :p ).

    quinta-feira, 25 de agosto de 2011

    052 - SBGames 2011[1]: Challenge acepted

    Depois de um tempão (mais um tempão) sem fazer quase nada aqui no indi, fui - digamos - alocado para mais um projeto na casa.

    Idealizado por Flavio Conterato e desenvolvido por Anderson Sampaio e eu, OfeDef (OFEnsiva DEFensiva) é um projeto desenvolvido em Unity3D que já foi submetido para o SBGames deste ano. Resumindo a história: o jogo é uma mistura dos gêneros tower defense e survival. Você começa na base de uma montanha e tem que matar os soldados inimigos que se aproximam.

    Atualmente estão no projeto: Flávio Conterato [ideia do jogo e pitacos no projeto], Anderson Sampaio [animação e programação], Alexia Corujas [arte] e eu [programação].

    Como o jogo já foi submetido, apenas aguardo resposta sobre a aprovação do jogo pela comissão do evento. Logo, torçam por todos nós :)

    Maiores informações podem ser obtidas no site do evento que acontecerá aqui em Salvador. \o/

    http://www.sbgames.org/sbgames2011/


    segunda-feira, 6 de junho de 2011

    051 - Trabalhando no novo Q.G

    Desde o dia 01/jun, o Indigente já trabalha em seu novo Q.G (um cubículo), como sempre ao lado da InfoJr (outro cubículo vizinho), dentro da sala 155.

    Dividindo o tempo entre os inumeros trabalhos de final de semestre e o Indigente, postarei em breve as novidades dos meus projetos atuais.

    Boa sorte para a gente nesta era das trevas - até a gente conseguir uma nova casa própria (kd Sílvio nessas horas?).

    terça-feira, 24 de maio de 2011

    050 - Deixando Space Invaders jogável

    Depois de muito tempo parado, Anderson me convenceu a retomar o Space Invaders, aquele projeto que nos fez entrar n Indigente, agora com o nome de Remake Invaders.

    Nossa meta é deixar o jogo mais bonitinho e jogável. Faremos o jogo do zero. Usaremos os mesmos modelos e reescreveremos os scripts do jogo antigo (agora em C# por questões de desempenho).

    Eu acredito que possamos gerar no mínimo dois tutoriais. Um tutorial sobre a programação do jogo e o outro sobre a modelagem dos modelos. Os dois tutoriais teriam versão para o blog (em linguagem mais informal) e para a comunidade acadêmica (em linguagem mais formal e voltado para eventos sobre jogos, como o SBGAMES).

    quarta-feira, 18 de maio de 2011

    049 - 1 ano de Indigente: presente para toda a galera!

    Nesse aniversário de 1 ano do blog, o presente vai pra todos vocês, mas não será de minha parte.

    Será de parte do também indigente (e grande amigo, diga - se de passagem) Anderson Sampaio.

    Como forma de deixar a todos nós uma lembrança daquilo que foi o refugio dos guerreiros no desenvolvimento de jogos, Mr. Anderson enfim lançou o release de seu modelo da sala do Indigente. Trata - se de uma réplica da sala, extremamente fiel ao original, inclusive nas medidas. Cada centímetro da sala original virou um centímetro na aplicação.

    Vale lembrar que o projeto ainda não está completo. É questão de tempo para que haja computadores, cadeiras, janela... Tudo o que realmente falta para efetivamente a simulação retratar a realidade.

    Quer ter uma ideia de onde a gente pesquisa sobre jogos? Entra no blog do manolo e veja!

    http://andersonsampaio-indigente.blogspot.com/p/pagina-teste.html

    terça-feira, 17 de maio de 2011

    048 - 1 ano de Indigente: Valeu galera :)

    Salve salve.

    Exatamente as 5:19 da tarde de 17 de maio de 2010, saia o post 000 deste blog. Inicialmente um blog de um mero calouro querendo fazer jogos em um dos grupos de desenvolvimento de jogos de maior destaque no estado, com direito a premios, pessoas renomadas trabalhando na Ubisoft e chamando a atenção da mídia em geral.

    Um ano no Indigente pra mim já significa um grande avanço em minha carreira profissional e na minha formação tanto acadêmica como pessoal. Ganhei uma nova visão dos jogos em geral graças a esse grupo. Aprendi muita coisa e, claro, fiz muita gente aprender.

    Nesse caminho para os próximos 365 dias de "Saulo Andrade - Indigente", apesar das dificuldades (o que chamo de "Era das trevas do Indigente"), pretendo aprender ainda mais e compartilhar aquilo que aprender com todos vocês.

    Valeu galera por este 1 ano de "Saulo Andrade - Indigente". De presente deixo o novo template do blog. Disfrutem com carinho.

    quinta-feira, 12 de maio de 2011

    047 - Indigente x Nova UFBA

    Salve salve.

    Desculpem pelos três meses sem postar absolutamente nada no blog. Poucos projetos em atividade, pouca coisa para fazer.

    Infelizmente volto ao blog para dar uma notícia triste.

    Para quem não sabe, desde o ano passado a Universidade Federal da Bahia passa por um processo de reforma total. Novos cursos, novas instalações, reforma do velho. Tudo isso graças a verba que o governo federal disponibilizou para as universidades federais de todo o país.

    Dentro do projeto da Nova Ufba está o projeto de reforma do Instituto de Matemática.

    Obvio que o Indigente não conseguiria escapar dessa.

    Como o nosso argumento não foi forte o suficiente para convencer a diretoria a manter a nossa sala, simplesmente a clássica 136 desaparecerá após a reforma.

    Isso não quer dizer que ficaremos sem casa - Indigentes de vez. Só teremos que rachar o aluguel com alguns outros grupos de pesquisa.

    Hoje [12/mai] recebemos a ordem de despejo. A previsão é até dia 26 nos mudarmos para o nosso futuro novo lar provisório (possivelmente a sala 155).

    Até lá, muita coisa há de acontecer. Podemos ficar na 155 eternamente, podemos recuperar a 136, podemos recuperar o prestígio de eras de outrora. Até lá rezem por mim e pelos meus colegas de grupo para que o Indigente não caia no ostracismo - vulgo esquecimento - de uma vez por todas.

    ;)

    sábado, 19 de fevereiro de 2011

    046 - Jogo em um dia 2011 [7]: Mission Complete (ou quase)

    Depois de nove horas - das quais duas tentando instalar e configurar o eclipse e o emulador do android - eu e Yuri terminamos a parte de física. Nossas classes, métodos e atributos estão todos prontos para exercer o seu trabalho no jogo. Resta - nos agora esperar as outras equipes e juntar tudo.

    Apesar dos diversos atrasos, como Jandson combatendo contra o emulador e João Victor tentando instalar o emulador - instalação essa que demora bastante, viu? - ainda creio que podemos terminar este jogo antes das nove horas.

    Ja recebi os arquivos com os assets, tudo separadinho, tudo bonitinho. Agora o trabalho é de adaptar os assets com a resolução da tela do jogo.

    045 - Jogo em um dia 2011 [6]: Registrando tudo

    Vale lembrar que todo o processo de criação de um jogo em um dia tem como principal objetivo escrever um artigo sobre como é o processo de desenvolvimento de um jogo em um dia.

    Neste momento temos João e Anderson fazendo entrevistas com a galera, buscando saber dessas coisas. Eu e
    Yuri fomos chamados.

    Bem, voltemos para o jogo. Estamos no estagio de detectar as colisões entre componentes estáticos e dinâmicos. É uma comparação entre elementos de arrays: pega o elemento do array estático, compara com cada elemento do array dinâmico. A pesquisa continua a base de muito rock n' roll para animar o ambiente.

    044 - Jogo em um dia 2011 [5]: A gravidade no kibe

    Uma coisa legal no estudo da gravidade do kibe é que não há a necessidade de a gente se preocupar com todas as definições de soma vetorial.

    Isso porque foi assim que os vetores foram definidos: vetor (x, y) onde x e y representam os modulos dos versores do vetor. Daí o vetor final é obtido supondo a soma vetorial tradicional.

    E a soma vetorial que será feita aqui toma como base apenas somar cada x e cada y de cada vetor.

    No nosso caso, só vamos fazer a soma de um vetor qualquer com o vetor gravidade. O modulo do vetor também tem que ser adaptado com o tempo por questões de aceleração.

    043 - Jogo em um dia 2011 [4]: A física do kibe

    A meta agora é desenvolver a física do jogo em geral. A visualização do jogo será similar a da primeira versão de Prince of Persia (câmeras diferentes para cenários diferentes).

    Estamos travados na implementação de vetores em Java. Precisamos criar uma classe específica para trabalhar com vetores. Depois de resolvido isso, poderemos pensar em uma forma de o jogo analisar as colisões apenas na area exibida na tela.

    Começo a perceber que física em jogo é algo bastante abstrato. Teremos de criar uma função que verifique se cada sprite colide com a outra. Dividimos entre estaticos e dinâmicos: os estáticos nunca colidem entre si, bastando apenas verificar se os dinâmicos colidem entre si e se cada estático colide com ao menos um dinâmico.

    042 - Jogo em um dia 2011 [3]: A colisão do kibe

    Eu e Yuri terminamos enfim a parte de colisão. Percebi a necessidade de criar diversas classes para diversos tipos de colisão: circulo + retangulo, retângulo + retangulo, circulo + circulo. Isso sem falar na imensa quantidade de fórmulas matemáticas envolvidas, o que finalmente justifica a necessidade de se estudar matemática em ciência da computação.

    Cabe agora completar a parte de física dentro da tela de jogo.

    041 - Jogo em um dia 2011 [2]: Primeiros passos no android

    Depois de tres horas lutando para conseguir o emulador do android e o eclipse pronto para programar, está na hora de brincar com a física do jogo.

    Pelo o que eu sei, será basicamente determinar os pontos de colisão. Mas antes, tentarei me familiarizar com a programação para o android.

    Yuri ta me ajudando com a parte de fisica. Também dando noções sobre programação orientada a objeto. To começando a tentar entender as diferenças entre programação orientada a objeto com java e programação usando C. Métodos, classes, atributos, muitas diferenças.

    Creio q essa foi uma dos meus maiores choques com a transição de C para java, apesar de ter uma pequena experiência com JavaScript em Unity: metodos dentro de classes, os padrões de declaração e a implementação das variaveis. A diferença entre privado, protegido e público. E outras coisas que ainda terei que me adaptar com o tempo.

    040 - Jogo em um dia 2011 [1]: Inicio de uma pequena reunião

    Hoje [19/fev] temos uma galera na sala 136 do indigente. Alem de mim temos Anderson Sampaio, João Costa, Elder, Sousa, Phillipe Yuri, Fagner, Luísa Lopes, Paulo, João Victor, Caio Thiago, Nanci Bonfim, Jandson Nunes [outro homem depois de formado]...

    Esses são os guerreiros que ficarão nesta sala, e em outra por causa de espaço, fazendo o jogo do kibe, ou melhor, "Kibe's Escape", que é o nome do tão aclamado jogo a ser feito em um dia nas diversas areas: audio, programação, design, etc.

    É tanta gente aqui na sala q a gente vai usar outra sala para trabalhar.

    sexta-feira, 11 de fevereiro de 2011

    039 - O primeiro projeto de 2011 será muito rápido

    Salve, salve, galera!
    Depois de um ano novo regado a Pink Floyd e Samba, um mês de janeiro contubardo pra mim por causa das aulas do curso de verão, chegou a hora de arranjar mais um pouco de tempo para atualizar este belo espaço do programador de jogos da Bahia.

    Dia 19 de fevereiro teremos um evento bem massa aqui no Indigente: o jogo de um dia.

    Já definimos em reunião prévia os rumos para a criação de um joguinho para Android. Enredo simples para um jogo simples: um kibe que foge de facas. Uma vez definido o jogo, a história e quem fara o que, teremos o desafio de fazer este jogo unica, e exclusivamente, no dia 19. É por isso que será um JOGO DE UM DIA.

    Todas as descobertas durante o desenvolvimento desse jogo serão documentados neste blog - pelos menos aquilo que eu descobrir - e serão tema de artigos desenvolvidos por membros do grupo. É esperar para ver.