J2ME/Lições/LayerManager

Já vimos como mostrar gráficos na nossa tela, agora iremos ver algo mais relacionado ao desenvolvimento de jogos em 2D utilizando as classes TiledLayer, Sprite e LayerManager.

Tiles podem ser compreendidos como blocos usados para a construção de cenários estáticos em jogos 2D, a técnica de construção usando Tiles é praticamente a mesma em qualquer plataforma, cria-se um objeto e utiliza-se um vetor para posicionar os Tiles no cenário. Sprites são os seres dinâmicos do jogo como personagens, inimigos, objetos móveis, etc. No J2ME temos a classe LayerManager que serve para controlar e mostrar o mundo do jogo construído através de Tiles e Sprites.

TiledLayer

editar

Vamos começar utilizando a mesma estrutura do GameCanvas.

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();
     
     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

Primeiramente precisamos carregar a imagem onde estão desenhados os tiles, para isso vamos instanciar e criar o objeto do tipo Image como vimos anteriormente.

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();

     Image minhaImagem;
     
     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         try{
             minhaImagem = minhaImagem.createImage("/Minha Imagem.png");
         }catch(Exception ex){
             ex.printStackTrance();
         }
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

Agora vamos instanciar a variável do tipo TiledLayer.

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();
     
     Image minhaImagem;
     TiledLayer meuTiledLayer;

     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         try{
             minhaImagem = minhaImagem.createImage("/Minha Imagem.png");
         }catch(Exception ex){
             ex.printStackTrance();
         }
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

Agora dentro do método run() vamos criar o objeto TiledLayer, vamos entrar com 4 parâmetros: O primeiro é a quantidade de linhas que o cenário vai ter. O segundo é q quantidade de colunas que o cenário vai ter. O terceiro é o objeto Image carregado. O quarto é a largura em pixels de cada tile. O quinto é a altura em pixels de cada tile.

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();
     
     Image minhaImagem;
     TiledLayer meuTiledLayer;

     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         try{
             minhaImagem = minhaImagem.createImage("/Minha Imagem.png");
             meuTiledLayer = new TiledLayer(5, 5, minhaImagem, 16, 16);
         }catch(Exception ex){
             ex.printStackTrance();
         }
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

Agora para vamos criar o vetor para desenharmos a grade de tiles, para isso devemos criar um vetor do tipo int[] e colocar o valor correspondente ao tile, lembre-se que no nosso exemplo usamos uma grade de no máximo 5x5 tiles.

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();
     
     Image minhaImagem;
     TiledLayer meuTiledLayer;

     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         try{
             minhaImagem = minhaImagem.createImage("/Minha Imagem.png");
             meuTiledLayer = new TiledLayer(5, 5, minhaImagem, 16, 16);
             int grade[] = { 2, 1, 1, 1, 3,
                             1, 0, 0, 0, 1,
                             1, 0, 1, 0, 1,
                             1, 0, 0, 0, 1,
                             4, 1, 1, 1, 5 };
         }catch(Exception ex){
             ex.printStackTrance();
         }
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

Agora com o vetor da grade já criado, devemos inseri-lo dentro do objeto TiledLayer, a inserção é feita através do método setCell() onde inserimos cada célula individualmente, para isso vemos criar um laço for criando uma variável de zero até menor que grade.length.

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();
     
     Image minhaImagem;
     TiledLayer meuTiledLayer;

     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         try{
             minhaImagem = minhaImagem.createImage("/Minha Imagem.png");
             meuTiledLayer = new TiledLayer(5, 5, minhaImagem, 16, 16);
             int grade[] = { 2, 1, 1, 1, 3,
                             1, 0, 0, 0, 1,
                             1, 0, 1, 0, 1,
                             1, 0, 0, 0, 1,
                             4, 1, 1, 1, 5 };
             for(int i=0; i<grade.length; i++){
             }
         }catch(Exception ex){
             ex.printStackTrance();
         }
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

Agora dentro do laço for vamos finalmente usar o método setCell() da classe TiledLayer utilizando os seguintes atributos: Primeiro a linha em que está sendo inserido. Segundo a coluna em que está sendo inserido. Terceiro o valor do tile (a célula do vetor grade[]).

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();
     
     Image minhaImagem;
     TiledLayer meuTiledLayer;

     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         try{
             minhaImagem = minhaImagem.createImage("/Minha Imagem.png");
             meuTiledLayer = new TiledLayer(5, 5, minhaImagem, 16, 16);
             int grade[] = { 2, 1, 1, 1, 3,
                             1, 0, 0, 0, 1,
                             1, 0, 1, 0, 1,
                             1, 0, 0, 0, 1,
                             4, 1, 1, 1, 5 };
             for(int i=0; i<grade.length; i++){
                 meuTiledLayer.setCell(i%6, i/6, grade[i]);
             }
         }catch(Exception ex){
             ex.printStackTrance();
         }
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

