Вы находитесь на странице: 1из 21

Desenvolvendo Jogos em JAVA!

Daniel Ricardo dos Santos Diogo de Campos Mauricio Oliveira Haensch Desenvolvendo Jogos com Java ME Daniel Ricardo dos Santos Diogo de Campos Mauricio Oliveira Haensch Desenvolvendo Jogos com Java ME PET Computacao Licenca: Atribuicao-Uso Nao-Comercial-Compartilhamento pela mesma Licenca 2.5 Brasil Para cada novo uso ou distribuicao, voce deve deixar claro para outros os termos da licenca desta obra. Qualquer uma destas condicoes podem ser renunciadas, desde que Voce obtenha permissao do autor. Nada nesta licenca prejudica ou restringe os direitos morais dos autores.

Sumario 1.1 A plataforma Java p. 5 1.2 Java Card p. 5 1.3 Java Micro Edition (ME) p. 6 1.4 Java Standard Edition (SE) p. 6 1.5 Java Enterprise Edition (E) p. 6 1 Introducao p.5 2.1 O que e p. 7 2.1.1 Aplicac oes p. 7 2.1.2 Vantagens p. 7 2.2 Principais diferencas entre Java SE e Java ME p. 8 2.3 Configurac oes e perfis p. 9 2.4 JCP e JSRs p. 1

2 Java ME p.7 3.1 Sun Wireless Toolkit p. 12 3.2 IDEs p. 12 3.2.1 NetBeans p. 12 3.2.2 Eclipse p. 13 3 Ferramentas de desenvolvimento p.12

5.1 Uso de memoria p. 16 5.2 Resolucao p. 16 5.3 Configurac oes e perfis p. 17 5 Desenvolvendo para Dispositivos Moveis p.16 6.1 A classe MIDLet p. 18 6.2 Commands p. 19 6.3 Displays e Displayables p. 20 6.4 Canvas p. 20 6.5 Sprites e Tiles p. 21 6.5.1 Sprites p. 21 6.5.2 TiledLayer p. 2 6.6 Sons p. 23 6 Desenvolvendo Jogos p.18 7.1 Introducao p. 26 7.2 Estrutura do codigo p. 26 7.2.1 Commands p. 26 7.2.2 Eventos do menu principal p. 29 7.2.3 A classe TelaDoJogo p. 30 7.2.4 A classe Bola p. 3 7.2.5 PlayTone p. 35 7 Estudo de Caso - Liga Quatro p.26 8 Bibliografia p.36 1.1 A plataforma Java

Java e uma tecnologia que se estende muito alem da propria linguagem de programacao. Trata-se, na verdade, de uma plataforma de desenvolvimento.

A plataforma Java compreende um conjunto de softwares e especificacoes da Sun Microsystems para o desenvolvimento de aplicativos. A grande vantagem desta plataforma e a sua compatibilidade nao apenas entre sistemas operacionais, mas tambem entre diversas arquiteturas, variando de PDAs e set-top boxes ate servidores. As aplicacoes desenvolvidas nesta plataforma tambem sao diversas, variando de aplicativos embarcados a jogos e aplicativos web. Devido a essa grande variedade a plataforma e dividida em quatro diferentes edicoes. Cada edicao e composta de um pacote de softwares que permitem o desenvolvimento e a execucao de programas escritos na linguagem Java. As plataformas sao desenhadas nao para um processador especfico, mas para uma Java Virtual Machine (JVM) e um compilador com um conjunto de bibliotecas. A principal vantagem do uso da maquina virtual e aumentar a portabilidade do codigo. 1.2 Java Card Java Card e a edicao mais limitada da plataforma Java e e destinada a smart cards ou dispositivos similares com pouqussima memoria. Seu principal foco e a seguranca, com suporte ao encapsulamento de dados no aplicativo, firewall entre aplicativos e criptografia. Atualmente, encontra-se em desenvolvimento a versao 3 da plataforma. 6 1.3 Java Micro Edition (ME) Voltada para dispositivos com pouca capacidade de processsamento e memoria limitada, principalmente dispositivos moveis. Muito usada em celulares e PDAs, estende-se tambem para aparelhos como set-top boxes e Blu-ray players. Apresenta algumas dificuldades no desenvolvimento devido a grande variedade de dispositivos e suas especificidades. A plataforma Java ME e detalhada no proximo captulo. 1.4 Java Standard Edition (SE) E a edicao usada para o desenvolvimento de aplicacoes portaveis de proposito geral. Contem o que necessario para o desenvolvimento de aplicacoes desktop e applets, como pacotes de interface grafica, entrada e sada, comunicacao com bancos de dados, etc. Atualmente, encontra-se na versao 6. 1.5 Java Enterprise Edition (E) Java E e a maior das edicoes de Java, compreendendo tudo o que esta presente na Standard Edition alem de coisas mais especficas, como o servidor de aplicacoes GlassFish. Voltada para aplicacoes que rodam no lado do servidor e pensada para tornar as aplicoes

