Projeto Conceitual de Jogos Desenvolvendo Jogos em J2ME para celulares Aula 2 Prática de jogos em J2ME Saulo Souto [email protected] Geber Ramalho [email protected] 18 de setembro, 2006 1 Exercício 1 - Criar o famigerado “Alô mundo!” - Conceitos de Display - Criação e exibição de um High-Level Displayable - Conceitos de adição e tratamento de Comandos 18 de setembro, 2006 2 Exercício 2 - Incrementar o “Alô Mundo” - Conceitos de Graphics e suas funções Fontes Criação e exibição de um Low-Level Displayable Tratamento de teclas Criação e renderização de Imagens 18 de setembro, 2006 3 Nosso Jogo! Shot´em up game simplificadíiiiiiiiiissimo!! “ Star Hero é um jogo singleplayer, no estilo shoot’em up . O jogo consiste em uma espaçonave controlada pelo jogador que trafega pelas galáxias, atirando em inimigos. Essas ações resultam em pontos para o jogador. O objetivo do jogo é acumular o máximo de pontos possíveis.” 18 de setembro, 2006 4 Já Temos as Características... Work! Projetando as classes. Precisamos de: – Um MIDlet (óbvio!) – Uma classe que trata os comandos alto-nível e possui o – – – – – – looping básico do jogo (lê entrada, atualiza estado e pinta a tela) Uma classe que representa um elemento do jogo (Sprite) Uma classe representando a nave Uma classe representando os inimigos Uma classe representando as balas Uma classe representando a tela principal com a lógica principal do jogo Uma classe com todas as constantes (facilitar o acesso) 18 de setembro, 2006 5 Projeto de classes Sprite setX() setY() intersects() update() draw() MIDlet <<extends>> Enemy <<extends>> CommandListener ShipMidlet startApp() pauseApp() destroyApp() update() draw() <<extends>> <<extends>> Ship update() draw() Fire * Runnable update() draw() <<implements>> * <<implements>> ShipController ShipGameScreen run() setPaused() setGameOver() commandAction() loadGameObjects() update() paint() keyPressed() 18 de setembro, 2006 Constants 6 Constants Comandos do jogo Características dos objetos Características do aparelho (largura e altura) Imagens usadas pelos objetos Método para carregar as imagens (loadImages()) 18 de setembro, 2006 7 ShipMidlet Possui referência para a tela principal do jogo Possui referência para o controlador do jogo Inicializa os objetos acima no startApp() Inicializa o looping do jogo no controlador Mostra a tela do jogo 18 de setembro, 2006 8 ShipController Thread que contêm o looping do jogo Trata todos os comandos “alto nível”do jogo Controla o estado de pause/resume do jogo (lembrar que não tem relação com o pauseApp()) 18 de setembro, 2006 9 Sprite Posição x e y na tela Altura e largura Representação gráfica Detecção de colisão Velocidades horizontal e vertical Métodos abstratos update() e draw() 18 de setembro, 2006 10 Ship É um Sprite Array de balas Indicação se a nave está explodindo Animação das imagens Métodos para mover a nave (exercício) Método pra disparar balas (exercício) 18 de setembro, 2006 11 Fire É um Sprite Renderiza a imagem (exercício) – Não possui animação (uma imagem apenas) Tratamento ao sair da tela Atualiza a posição, dada a velocidade (exercício) 18 de setembro, 2006 12 Enemy É um Sprite Possui um comportamento ingênuo (randômico) Imagens animadas 18 de setembro, 2006 13 ShipGameScreen Inicializa e possui todos os objetos do jogo (Nave, Inimigos e Balas) (exercício) Centraliza a atualização dos estados dos objetos (exercício) Controla colisão de balas com inimigos (exercício) Controla colisão de inimigos com a nave (exercício) Renderiza todos os objetos (exercício) Controla e pinta informações do jogo (pontuação, level e vidas) Trata pressionamento das teclas (esquerda,direita e fire) (exercício) 18 de setembro, 2006 14 BUILD & RUN! 18 de setembro, 2006 15 Limitações – – – – – – – Tamanho das telas Memória heap Número de cores Som Tamanho do JAR Latência da rede Custo alto no uso da rede 18 de setembro, 2006 16 Otimize, se necessário Obfuscadores para diminuir tamanho de código – Proguard, Retroguard, etc. Cautela no uso de herança e excesso de classes Evite usar classes anônimas ou aninhadas Acessos a variáveis estáticas e métodos estáticos é mais rápido Arrays no lugar de Vectors Loops de trás pra frente (comparação com 0,null e false é mais rápida) Reuse objetos Cuidado no uso de Strings 18 de setembro, 2006 17 Otimização (cont.) Combine várias imagens em uma só 1 PNG 0.7k 4 PNG 1.6k Número de cores das imagens Uso do Clip pra pintura Preocupações – Tamanho do Jar (64k ~ 100k) – Memória (200k ~ 600k) – Processamento (5 fps ~ 10 fps) 18 de setembro, 2006 18 Exercício (Portar para MIDP 2.0) Fazer nosso Sprite herdar do Sprite de MIDP 2.0 Usar colisão do sprite de MIDP2.0 Usar GameCanvas – Usar tratamento de teclas usando getKeyStates() – Usar back buffer usando getGraphics() – Usar full screen Adição de som (sugestão MIDI) 18 de setembro, 2006 19 Pacote Jogos MIDP 2.0 MIDP 2.0 Packages: – javax.microedition.lcdui.game game lcdui Layer * TiledLayer Sprite LayerManager Displayable GameCanvas Canvas – Vide API http://java.sun.com/javame/reference/apis/jsr118/ 18 de setembro, 2006 20 Sprite s.setFrameSequence(new int[]{0, 1, 2, … , 1, 1, 1, 1}); Sprite s = new Sprite(image, frameWidth, frameHeight); s.move(10, 0); s.nextFrame(); 18 de setembro, 2006 21 Herdar Sprite de MIDP 2.0 Passos gerais – Fundir imagens separadas – Usar frame sequence no lugar de vetores de imagens – Alterar classe Sprite para herdar do Sprite do MIDP 2.0 – Alterar classes dos objetos para adaptações da nova interface de Sprite 18 de setembro, 2006 22 Herdar Sprite de MIDP 2.0 Detalhando.... – Fundir imagens separadas Adaptar método Contants.loadImages() (exercício) Transformar vetores de imagens em frame sequences na classe – – – Constants (exercício) Alterar classe Sprite Declarar herança Remover declaração de campos já herdados Delegar posicionamento a métodos do Sprite MIDP 2.0 (exercício) Adaptar interface do construtor para receber frame sequence Implementar draw() usando Sprite.paint() Usar frame sequence para controlar as animações nas classes Ship, Enemy e Fire Converter chamadas a setImage(…) em setFrameSequence(…) Inicializar frame sequences nos contrutores e nas mudanças de estado das classes (exercício) Remover métodos draw(). Atualizar frames no update() Adaptar inicialização das classes usando novo construtor Adaptar classe ShipGameScreen para passar frame sequence no lugar do vetor de imagens (exercício) 18 de setembro, 2006 23 Melhorias no uso de MIDP 2.0 Fazer nosso Sprite herdar do Sprite de MIDP 2.0 Usar colisão do sprite de MIDP2.0 Usar GameCanvas – Usar tratamento de teclas usando getKeyStates() – Usar back buffer usando getGraphics() – Usar full screen Adição de som (sugestão MIDI) 18 de setembro, 2006 24 Um pouco mais sobre porte Importância do porte – Boa parte do desenvolvimento (~ 40%) – Pensar no porte desde o projeto do jogo Exemplos de variações – Tamanho de tela – API de som – Versão MIDP – Bugs do celular – Idioma – Funcionalidades do jogo – etc… Escala – Chega-se a gerar +1000 versões de uma aplicação 18 de setembro, 2006 25 Boas práticas para o porte Manter código único – Pré-processamento //#ifdef <symbol> http://antenna.sourceforge.net/ http://eclipseme.org/index.html – Aspectos Pesquisas acadêmicas Sistemas de build – Responsável por gerar as várias versões da aplicação – Pré-processa código antes de compilar – Gerencia resources: seleciona arquivos (imagens, sons, etc) por versão – Empacota tudo gerando executáveis (jar e jad) – http://ant.apache.org/manual/ 18 de setembro, 2006 26 Dicas finais Sites interessantes – – – – – http://www.forum.nokia.com http://www.motocoder.com http://wireless.java.sun.com http://www.microjava.com http://www.midlet-review.com Listas de discussão – kvm-interest – j2me-brasil 18 de setembro, 2006 27 Obrigado! Dúvidas? [email protected] 18 de setembro, 2006 28