Sprite

editar

Sprites são imagens com animação geralmente usados como personagens, inimigos ou objetos móveis, vamos ver como implementa-los no J2ME. Inicialmente vamos carregar a imagem onde está desenhado o Sprite, para isso vamos instanciar e criar um objeto do tipo Image como vimos anteriomente.

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();

     Image minhaImagem;
     
     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         try{
             minhaImagem = minhaImagem.createImage("/Minha Imagem.png");
         }catch(Exception ex){
             ex.printStackTrance();
         }
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

Agora vamos instanciar a variável do tipo Sprite.

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();

     Image minhaImagem;
     Sprite meuSprite;
     
     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         try{
             minhaImagem = minhaImagem.createImage("/Minha Imagem.png");
         }catch(Exception ex){
             ex.printStackTrance();
         }
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

Agora dentro do método run() vamos criar o objeto do tipo Sprite, vamos entrar 3 parâmetros: Primeiro o objeto do tipo Image. Segundo a largura em pixels de cada cena. Terceiro a altura em pixels de cada cena.

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();

     Image minhaImagem;
     
     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         try{
             minhaImagem = minhaImagem.createImage("/Minha Imagem.png");
             meuSprite = new Sprite(minhaImagem, 32, 32);
         }catch(Exception ex){
             ex.printStackTrance();
         }
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

LayerManager

editar

Vimos como carregar e criar Tiles e Sprites, agora vamos ver como coloca-los para serem exibidos na tela, para isso iremos ver como usar o LayerManager. Para começar vamos instanciar e inicializar os objetos do tipo TiledLayer e Sprite vistos anteriormente.

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();
     
     Image minhaImagemTile;
     TiledLayer meuTiledLayer;
     Image minhaImagemSprite;
     Sprite meuSprite;

     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         try{
             minhaImagemTile = minhaImagemTile.createImage("/Minha Imagem tile.png");
             meuTiledLayer = new TiledLayer(5, 5, minhaImagemTile, 16, 16);
             int grade[] = { 2, 1, 1, 1, 3,
                             1, 0, 0, 0, 1,
                             1, 0, 1, 0, 1,
                             1, 0, 0, 0, 1,
                             4, 1, 1, 1, 5 };
             for(int i=0; i<grade.length; i++){
                 meuTiledLayer.setCell(i%6, i/6, grade[i]);
             }
             minhaImagemSprite = minhaImagemSprite.createImage("/Minha Imagem sprite.png");
             meuSprite = new Sprite(minhaImagemSprite, 32, 32);
         }catch(Exception ex){
             ex.printStackTrance();
         }
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

Agora para começarmos a controlar a exibição de Tiles e Sprites primeiramente devemos instanciar uma variável do tipo LayerManager.

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();
     
     Image minhaImagemTile;
     TiledLayer meuTiledLayer;
     Image minhaImagemSprite;
     Sprite meuSprite;
     LayerManager meuLayerManager;

     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         try{
             minhaImagemTile = minhaImagemTile.createImage("/Minha Imagem tile.png");
             meuTiledLayer = new TiledLayer(5, 5, minhaImagemTile, 16, 16);
             int grade[] = { 2, 1, 1, 1, 3,
                             1, 0, 0, 0, 1,
                             1, 0, 1, 0, 1,
                             1, 0, 0, 0, 1,
                             4, 1, 1, 1, 5 };
             for(int i=0; i<grade.length; i++){
                 meuTiledLayer.setCell(i%6, i/6, grade[i]);
             }
             minhaImagemSprite = minhaImagemSprite.createImage("/Minha Imagem sprite.png");
             meuSprite = new Sprite(minhaImagemSprite, 32, 32);
         }catch(Exception ex){
             ex.printStackTrance();
         }
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