robustas, seguras, escalaveis e portaveis. E usada para o desenvolvimento de aplicacoes web e baseadas na arquitetura orientada a servicos (SOA), como web services. Atualmente, encontra-se na versao 5. Java ME e uma das edicoes da plataforma Java e, como tal, e composta pela propria linguagem, por uma Maquina Virtual e por uma colecao de APIs. A linguagem e a mesma usada nas outras edicoes, portanto e familiar para qualquer pessoa que ja tenha programado Java em qualquer plataforma. Para se entender Java ME, entao, e necessario conhecer a Maquina Virtual e a colecao de APIs. Java ME aceita diferentes implementacoes de maquinas virtuais e normalmente a maquina virtual e definida pela Configuracao. Alem desses elementos comuns, esta edicao da plataforma Java apresenta alguns elementos especficos como Profiles e Configuracoes, que serao estudados adiante. E usado principalmente para o desenvolvimento em sistemas moveis e embarcados, alguns exemplos de sistemas que adotam Java ME sao: Celulares; PDAs; Set-top boxes; Blu-ray players. Por ter um campo de aplicacao bem especificado, Java ME apresenta diversas facilidades para os desenvolvedores, tais como: Portabilidade: Um aplicativo criado utilizando Java ME pode ser portado para diversos aparelhos, desde que sigam as mesmas especificacoes. Isso e muito importante no desenvolvimento para celulares, pois um mesmo aplicativo desenvolvido podera rodar em modelos de diferentes fabricantes. Boa compatibilidade entre aparelhos: Como ja foi citado acima, desde que sigam as mesmas especificacoes, nao ha grandes problemas de compatibilidade entre os aparelhos que irao rodar um aplicativo. Constante desenvolvimento: Assim como todo o resto da tecnologia Java, Java ME se encontra em constante desenvolvimento, com novas funcoes e capacidades sendo adicionadas a todo momento. Esse processo de desenvolvimento segue a JCP (Java Community Process), que sera detalhado mais a frente. Boa documentacao: A plataforma conta com uma vasta documentacao online, no proprio site da Sun, alem de inumeros outros exemplos e tutoriais que podem ser encontrados em sites e foruns.

Desenvolimento integrado: Uma das principais vantagens de Java ME e o desenvolvimento integrado, proporcionado por ferramentas como o Wireless Toolkit (WTK) e IDEs como o NetBeans. 2.2 Principais diferencas entre Java SE e Java ME As principais diferencas entre Java SE e Java ME sao descritas a seguir: Maquina Virtual: As maquinas virtuais utilizadas em Java ME sao desenhadas para serem mais compactas e eficientes que a maquina virtual utilizada em Java SE, por isso alguns recursos sao perdidos. Numeros de ponto flutuante: O suporte a ponto flutuante so foi adicionado na versao 1.1 do CLDC, por isso ao desenvolver aplicacoes para dispositivos mais antigos e possvel que o desenvolvedor nao encontre suporte para esta representacao numerica. Reflexao: O pacote java.lang.reflect so esta presente no CDC. Por isso nao e possvel utilizar reflexao em dispositivos de menor capacidade. APIs de alto nvel (Swing e AWT): Algumas APIs de mais alto nvel, como as utilizadas para interface grafica nao estao presentes em Java ME. Acesso ao sistema de arquivos: Para se ter acesso ao sistema de arquivos e necessario utilizar o PDA Profile, ou uma implementacao especfica de um fabricante. Grupos de threads: O suporte a grupos de threads, threads que podem ser manipuladas em conjunto, tambem so e provido pelo CDC. A figura abaixo mostra uma visao geral dos componentes de Java ME e como eles se relacionam as outras tecnologias Java:

As configuracoes (Configurations) e perfis (Profiles) representam as configuracoes e APIs mnimas disponveis em um dispositivo movel.

Cada aplicativo desenvolvido necessita de uma configuracao mnima para ser rodado, e a garantia de que o dispositivo alvo tera essa configuracao e fornecida pelo sistema de Configurations e Profiles. As principais Configurations sao o CDC e o CLDC e o principal Profile e o MIDP, que sao explicados a seguir. O MIDP e a definicao de uma arquitetura, e define varias APIs que devem estar disponveis em uma plataforma para promover um ambiente de desenvolvimento para as suas MIDlets. A diferenca mais importante entre o MIDP 1.0 e o MIDP 2.0 e a introducao de uma API para jogos, que facilita muito a criacao deste tipo de aplicativo. A maioria dos aplicativos desenvolvidos para dispositivos moveis sao capazes de rodar em plataformas MIDP 1.0, que devem ter as seguintes caractersticas, entre outras: Tamanho da tela mnimo de 96x54pixels. Input atraves de One handed keyboard ou Two handed keyboard ou Touch Screen. 128Kbytes de memoria para os componentes MIDP. 8Kbytes de memoria para dados das aplicacoes. 32Kbytes de memoria dinamica. O MIDP 1.0 e baseado em aparelhos que seguem a configuracao CLDC, ou seja, os aparelhos compatveis com MIDP tambem o serao com CLDC. Dispositivos CLDC (Connected Limited Device Configuration) sao os aparelhos mais simples, que possuem uma interface menor e pouca memoria e velocidade de processamento. Devem ter no mnimo as seguintes caractersticas: 128Kb de memoria para rodar a maquina virtual. 32Kb de memoria dinamica. Comunicacao em rede com baixa largura de banda. Baixa potencia (para diminuir o gasto de energia). Dispositivos CDC (Connected Device Configuration) sao aparelhos mais potentes que os CLDC e devem ter pelo menos as seguintes caractersticas: 512Kb de memoria para executar a maquina virtual. 256Kb de memoria dinamica. Capacidade para comunicacao em rede com alta largura de banda.

O Java Community Process (JCP) e um processo formalizado para que varias partes interessadas colaborem no desenvolvimento de especificacoes e futuras versoes da plataforma Java.

Entre os membros da JCP podemos encontrar operadoras de telefonia como a NTT DoCoMo, desenvolvedores de dispositivos moveis como a Nokia, a Sony Ericsson e a Motorola, outras empresas e ate mesmo pessoas fsicas. Os documentos descrevendo as especificacoes e tecnologias propostas sao chamados Java Specification Request (JSR). Esses documentos sao publicamente revisados ate que um JSR se torne final e seja votado pelo Comite Executivo da JCP. Um JSR final prove uma implementacao de referencia, na forma de codigo fonte e um Technology Compatibility Kit para verificar a especificacao da API. O proprio JCP e descrito por um JSR, o JSR 215 de 2006. Os JSRs sao especialmente importantes em Java ME, por causa do numero de recursos novos e da velocidade com que mudam em dispositivos moveis. Alguns exemplos de JSRs em Java ME:

