Mostrando postagens com marcador Games. Mostrar todas as postagens
Mostrando postagens com marcador Games. Mostrar todas as postagens

domingo, 7 de agosto de 2011

MANIFESTO ANDROID

    Eu me chamo Cleverton Heusner, tenho 29 anos, sou aficionado por tecnologia e vou falar um pouco do meu relacionamento com Java.
    Moro no sul do Pará há muitos anos e em 2008, comecei a estudar Java. Nessa época, trabalhava em um escritório de contabilidade durante o dia e à noite cursava Análise de Sistemas, com sua grade curricular tapa-buracos. Eu sempre queria estar a sós com minha bíblia de Java e conhecer cada vez mais a linguagem.
    O tempo livre dedicado a praticar tudo o que eu lia sobre Java era relativamente curto. Logo, eu me contentava com códigos simples. Tudo em que pensava era desenvolver games e aplicativos para celulares profissionalmente. O mercado de softwares onde moro é nulo, mas não dei bola.
    A formatura se aproximava e logo eu teria mais tempo para um segundo e apetitoso livro que me esperava. Era sobre desenvolvimento de games pra celulares com JavaME.
    Depois de me socializar com algumas novas ferramentas e avançar algumas páginas no novo livro, eu estava pronto para exibir um personagem na tela e fazê-lo reagir a meus comandos. Quando consegui isso, só posso dizer que foi uma das maiores alegrias que já senti. Passei o build para um celular que tinha comprado apenas pra isso e comecei a exibir aquela façanha para todos em minha volta, ignorando se tinham ou não algum interesse pelo assunto.
    Essa experiência melhorou o ritmo de meus estudos. Eu acompanhava reportagens sobre o mercado de games com ansiedade, pois sabia que ainda não estava pronto. Quando esse momento chegasse, eu deveria estar preparado para deixar a cidade.
    Aos poucos, eu ia me dando conta do quão complexo e extenso era o código de um game, ainda que simples. Queria programar um jogo completo não apenas por prazer e conhecimento, mas porque eu precisava de um portfólio.
    Como precisava de mais tempo, fiz uma aposta arriscada e deixei meu emprego. Agora eu teria alguns meses para criar um game.
    Por aspirar a uma vaga de programador, priorizei o código. Os gráficos e sons peguei emprestados de games antigos, já que não contava com um artista. Não havia pra mim jeito mais divertido de se exercitar Java.
    A meta inicial era um game completo. Porém, já havia se passado três meses e eu tinha programado apenas uma fase. Como não me restava muito tempo, resolvi usar aquele simples e suado demo como portfólio. Filmei a gameplay e publiquei no youtube. Logo em seguida, corri para comunidades, blogs e fóruns pedindo críticas. Para minha surpresa, a maioria delas foi calorosa e até consegui formar contatos com os mesmos interesses.
    Meu próximo passo era contatar estúdios no Brasil, na esperança de uma oportunidade. Antes que eu fizesse isso, uma empresa gringa achou meu trabalho no youtube e me convidou a participar de projetos como freelancer. Agora eu tinha em mãos o que queria, mesmo morando no fim do mundo. Embora se tratasse de trabalho, eu estava agora em um ambiente nerd e interativo. Era meu primeiro projeto real, o que me levou a buscar muitos conhecimentos que me faltavam, amadurecer meu espírito de equipe e de quebra, afiar o inglês.
    Um mês depois, tudo ainda ia bem. Era agosto, quando começa a chover nesta região. O que eu não lembrava é que os serviços de energia elétrica e internet são duramente castigados por aqui em períodos de chuva. Blackouts e quedas de conexão passaram a comprometer drasticamente o ritmo do trabalho.
    Após muitos atrasos, o projeto finalmente havia chegado à fase de porting, na qual um mesmo aplicativo precisa ser testado em vários celulares diferentes. Por diversas vezes, enquanto o tester me reportava algum bug em determinado aparelho, a net e/ou a energia elétrica resolvia me deixar na mão.
    Como eu seria pago apenas após a conclusão do game, aquela experiência estava se tornando cara, apesar de todo o conhecimento adquirido até então. Fui obrigado a deixar o grupo e procurar por uma oportunidade similar no Brasil, mas desta vez bem longe do Pará.
    Agora eu tinha a engine completa para um game como portfólio. Infelizmente, o visual e a trilha sonora não pertenciam a mim. Antes de me unir ao grupo que acabara de deixar, conheci um artista promissor enquanto divulgava meu demo. Embora focado em arte 3D, substitui toda a carcaça 2D de forma brilhante.
    Lembro que quando havia finalizado o game oficial, sua velocidade deixava a desejar em certos aparelhos, mesmo com imagens e sons otimizados ao máximo. Suspeitei que devesse melhorar o código, mas não sabia onde. Enquanto Juliano se ocupava com a arte, eu li o que pude sobre técnicas de otimização de código. Depois de uma semana lapidando o código com base no que havia estudado, tive uma surpresa. A velocidade do game havia aumenado de forma esmagadora, me ensinando o efeito do código sobre a mesma.
    Após algumas pesquisas, vi o quanto a demanda por JavaME tinha diminuído. Eu entendi que precisaria dominar Android ou iPhone. Há quatro meses, tenho estudado e praticado a plataforma Android. Minha simpatia pelo Android me levou a erguer este blog, que inicialmente será um portfólio. Com o tempo, pretendo fazer deste lugar um grande acervo de artigos cobrindo o desenvolvimento Android, aspectos da linguagem Java e a criação de games unindo estas duas armas.
    Este é meu primeiro blog e seu visual está um tanto capenga, mas irei melhorar. Só peço que leiam e comentem os artigos. Abaixo, arte e video de Juliano Silveira para o game de celular Cura em Gaia, que desenvolvemos a partir de minha antiga engine, a qual futuramente adaptaremos para Android.