Agora dentro do run() vamos criar o objeto do tipo LayerManager

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();
     
     Image minhaImagemTile;
     TiledLayer meuTiledLayer;
     Image minhaImagemSprite;
     Sprite meuSprite;
     LayerManager meuLayerManager;

     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         try{
             minhaImagemTile = minhaImagemTile.createImage("/Minha Imagem tile.png");
             meuTiledLayer = new TiledLayer(5, 5, minhaImagemTile, 16, 16);
             int grade[] = { 2, 1, 1, 1, 3,
                             1, 0, 0, 0, 1,
                             1, 0, 1, 0, 1,
                             1, 0, 0, 0, 1,
                             4, 1, 1, 1, 5 };
             for(int i=0; i<grade.length; i++){
                 meuTiledLayer.setCell(i%6, i/6, grade[i]);
             }
             minhaImagemSprite = minhaImagemSprite.createImage("/Minha Imagem sprite.png");
             meuSprite = new Sprite(minhaImagemSprite, 32, 32);
             meuLayerManager = new LayerManager();
         }catch(Exception ex){
             ex.printStackTrance();
         }
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

Agora vamos colocar organizar os objetos do tipo Sprite e TiledLayer para serem exibidos, para isso vamos usar o método append() da classe LayerManager, note que quando se pintar a tela a ordem dos elementos inseridos irá influenciar o que será exibido em cima do outro, sempre o primeiro objeto colocado no append() será o que ficará sempre visível, nesse exemplo vamos insrir na ordem, meuSprite -> meuTile.

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();
     
     Image minhaImagemTile;
     TiledLayer meuTiledLayer;
     Image minhaImagemSprite;
     Sprite meuSprite;
     LayerManager meuLayerManager;

     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         try{
             minhaImagemTile = minhaImagemTile.createImage("/Minha Imagem tile.png");
             meuTiledLayer = new TiledLayer(5, 5, minhaImagemTile, 16, 16);
             int grade[] = { 2, 1, 1, 1, 3,
                             1, 0, 0, 0, 1,
                             1, 0, 1, 0, 1,
                             1, 0, 0, 0, 1,
                             4, 1, 1, 1, 5 };
             for(int i=0; i<grade.length; i++){
                 meuTiledLayer.setCell(i%6, i/6, grade[i]);
             }
             minhaImagemSprite = minhaImagemSprite.createImage("/Minha Imagem sprite.png");
             meuSprite = new Sprite(minhaImagemSprite, 32, 32);
             meuLayerManager = new LayerManager();
             meuLayerManager.append(meuSprite);
             meuLayerManager.append(meuTile);
         }catch(Exception ex){
             ex.printStackTrance();
         }
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

Agora colocaremos a cena para ser exibida na tela, dentro do loop principal vamos usar o método paint() da classe LayerManager e entrar como parâmetros: 1º o objeto do tipo Graphics. 2º o pixel x de onde a cena começará a ser exibida. 3º o pixel y de onde a cena começará a ser exibida.

 import javax.microedition.lcdui.game.*;
 import javax.microedition.lcdui.*;
 
 public class MeuGameCanvas extends GameCanvas implements Runnable {
     Thread meuThread;
     Graphics meuGrafico = this.getGraphics();
     
     Image minhaImagemTile;
     TiledLayer meuTiledLayer;
     Image minhaImagemSprite;
     Sprite meuSprite;
     LayerManager meuLayerManager;

     public MeuGameCanvas(){
         super(false);
         meuThread = new Thread(this);
         meuThread.start();
     }
     public void run(){
         try{
             minhaImagemTile = minhaImagemTile.createImage("/Minha Imagem tile.png");
             meuTiledLayer = new TiledLayer(5, 5, minhaImagemTile, 16, 16);
             int grade[] = { 2, 1, 1, 1, 3,
                             1, 0, 0, 0, 1,
                             1, 0, 1, 0, 1,
                             1, 0, 0, 0, 1,
                             4, 1, 1, 1, 5 };
             for(int i=0; i<grade.length; i++){
                 meuTiledLayer.setCell(i%6, i/6, grade[i]);
             }
             minhaImagemSprite = minhaImagemSprite.createImage("/Minha Imagem sprite.png");
             meuSprite = new Sprite(minhaImagemSprite, 32, 32);
             meuLayerManager = new LayerManager();
             meuLayerManager.append(meuSprite);
             meuLayerManager.append(meuTile);
         }catch(Exception ex){
             ex.printStackTrance();
         }
         boolean fimDeJogo = false;
         while(fimDeJogo == false){
             try{
                 meuLayerManager.paint(meuGrafico, 0, 0);
                 meuThread.sleep(50);
             }(catch Exception minhaEscessao){
                 minhaExcessao.printStackTrance();
             }finally{
                 flushGraphics();
             }
         }
     }
 }

Colisão

editar