JSR 68: J2ME Platform Specification JSR 82: Bluetooth JSR 133: Java Game Profile JSR 184: Mobile 3D Graphics API for J2ME 12 3 Ferramentas de desenvolvimento 3.1 Sun Wireless Toolkit O Wireless Toolkit, ou WTK, e uma ferramenta de auxlio ao desenvolvimento de aplicacoes em Java ME (CLDC e MIDP). O WTK possui exemplos, documentacao, funcoes de otimizacao e um emulador para dispositivos moveis. Ha algumas IDEs (Integrated Development Enviroment, ou ambiente de desenvolvimento) que ja vem com o Sun Wireless ToolKit integrado, outras possuem plugins para integracao e tambem e possvel usar apenas o WTK para desenvolver suas aplicacoes. 3.2 IDEs Duas IDEs ja bem conhecidas para desenvolvimento em Java (e tambem em outras linguagens de programacao) sao o Eclipse e o NetBeans. Ambos os ambientes suportam

o desenvolvimento em Java ME e serao descritos com um pouco mais de caractersticas a seguir. 3.2.1 NetBeans O ambiente de desenvolvimento NetBeans se iniciou como um projeto de dois estudantes, e posteriormente foi comprado pela Sun Microsystems. Por aproximadamente um ano, a empresa manteve o ambiente como software proprietario, mas apos esse perodo o codigo foi aberto e a partir disso foram surgindo muitas melhoras no ambiente em si e diversos plugins foram criados. Entre esses avancos, surgiu o NetBeans Mobility Pack, que e uma extensao da IDE para desenvolvimento com Java ME. O NetBeans Mobility Pack ja vem integrado com o emulador da Sun (WTK), alem de suportar outros emuladores. Essa extensao tambem tem algumas ferramentas que auxiliam no desenvolvimento para dispositivos moveis, como algumas classes que podem ser utilizadas nas suas aplicacoes fora as padroes da biblioteca Java ME. Um exemplo disso e a SplashScreen, que estende a classe Canvas do Java ME e pode ser bem util para as aplicacoes desenvolvidas. O Mobility Pack tambem possui o Game Builder, que auxilia o desenvolvimento de jogos. Atraves dessa ferramenta, fica mais facil criar Sprites e Tiles para seu jogo, e o Game Builder tambem permite a construcao de cenas (combinacoes de objetos estaticos e dinamicos) de uma maneira mais simples e rapida, ajudando na criacao do seu jogo. Alem de todas as vantagens do ambiente para o desenvolvimento de aplicacoes com JavaME, e um ambiente gratuito e com boa documentacao, alem de um forte apoio da comunidade. 3.2.2 Eclipse Existem plugins para a IDE Eclipse para desenvolvimento com Java ME. A grande vantagem de se desenvolver com esse ambiente sao todas as facilidades do Eclipse, que e bem poderoso e versatil para geracao de software em Java. Um dos plugins existentes para desenvolvimento com JavaME no ambiente Eclipse e o chamado EclipseME. Este plugin e um pouco antigo e so funciona com algumas versoes tambem antigas da IDE. Porem, existem diversos outros plugins que podem ser utilizados para desenvolvimento de aplicacoes para a plataforma ME do Java. Esses plugins podem ser encontrados na propria pagina da IDE Eclipse, na secao de plugins, mas varios deles sao pagos. 14 4 Bibliotecas Java ME 4.1 Java SE x Java ME O Java Micro Edition possui apenas um subconjunto dos componentes da Standard Edition, com uma maquina virtual e algumas APIs mais limitadas. As APIs presentes no

Java ME sao definidas no JCP (Java Community Process). A limitacao de memoria dos dispositivos que rodam Java ME acabou resultando na retirada de algumas das bibliotecas presentes no Java Standard Edition, para manter a plataforma pequena e adequada ao seu objetivo. Porem, o Java Micro Edition nao possui apenas uma especificacao. Dependendo da configuracao e perfil escolhidos, voce pode utilizar diferentes APIs para desenvolver sua aplicacao. Com a evolucao do poder de processamento e capacidade de memoria dos dispositivos, surgem novas funcionalidades mais complexas atraves dos JSRs. Como exemplo disso, podemos citar a ausencia de variaveis do tipo ponto flutuante (como o double) em versoes mais antigas de configuracoes e perfis do Java ME. Devido a essa diferenca entre as duas edicoes, nem toda aplicacao desenvolvida em Java SE funcionara num dispositivo que roda Java ME. 4.2 Bibliotecas disponveis Como dito anteriormente, as APIs disponveis para desenvolver a sua aplicacao resultam da combinacao de configuracao e perfil adotados pelo programador. Utilizando como exemplo a versao 1.1 do CLDC (Connected Limited Device Configuration), os pacotes presentes para o desenvolvimento da sua aplicacao sao: java.io java.lang java.lang.ref java.util Outra diferenca de bibliotecas entre a Standard Edition e a Micro Edition e em relacao a interface das aplicacoes. O SWT e Swing da edicao padrao de Java nao se encontram na versao ME. A Micro Edition conta com um novo pacote para este fim, chamado java.microedition.lcdui, que pode ser encontrado em qualquer versao do MIDP. A versao 2.0 do MIDP contem os seguintes pacotes: java.io java.lang java.util javax.microedition.io javax.microedition.lcdui javax.microedition.lcdui.game javax.microedition.media javax.microedition.media.control javax.microedition.midlet javax.microedition.pki