Arte promocional de Cura em Gaia, game pra celulares em J2ME


Gameplay de Cura em Gaia

    Você pode ficar a par de outros trabalhos de Juliano Silveira acessando os links abaixo:

terça-feira, 2 de agosto de 2011

Recuperando e Lendo Arquivos de um Cartão de Memória - PARTE 3

01. private final void tocarMusica(String dirArq)
02. {
03.     ProgressBar splash = new ProgressBar(this);
04.
05.     setContentView(splash, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
06.
07.     try
08.     {
09.         player.setDataSource(dirArq);
10.         player.prepare();
11.         player.setLooping(true);
12.         player.start();
13.     }
14.     catch (Exception e)
15.     {}
16. }

Seguiremos para o método que toca uma música, caso o arquivo escolhido na tela anterior esteja no formato sonoro.  A classe ProgressBar é novidade aqui. Sua finalidade original é servir de splash nas aplicações, informando o usuário sobre o andamento de um processo. Como achei sua animação bastante parecida com a de um tocador de músicas, resolvi apresentá-la na tela enquanto rola a faixa. Assim como aconteceu com ImageView, ProgressBar também irá ocupar a tela toda:

Objeto ProgressBar ocupando toda a tela
    As linhas 07-15 correspondem ao código que tocará a música. Antes de tudo, lembremos que player é uma instância de MediaPlayer(), que foi definida como global nesta classe. Mais adiante você entenderá por que não a declaramos localmente. 
    O método setDataSource(dirArq) diz ao player onde está o arquivo, que nada mais é que o diretório passado pela Activity inicial. O método prepare() avisa ao player que tudo está pronto para que a faixa seja tocada. Sempre chame este método antes de tocar a música. O método  setLooping(true) é opcional  e serve para reproduzir a música continuamente. Por fim, reproduzimos a música com start(). Por uma questão de simplicidade, não foi fornecido um tratamento adequado das possíveis exceções disparadas caso houvesse erro na reprodução da mídia.


REPRODUZINDO O VIDEO

01. private final void reproduzirVideo(String dirArq)
02. {
03.     VideoView video = new VideoView(this);
04.     video.setVideoPath(dirArq);
05.     video.setMediaController(new android.widget.MediaController(this));
06.     video.start();
07.
08.     setContentView(video);
09. }

A próxima parada será no método que reproduz um vídeo na tela. Embora seja possível fazê-lo com a classe MediaPlayer, usaremos uma específica pra isso.
Após criar um objeto de VideoView, nós lhe indicamos a localidade do arquivo de vídeo. O método setMediaController(MediaController controles) , embora opcional, é importante, pois insere abaixo do vídeo botões para reproduzi/pausar e avançar/retroceder o vídeo. Finalmente, chamamos start() para iniciar a reprodução, como ocorre com MediaPlayer().
VISUALIZANDO O TEXTO

01. private final void visualizarTexto(String dirArq)
02. {
03.     try
04.     {
05.         FileInputStream textoLeitura = new FileInputStream(new java.io.File(dirArq));
06.
07.         byte[] textoTemp = new byte[textoLeitura.available()];
08.
09.         try
10.         {
11.             int index = 0;
12.             int c = 0;
13.
14.             while((c = textoLeitura.read()) != -1)
15.             {
16.                 textoTemp[index++] = (byte)c;
17.             }
18.
19.             textoLeitura.close();
20.         }
21.         catch (Exception e)
22.         {
23.             e.printStackTrace();
24.         }
25.
26.         ByteArrayInputStream bais = new ByteArrayInputStream(textoTemp);
27.         DataInputStream dis = new DataInputStream(bais);
28.         char[] chars = new char[textoTemp.length];
29.
30.         try
31.         {
32.             int index = 0;
33.             int c = 0;
34.
35.             while((c = dis.read()) != -1)
36.             {
37.                 chars[index++] = (char)c;
38.             }
39.
40.             bais.close();
41.             dis.close();
42.         }
43.         catch (Exception e)
44.         {
45.             e.printStackTrace();
46.         }
47.
48.         TextView texto = new TextView(this);
49.         texto.setText(new String(chars));
50.
51.         LinearLayout layout = new LinearLayout(this);
52.         layout.addView(texto);
53.         ScrollView scroll = new ScrollView(this);
54.         scroll.addView(layout);
55.         setContentView(scroll);
56.     }
57.     catch (Exception e)
58.     {}
59. }

    O método que mostra o texto na tela merece maior atenção, principalmente por lidar com fluxos, parte melindrosa do Java.
    A primeira coisa a fazer é extrair do arquivo de texto seu conteúdo em forma de fluxo de bytes para entrada. A classe FileInputStream, filha de InputStream, é a indicada para extrair armazenar esse stream. Depois, precisaremos de um array de bytes que virá a armazenar esse fluxo.
    FileInputStream, através do método read(), tem o poder de ler dado por dado o fluxo que
armazena, retornando um valor inteiro que representa cada dado. Este inteiro, após ser 
convertido em byte, passará a ser armazenado pelo vetor de bytes, que nos interessará em
breve. Quando FileInputStream retornar -1, significa que chegou ao final de seu fluxo. É
importante fechá-lo depois com close(), fazendo que com que seus recursos sejam liberados
da memória.
    Daqui, nós poderíamos saltar para a linha 48, passando para o construtor da String o array de bytes já alimentado. Conseguiríamos exibir o texto? Sim. No entanto, se esse texto contiver caracteres acentuados, esse será o resultado:

Leitura imprecisa de um arquivo de texto
    
    Para evitar isso, faremos uso das classes ByteArrayInputStream e DataInputStream. Funciona assim: ByteArrayInputStream recebe em seu construtor o array de bytes criado anteriormente. Depois, instanciamos um DataInputStream, utilizada para ler tipos específicos de dados a partir de  um fluxo de bytes, tais como booleanos, strings e caracteres. Ela recebe no construtor a referência a ByteArrayInputStream, da qual lerá o texto. O método de leitura é idêntico ao loop anterior e também é necessário liberar os recursosde cada um com close().
    Agora temos um array de caracteres acentuados que compõe o texto que será exibido. Ocomponente TextView(), apresentado agora, é muito útil para exibir texto na tela. Depois de instanciá-lo, configure o texto que ele irá mostrar com o método setText()dando-lhe o array de caracteres que acabou de encontrar.
    Desta vez, ao invés de exibir o View diretamente, adicionaremos ele a um LinearLayout().  Essa classe atua como um contêiner que, além de abrigar componentes, controla como estes serão exibidos.
    Você deve ter se perguntado o que acontecerá se a tela não for grande o bastante para
abrigar o texto. Felizmente podemos contar com a famosa barra de rolagem, representadano Android pela classe ScrollView. Uma vez criada, você pode adicionar a ela um View, seja ele um componente ou um layout. Como o TextView que exibirá o texto está dentro de umLinear Layout, nós usaremos o método add(View view) para adicionar o layout ao ScrollView. Finalmente, o método setContentView(View view) recebe a instância de ScrollView, que guarda LinearLayout, que por sua vez guarda o TextView. Eis como o texto será apresentado desta vez:

Leitura correta de um arquivo de texto
   
A prática comum é que se escreva a interface gráfica das aplicações em arquivos XML à
parte, tornando o código Java mais limpo e permitindo uma separação lógica entre o visual e o comportamento da aplicação. Porém, haverá situações em que é mais conveniente criar o layout da aplicação dinamicamente, isto é, com puro Java. 

FINALIZANDO A ACTIVITY

01. @Override
02. protected final void onDestroy()
03. {
04.     if(formato == MUSICA)
05.     {
06.         player.release();
07.     }
08.
09.     super.onDestroy();
10. }

    Chamaremos a atenção para o método onDestroy(). Ele faz parte do ciclo de vida de uma Activity, sendo chamado implicitamente quando uma Activity é finalizada ou quando o provocamos através de finish(). A razão de termos sobrescrito esse método aqui é para liberar os recursos alocados pelo player de música, caso a Activity tenha sido invocada para reproduzir uma música. Assim como ocorre com fluxos e conexões, você precisa de um método próprio pra liberar os recursos alocados. Neste caso você chama release().


Dados.Java

INTERFACE COMO REPOSITÓRIO DE CONSTANTES

01. public interface Dados
02. {
03.     static final int MUSICA = 0;
04.     static final int VIDEO = 1;
05.     static final int IMAGEM = 2;
06.     static final int TEXTO = 3;
07. }

Um uso pouco comum para uma interface é usá-la como repositório de constantes que são
compartilhadas por diferentes classes da aplicação. Embora quatro constantes possam não ser uma desculpa para armazená-las em uma interface, pode haver situações em que diversas classes irão ter em comum um grande número de constantes, como em um game, tipo de app mais popular atualmente para Android. Há alguns meses, desenvolvendo meu primeiro game em J2ME (confira video no final do artigo), tinha em mãos oito classes que compartilhavam um bom número de constantes, que envolviam desde estados do game e dos inimigos até dimensões de imagens. Ao organizar quase cem constantes em uma única interface, além de tornar as outras classes  mais legíveis, boa parte do código passou a ter uma manutenabilidade centralizada.