UNIVERSIDADE DO ESTADO DO AMAZONAS - UEA ESCOLA SUPERIOR DE TECNOLOGIA ENGENHARIA DE COMPUTAÇÃO GEORGE DA ROCHA MEDEIROS NUNES DESENVOLVIMENTO DE UM JOGO DE DOMINÓ PARA ANDROID Manaus 2011 GEORGE DA ROCHA MEDEIROS NUNES DESENVOLVIMENTO DE UM JOGO DE DOMINÓ PARA ANDROID Trabalho de Conclusão de Curso apresentado à banca avaliadora do Curso de Engenharia de Computação, da Escola Superior de Tecnologia, da Universidade do Estado do Amazonas, como pré-requisito para obtenção do tı́tulo de Engenheiro de Computação. Orientador: Prof. M. Sc. Jucimar Maia da Silva Júnior Manaus 2011 ii Universidade do Estado do Amazonas - UEA Escola Superior de Tecnologia - EST Reitor: José Aldemir de Oliveira Vice-Reitor: Marly Guimarães Fernandes Costa Diretor da Escola Superior de Tecnologia: Mário Augusto Bessa de Figueirêdo Coordenador do Curso de Engenharia de Computação: Danielle Gordiano Valente Coordenador da Disciplina Projeto Final: Raimundo Corrêa de Oliveira Banca Avaliadora composta por: Data da Defesa: 16/12/2011. Prof. M.Sc. Jucimar Maia da Silva Júnior (Orientador) Prof. M.Sc. Tiago Eugênio de Melo Prof. M.Sc. Antenor Ferreira Filho CIP - Catalogação na Publicação N972d NUNES, George Densenvolvimento de um jogo de dominó para Android / George Nunes; [orientado por] Prof. MSc. Jucimar Maia da Silva Júnior - Manaus: UEA, 2010. 61 p.: il.; 30cm Inclui Bibliografia Trabalho de Conclusão de Curso (Graduação em Engenharia de Computação). Universidade do Estado do Amazonas, 2011. CDU: 004 iii GEORGE DA ROCHA MEDEIROS NUNES DESENVOLVIMENTO DE UM JOGO DE DOMINÓ PARA ANDROID Trabalho de Conclusão de Curso apresentado à banca avaliadora do Curso de Engenharia de Computação, da Escola Superior de Tecnologia, da Universidade do Estado do Amazonas, como pré-requisito para obtenção do tı́tulo de Engenheiro de Computação. Aprovado em: 16/12/2011 BANCA EXAMINADORA Prof. Jucimar Maia da Silva Júnior, Mestre UNIVERSIDADE DO ESTADO DO AMAZONAS Prof. Tiago Eugênio de Melo, Mestre UNIVERSIDADE DO ESTADO DO AMAZONAS Prof. Antenor Ferreira Filho, Mestre UNIVERSIDADE DO ESTADO DO AMAZONAS iv Agradecimentos Agradeço a Deus, por permitir que eu desenvolvesse esse trabalho de conclusão de curso. Ao meus pais, Mário César e Maria Julieta, por terem me dado condições de cursar uma universidade estadual. Ao professor Jucimar Júnior pela compreensão, paciência e aceitar ser orientador desta monografia. Aos meus amigos de Engenharia da Computação, Bruno Mendes, Clarice Souza, Emiliano Firmino, João Guilherme, Victor Kaleb e Yasmine Souza que me acompanharam desde a metade final do curso e sempre me apoiaram e não me deixaram desistir. E ao Igor Jacaúna Martins, designer que fez a arte do jogo. v Resumo Esta monografia descreve o desenvolvimento de um jogo de dominó para Android, um jogo popular no Amazonas onde é jogado com regras especı́ficas que o tornam mais interessante. Palavras Chave: jogo, dominó, Android, Amazonas. vi Abstract This thesis describes the development of a domino game for Android, a popular game on Amazonas where it is played with specific rules that make it more interesting. Key-words: domino, game, Android, Amazonas. vii Sumário Lista de Figuras ix Lista de Códigos ix 1 Introdução 1.1 Objetivo . . . . . 1.1.1 Geral . . . 1.1.2 Especı́ficos 1.2 Justificativa . . . 1.3 Metodologia . . . . . . . . 1 2 2 2 2 3 . . . . . . . . . . . . 4 4 5 6 7 8 8 9 10 10 11 12 13 3 Dominó 3.1 História . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Modalidade Amazonense . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 15 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Android 2.1 História . . . . . . . . . . . . . . . . . . . . . 2.2 Open Handset Alliance . . . . . . . . . . . . . 2.3 Licença . . . . . . . . . . . . . . . . . . . . . 2.4 Fragmentação . . . . . . . . . . . . . . . . . . 2.5 Segurança . . . . . . . . . . . . . . . . . . . . 2.6 Caracterı́sticas . . . . . . . . . . . . . . . . . 2.7 Arquitetura . . . . . . . . . . . . . . . . . . . 2.7.1 Kernel . . . . . . . . . . . . . . . . . . 2.7.2 Runtime e Dalvik . . . . . . . . . . . . 2.7.3 Bibliotecas de Sistema . . . . . . . . . 2.7.4 Camada de Aplicação . . . . . . . . . . 2.8 O Kit de Desenvolvimento de Software (SDK) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . viii 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.2.10 Inı́cio . . . . . Saı́da . . . . . Jogada . . . . Bucho . . . . Pontuação . . Passe . . . . . Galo . . . . . Batida . . . . Jogo fechado Fim do jogo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 17 18 18 19 20 20 21 21 21 . . . . . 22 22 23 25 30 44 5 Conclusão 5.1 Trabalhos futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 48 Referências Bibliográficas 49 6 Apêndice 50 4 Desenvolvimento 4.1 Projeto . . . . . . . . . . 4.1.1 Interface Gráfica 4.2 Modelagem . . . . . . . 4.3 Codificação . . . . . . . 4.4 Imagens do jogo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix Lista de Figuras 2.1 Arquitetura do Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.1 3.2 3.3 3.4 3.5 3.6 Peças do jogo de dominó . . . . . . . . . . . . . . . . . . . . . . . . . . . . Inicio de uma partida na modalidade Amazonense de dominó . . . . . . . . Saı́da em uma partida na modalidade Amazonense de dominó . . . . . . . Jogada em uma partida na modalidade Amazonense de dominó . . . . . . Jogada no “bucho” em uma partida na modalidade Amazonense de dominó Placar da partida após as jogadas da figura 3.4 e da figura 3.5 . . . . . . . 15 17 17 18 19 20 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12 4.13 4.14 4.15 4.16 Idéia inicial da tela de jogo . . . . . . . . . . . . . . . . . . . . . . . Printscreen da interface Sony Ericsson Xperia Android 1.6 e 2.1 . . Esboço da tela de jogo . . . . . . . . . . . . . . . . . . . . . . . . . Diagrama de fluxo de telas do jogo Dominó Manaus . . . . . . . . . Diagrama de Casos de Uso do jogo Dominó Manaus . . . . . . . . . Diagrama de Atividades do jogo Dominó Manaus . . . . . . . . . . Diagrama de Classes do jogo Dominó Manaus . . . . . . . . . . . . Tela de menu principal e tela de inı́cio de jogo (saı́da) . . . . . . . . Vez do jogador humano e jogada inicial da 1a partida . . . . . . . . Vez do jogador máquina e tela de jogo fechado . . . . . . . . . . . . Recomeço de jogo fechado pela dupla adversária e jogada no bucho Jogada de carroça marcando 5 pontos . . . . . . . . . . . . . . . . . Tela de garagem e nova partida iniciada pelo jogador que bateu . . Jogador humano sem jogada (só pode passar) e tela de pause . . . . Tela de fim de jogo e paginação do placar . . . . . . . . . . . . . . . Tela de créditos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 24 24 25 26 27 29 44 44 45 45 45 46 46 47 47 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x Lista de Códigos 4.3.1 AndroidManifest.xml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 4.3.2 Classe DominoManausGame.java . . . . . . . . . . . . . . . . . . . . . . . 32 4.3.3 Classe LoadingScreen.java . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 4.3.4 Classe Assets.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 4.3.5 Classe MainMenuScreen.java . . . . . . . . . . . . . . . . . . . . . . . . . 35 4.3.6 Atributos e Construtor da Classe GameScreen.java . . . . . . . . . . . . . 37 4.3.7 Método de update da Classe GameScreen.java . . . . . . . . . . . . . . . . 38 4.3.8 Método present da Classe GameScreen.java . . . . . . . . . . . . . . . . . . 38 4.3.9 Método updateSaida da Classe GameScreen.java . . . . . . . . . . . . . . . 39 4.3.10Método saida da Classe Jogo.java . . . . . . . . . . . . . . . . . . . . . . . 39 4.3.11Método update da Classe Jogo.java . . . . . . . . . . . . . . . . . . . . . . 40 4.3.12Método desenhaPartida da Classe GameScreen.java . . . . . . . . . . . . . 41 4.3.13Método updateFechado da Classe GameScreen.java . . . . . . . . . . . . . . 42 4.3.14Método updateGaragem da Classe GameScreen.java . . . . . . . . . . . . . 43 Capı́tulo 1 Introdução O dominó é um jogo de mesa tradicional no Amazonas, onde é disputado de maneira peculiar, com caracterı́sticas e termos próprios. Por exemplo, as peças (ou pedras, como são chamadas) recebem nomes de acordo com a quantidade de pontos: 0 pontos - “branco”, 1 ponto - “ás”, 2 pontos - “duque”, 3 - “terno”, 4 - “quadra”, 5 - “quina” e 6 - “sena”. Pedras com as duas pontas iguais são chamadas de “carroça”. Na modalidade Amazonense, as partidas são disputadas por quatro participantes, que formam duas duplas e sentam em posições alternadas. A primeira partida é iniciada com a carroça de sena. É possı́vel jogar nas 4 pontas da pedra inicial. Os pontos devem ser múltiplos de 5. O passe concede 20 pontos aos adversários. Ganha o jogo a dupla que fizer 200 ou mais pontos. Em 2011 foi realizada a 4a edição da Copa A Critica de Dominó, evento promovido pela Rede Calderaro de Comunicação e que tem por finalidade incentivar a prática do esporte, que estimula o raciocı́nio lógico e proporciona integração e confraternização entre os participantes, conforme [Crı́tica2011]. O evento contou com a participação de 216 duplas e tinha como premiação a quantia de R$20.000,00 para a dupla 1a colocada e de dois freezers cheios de cerveja para os 2os colocados. Objetivo 1.1 1.1.1 2 Objetivo Geral Desenvolver um jogo de dominó para Android. 1.1.2 Especı́ficos • Design da GUI do jogo de dominó. • Engine básica do jogo de dominó. • Engine completa da modalidade Amazonense do jogo de dominó. • Nı́vel de dificuldade iniciante. • Nı́vel de dificuldade intermediário. 1.2 Justificativa Com a intenção de padronizar uma plataforma livre e de código aberto para celulares e atender às expectativas e tendências do mercado atual, empresas lı́deres em tecnologia móvel formaram um grupo chamado Open Handset Alliance (OHA). O grupo, liderado pelo Google, tem como integrantes nomes consagrados como a HTC, LG, Motorola, Samsung, Sony Ericsson, Toshiba, Sprint Nextel, China Mobile, T-Mobile, Asus, Intel, Garmim, entre outros. O resultado dessa união foi o nascimento do Android. De acordo com [Lecheta], o Android é uma nova plataforma de desenvolvimento para aplicativos móveis, baseada no sistema operacional Linux, com interface visual rica e ambiente de desenvolvimento multiplataforma. Segundo [Farago2011], em 2009 os sistemas operacionais móveis iOS e Android cresceram em 5% do mercado de games nos Estados Unidos, com um volume total de US$ 500 milhões em vendas. Em 2010, o aumento foi de 8%. Isso representa um aumento de US$ 300 milhões em receita e equivale à metade da participação do mercado de videogames portáteis, uma concorrência para os fabricantes tradicionais. Metodologia 3 Nos dados especı́ficos para os dispositivos móveis, os números são ainda mais expressivos para os sistemas da Apple e da Google. As vendas de jogos para iOS e Android saltaram de 10% em 2009 para 32% em 2010, fazendo com que as vendas de jogos do Nintendo DS reduzissem de 70% para 57%, e no caso do PlayStation Portable, a redução foi de 11% para 9%, no mesmo perı́odo. Outro dado a ser observado é que, segundo as análises, as vendas de jogos para iOS e Android no ano passado foram maiores que as vendas de jogos para PCs, que arrecadou o volume total de US$ 700 milhões nos Estados Unidos. Os resultados dos estudos mostram que os smartphones com sistema Android e iOS estão se tornando os preferidos entre os jogadores de videogames portáteis. 1.3 Metodologia • Projetar as telas que o jogo irá possuir. • Diagramar o fluxo das telas projetadas. • Modelar o jogo de dominó utilizando UML. • Criar as classes do jogo de dominó em Java. • Montar o jogo em cima do framework. • Criar as interfaces gráficas usando o framework. • Tratar os eventos para cada tela utilizando o framework. • Executar e testar o jogo em dispositivos móveis. Capı́tulo 2 Android O Android é uma plataforma de código aberto para dispositivos móveis que inclui sistema operacional, middleware e aplicativos. 2.1 História A Android, Inc. foi fundada em Palo Alto, Califórnia, Estados Unidos, em outubro de 2003 por Andy Rubin (co-fundador da Danger), Rich Miner (co-fundador da Wildfire Communications, Inc.), Nick Sears (vice-presidente da T-Mobile) e Chris White (lı́der de projeto e desenvolvimento de interface na WebTV), para desenvolver, nas palavras de Rubin ”... dispositivos móveis mais inteligentes que conhecem melhor a localização e preferências de seus donos”. Apesar das óbvias realizações passadas de seus funcionários iniciais, a Android Inc. operava secretamente, revelando apenas que estava trabalhando em software para celulares. O Google adquiriu a Android, Inc. em agosto de 2005, tornando-a uma subsidiária da Google Inc. Funcionários-chave como Andy Rubin, Rich Miner e Chris White, permaneceram na empresa após a aquisição. Pouco se sabia sobre a Android Inc. quando ela foi adquirida, mas muitos acharam que o Google estava planejando entrar no mercado de celulares com essa aquisição. A equipe liderada por Rubin desenvolveu uma plataforma para dispositivos móveis sobre o kernel do Linux e o Google apresentou a plataforma aos Open Handset Alliance 5 fabricantes de celulares e operadoras com a premissa de ser uma plataforma flexı́vel, aberta e de fácil atualização. Especulações sobre a intenção do Google em entrar no mercado de comunicações móveis continuaram a surgir até dezembro de 2006. Houveram rumores de que o Google estaria desenvolvendo um celular com a sua marca. Especulava-se que o Google estaria definindo especificações técnicas e estava mostrando protótipos para os fabricantes de celular e operadores de telefonia móvel. Em setembro de 2007 a InformationWeek1 cobriu um estudo da Evalueserve reportando que o Google apresentou vários pedidos de patentes na área de telefonia móvel. No dia 5 de novembro de 2007, é revelada a Open Handset Alliance, um consórcio de 34 empresas de hardware, software e telecomunicações lideradas pelo Google com o objetivo de desenvolver padrões abertos para dispositivos móveis e também seu primeiro produto, o Android, uma plataforma para dispositivos móveis construı́da sobre o kernel 2.6 do Linux. Segundo [Zechner2011], desde o seu lançamento em 2008, o Android recebeu várias atualizações de versão, todas com nomes de sobremesa. Cada versão adicionou novas funcionalidades a plataforma Android, que são relevantes aos desenvolvedores de jogos de um jeito ou de outro. A versão 1.5 (Cupcake) adicionou suporte a bibliotecas nativas as aplicações Android, que antes eram restritas a serem escritas em Java puro. Código nativo pode ter muitos benefı́cios em sintuações onde o desempenho é o mais importante. A versão 1.6 (Donut) introduziu support para diferentes resoluções de tela. Na versão 2.0 (Éclair) foi adicionado suporte a telas multi-toques, e na versão 2.2 (Froyo) adicionaram a compilação just-in-time (JIT) à máquina virtual Dalvik. O JIT acelera a execução de aplicações Android, dependendo do cenário, em até 5 vezes. A versão mais atual é a 2.3, chamada de Gingerbread, que adicionou um garbage collector concorrente ao da máquina virtual Dalvik. 2.2 Open Handset Alliance Conforme [Pereira and Silva], a Open Handset Alliance consiste em todas as estruturas envolvidas no processo de telefonia móvel: 1 http://www.informationweek.com/news/201807587 Licença 6 • Operadoras de telefonia móvel: responsável pela conexão. Fornecem o serviço para o usuário final; • Fabricantes de aparelhos: responsáveis pela criação do hardware; • Empresas de semicondutores: fazem os chips dos aparelhos celulares; • Empresas de software: desenvolvem os softwares que serão executados no Android; • Empresa de comercialização: responsáveis pela divulgação, marketing e comercialização dos produtos para o usuário; Como refere [Zechner2011], muitos membros da OHA desenvolvem versões personalizadas do Android para seus dispositivos, com interface gráfica modificada - por exemplo a HTC Sense da HTC e a MOTOBLUR da Motorola. A natureza de código aberto do Android também permite que entusiastas criem e distribuam suas próprias versões do Android, chamadas de mods, firmwares ou ROMs. A mais conhecida ROM alternativa é desenvolvida por um colaborador conhecido como Cyanogen e tem como objetivo trazer as mais novas e melhores mudanças a todos os tipos de dispositivos com Android. 2.3 Licença O Android está disponı́vel sob licenças livres e de código aberto, desde 21 de outubro de 2008 até março de 2011. O Google publicou o código fonte das modificações ao kernel do Linux sob a licença GNU General Public License versão 2, e o resto do código (incluindo a pilha de rede e telefonia) sob a licença Apache versão 2. E também mantem uma lista de correções revisadas aberta publicamente para qualquer um ver e comentar. A Open Handset Alliance desenvolve a parte sob licença GPL do Android, que são as modificações ao kernel do Linux, com código fonte disponı́vel publicamente a qualquer momento. O resto do Android é desenvolvimento em particular, com código fonte liberado publicamente quando uma nova versão principal é lançada. Tipicamente o Google faz parceria com um fabricante de hardware para produzir um dispositivo carro-chefe figurando a nova versão do Android, tornando o código fonte disponı́vel depois de o dispositivo ter sido lançado. Fragmentação 7 No começo de 2011, o Google decidiu não publicar o código fonte da versão somente para tablets Honeycomb, criando dúvidas sobre seu compromisso com o código aberto do Android. A razão, segundo Andy Rubin (executivo responsável pelo Android e atual vice presidente senior do Google) em sua postagem no blog oficial do Android, foi porquê a Honeycomb foi apressada para a produção do Motorola Xoom, e eles não queriam terceiros criando uma experiência ruim para o usuário, tentando colocar em celulares uma versão que é destinada a tablets. O Google confirmou depois que o código fonte da Honeycomb não será liberado até que ela seja mesclada com a Gingerbread e lançada como Ice Cream Sandwich. Apesar de ser um software de código aberto, os fabricantes não podem usar a marca Google Android a menos que o Google certifique que o dispositivo é compatı́vel com seu Documento de Definição de Compatibilidade. Dispositivos também devem obedecer a essa definição para poderem licenciar aplicações de código fechado do Google, como o Android Market. 2.4 Fragmentação De acordo com [Zechner2011], a grande flexibilidade do Android tem um preço: empresas que optam por desenvolver suas próprias interfaces gráficas tem que acompanhar o passo do lançamento de novas versões do Android. Isso pode levar celulares lançados a alguns meses a ficarem rapidamente desatualizados já que as operadoras e fabricantes de celulares se recusam a criar atualizações que incorporem as melhorias das novas versões do Android. A fragmentação tem várias caras. Para o usuário final, significa não poder instalar e usar certas aplicações e funcionalidades por estarem encalhados em uma versão antiga do Android. Para desenvolvedores, significa que alguns cuidados tem de ser tomados na criação de aplicações que devem rodar em todas as versões do Android. Enquanto aplicações escritas para as primeiras versões do Android rodarão normal em versões novas, o inverso não é verdadeiro. Algumas funcionalidades adicionadas em versões novas do Android não estão disponı́veis em versões antigas, como o suporte ao multi-toque. Isso faz com que os desenvolvedores tenham que criar caminhos separados de código para diferentes versões do Segurança 8 Android. No caso dos desenvolvedores de jogos, a preocupação maior é com a capacidade do hardware do que com a diferença entre as APIs. 2.5 Segurança Segundo [Pereira and Silva], como é executado em um kernel Linux, toda vez que um aplicativo for instalado em um dispositivo com Android, é criado um novo usuário Linux para aquele programa, com diretórios que serão usados pelo aplicativo, mas somente para aquele usuário Linux. Como os aplicativos ficam completamente isolados uns dos outros, qualquer tentativa de acessar informações de outro aplicativo precisa ser explicitamente autorizada pelo usuário, podendo ser negada a instalação do aplicativo, ou autorizada a instalação, mas controlando as permissões que este aplicativo poderá ter através de um mecanismo de permissão. Cada processo da aplicação no Android é considerado uma sandbox, um mecanismo de segurança que separa os programas em execução em um ambiente isolado, com acesso limitado aos recursos do sistema. Só é possı́vel acessar outras aplicações caso tenha as permissões explicitamente declaradas, para que elas possam ser conhecidas desde o momento da instalação, e nada irá fazer com que sejam alteradas após isto. 2.6 Caracterı́sticas O Android não é só mais uma distribuição Linux para dispositivos móveis. Muitas vezes o programador nem chega a ter contato direto com o kernel do Linux. A face do Android vista pelo programador é uma plataforma que abstrai a camada do kernel do Linux e é programada via linguagem Java. Em uma visão de alto nı́vel, o Android possui algumas caracterı́sticas: Uma camada de aplicação que fornece um conjunto de APIs para criar vários tipos de aplicação. Também permite a reutilização e substituição de componentes fornecidos pela plataforma e aplicativos de terceiros. Arquitetura 9 A máquina virtual Dalvik, que é responsável por executar aplicações no Android e é otimizada para dispositivos portáteis. Navegador de internet baseado no motor de código aberto WebKit. Um conjunto de bibliotecas gráficas para programação 2D e 3D. Suporte multimı́dia para áudio comum, vı́deo e formatos de imagem como Ogg Vorbis, MP3, AAC, AMR, MPEG-4, H.264, PNG, GIF e JPEG. Possui inclusive uma API especializada para tocar efeitos sonoros, útil no desenvolvimento de jogos. APIs para acessar periféricos como a camera, sistema de posicionamento global (GPS), bússola, acelerometro, tela sensı́vel ao toque, dispositivos apontadores e teclado. Nem todos os dispositivos Android possuem todos esses periféricos, resultando na fragmentação de hardware. Ambiente de desenvolvimento rico, incluindo emulador de dispotivos, ferramentas de depuração, profiling de memória e desempenho e plugin para a IDE Eclipse. 2.7 Arquitetura A arquitetura do Android é composta de uma pilha de componentes e cada componente é construı́do sobre os componentes da camada inferior. A figura 2.1 mostra uma visão dos principais componentes do Android: Arquitetura 10 Figura 2.1: Arquitetura do Android 2.7.1 Kernel O Android baseia-se na versão 2.6 do Linux para os serviços centrais do sistema como segurança, gerenciamento de memória e de processos e rede. O kernel age com uma camada de abstração entre o hardware e o restante da pilha de software e fornece os drivers básicos para os componentes de hardware. 2.7.2 Runtime e Dalvik O runtime do Android é construido em cima do kernel do Linux e é responsável por criar e executar aplicações Android. Cada aplicação executa em seu próprio processo e com sua própria máquina virtual Dalvik. A Dalvik executa programas no formato de bytecode DEX. O arquivo comum .class do Java é transformado para o formato DEX através de uma ferramenta chamada dx que é fornecida no kit de desenvolvimento de software. O formato DEX foi projetado para ter Arquitetura 11 menos utilização de memória se comparado com o arquivo .class clássico do Java. Isso é alcançado através de compressão pesada, tabelas e fusão de múltiplos arquivos .class. A máquina virtual Dalvik utiliza as bibliotecas de núcleo, que fornecem as funcionalidades básicas disponı́veis para os programas Java. As bibliotecas de núcleo fornecem algumas, mas não todas, as classes disponı́veis no Java SE por meio do uso de um subconjunto da implementação Java Apache Harmony. Isso quer dizer que não há Swing ou Abstract Window Toolkit (AWT) disponı́vel, nem classes que podem ser encontradas no Java ME. Entretanto, com algum cuidado, ainda é possı́vel utilizar muitas bibliotecas de terceiros disponı́veis para Java SE na Dalvik. Antes do Android 2.2 (Froyo), todo bytecode era interpretado. O Froyo introduziu um compilador JIT rastreável, que compila partes do bytecode para código de máquina no momento do uso. O compilador JIT pode usar funcionalidades da CPU espeficiamente adaptados para processamentos especiais como a unidade de processamento de ponto flutuante (FPU) dedicada. A Dalvik também possui um garbage collector (GC) integrado. A versão 2.3 do Android (Gingerbread) tem um aperfeiçoado GC concorrente. Cada aplicação executando em uma instância da máquina virtual Dalvik tem um total de 16MB a 24MB de memória heap disponı́vel. 2.7.3 Bibliotecas de Sistema Além das bibliotecas de núcleo, existe um conjunto de bibliotecas nativas em C/C++ que constroem a base para a camada de aplicação. Essas bibliotecas de sistemas são as principais responsáveis por tarefas computacionamente pesadas como renderização gráfica, reprodução de audio e acesso à banco de dados, que não seria adequado para a máquina virtual Dalvik. As APIs estão embrulhadas por meio das classes Java na camada de aplicação. Abaixo a relação das principais bibliotecas e suas caracterı́sticas: • System C library: uma implementação da biblioteca de sistema padrão C (libc) derivada do BSD, ajustada para dispositivos embarcados baseados em Linux. • Surface Manager: gerencia o acesso ao subsistema de exibição e combina camadas 2D e 3D de multiplas aplicações. Arquitetura 12 • Skia Graphics Library (SGL): renderizador de gráficos 2D, é responsável por rederizar a interface gráfica das aplicações Android. • 3D Libraries: uma implementação baseada no OpenGL for Embedded Systems (OpenGL ES), o padrão da indústria para renderizaçãp de gráficos acelerado por hardware. A versão 1.0 e 1.1 está disponı́vel no Java em todas as versões do Android. A versão 2.0 que possui sombreadores (shaders) só está disponı́vel no Android 2.2 (Froyo) em diante. • Media Libraries: baseada na OpenCORE da PacketVideo, as bibliotecas permitem reprodução e gravação de audio, video e imagens em vários formatos populares como Ogg Vorbis, MP3, AAC, AMR, MPEG4, H.264, JPG e PNG. • FreeType: é uma biblioteca para carregar e renderizar fonts bitmaps e vetoriais, mais especificamente o formato TrueType. • SQLite: um leve e poderoso motor de banco de dados relacional disponı́vel para todas as aplicações. 2.7.4 Camada de Aplicação A camada de aplicação reune as bibliotecas de sistema e o runtime, criando o lado do usuário do Android. A camada gerencia as aplicações e fornece um framework elaborado no qual as aplicações funcionam. Os desenvolvedores criam aplicações para essa camada através do conjunto de APIs Java que cobrem tais areas como programação da interface gráfica, serviços em segundo plano, notificações, gerenciamento de recursos, acesso a periféricos e assim por diante. Todas as aplicações de núcleo fornecidas juntamente com o Android, como o cliente de email, são escritas usando essas APIs. Aplicações, sejam gráficas ou serviços de segundo plano, podem comunicar suas capacidades com outras aplicações. Um exemplo simples é uma aplicação que precisa tirar uma foto e então realizar alguma operação com ela. A aplicação requisita do sistema um componente de outra aplicação que fornece esse serviço. A primeira aplicação pode reusar o componente (por exemplo a aplicação nativa da câmera ou galeria de fotos). Isso re- O Kit de Desenvolvimento de Software (SDK) 13 duz significativamente o fardo dos programadores e permite a personalização de diversos aspectos do comportamento do Android. Os desenvolvedores de jogos criam aplicações com interface gráfica nessa camada. Por isso é importante conhecer a arquitetura e o ciclo de vida da aplicação, e também como ela interage com o usuário. Por baixo de todas as aplicações estão uma serie de serviços e sistemas, incluindo: • Um rico e extenso conjunto de Views que podem ser usados para construir aplicações, incluindo listas, grids, caixas de texto, botões e até mesmo um navegador que pode ser embutido. • Content Providers que permitem aplicações acessar dados de outras aplicações (como o aplicativo nativo Contatos), ou compartilhar seus próprios dados. • Um Resource Manager, fornecendo acesso a recursos que não são código fonte como cadeias de caracteres, desenhos e arquivos de disposição (layout). • Um Notification Manager que permite a todas as aplicações exibirem alertas personalizados na barra de status. • Um Activity Manager que gerencia o ciclo de vida das aplicações e fornece uma pilha de volta para navegação 2.8 O Kit de Desenvolvimento de Software (SDK) Para desenvolver aplicações para Android, utiliza-se o Kit de Desenvolvimento de Software (SDK) do Android. O SDK é composto por um conjunto de ferramentas, documentação, tutoriais e amostras que ajudaram o desenvolvedor a começar a qualquer momento. Também estão inclusas as bibliotecas Java necessárias para criar aplicações para Android. Essas contem as APIs da camada de aplicação. A maioria dos sistemas operacionais para desktop são suportados como ambiente de desenvolvimento. As caracterı́sticas principais do SDK são: • O depurador, capaz de depurar aplicações executando em um dispositivo ou emulador O Kit de Desenvolvimento de Software (SDK) 14 • O profile de memória e desempenho que ajudam a encontrar vazamentos de memória e identificar trechos de código lento • O emulador de dispositivos, baseado no QEMU (uma máquina virtual de código aberto para simular diferentes plataformas de hardware), que, apesar de preciso, pode ser um pouco lento algumas vezes • Utilitários de linha de comando para comunicar com os dispositivos • Scripts prontos e ferramentas para empacotamento e instalação de aplicações O SDK pode ser integrado ao Eclipse, um completo e popular ambiente de desenvolvimento integrado (IDE) Java de código aberto. A integração é feita atraves do plugin Android Development Tools (ADT), que adiciona uma série de novas funcionalidades ao Eclipse para criar projetos, executar, depurar e analizar (profiling) aplicações no emulador ou em um dispositivo, além de empacotar e implantar aplicações no Android Market. É possı́vel integrar o SDK a outras IDEs, como o NetBeans, mas não há suporte oficial pra isso. Capı́tulo 3 Dominó Dominó é um tipo de jogo de mesa jogado com peças retangulares, dotadas de uma espessura que lhes dá a forma de paralelepı́pedo, em que uma das faces está marcada por pontos indicando valores numéricos. A figura 3.1 mostra as peças de dominó. O conjunto tradicional de dominós, conhecido como sino-europeu, é formado por 28 peças, ou pedras. O termo dominó também é usado para designar individualmente as peças que compõem este jogo. Uma das faces retangular de um dominó é divida em duas partes quadradas, ou ”pontas”, que são marcadas por um número de pontos de 1 a 6, ou deixadas em branco. Figura 3.1: Peças do jogo de dominó 3.1 História De acordo com [Kelley1999], o dominó não tem sua origem esclarecida. É conhecido por inúmeros povos e, portanto, tem inúmeras variações. A primeira menção ao jogo de Modalidade Amazonense 16 dominó vem da China. Segundo lendas daquele paı́s, o jogo teria sido inventado por um funcionário do imperador Hui Tsung. Outra remete a invenção do jogo aos anos de 234 a 181 a.C, quando teria vivido Huang Ming, um soldado-herói. No Brasil, o jogo teria chegado com os portugueses no sec. XVI, virando passatempo para os escravos. 3.2 Modalidade Amazonense O dominó jogado no Amazonas tem regras bastante peculiares, tornando o jogo mais interessante. Além disso, é usada a seguinte nomeclatura para as pedras, conforme a quantidade de pontos em cada ponta: 0 pontos - “branco”, 1 ponto - “ás”, 2 pontos - “duque”, 3 - “terno”, 4 - “quadra”, 5 - “quina” e 6 - “sena”. A pedra [2|4] por exemplo é chamada de duque e quadra ou quadra e duque. Pedras com as duas pontas iguais são chamadas de “carroça”. A seguir são explicadas detalhadamente cada uma das caracterı́sticas dessa modalidade. 3.2.1 Inı́cio Os jogadores de cada dupla sentam-se à mesa, de frente um para o outro, e colocam as pedras na mesa com a face marcada voltada para baixo para que possam ser misturadas, ilustrado na figura 3.2. Após a mistura cada jogador deve pegar 7 pedras. Caso algum jogador possua 5 carroças, ele deve mostrá-las aos outros jogadores que devem devolver suas pedras para que todas possam ser misturadas novamente. Modalidade Amazonense 17 Figura 3.2: Inicio de uma partida na modalidade Amazonense de dominó 3.2.2 Saı́da A saı́da é a jogada que inicia uma partida. Na primeira partida do jogo é realizada pelo jogador que possui a carroça de sena [6|6]. O jogador “saı́do” posiciona a carroça no centro da mesa voltada horizontalmente para sı́, para que seja possı́vel identificar a dupla que “saiu”. Um exemplo de saı́da feito pelo jogador 3 pode ser visto na figura 3.3. Figura 3.3: Saı́da em uma partida na modalidade Amazonense de dominó Modalidade Amazonense 3.2.3 18 Jogada Após a saı́da, o jogador à esquerda do jogador que iniciou a partida deve escolher uma pedra, entre as 7 que possui (chamada de ”mão”), cuja ponta corresponda a uma das pontas do jogo na mesa. Então deve encaixá-la na ponta da mesa com a ponta correspondente. Inicialmente as jogadas são feitas nos lados da pedra saı́da (e não nas pontas). As carroças são jogadas na perpedicular em relação as demais pedras. Na figura 3.4 é possı́vel ver a jogada feita pelo jogador 4. Figura 3.4: Jogada em uma partida na modalidade Amazonense de dominó 3.2.4 Bucho Após os dois lados da saı́da estarem ocupados, é possı́vel jogar nas duas pontas da pedra saı́da, chamado de “bucho”. A jogada no “bucho” também recebe o nome de “furar o bucho” ou “correr para o bucho” em alusão a uma possı́vel falta de pedra para jogar nas outras pontas. A figura 3.5 ilustra uma jogada feita no bucho pelo jogador 1. Modalidade Amazonense 19 Figura 3.5: Jogada no “bucho” em uma partida na modalidade Amazonense de dominó 3.2.5 Pontuação A pontuação é contada com múltiplos de 5. Caso o jogador anuncie que irá pontuar (chamado de “cantar”) antes de efetuar sua jogada, e ao realizá-la, a soma das pontas da mesa corresponda a pontuação “cantada” por ele, essa pontuação é adicionada ao placar da dupla. Em pontas que houverem carroças, as duas pontas da carroça seram contabilizadas. Normalmente, os pontos são marcados usando papel e caneta, onde são anotadas as iniciais de cada jogador da dupla e para cada 5 pontos da dupla é marcado um traço, sendo o próximo traço marcado perpendicular ao primeiro, formando uma cruz, que equivale a 10 pontos (2 traços). A primeira cruz é desenhada grande e as 4 próximas são desenhadas menores nos quadrantes determinados pela primeira, fechando 50 pontos. Daı́ então é feito uma nova cruz grande para os próximos 10 pontos e assim por diante. Na figura 3.6 é possı́vel observar o placar da partida após as jogadas da figura 3.4 e da figura 3.5, se os respectivos pontos tiverem sido contados. Modalidade Amazonense 20 Figura 3.6: Placar da partida após as jogadas da figura 3.4 e da figura 3.5 Outra forma de marcar a pontuação é utilizando fichas pontuadas ou coloridas. São usadas 2 fichas de 5 pontos, 8 fichas de 10 pontos e 6 fichas de 50 pontos. Conforme os pontos são marcados pelas duplas, as fichas são trocadas por fichas de maior valor, até que uma dupla complete 200 pontos e devolva suas fichas para o marcador, chamado de “pagar a casa”. Novos pontos marcados pela dupla que “pagou a casa” são novamente contabilizados com as fichas correspondentes, lembrando sempre que esta dupla possui 200 pontos além daqueles representados pelas fichas que possui. 3.2.6 Passe Quando um jogador não possui nenhuma pedra que possa jogar, ele passa a vez ao próximo jogador a sua esquerda e são marcados 20 pontos para os adversários. Se o próximo jogador também não tiver pedra jogável, somente passa a vez, sem dar 20 pontos aos adversários, chamado de “passe nas costas”. 3.2.7 Galo Dá-se o nome de “galo” a jogada previamente cantada pelo jogador, na qual ele faz a sua jogada e nenhum outro jogador consegue jogar, sendo a vez novamente do jogador que deu o galo. Essa jogada por sı́ só vale 50 pontos (além dos pontos na mesa, se forem Modalidade Amazonense 21 cantados). Caso um jogador cante galo e após a sua jogada algum outro jogador consiga jogar, chamado de “galo gay”, os 50 pontos são marcados para os adversários e a partida segue. 3.2.8 Batida É chamado de “batida” a jogada da última pedra de um jogador. Quando a batida é feita de carroça, se for cantada, dá direito a 20 pontos a dupla que bateu, chamado de “dominó de 20”. A batida encerra a partida e calcula-se a “garagem”, a soma das pedras dos adversários, que arredondada para baixo de um múltiplo de 5, é adicionada a pontuação da dupla que bateu. A partida seguinte, caso haja, é iniciada pelo jogador que bateu, que pode “sair” com qualquer carroça. Caso não tenha carroça, passa a vez (regra do passe), até que o próximo jogador que possua uma carroça possa começar a nova partida. 3.2.9 Jogo fechado O chamado “jogo fechado” ocorre quando nenhum jogador possui pedra possı́vel de jogar. Nesse caso, a partida é encerrada e são somadas as mãos de cada dupla, sendo as somas diferentes, a maior soma arredondada para baixo de um múltiplo de 5, é computada ao placar da dupla de menor soma. A partida seguinte, caso haja, é iniciada pelo jogador que pegar a carroça de sena. 3.2.10 Fim do jogo O jogo termina quando, ao final de uma partida, uma dupla tenha somado 200 ou mais pontos. Em caso de empate, é jogado uma nova partida de desempate até que haja uma dupla vencedora. Capı́tulo 4 Desenvolvimento Este capı́tulo descreve o desenvolvimento do jogo Dominó Manaus, uma versão eletrônica do jogo de dominó de mesa do mundo real. Por ser uma implementação da modalidade jogada no Amazonas, o jogo recebeu o nome da capital do estado, Manaus. 4.1 Projeto Nesta fase foram tomadas as decisões de projeto do jogo, como: • Android 1.6 ou superior - para ser compatı́vel com a maioria dos dispositivos com Android. • Resolução de 240x320 - menor resolução de tela de um dispositivo com Android, por motivos de compatibilidade. • Controles na tela (Touchscreen) - tecnologia disponı́vel em todos os dispositivos com Android e de fácil uso. • Modalidade Amazonense - o jogo deve conter todos os elementos da modalidade Amazonense de dominó. Na modalidade Amazonense de dominó, o jogador pode fazer 4 ações na sua vez: • Cantar ponto - é preciso cantar ponto para que a pontuação seja computada. Projeto 23 • Cantar galo - é preciso cantar galo para ganhar os 50 pontos e poder jogar novamente. • Jogar - ação de escolher uma pedra e uma ponta válida e realizar a jogada na mesa. • Passar - ação realizada quando não se tem pedra possı́vel de jogar. Para tornar o jogo eletrônico fiel à sua versão de mesa, definiu-se que o placar seguirı́a o modelo de marcação com papel e caneta, em que cada traço representa 5 pontos. 4.1.1 Interface Gráfica Definidos os requisitos, partiu-se para o design da tela do jogo. Nela o jogador deve poder visualizar as suas pedras, a mesa de jogo, a quantidade de pedras do seu parceiro e adversários, o placar e também poder realizar as ações descritas anteriormente quando for a sua vez. Uma idéia inicial de como seria a tela de jogo pode ser visto na figura 4.1. Figura 4.1: Idéia inicial da tela de jogo Devido a resolução limitada, optou-se por utilizar o artifı́cio adotado pela Sony Ericsson em sua interface personalizada do Android em sua linha de celulares Xperia, na qual as principais funcionalidades podem ser realizadas por meio de ı́cones posicionados nos cantos da tela, conforme é possı́vel observar na figura 4.2. Projeto 24 Figura 4.2: Printscreen da interface Sony Ericsson Xperia Android 1.6 e 2.1 A figura 4.3 mostra um esboço da tela do jogo, com o espaço reservado aos ı́cones das ações e a forma como é realizada a jogada pelo jogador humano, na qual uma pedra fantasma aparece no lugar onde é possı́vel se jogar a pedra escolhida. Para facilitar a escolha de uma pedra pelo jogador, foram adicionadas setas ao lado das suas pedras. Figura 4.3: Esboço da tela de jogo Nesta fase também foi elaborado o diagrama de fluxo de telas, que pode ser visto na figura 4.4. Ele é importante para se ter uma visão global de como será o jogo, descrevendo a sequência de transição das telas. Modelagem 25 Figura 4.4: Diagrama de fluxo de telas do jogo Dominó Manaus Com o jogo projetado, passou-se para a fase de modelagem. 4.2 Modelagem A modelagem permite avaliar o projeto como um todo antes que se inicie a fase de codificação. Isso possibilita identificar e solucionar problemas antecipadamente, evitando retrabalho durante programação. É importante ressaltar que os diagramas apresentados a seguir representam a versão final do jogo, pois foram alterados durante a fase de codificação para atender às necessidades que não foram previstas. O primeiro diagrama produzido foi o de Casos de Uso, que identifica os atores e suas interações com o sistema. No jogo Dominó Manaus o único ator é o jogador humano, pois é ele quem interage com o sistema realizando as ações de pegar suas pedras, jogar, cantar ponto, cantar galo e passar a vez, conforme é possı́vel ver na figura 4.5. Modelagem 26 Figura 4.5: Diagrama de Casos de Uso do jogo Dominó Manaus Em seguida, produziu-se o diagrama de sequência, pois a partir dele seria possı́vel analisar o passo a passo do programa e determinar se estava correto. A figura 4.6 mostra a versão final do diagrama de atividades do jogo Dominó Manaus. Modelagem 27 Figura 4.6: Diagrama de Atividades do jogo Dominó Manaus Modelagem 28 Conhecendo os atores, suas ações e o passo a passo do jogo, foi possı́vel elaborar o diagrama de Classes, que pode ser visto na figura 4.7. Nele são especificadas as classes, seus atributos e métodos e como elas interagem entre si. As classes JogadorHumano e JogadorMaquina são especificações da classe Jogador e implementam seu método abstrato joga de maneiras diferentes. Modelagem 29 Figura 4.7: Diagrama de Classes do jogo Dominó Manaus Codicação 30 Com o projeto modelado, partiu-se a codificação do jogo. 4.3 Codificação A arquitetura do jogo estava definida, mas ainda não se sabia como implementá-lo para o Android. O que se sabia era que para programar para Android utilizava-se a linguagem Java, e por isso o primeiro passo foi criar as classes do jogo com seus atributos e métodos, uma vez que para isso não é necessário conhecimento das APIs do Android. Segundo [Zechner2011], todo jogo necessita de um pequeno framework para facilitar a comunicação com a camada do sistema operacional, podendo ser dividido em módulos como: • Window management: responsável por criar uma janela e gerenciar o fechamento, pausa ou resumo da aplicação no Android. • Input: relativo ao módulo Window management, monitora os Inputs do usuário (como eventos de toque na tela, pressionar de teclas e leitura do acelerometro). • File I/O: permite acessar o disco para obter os recursos utilizados no jogo. • Graphics: módulo responsável por carregar e desenhar na tela a parte gráfica do jogo. • Audio: módulo responsável por carregar e tocar sons. • Game framework: junta todos os anteriores e fornece uma base de fácil uso para codificar jogos. Cada módulo desse é composto de uma ou mais interfaces. Cada interface tem pelo menos uma implementação concreta que implementa a semântica da interface baseada no que a plataforma abaixo dela fornece, no caso o Android. Isso permite focar na semântica e não em detalhes de implementação. Além disso, mudanças na implementação da interface são transparentes à camada superior. Um exemplo seria trocar a renderização 2D feita pela CPU por OpenGL ES. Codicação 31 O processo de criação e implementação do framework utilizado neste trabalho pode ser acompanhado em [Zechner2011] e por este motivo não será detalhado neste capı́tulo. No framework define-se uma resolução de tela nativa para a aplicação e a imagem da aplicação é ampliada ou reduzida conforme a resolução de tela do dispositivo onde ela será executada. O mesmo acontece com o sistema de coordenadas para os eventos de toque na tela. Isso faz com que o desenvolvedor somente precise se preocupar com uma única resolução de tela, a resolução nativa da aplicação. No caso do jogo Dominó Manaus, em que é preciso que todas a pedras da mesa possam ser vistas, as pedras precisam ter uma resolução pequena para que seja possı́vel mostrar um maior número de pedras na mesa. Caso se optasse por uma resolução nativa alta, quando um dispositivo de baixa resolução executasse o jogo, talvez não fosse possı́vel identificar a pedra por ela ter sido reduzida, por isso optou-se pela resolução nativa de 320x240 (menor resolução de tela de um dispositivo com Android). O primeiro passo foi editar o arquivo AndroidManifest.xml para definir a orientação da tela para paisagem e esconder o teclado virtual, adicionando os atributos screenOrientation=“landscape” e configChanges=“keyboard|keyboardHidden|orientation” ao elemento <activity>, conforme é possı́vel observar no Código 4.3.1. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="br.domino.manaus" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="Domino Manaus"> <activity android:name=".DominoManausGame" android:label="Domino Manaus" android:configChanges="keyboard|keyboardHidden|orientation" android:screenOrientation="landscape"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="3"/> </manifest> Código 4.3.1: AndroidManifest.xml Para permitir que a aplicação não deixe a tela desligar após um perı́odo de inatividade e possa escrever em arquivos externos (salvar configurações, por ex- Codicação 32 emplo), foram adicionados dois elementos <uses-permission> ao elemento <manifest>, cujos atributos são respectivamente “android.permission.WAKE LOCK” e “android.permission.WRITE EXTERNAL STORAGE”. No elemento <activity> está definida a classe da activity que será chamada ao iniciar a aplicação, que nesse caso é a classe DominoManausGame.java vista no Código 4.3.2. 1 2 package br.domino.manaus; 3 4 import br.domino.manaus.framework.Screen; import br.domino.manaus.framework.impl.AndroidGame; 5 6 7 8 9 10 11 public class DominoManausGame extends AndroidGame { @Override public Screen getStartScreen() { return new LoadingScreen(this); } } Código 4.3.2: Classe DominoManausGame.java A classe DominoManausGame herda da classe AndroidGame que é definida no framework como uma classe que herda da classe Activity e implementa a classe Game do framework. Ela cria uma instância da classe LoadingScreen (Código 4.3.3), que é a classe responsável por carregar para a classe Assets (Código 4.3.4) os recursos que serão utilizados pelo jogo e setar a tela de Menu como tela inicial do jogo. Codicação 1 2 3 4 5 6 7 8 9 10 11 33 package br.domino.manaus; import import import import br.domino.manaus.framework.Game; br.domino.manaus.framework.Graphics; br.domino.manaus.framework.Screen; br.domino.manaus.framework.Graphics.PixmapFormat; public class LoadingScreen extends Screen { public LoadingScreen(Game game) { super(game); } 12 13 14 @Override public void update(float deltaTime) { Graphics g = game.getGraphics(); 15 16 Assets.cantar = g.newPixmap("cantar.png", PixmapFormat.ARGB4444); Assets.galo = g.newPixmap("galo.png", PixmapFormat.ARGB4444); Assets.passar = g.newPixmap("passar.png", PixmapFormat.ARGB4444); Assets.placar = g.newPixmap("placar.png", PixmapFormat.ARGB4444); Assets.pontuacao = g.newPixmap("pontuacao.png", PixmapFormat.ARGB4444); Assets.pxxV = g.newPixmap("pxxv.png", PixmapFormat.ARGB4444); Assets.pppV = g.newPixmap("pppv.png", PixmapFormat.ARGB4444); Assets.pxxH = g.newPixmap("pxxh.png", PixmapFormat.ARGB4444); Assets.pppH = g.newPixmap("ppph.png", PixmapFormat.ARGB4444); Assets.direita = g.newPixmap("direita.png", PixmapFormat.ARGB4444); Assets.esquerda = g.newPixmap("esquerda.png", PixmapFormat.ARGB4444); Assets.dominoV = g.newPixmap("dominov.png", PixmapFormat.ARGB4444); Assets.dominoH = g.newPixmap("dominoh.png", PixmapFormat.ARGB4444); Assets.logo = g.newPixmap("logo.png", PixmapFormat.ARGB4444); Assets.confirm = g.newPixmap("confirm.png", PixmapFormat.ARGB4444); Assets.home = g.newPixmap("home.png", PixmapFormat.ARGB4444); Assets.help = g.newPixmap("help.png", PixmapFormat.ARGB4444); Assets.info = g.newPixmap("info.png", PixmapFormat.ARGB4444); Assets.play = g.newPixmap("play.png", PixmapFormat.ARGB4444); Assets.config = g.newPixmap("config.png", PixmapFormat.ARGB4444); Assets.fundo = g.newPixmap("fundo.png", PixmapFormat.RGB565); 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 game.setScreen(new MainMenuScreen(game)); 39 40 41 } 42 43 @Override public void present(float deltaTime) { 44 45 46 } 47 48 49 @Override public void pause() { 50 51 } 52 53 54 @Override public void resume() { 55 56 57 } @Override public void dispose() { 58 59 60 61 } } Código 4.3.3: Classe LoadingScreen.java Codicação 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 34 package br.domino.manaus; import br.domino.manaus.framework.Pixmap; public class Assets { public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap public static Pixmap } cantar; galo; passar; placar; pontuacao; pxxV; pxxH; pppV; pppH; direita; esquerda; dominoV; dominoH; fundo; logo; confirm; home; help; info; play; config; Código 4.3.4: Classe Assets.java A tela de menu é descrita pela classe MainMenuScreen (Código 4.3.5) e, assim como todas as telas do jogo, possui dois métodos principais, o método update, que verifica eventos de toque na tela e o método present que desenha a tela. Ambos os métodos são chamados automaticamente pelo framework, repetidas vezes, enquanto a tela estiver sendo mostrada. Codicação 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 35 package br.domino.manaus; import java.util.List; import import import import import android.graphics.Color; br.domino.manaus.framework.Game; br.domino.manaus.framework.Graphics; br.domino.manaus.framework.Input.TouchEvent; br.domino.manaus.framework.Screen; public class MainMenuScreen extends Screen { public MainMenuScreen(Game game) { super(game); } @Override public void update(float deltaTime) { List<TouchEvent> touchEvents = game.getInput().getTouchEvents(); game.getInput().getKeyEvents(); 20 21 22 int len = touchEvents.size(); for (int i = 0; i < len; i++) { TouchEvent event = touchEvents.get(i); if (event.type == TouchEvent.TOUCH_UP) { if (inBounds(event, 272, 0, 48, 48)) { // play game.setScreen(new GameScreen(game)); return; } if (inBounds(event, 272, 192, 48, 48)) { // config game.setScreen(new ConfigScreen(game)); return; } if (inBounds(event, 0, 192, 48, 48)) { // help game.setScreen(new HelpScreen(game)); return; } if (inBounds(event, 0, 0, 48, 48)) { // info game.setScreen(new InfoScreen(game)); return; } } } 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 } private boolean inBounds(TouchEvent event, int x, int y, int width, int height) { if (event.x > x && event.x < x + width - 1 && event.y > y && event.y < y + height - 1) return true; else return false; } @Override public void present(float deltaTime) { Graphics g = game.getGraphics(); // pinta o fundo g.clear(Color.rgb(35, 175, 75)); 58 59 60 61 62 // desenha o logo g.drawPixmap(Assets.logo, (g.getWidth() - Assets.logo.getWidth()) / 2, (g.getHeight() - Assets.logo.getHeight()) / 2); 63 64 65 // desenha os icones g.drawPixmap(Assets.info, 0, 0, 0, 0, 48, 48); g.drawPixmap(Assets.play, g.getWidth() - Assets.play.getHeight(), 0, 0, 0, 48, 48); g.drawPixmap(Assets.help, 0, g.getHeight() - Assets.help.getHeight(), 0, 0, 48, 48); g.drawPixmap(Assets.config, g.getWidth() - Assets.config.getHeight(), g.getHeight() - Assets.config.getHeight(), 0, 0, 48, 48); 66 67 68 69 70 71 72 73 74 75 } Código 4.3.5: Classe MainMenuScreen.java Codicação 36 A partir da tela de menu é possı́vel iniciar um novo jogo ou abrir as telas de Ajuda, Configurações ou Informações. Essas telas seguem o mesmo padrão da tela de menu, e seus respectivos códigos podem ser encontrados no Apêndice. A classe GameScreen é responsável pela a tela de jogo, fazendo a interface com o usuário e controlando o jogo. Por isso seu código é bastante extenso e somente as partes mais importantes dele serão mostradas e comentadas no decorrer deste capı́tulo. O código na ı́ntegra pode ser visto no Apêndice. Codicação 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 37 package br.domino.manaus; import java.util.ArrayList; import java.util.List; import import import import android.graphics.Color; android.graphics.Paint; android.graphics.Rect; android.graphics.Typeface; import import import import import br.domino.manaus.framework.Game; br.domino.manaus.framework.Graphics; br.domino.manaus.framework.Input.TouchEvent; br.domino.manaus.framework.Pixmap; br.domino.manaus.framework.Screen; public class GameScreen extends Screen { enum GameState { Saida, Partida, Fechado, Garagem, Fim, Pausa } static int espaco = 2; // pixels static int margem = 3; // pixels static int pedraVertH = Assets.pxxV.getHeight(); static int pedraVertW = Assets.pxxV.getWidth(); static int pedraHorzH = pedraVertW; static int pedraHorzW = pedraVertH; static int maoW = 7*pedraVertW + 6*espaco;; static int maoH = pedraVertH; static int maoX = 48 + (((320 - (112 + 48)) / 2) - (maoW / 2));; static int maoY = 240 - (margem + pedraVertH);; static int direitaH = Assets.direita.getHeight(); static int direitaW = Assets.direita.getWidth(); static int direitaX = (maoX + maoW); static int direitaY = 240 - (margem + direitaH); static int esquerdaH = Assets.esquerda.getHeight(); static int esquerdaW = Assets.esquerda.getWidth(); static int esquerdaX = maoX - esquerdaW; static int esquerdaY = direitaY; GameState state = GameState.Saida; Jogo jogo; public ArrayList<Jogada> jogadas = new ArrayList<Jogada>(4); Paint paint = new Paint(); Typeface font = Typeface.SANS_SERIF; Rect bounds = new Rect(); int iPedraEscolhida = -1; int iPlacar = 0; int iPlacarMax = 0; public GameScreen(Game game) { super(game); jogo = new Jogo(); } Código 4.3.6: Atributos e Construtor da Classe GameScreen.java No trecho de Código 4.3.6 é possı́vel ver os atributos e o construtor da classe, onde é criado uma instância da classe Jogo, responsável pelo jogo em si. O construtor da classe Codicação 38 Jogo cria três jogadores máquina e um jogador humano. Para controlar os estados do jogo, utilizou-se um atributo do tipo GameState, que é uma enumeração de estados possı́veis do jogo. Ele é utilizado no método update (Código 4.3.7) para determinar os eventos de toque na tela esperados em cada estado. 60 61 62 63 @Override public void update(float deltaTime) { List<TouchEvent> touchEvents = game.getInput().getTouchEvents(); game.getInput().getKeyEvents(); 64 65 switch (state) { case Saida: updateSaida(touchEvents); break; case Partida: updatePartida(touchEvents, deltaTime); break; case Pausa: updatePausa(touchEvents); break; case Fechado: updateFechado(touchEvents); break; case Garagem: updateGaragem(touchEvents); break; case Fim: updateFim(touchEvents); break; } 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 } Código 4.3.7: Método de update da Classe GameScreen.java No método present (Código 4.3.8), a tela do jogo é desenhada conforme o estado. 322 323 @Override public void present(float deltaTime) { 324 325 326 if(state == GameState.Saida) desenhaSaida(); if(state == GameState.Partida) desenhaPartida(); if(state == GameState.Pausa) desenhaPausa(); if(state == GameState.Fechado) desenhaFechado(); if(state == GameState.Garagem) desenhaGaragem(); if(state == GameState.Fim) desenhaFim(); 327 328 329 330 331 332 333 334 335 336 337 338 339 } Código 4.3.8: Método present da Classe GameScreen.java Codicação 39 O jogo inicia no estado Saida e aguarda que o usuário toque na tela. Ao tocar na tela o estado do jogo é alterado para Partida e é chamado o método iniciaPartida da classe Jogo, como pode ser visto no Código 4.3.9. private void updateSaida(List<TouchEvent> touchEvents) { if(touchEvents.size() > 0) { state = GameState.Partida; jogo.iniciaPartida(); } } 87 88 89 90 91 92 93 Código 4.3.9: Método updateSaida da Classe GameScreen.java O método iniciaPartida da classe Jogo cria a mesa e mistura as pedras evitando que os jogadores possam pegar cinco carroças (na versão de mesa as pedras são misturadas novamente). Cada jogador puxa suas 7 pedras para formar a sua mão e é chamado o método saida. public void saida() { if ((numPartida == 1) || (jogoFechado)) { // encontra jogador com a sena while (!jogadorVez.temPedra(6,6)) proximoJogador(); jogadorVez.jogaveis.add(new Pedra(6,6)); } else setaJogaveis(); novaJogada = true; } 117 118 119 120 121 122 123 124 125 126 Código 4.3.10: Método saida da Classe Jogo.java No método saida (Código 4.3.10) é verificado se é a primeira partida ou a partida anterior terminou com jogo fechado. Nesse caso o jogador que possui a carroça de sena é localizado para iniciar a partida. Perceba que o atributo novaJogada é setado como verdadeiro. Na próxima chamada do método update da classe GameScreen, o estado do jogo será Partida e será chamado o método updatePartida, que verifica analiza os eventos de toque na tela para esse estado e atualiza o jogo chamando o método update da classe Jogo. Codicação 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 40 public void update(float deltaTime) { int iDupla, iDuplaAdv; if (fimPartida) return; // desenha a partida e depois desenha a jogada if (novaJogada) { // diferenca perceptivel na saida do jogador maquina devido ao delay novaJogada = false; jogadorVez.joga(mesa); } if (jogadorVez.confirmaPasse) { // confirma passe if (!jogadorAntPassou) { // nao eh passe na costa iDuplaAdv = (getiVez()+1) % 2; pontuacao[iDuplaAdv] += 20; } jogadorAntPassou = true; jogadorVez.confirmaPasse = false; proximoJogador(); setaJogaveis(); novaJogada = true; } else { // nao passou if (jogadorVez.confirmaJogada) { // confirma jogada // se for saida, as pontas da mesa estao vazias, seta o jogador saido if ((mesa.pontas.get(0).isEmpty()) && (mesa.pontas.get(1).isEmpty()) && (mesa.pontas.get(2).isEmpty()) && (mesa.pontas.get(3).isEmpty())) mesa.iJogadorSaido = getiVez(); jogadorVez.confirmaJogada = false; jogadorAntPassou = false; iDupla = getiVez() % 2; if (jogadorVez.cantouPonto) { pontuacao[iDupla] += mesa.contaPontos(); if ((jogadorVez.bateu()) && (mesa.ultimaPedra.ehCarroca())) pontuacao[iDupla] += 20; jogadorVez.cantouPonto = false; } if (jogadorVez.bateu()) { fimPartida = true; numPartida++; jogoFechado = false; contaGaragem(); } else { if (fechado()) { fimPartida = true; numPartida++; jogoFechado = true; contaMaos(); } } if (jogadorVez.cantouGalo) { jogadorVez.cantouGalo = false; // desmarca botao de galo if ((!fimPartida) && (ehGalo())) { pontuacao[iDupla] += 50; ehGalo = true; } else { // galo gay iDuplaAdv = (getiVez()+1) % 2; pontuacao[iDuplaAdv] += 50; ehGalo = false; } } if (!fimPartida) { if (!ehGalo) // se nao for galo a vez eh do proximo proximoJogador(); ehGalo = false; setaJogaveis(); novaJogada = true; } } } Código 4.3.11: Método update da Classe Jogo.java Codicação 41 O método update da classe Jogo (Código 4.3.11) é o laço principal do jogo. Nele é verificado se é a novaJogada e em caso afirmativo é chamado o método joga do jogadorVez. Caso o jogador da vez confirme seu passe, a vez é passada ao próximo jogador, conforme a regra do passe, caso contrário, é verificado se o jogador da vez confirmou a jogada. Nesse caso, é checado se é a primeira jogada da mesa, para identificar o jogador saı́do. É também tratado se o jogador cantou ponto. Em caso de batida, é contada a garagem, caso contrário, é verificado se o jogo fechou, e se for o caso é somada as mãos. Os dois últimos setam a fimPartida como verdadeiro, se forem verdadeiros. Por último, é checado se o jogador cantou galo e se é um galo válido. Ao retornar ao método update da classe GameScreen, é verificado se é fim de partida e se for o caso o estado é alterado para Garagem em caso de batida ou para Fechado em caso de jogo fechado. Na próxima chamada ao método present da classe GameScreen a tela será desenhada de acordo com o estado do jogo. Se o estado for Partida é chamado o método desenhaPartida. 356 357 358 359 360 361 362 363 364 365 366 367 368 369 private void desenhaPartida() { Graphics g = game.getGraphics(); desenhaFundo(g); desenhaBotoes(g); desenhaPlacar(g); desenhaMaoOutros(g); desenhaMaoJogador(g); desenhaMesaCentralizada(g); // vez do jogador humano if (jogo.getiVez() == 2) { desenhaSetas(g); desenhaJogadas(g); } } Código 4.3.12: Método desenhaPartida da Classe GameScreen.java Nesse método (Código 4.3.12) são desenhados o fundo, os botões (habilitados quando é a vez do jogador e desabilitados quando não), o placar, as mãos dos outros jogadores (pedra com a face virada para baixo), a mão do jogador, a mesa, e se for a vez do jogador as setas para facilitar a escolha das pedras e as jogadas caso seja possı́vel jogar com a pedra selecionada. Caso o estado do jogo seja Garagem, é chamado o método desenhaGaragem, que desenha as pedras e o valor da garagem, além do placar e o icone de continuar o jogo no canto superior direito. No caso do estado ser Fechado, o método desenhaFechado é chamado e Codicação 42 desenha as pedras restantes de ambas as duplas e o valor da soma das mãos da dupla, além do ı́cone de continuar o jogo no canto superior direito. Se na próxima chamada ao método update da classe GameScreen o estado do jogo for Fechado ou Garagem, serão chamados os métodos updateFechado (Código 4.3.13) e updateGaragem (Código 4.3.14) respectivamente para tratar dos eventos de toque na tela para esses estados. private void updateFechado(List<TouchEvent> touchEvents) { if(touchEvents.size() > 0) { int len = touchEvents.size(); for(int i = 0; i < len; i++) { TouchEvent event = touchEvents.get(i); if(event.type == TouchEvent.TOUCH_UP) { if ((event.x > 320-48) && (event.y < 48)) { jogo.processaJogoFechado(); if (jogo.terminou()) state = GameState.Fim; else { // comeca nova partida state = GameState.Partida; jogo.iniciaPartida(); } } // avanca placar if ((event.x > (320 - (112 / 2))) && (event.y > (240 - 48))) { iPlacar++; if (iPlacar > iPlacarMax) iPlacar = iPlacarMax; } // retrocede placar if ((event.x > (320 - 112)) && (event.x < (320 - (112 / 2))) && (event.y > iPlacar--; if (iPlacar < 0) iPlacar = 0; } } } } 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 } Código 4.3.13: Método updateFechado da Classe GameScreen.java Codicação 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 43 private void updateGaragem(List<TouchEvent> touchEvents) { if(touchEvents.size() > 0) { int len = touchEvents.size(); for(int i = 0; i < len; i++) { TouchEvent event = touchEvents.get(i); if(event.type == TouchEvent.TOUCH_UP) { if ((event.x > 320-48) && (event.y < 48)) { jogo.processaGaragem(); if (jogo.terminou()) state = GameState.Fim; else { // comeca nova partida state = GameState.Partida; jogo.iniciaPartida(); } } // avanca placar if ((event.x > (320 - (112 / 2))) && (event.y > (240 - 48))) { iPlacar++; if (iPlacar > iPlacarMax) iPlacar = iPlacarMax; } // retrocede placar if ((event.x > (320 - 112)) && (event.x < (320 - (112 / 2))) && (event.y > iPlacar--; if (iPlacar < 0) iPlacar = 0; } } } } } Código 4.3.14: Método updateGaragem da Classe GameScreen.java Em ambos os métodos, é possı́vel paginar o placar, pois este somente exibe no máximo 200 pontos de cada vez. Após clicar no ı́cone no canto superior direito para seguir o jogo, é processada a garagem ou a contagem de mãos e verificado se o jogo terminou, em caso afirmativo é mudado o estado para Fim, e em caso negativo o estado é mudado para Partida e o método iniciaPartida da classe Jogo é chamado novamente. Quando o estado do jogo é Fim, o método present da classe GameScreen chama o método desenhaFim que desenha a dupla vencedora, a pontuação final, o placar do jogo e o icone de voltar a tela inicial do jogo no canto superior esquerdo. Imagens do jogo 4.4 Imagens do jogo Figura 4.8: Tela de menu principal e tela de inı́cio de jogo (saı́da) Figura 4.9: Vez do jogador humano e jogada inicial da 1a partida 44 Imagens do jogo 45 Figura 4.10: Vez do jogador máquina e tela de jogo fechado Figura 4.11: Recomeço de jogo fechado pela dupla adversária e jogada no bucho Figura 4.12: Jogada de carroça marcando 5 pontos Imagens do jogo Figura 4.13: Tela de garagem e nova partida iniciada pelo jogador que bateu Figura 4.14: Jogador humano sem jogada (só pode passar) e tela de pause 46 Imagens do jogo 47 Figura 4.15: Tela de fim de jogo e paginação do placar Figura 4.16: Tela de créditos Capı́tulo 5 Conclusão Neste trabalho foi desenvolvido um jogo para Android, sendo possı́vel concluir que o Android é uma plataforma completa, com curva de aprendizado médio e com a vantagem de ser aberto e multiplataforma. Programar jogos não é um ciência exata e pode ser feito de diversas maneiras. A maneira adotada neste trabalho, definindo os requisitos e modelando o jogo antes de iniciar a codificação, permitiram codificar de maneira simples um jogo de diversas regras. A utilizacão de um framework como interface entre o jogo e a arquitetura do Android, possibilitou o foco na semântica do jogo e não em detalhes de implementação. Para que a mesa de jogo estivesse sempre visı́vel em uma tela de resolução limitada como a adotada (para aumentar a compatibilidade) seria necessário, além de centralizar a mesa, a quebra das pontas que atingissem seu limite. Devido à complexidade desta solução, não foi possı́vel implementá-la durante o desenvolvimento desta monografia. 5.1 Trabalhos futuros Desenvolver um novo método de desenhar a mesa que além de centralizar o jogo faça a quebra da ponta da mesa caso ela atinja o limite da mesma. Poderia ser desenvolvido um modo para múltiplos jogadores, criando uma classe JogadorRemoto e deixando ela transparente para o jogo. Seria interessante desenvolver uma inteligência artificial mais avançada, que analizasse o jogo na mesa, as jogadas do parceiro, os passes dos adversários e as pedras na mão antes de realizar a jogada. Referências Bibliográficas [Crı́tica2011] Crı́tica, A. (2011). Regulamento geral - 4a copa a crı́tica de dominó. [Farago2011] Farago, P. (2011). Apple and google capture u.s. video game market share in 2010. http://blog.flurry.com/bid/60307/Apple-and-Google-Capture-U-S-Video-Game- Market-Share-in-2010. [Kelley1999] Kelley, J. (1999). Great Book of Domino Games. Sterling. [Lecheta] Lecheta, R. Google ANDROID - Aprenda a criar aplições para dispositivos móveis com o Android SDK. Novatec. [Pereira and Silva] Pereira, L. and Silva, M. Android para desenvolvedores. Brasport. [Zechner2011] Zechner, M. (2011). Beginning Android Games. Apress Series. Apress. Capı́tulo 6 Apêndice Os códigos-fonte desta monografia encontram-se no CD que acompanha a mesma.