javax.microedition.rms Como podemos notar, existe uma serie de pacotes exclusivos do JavaME (os iniciados com javax.microedition). Assim, com a presenca de alguns pacotes exclusivos, tambem pode-se afirmar que nem toda aplicacao escrita em Java ME funcionara na plataforma Java SE. 5 Desenvolvendo para Dispositivos Moveis 5.1 Uso de memoria Os dispositivos para os quais se desenvolve em Java ME, em geral, possuem pouca memoria, sendo isso um fator de risco para o desenvolvimento de aplicacoes desse tipo, juntamente com a capacidade de processamento. Para evitar isso, deve-se ter um cuidado maior para essa classe de software. A utilizacao de estruturas de dados e tipos de dados mais simples e um bom comeco para reduzir o uso de memoria. Outra sada e reduzir o numero de objetos criados, ou reduzir o tamanho dos objetos que sao utilizados na aplicacao. As imagens utilizadas tambem sao uma grande fonte de Out of Memory Error, a excecao que ocorre ao se utilizar memoria em excesso. Se mesmo com esses cuidados ainda existem problemas com memoria, voce pode usar um profiler para auxiliar a encontrar usos desnecessarios ou ineficientes de memoria. Um Profiler e uma ferramenta que ajuda a encontrar bottlenecks da sua aplicacao, achando memory leaks e rastreando a vida dos objetos. Com essas informacoes, e mais facil encontrar problemas na implementacao que ocasionam os erros de uso de memoria da sua aplicacao. Os diferentes dispositivos que suportam aplicacoes em Java ME possuem resolucoes de tela diferentes. Assim, na hora de desenvolver esse tipo de software, e preciso ter em mente alguma resolucao um pouco mais especfica para a qual sera desenvolvida a aplicacao. E muito mais facil desenvolver para uma resolucao especfica do que tentar fazer um software mais geral que rode em varias resolucoes diferentes. Normalmente sao lancadas algumas versoes do software, cada uma para uma resolucao di- ferente. Isso tambem ajuda na questao de capacidade do dispositivo. Geralmente dispositivos com uma mesma resolucao da tela possuem uma capacidade de processamento e memoria parecidos, facilitando com que uma aplicacao funcione em uma quantidade maior de aparelhos moveis ao ser desenvolvida especificamente para um conjunto de dispositivos similares. A escolha da configuracao e sua versao, assim como a versao do perfil adotado pelo programador, devera levar em conta o dispositivo para o qual se esta desenvolvendo a aplicacao, assim como as funcionalidades da aplicacao sendo desenvolvida. Essa escolha acaba definindo em que tipos de dispositivos a sua aplicacao ira rodar. Por esse motivo, e fundamental que se verifique as configuracoes e perfis suportados pelo dispositivo de destino da sua aplicacao. 18 6 Desenvolvendo Jogos

6.1 A classe MIDLet A classe MIDlet corresponde as aplicacoes do MIDP, e deve ser estendida para que o software que gerencia as aplicacoes do dispositivo consiga controlar e modificar o estado das aplicacoes (rodando ou pausada, por exemplo). A classe principal de sua aplicacoes deve estender a esta classe e implementar os metodos utilizados para criar, comecar, pausar e destruir a aplicacao. A MIDLet funciona como uma interface entre o gerenciador de aplicacoes e a sua aplicacao. Essa comunicacao funciona atraves de sinais enviados entre o software gerenciador do dispositivo e a aplicacao. Para comecar a sua aplicacao, a classe MIDlet possui o metodo startApp, que faz com que o estado atual se torne Active, enviando um sinal para o software gerenciador de aplicacoes. Caso alguma excecao ocorra durante a execucao desse metodo, a aplicacao e destruda automaticamente e o metodo destroyApp e chamado. A aplicacao tambem pode ser pausada com o pauseApp, entrando no estado Paused. Nesse estado, o MIDlet deve liberar todos os recursos alocados. Alem dos metodos que enviam um sinal ao MIDlet para a mudanca de estado, ha tambem metodos da classe que enviam um sinal ao gerenciador de aplicacoes para informar da mudanca de estado da sua aplicacao, como o notifyDestroyed e notifyPaused. Ao utilizar o notifyDestroyed, por exemplo, o software gerenciador nao ira chamar o destroyApp, mas o proprio MIDlet deve ter realizado as mesmas operacoes que o metodo de destruicao, como a liberacao de recursos. Atraves da combinacao desses metodos da classe MIDlet monta-se o ciclo de vida de sua aplicacao. E importante manter correta a comunicacao entre a aplicacao e o software gerenciador de aplicacoes, estando sempre atento a questao de liberacao de recursos e troca de sinais para mudanca de estado.

Os commands do Java ME sao usados para gerar e tratar eventos. Por exemplo, um comando pode ser associado a um botao, ou imagem, de modo que, quando este for selecionado, ou clicado, o evento sera disparado. Um command guarda a informacao semantica de uma acao, como pode ser visto pelos tipos de comandos existentes, mostrados mais abaixo. Desse modo, ele e responsavel apenas pelo significado, e nao a acao propriamente dita. A acao fica como responsabilidade da implementacao de um CommandListener associado a tela em o Command se encontra. Um comando deve ser criado da seguinte maneira: Command(String shortLabel, String longLabel, int commandType, int priority) Onde shortLabel e o nome abreviado do comando, longLabel e o nome completo do comando e commandType e o tipo do comando. Ha tambem um outro construtor para objetos da classe Command, com a ausencia do parametro longLabel.

Os tipos possveis do commandType sao os seguintes: A prioridade de um comando so e importante se algum objeto disparar mais de um evento de uma vez, neste caso, somente o comando de maior prioridade e avaliado. Estes comandos devem entao ser tratados por uma classe que implementa a interface CommandListener. Nesta classe sera definido o metodo commandAction que vai decidir que acao deve ser tomada quando cada evento e disparado. Exemplos de implementacoes de commands e CommandListeners podem ser encontrados no final desta apostila, na secao Estudo de Caso - Liga Quatro ou neste site: http://pt. wikibooks.org/wiki/J2ME/Li%C3%A7%C3%B5es/CommandListener 6.3 Displays e Displayables O Display e unico por MIDlet e e o responsavel por funcoes relacionadas a tela do dispositivo. Para obter uma referencia ao Display, a aplicacao deve utilizar o metodo getDisplay. Atraves dessa classe, e possvel chamar metodos para obter algumas informacoes importantes para a sua aplicacao, como o numero de cores do aparelho, ou ate mesmo se ele suporta cores. A classe Display tambem possui metodos para controlar funcoes do dispositivo, como vibrar, atraves do metodo vibrate, e um efeito de luz do aparelho, com o metodo flashBackLight. Um objeto so possui a capacidade de ser inserido no Display ao estender a classe Displayable. Porem, um Displayable apenas tem capacidade para ter comandos, listeners, ttulos e tickers associados a ele. Tudo que e mostrado e a sua interacao com o usuario e definida atraves de subclasse, como e o exemplo do Canvas. A utilizacao do Displayable e feita com os metodos setCurrent e getCurrent da classe Display, que troca e retorna o objeto do tipo Displayable atualmente na tela, respectivamente. Caso nao seja definido nas subclasses do Displayable, a configuracao inicial do seu objeto sera:

Nenhum ticker associado ao Displayable em questao; Nenhum command existente; Nenhum listener para comandos. 6.4 Canvas A classe Canvas e uma subclasse de Displayable, e e utilizada para objetos da sua aplicacao que precisam fazer alteracoes graficas na tela, ou receber eventos de teclas pressionadas no dispositivo. Em geral, os jogos utilizam muito essa classe, para poder interagir com o usuario tanto na recepcao de estmulos quanto na apresentacao dos resultados desses estmulos.

Esta classe e responsavel por tratar eventos de entrada, como teclas pressionadas, soltas ou mantidas pressionadas (keyPressed, keyReleased e keyRepeated, respectivamente) e tambem eventos com um pointer de um PDA (similares aos de tecla). E possvel verificar qual das teclas foi pressionadas com o metodo getKeyCode, mas em Java ME existe um artifcio que e recomendado para os desenvolvedores de jogos, que e o sistema de Game Actions. Os Game Actions sao definidos para aplicacoes portaveis que utilizam as teclas de setas de um dispositivo e eventos relacionados a jogos. O MIDP prove os seguintes Game Actions: UP, DOWN,LEFT,RIGHT,FIRE,GAME A,GAME B,GAME CeGAME D.CadaGameAction pode estar a associado a mais de um Key Code, porem cada tecla so pode estar associada a um Game Action. A aplicacao pode traduzir um Key Code para um Game Action atraves do metodo getGameAction e fazer o oposto atraves de getKeyCode. Apesar de varios Key Codes poderem estar associados ao mesmo Game Action, apenas um deles e retornado com este metodo. Outra funcao do Canvas e o controle grafico do que e exibido. Isso e feito atraves do setFullScreenMode, que tanto coloca quanto tira do modo de exibicao em tela cheia, e o metodo repaint, que renderiza o Canvas por completo ou apenas uma regiao dele, artficio muito util para reduzir o tempo gasto com processamento para repintar uma area sem alteracoes. 6.5 Sprites e Tiles Entre as bibliotecas do Java ME, existem as classes Sprite e TiledLayer, que sao utilizadas para fazer os objetos animados e o fundo do seu jogo, respectivamente. Um Sprite, por sua definicao, e uma imagem ou animacao em duas ou tres dimensoes que sera utilizada para representar um objeto, e muitas vezes sao usados para detectar colisoes ou fazer algum tipo de interacao do jogo. Ja os Tiles sao usados para representar o fundo da tela, usualmente uma paisagem, um tabuleiro ou alguma cena de um jogo. 6.5.1 Sprites Para a classe Sprite, um arquivo de imagem e dividido em varios frames de tamanho igual, e voce pode criar livremente uma sequencia dos frames para gerar sua animacao. Para animar sua sequencia, sao usados metodos como o nextFrame, setFrame e prevFrame. Com esta classe do Java ME tambem e possvel definir a area de colisao de um sprite, assim como verificar se houve colisao entre dois sprites, entre um sprite e um Tile ou ate mesmo entre um sprite e uma imagem, utilizando metodos como defineCollisionRectangle e collidesWith. Os Sprites em Java ME sao produzidos a partir de uma unica imagem com todos os frames que serao utilizados para renderizar a animacao. E possvel fazer apenas um frame, mas nos demais casos a imagem fonte e dividida igualmente em frames de uma determinada largura e altura. A sequencia da animacao e criada atraves de uma Frame Sequence, que nada mais e do que um array com os ndices dos frames gerados. Um objeto do tipo Sprite pode ter um pixel de referencia. Esse pixel e definido por padrao como a posicao (0,0) do sprite, podendo ser redefinida para qualquer outra

posicao, ate mesmo fora dos limites do sprite. Esse pixel existe para permitir algumas operacoes que sao realizadas baseadas em algum referencial, como transformacoes de rotacao e espelhamento do sprite. Segue abaixo um exemplo de sprite com um pixel de referencia influenciando na rotacao.

Figura 6.1: Imagens retiradas de: http://java.sun.com/javame/reference/apis/jsr118/javax/ microedition/lcdui/game/Sprite.html 6.5.2 TiledLayer Uma TiledLayer se trata de uma imagem composta de uma grade de celulas, onde cada celula e preenchida com uma imagem estatica chamada tile. Essa composicao de imagens menores permite economia de espaco, e e uma tecnica muito usada em diversos jogos de duas dimensoes. Cada posicao na grade da TiledLayer recebe um indce, ao qual e associado um tile. Cada um desses tiles e considerado estatico e fica ligado a imagem que ele representa. Existe tambem um animated tile, que e um tile virtual associado dinamicamente a um estatico. Com os tiles animados, ao se utilizar o mesmo animated tile em diversas celulas da grade, e possvel mudalas ao mesmo tempo apenas modificando o tile estatico ao qual eles estao associados. A grade da TiledLayer possui um numero de celulas de mesmo tamanho distribudas por linhas e colunas, definidas na criacao do objeto. As celulas da grade nao podem receber mais de um tile por vez, mas varias celulas podem receber o mesmo tile. Para mudar o conteudo de uma das celulas, podem ser utilizados os metodos setCell e fillCells. 6.6 Sons O JavaME possui uma API responsavel por funcionalidades multimdia, como gravacao de audio e vdeo, alem dos controle de sons. A Mobile Media API, ou MMAPI, funciona basicamente atraves das classes Manager, Player e os controladores VolumeControl e ToneControl. A classe Manager e utilizada para criar os Players. Isso pode ser feito atraves do metodo createPlayer, onde voce passa como parametros um InputStream do arquivo de som que sera tocado e o tipo (wave, midi, mp3, etc). Assim, voce obtem um Player para tocar o som/musica desejada e devera controlar esse novo objeto para obter o efeito desejado.

Alguns exemplos de formatos e as Strings que devem ser passados como parametro para o createPlayer: Wave - audio/x-wav AU - audio/basic MP3 - audio/mpeg Midi - audio/midi Tone - audio/x-tone-seq O Player que foi obtido pode ser utilizado de uma forma simples, apenas chamando o metodo start para que ele comece e pare ao chegar ao fim da mdia especificada. InputStream stream = getClass().getResourceAsStream(sound_file); Player p = Manager.createPlayer(stream, format); p.start(); O Player permite uma maior variedade de acoes, com a combinacao dos metodos da classe e o seu sistema de estados. Os estados da classe Player sao: Unrealized, Realized, Started, Closed e Prefetched. A imagem abaixo mostra como sao feitas as transicoes entre os estados atraves dos metodos mostrados nas flechas presentes na figura. O estado Unrealized indica que o Player nao possui nem informacoes nem recursos necessarios para funcionar. Realized indica que apenas os recursos nao foram adquiridos ainda. O estado Prefetched significa que todos os recursos ja foram adquiridos. Ja o estado Closed mostra que o Player esta fechado e, por fim, Started e o estado de um Player que ja foi iniciado. Alem dos estados e dos metodos para se trocar entre eles, a classe Player tem tambem metodos para descobrir a duracao da mdia a ela atribuda, fixar um numero de repeticoes para a mdia e descobrir o estado atual, entre outros (getDuration, setLoopCount e getState, respectivamente). A Mobile Media API tambem possui o Control, cujos objetos podem ser utilizados para controlar algumas funcoes das mdias. Por exemplo, o Player suporta um VolumeControl, que pode ser utilizado para controlar o volume do audio desse Player. Existe tambem o ToneControl, que e responsavel por manipular sequencias de tons monotonicos, uma outra forma de produzir sons para a sua aplicacao. A classe Manager ainda possui o metodo playTone, que e uma maneira bem mais simples de se colocar sons no seu jogo. Este metodo recebe como parametros a nota, a duracao e o volume, e produz um tom monotonico como resultado. Este tipo de som pode ser util em diversos tipos de jogos ou aplicacoes, que nao necessitam de algo mais complexo do que pequenos tons para os efeitos sonoros. Ha apenas o risco de esse tipo de solucao ocupar muitos recursos da CPU, 25 que acontece apenas em casos de dispositivos que nao possuem suporte para geracao de tons. 26 7 Estudo de Caso - Liga Quatro 7.1 Introducao

Nesta secao vamos falar um pouco sobre o jogo que nos escolhemos para implementar na plataforma Java ME, o Liga Quatro. O jogo, tambem conhecido em ingles como Four in a Row, Four in a Line, ou pelo nome registrado Connect 4, e um jogo simples de tabuleiro para dois jogadores, que jogam em turnos alternados colocando suas fichas em colunas com o objetivo de ser o primeiro a conectar quatro fichas, seja na vertical, na horizontal ou em qualquer diagonal. Cada jogador escolhe uma coluna por turno e sua ficha e depositada no primeiro espaco livre daquela coluna. Este jogo foi escolhido por dois motivos principais: a possibilidade de se comparar a implementacao do jogo em Java ME e Java SE, ampliando o aprendizado da tecnologia em estudo, e a interface simples. A possibilidade de comparacao de implementacoes se deu porque os bolsistas envolvidos ja estavam desenvolvendo o jogo em Java SE para a disciplina de Estruturas de Dados. Essa comparacao permitiu uma analise detalhada das diferenca entre as duas tecnologias e as dificuldades de se portar o codigo para uma plataforma movel. Uma das maiores dificuldades foi modificar alguns trechos para se adaptar a baixa capacidade de processamento e de memoria dos dispositivos moveis. 7.2 Estrutura do codigo 7.2.1 Commands Aqui estao declarados os atributos da classe MidletL4 do tipo Command. O construtor do Command recebe como primeiro parametro o texto que sera mostrado ao usuario para representar o comando. Outro parametro e o tipo de comando, que pertence a um Enum (BACK, EXIT, HELP, OK, CANCEL, SCREEN, STOP, ITEM). O terceiro parametro corresponde a prioridade do comando com relacao aos outros comandos da mesma tela, sendo o menor numero a maior prioridade. Neste caso, como todos tem a mesma prioridade, os comandos irao aparecer na ordem em que sao adicionados. Com prioridades diferentes, os comandos ficam listados por ordem de maior prioridade para menor, para facilitar o acesso do usuario aos comandos mais importantes. private Command botaoIrParaMenu = new Command("Voltar", Command.BACK, 0); private Command botaoOK = new Command("OK", Command.OK, 0); private Command botaoSairDoJogo = new Command("Sair", Command.EXIT, 0); A nossa classe MidletL4 implementa a interface CommandListener e precisamos implementar o metodo commandAction. Assim, ele recebe um comando e a tela (Displayable) em que o comando foi executado. No codigo demonstrado, fazemos comparacoes para saber em qual tela o jogo se encontra atualmente. Ha algumas telas em que so existe uma acao possvel, como por exemplo as telas de Splash. Desse modo,

nao e preciso saber qual comando foi executado, ja que obrigatoriamente deveremos passar para a tela seguinte. Sempre que o comando botaoSairDoJogo for executado, a acao e fechar o aplicativo, nao importando em qual tela o jogo se encontra atualmente. Ja com o comando botaoIrParaMenu, podemos notar que existe uma condicao que verifica se o usuario esta no meio do jogo. Caso isso seja verdade, o jogo fica pausado e a tela de menu recebe um novo botao Continuar Jogo. /** * Recebe os eventos que ocorreram, e a tela em qual ocorreu e * realiza a ac~ao correspondente. * @param comando * O evento recebido. * @param tela * A tela na qual o evento ocorreu. */ public void commandAction(Command comando, Displayable tela) { if (tela == telaSplashL4) { trocarTela(getTelaSplashPET()); } else if (tela == telaSplashPET) { trocarTela(getTelaMenu()); } if (tela == telaOpcoes) { setarOpcoes(); trocarTela(getTelaMenu()); } else if (comando == botaoSairDoJogo) { fecharMIDlet(); } else if (tela == telaVitoria || tela == telaDerrota || tela == telaEmpate) { trocarTela(telaMenu); } else if (comando == botaoIrParaMenu) { if (Controlador.getInstance().jogoNaoAcabou() && tela == telaJogo) { pausado = true; telaMenu.insert(0, getBotaoDeContinuarJogo()); } trocarTela(telaMenu); As trocas de tela sao feitas utilizando o metodo abaixo: /** * Troca a tela atualmente exibida no celular. * @param proximaTela * Tela a ser exibida. */ public void trocarTela(Displayable proximaTela) { display = getDisplay(); display.setCurrent(proximaTela); } 7.2.2 Eventos do menu principal Os comandos executados na tela principal do jogo sao tratados de forma um pouco diferente. Os comandos foram associados a botoes da telaMenu. Assim, toda vez que um botao e pressionado, emitindo um evento, o comando e disparado e tratado por um ItemCommandListener. /** * Cria um Listener para comandos nos itens do menu principal do jogo.

*/ private ItemCommandListener listenerDeItens = new ItemCommandListener() { public void commandAction(Command comando, Item item) { if (item == botaoDeNovoJogo) { Controlador.getInstance().resetar(); comecarNovoJogo(); if (pausado == true) { pausado = false; telaMenu.delete(0); //Remove a opcao de continuar o jogo } } else if (item == botaoDeContinuarJogo) { trocarTela(telaJogo); pausado = false; telaMenu.delete(0); } else if (item == botaoDeOpcoes) { 30 trocarTela(getTelaOpcoes()); } else if (item == botaoDeAjuda) { trocarTela(getTelaAjuda()); } else if (item == botaoDeSobre) { trocarTela(getTelaSobre()); } else if (item == botaoDeSair) { fecharMIDlet(); } Como cada Item (botao) possui somente um comando, o metodo so precisa avaliar qual foi o item pressionado. Abaixo, temos um exemplo de associacao de um comando a um botao. Em seguida, associamos ao botao o ItemCommandListener mostrado no codigo acima. botaoDeNovoJogo.addCommand(botaoOK); botaoDeNovoJogo.setItemCommandListener(listenerDeItens); 7.2.3 A classe TelaDoJogo A classe TelaDoJogo estende GameCanvas e e responsavel pela tela principal do jogo, incluindo deteccao das teclas pressionadas, atualizacao do que e mostrado na tela e efeitos sonoros. O metodo abaixo e responsavel pela atualizacao da tela. Os parametros recebidos servem para delimitar a regiao que sera redesenhada na tela, para questoes de minimizacao de esforco em certos momentos da execucao do programa. O metodo flushGraphics chamado e o que atualiza na tela aquilo que estava no buffer dentro de area desejada. /** * Atualiza uma parte da tela do jogo. * Posic~ao horizontal em pixels onde comeca a area a ser atualizada. * Posic~ao vertical em pixels onde comeca a area a ser atualizada. * @param largura * Largura em pixels da area a ser atualizada.

* @param altura * Altura em pixels da area a ser atualizada. */ public void refresh(int x, int y, int largura, int altura) { layer.paint(g, 0, 0); flushGraphics(x, y, largura, altura); } Para a deteccao de estmulos do usuario, o metodo keyPressed e definido recebendo o codigo da tecla pressionada como parametro. O que fazemos e detectar se o que foi passado corresponde as teclas 4, 6 ou 5, que movimentam a ficha do jogador para esquerda, para a direita ou confirma a jogada, respectivamente. Ha outro trecho condicional que verifica se o codigo da tecla pressionada corresponde a algum gameAction. O gameAction e um mapeamento das teclas especiais de movimentacao um aparelho celular especfico para jogos. Assim, com os dois tipos de verificacao de teclas apresentados abaixo, e possvel utilizar tanto as teclas numericas quanto as direcionais para se jogar. /** * Detecta as teclas que s~ao pressionadas durante o jogo. * @param keyCode * Codigo da tecla pressionada. */ public void keyPressed(int keyCode) { switch (keyCode) { case KEY_NUM4: controle.clicouParaEsquerda(); return; case KEY_NUM6: controle.clicouParaDireita(); return; case KEY_NUM5: controle.clicouPraBaixo(); controle.animando = true; return; } switch (getGameAction(keyCode)) { case LEFT: controle.clicouParaEsquerda(); return; case RIGHT: controle.clicouParaDireita(); return; case DOWN: controle.clicouPraBaixo(); controle.animando = true; return; case FIRE: controle.clicouPraBaixo(); controle.animando = true; return; } Para fazer a tela do jogo, sao utilizadas varias camadas. Cada camada adicionada e posicionada num array, e a camada mais proxima do usuario e a situada na primeira posicao, e a da ultima posicao e a que fica ao fundo de todas. Desse modo, o metodo append insere a camada adicionada no final do array e portanto mais ao fundo. Demonstrando o sistema de camadas da classe GameCanvas, no metodo abaixo adicionamos primeiramente a grade transparente do tabuleiro, que e na verdade a camada que fica acima de todas na tela, em seguida as duas bolas usadas para a animacao das jogadas e por ultimo o fundo com o tabuleiro totalmente pintado. Assim, as bolas ficam na frente do fundo e por tras das grades, o que cria o efeito das bolas deslizando para dentro do tabuleiro. /** * Junta as camadas com imagens do fundo, sprites e grade * transparente do tabuleiro da tela do jogo.

*/ private void juntarCamadasDeImagens() { layer.append(tabuleiro.getTabuleiroTransparente()); layer.append(bolaDeEscolha.getSprite()); layer.append(bolaAuxiliarDeAnimacao.getSprite()); layer.append(tabuleiro.getFundoDoTabuleiro()); flushGraphics(); } 7.2.4 A classe Bola Os objetos da classe Bola possuem os sprites das fichas utilizadas no jogo, assim como metodos para operar sobre esses sprites. Este campo e o proprio sprite, que vai ser utilizado nos metodos da classe. private Sprite bola; Segue abaixo a sequencia que representa a ordem dos frames do sprite e serve para definir a animacao da bola. Os numeros dos frames sao definidos durante a criacao do sprite. Neste caso, ao executar a sequencia (com o metodo bola.nextFrame()), a bola parece estar caindo. Para criar o sprite, passamos como parametro a imagem contendo os frames desejados, e tambem a dimensao do sprite (neste caso, a altura e a largura sao iguais). bola = new Sprite(imagemDaAmarela, diametro, diametro); Abaixo temos o metodo responsavel por mover a bola para a direita. O metodo inicia tomando a posicao atual da bola. A seguir, o sprite e atualizado para o ultimo frame da sequencia do sprite, que representa uma imagem vazia. Essa imagem e pintada na tela com o metodo refresh da classe TelaDoJogo. Isso faz com que a bola suma na tela do usuario. Logo apos, o sprite e movido uma casa para a direita e o sprite e atualizado para o primeiro frame da sequencia, que contem a bola cheia. Essa bola e pintada novamente na tela com o mesmo metodo, fazendo com que ela reapareca. Por questoes de otimizacao, o metodo refresh() pinta apenas a area em que a bola esta se movimentando, para nao pintar desnecessariamente as regioes em que nao ha modificacao na tela. /** * Move a bola para uma casa para a direita. bola.setFrame(3); TelaDoJogo.getInstance().refresh(x, y, diametro, diametro); bola.move(diametro, 0); bola.setFrame(0); TelaDoJogo.getInstance().refresh(x + diametro, y, diametro, diametro); } Este metodo simples move o sprite x pixels no eixo x e y no eixo y. public void mover(int x, int y) { bola.move(x, y); } 7.2.5 PlayTone

Para a utilizacao de sons no jogo, optamos pelo uso do metodo playTone. Este metodo pertence a classe Manager do Java ME e e responsavel por produzir um tom, dado sua duracao e a nota. Os sons presentes no Liga Quatro sao produzidos apos cada jogada e ao mostrar a tela de vitoria, derrota ou empate. Um exemplo pode ser conferido abaixo: /** * Toca o efeito sonoro da bola amarela. */ public void tocarEfeitoBolaAmarela() { try { } catch (InterruptedException ex) { ex.printStackTrace(); } catch (MediaException ex) { ex.printStackTrace(); } O metodo playTone recebe como primeiro parametro a nota, que deve ser um numero entre 0 e 127 e e calculada atraves de uma formula encontrada em http://java.sun.com/javame/ reference/apis/jsr118/. Como segundo parametro, e passada a duracao da nota em milissegundos. O terceiro parametro do metodo corresponde ao volume do tom, que deve ser entre 0 e 100. Assim, produzimos dois tons para o efeito sonoro da bola amarela, com uma pausa entre eles. O Thread.sleep e utilizado para que os tons produzidos nao se sobreponham durante sua execucao.

CLDC 1.1 http://java.sun.com/javame/reference/apis/jsr139/ MIPD 2.0 http://java.sun.com/javame/reference/apis/jsr118/ IDE Netbeans http://www.netbeans.org/ Sun http://www.sun.com/ Wikipedia http://en.wikipedia.org/wiki/Java_Community_Process The Java ME Frequently Asked Questions List http://bellsouthpwp.net/m/c/mcpierce/javamefaq.html

Вам также может понравиться