J2ME: diferenças entre revisões

[edição verificada][edição verificada]
Conteúdo apagado Conteúdo adicionado
Guiwp (discussão | contribs)
Sem resumo de edição
Abacaxi (discussão | contribs)
Sem resumo de edição
Linha 2:
 
Esse Wikibook é destinado ao aprendizado da programação na plataforma J2ME.
{{livro}}
#[[/API|APIs]]
#[[/Lições/]]
#[[/Tutoriais/]]
#[[/Exemplos/]]
#[[/Colaboradores/]]
 
==Ligações Audio externas==
*[http://java.sun.com/javame/index.jsp Site da Sun]
 
**[http://java.sun.com/products/sjwtoolkit/download.html Download do Wireless Toolkit]
<center>''Por faltar instruções''</center>
*[http://download.netbeans.org/netbeans/6.0/final/ NetBeans 6.0 IDE]
{{reciclagem}}
*[http://www.m3gexporter.com/ M3G Exporter para 3D Studio Max]
{{wikificação}}
*[http://www.m3gexport.com/ M3G Exporter para Maya]
 
*[http://www.nelson-games.de/bl2m3g/default.html M3G Exporter para Blender]
<syntaxhighlight lang="java" enclose="div">
*[http://www.gimp.org/ GIMP]
import java.io.IOException;
*[http://www.anvilstudio.com/ Anvil Studio]
import java.io.InputStream;
*[http://www.blender.org/ Blender]
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Gauge;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.control.VolumeControl;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
 
public class SoundTest extends MIDlet implements Runnable
{
private Display display;
private Player player;
private Form form;
private Gauge volume;
private VolumeControl vc;
private int value=10;
public SoundTest()
{
try
{
display = Display.getDisplay(this);
form = new Form("MP3");
volume = new Gauge("Volume",true,100,10);
form.append(volume);
// form.setItemStateListener(this);
display.setCurrent(form);
 
}
catch (Exception ex)
{
System.out.println(ex);
}
 
}
public void startApp() throws MIDletStateChangeException
{
playMP3();
Thread t = new Thread(this);
t.start();
}
public void pauseApp()
{
 
}
public void destroyApp(boolean unconditional)
{
 
}
public void playMP3()
{
try
{
InputStream is = getClass().getResourceAsStream("/t.mid");
player = Manager.createPlayer(is,"audio/midi");
player.realize();
vc = (VolumeControl) player.getControl("VolumeControl");
player.prefetch();
if(vc != null)
{
vc.setLevel(value);
}
player.start();
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
catch(MediaException me)
{
me.printStackTrace();
}
}
 
public void run()
{
while (true)
{
vc.setLevel(volume.getValue());
try
{
Thread.sleep(20);
}
catch (InterruptedException ie)
{
}
}
 
}
}
</syntaxhighlight>
 
== Canvas ==
 
Durante as primeiras lições trabalhamos com a chamada "interface de alto nível", ou seja, aplicávamos os comandos para a interface pré construída no celular executa-las, agora iremos começar a trabalhar com a chamada "interface de baixo nível", ou seja, iremos dar os comandos diretamente para os gráficos, trabalhando com a manipulação de pixels. Para isso iremos usar amplamente a classe '''Canvas'''.
 
=== Estrutura Canvas ===
 
Primeiramente precisamos criar uma classe exclusiva separada da classe principal para trabalhar com o Canvas, essa também será importada do pacote '''javax.microedition.lcdui''', e irá estender a classe '''Canvas'''.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
}
</syntaxhighlight>
 
Agora devemos colocar o método '''paint()''' que entra como parâmetro um objeto da classe '''Graphics''' que irá controlar o que irá ser exibido no canvas.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
public void paint(Graphics meuGrafico){
}
}
</syntaxhighlight>
 
Agora na classe principal, a chamada do objeto da '''ClasseMeuCanvas''' é feita do mesmo modo das chamadas dos outros objetos, através de um método do objeto '''Display''', vejamos abaixo o conteúdo dos 2 arquivos, o '''ClasseMeuCanvas.java''' e o '''ClassePrincipal.java'''.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
public void paint(Graphics meuGrafico){
}
}
</syntaxhighlight>
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClassePrincipal.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class ClassePrincipal extends MIDlet {
Display meuDisplay = Display.getDisplay(this);
ClasseMeuCanvas meuCanvas = new ClasseMeuCanvas();
 
public void startApp() {
meuDisplay.setCurrent(meuCanvas);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
</syntaxhighlight>
 
=== Desenhando objetos primitivos ===
 
Agora que já sabemos a estrutura de um canvas, vamos desenhar algo na tela, para isso iremos usar o objeto do tipo '''Graphics''' e aplicar sobre ele métodos pré-fabricados pelo J2ME que irão desenhar coisas simples na tela como strings, retângulos, arcos, triângulos, etc. Esses comandos ficarão dentro do método '''paint()'''.
 
==== Desenhando uma linha ====
 
Vamos desenhar uma linha simples, vamos usar o método '''drawLine()''' da classe '''Graphics''', ele irá receber 4 atributos: o 1ª será o pixel x de onde a linha vai começar, o 2º será o pixel y de onde a linha vai começar, o 3º o pixel x onde a linha vai terminar, o 4º será o pixel y onde a linha vai terminar.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
public void paint(Graphics meuGrafico){
meuGrafico.drawLine(30, 40, 70, 90);
}
}
</syntaxhighlight>
 
==== Desenhando um retângulo ====
 
Vamos desenhar um retângulo, vamos usar o método '''drawRect()''' da classe '''Graphics''', ele irá receber 4 atributos: o 1ª será o pixel x de onde o retângulo vai começar, o 2º será o pixel y de onde o retângulo vai começar, o 3º será a largura em pixels do retângulo, o 4º será a altura em pixels do retângulo.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
public void paint(Graphics meuGrafico){
meuGrafico.drawRect(20, 30, 60, 70);
}
}
</syntaxhighlight>
 
==== Desenhando um retângulo cheio ====
 
Você viu anteriormente como desenhar um retângulo na tela, só que no exemplo anterior esse retângulo era oco por dentro, ou seja, você só desenhou as bordas do retângulo, vamos agora fazer um retângulo totalmente pintado por dentro, para isso vamos usar o método '''fillRect()''' da classe '''Graphics''', ele irá receber os mesmos atributos do método '''drawRect()''': o 1ª será o pixel x de onde o retângulo vai começar, o 2º será o pixel y de onde o retângulo vai começar, o 3º será a largura em pixels do retângulo, o 4º será a altura em pixels do retângulo.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
public void paint(Graphics meuGrafico){
meuGrafico.fillRect(20, 30, 50, 60);
}
}
</syntaxhighlight>
 
==== Desenhando uma String ====
 
Vamos desenhar uma string, note que não vamos simplesmente colocar a string na tela, vamos desenhá-la, apesar disso o J2ME já vem com uma fonte string padrão para o Canvas. Vamos usar o método '''drawString()''' da classe '''Graphics''', ele irá receber 4 atributos: o 1º será o texto da string, o 2º será o pixel x de onde vai ser desenhado, o 3º será o pixel y de onde vai ser desenhado, o 4º será a "raiz" do objeto, ou seja, onde será a referência dos pixels x e y.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
public void paint(Graphics meuGrafico){
meuGrafico.drawString("Texto da string", 50, 100, Graphics.LEFT|Graphics.TOP);
}
}
</syntaxhighlight>
 
Nesse caso a raiz do pixel x está no ponto esquerdo do objeto ('''Graphics.LEFT'''), e a raiz do pixel y está no ponto acima do objeto ('''Graphics.TOP'''). Você também pode colocar a raiz do pixel x na direita ('''Graphics.RIGHT''') ou no centro ('''Graphics.HCENTER'''), e a raiz do pixel y na parte de baixo ('''Graphics.BOTTOM''') ou no centro ('''Graphics.VCENTER''').
 
=== Colocando uma cor ===
 
Você pode setar cores para desenhar objetos com cores diferentes, para isso use o método '''setColor()''' da classe '''Graphics''' entrando como parâmetro os valores das cores vermelho, verde e azul respectivamente.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
public void paint(Graphics meuGrafico){
meuGrafico.setColor(255, 0, 0);
meuGrafico.drawRect(50, 50, 20, 30);
}
}
</syntaxhighlight>
 
=== Pegando uma cor ===
 
Para pegar uma cor vamos utilizar o método '''getColor()''' da classe '''Graphics''' que irá retornar um inteiro com os valores RGB agrupados.
 
Primeiro vamos criar a variável inteira que irá armazenar a cor.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
int corPega;
public void paint(Graphics meuGrafico){
}
}
</syntaxhighlight>
 
Agora vamos setar alguma cor através do método '''setColor()'''.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
int corPega;
public void paint(Graphics meuGrafico){
meuGrafico.setColor(255, 128, 64);
}
}
</syntaxhighlight>
 
Agora vamos utilizar o método '''getColor()''', e armazenar o resultado na variável '''corPega'''.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
int corPega;
public void paint(Graphics meuGrafico){
meuGrafico.setColor(255, 128, 64);
corPega = meuGrafico.getColor();
}
}
</syntaxhighlight>
 
O valor obtido na variável '''corPega''' é equivalente ao número hexadecimal agrupado FF, 80, 40 que se traduz em inteiro como 255, 128, 64.
 
=== Desenhando uma imagem ===
 
Vimos anteriormente as primitivas que o J2ME nos oferece, agora vamos mostrar na tela uma imagem feita por nós mesmo. Primeiro crie a sua imagem em algum editor externo a sua escolha, salve a imagem e coloque no mesmo diretório onde se localiza o arquivo ClasseMeuCanvas.java.
 
Agora primeiramente vamos incluir o pacote '''java.io''' que contém o tratamento de exceção.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
</syntaxhighlight>
 
Agora criar uma variável da classe '''Image'''.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
Image minhaImagem;
public void paint(Graphics meuGrafico){
}
}
</syntaxhighlight>
 
Agora vamos usar o construtor para inicializar o objeto '''minhaImagem'''. Para isso vamos jogar a exceção.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
Image minhaImagem;
 
ClasseMeuCanvas throws Exception {
}
public void paint(Graphics meuGrafico){
}
}
</syntaxhighlight>
 
Agora dentro do construtor vamos inicializar o objeto '''minhaImagem''' utilizando o método '''createImage()''' da classe '''Image''', ele receberá como parâmetro o endereço da imagem que você criou.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
Image minhaImagem;
 
ClasseMeuCanvas throws Exception {
minhaImagem = minhaImagem.createImage("/Minha Imagem.png");
}
public void paint(Graphics meuGrafico){
}
}
</syntaxhighlight>
 
Agora dentro do método '''paint()''' vamos botar a nossa imagem para ser exibida, utilizando o método '''drawImage()''' da classe '''Graphics''', como parâmetro ele irá receber 4 atributos: o 1ª será o nome da variável da classe '''Image''', o 2º será o pixel x de onde vai ser desenhado, o 3º será o pixel y de onde vai ser desenhado, o 4º será a "raiz" do objeto, ou seja, onde será a referência dos pixels x e y.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
Image minhaImagem;
 
ClasseMeuCanvas throws Exception {
minhaImagem = minhaImagem.createImage("/Minha Imagem.png");
}
public void paint(Graphics meuGrafico){
meuGrafico.drawImage(minhaImagem, 30, 40, Graphics.LEFT|Graphics.TOP);
}
}
</syntaxhighlight>
 
=== Criando uma atualização de tela ===
 
Vimos como colocar objetos na tela através de um comando, agora vamos ver como se cria uma atualização de tela, para isso dentro do método '''paint()''' iremos usar o método '''repaint()''' que irá funcionar como um "retornador" para o método '''paint()''' ser executado novamente. Para isso vamos primeiro criar uma variável inteira i na ClasseMeuCanvas e vamos inicia-la com o valor 0.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
int i=0;
public void paint(Graphics meuGrafico){
}
}
</syntaxhighlight>
 
Agora vamos desenhar um simples retângulo na tela, vamos usar como os primeiros atributos a variável i que criamos (que no caso vale 0).
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
int i=0;
public void paint(Graphics meuGrafico){
meuGrafico.drawRect(i, i, 100, 100);
}
}
</syntaxhighlight>
 
Vamos agora dar um incremento no i, para sempre que se retornar ao '''paint()''' seu valor ser acrescido de +1.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
int i=0;
public void paint(Graphics meuGrafico){
meuGrafico.drawRect(i, i, 100, 100);
i++;
}
}
</syntaxhighlight>
 
Vamos agora finalmente aplicar o método '''repaint()''' dentro do método '''paint()''', e ver a movimentação do nosso retângulo na tela. Vamos mostrar abaixo o código completo.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
int i=0;
public void paint(Graphics meuGrafico){
meuGrafico.drawRect(i, i, 100, 100);
i++;
repaint();
}
}
</syntaxhighlight>
 
=== Comandos ===
 
Vamos entrar agora na parte de entrada de comandos através das teclas do celular, primeiramente a classe Canvas tem 3 métodos pré-definidos para isso, são o '''keyPressed()''' para quando se aperta a tecla do celular, '''keyRepeated()''' para quando se segura a tecla do celular e '''keyReleased()''' para quando se solta a tecla do celular.
 
Primeiramente para usá-lo vamos fazer a chamada do método fora do médodo '''paint()''', o método deverá ser do tipo protected.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
protected void keyPressed(int getTecla){
}
 
public void paint(Graphics meuGrafico){
repaint();
}
}
</syntaxhighlight>
 
Agora vamos definir uma ação para o caso de o usuário apertar a tecla que queremos, no caso vamos escolher a tecla 1 do celular, vamos colocar um '''if'' dentro do método '''keyPressed()'''. Você pode comparar com as constantes '''KEY_NUM1''', '''KEY_NUM2''', ..., '''KEY_STAR''', '''KEY_POUND'''.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
protected void keyPressed(int getTecla){
if (getTecla == KEY_NUM1);
}
 
public void paint(Graphics meuGrafico){
repaint();
}
}
</syntaxhighlight>
 
Agora vamos colocar uma ação para quando pressionarmos a tecla, nesse caso vamos exibir uma mensagem no console.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
protected void keyPressed(int getTecla){
if (getTecla == KEY_NUM1){
System.out.println("Pressionou tecla 1 do celular");
}
}
 
public void paint(Graphics meuGrafico){
repaint();
}
}
</syntaxhighlight>
 
Você pode usar o mesmo processo apenas trocando método '''keyPressed()''' por '''keyRepeated()''' ou '''keyReleased()'''.
 
=== Comandos de jogo ===
 
Vimos como obter as teclas do teclado padrão do celular (apenas os números e as teclas * e #), agora vamos ver como pegar as teclas auxiliares.
 
Primeiramente vamos usar o mesmo método '''keyPressed()''', '''keyRepeated()''' ou '''keyReleased()''' do módulo anterior.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
protected void keyPressed(int getTecla){
}
 
public void paint(Graphics meuGrafico){
repaint();
}
}
</syntaxhighlight>
 
Agora as constantes das teclas auxiliares não podem ser pegas de forma direta, para isso vamos usar o método '''getKeyCode()''' e como parâmetro vamos entrar o código da tecla que queremos, nesse caso usamos a tecla '''FIRE''' que fica no meio das setas do celular.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
 
public class ClasseMeuCanvas extends Canvas {
protected void keyPressed(int getTecla){
if (getTecla == getKeyCode(FIRE));
}
 
public void paint(Graphics meuGrafico){
repaint();
}
}
</syntaxhighlight>
 
Agora vamos colocar uma ação para quando pressionarmos a tecla, nesse caso vamos exibir uma mensagem no console.
 
<syntaxhighlight lang="java" enclose="div">
public class ClasseMeuCanvas extends Canvas {
protected void keyPressed(int getTecla){
if (getTecla == getKeyCode(FIRE)){
System.out.println("Pressionou tecla FIRE do celular");
}
}
 
public void paint(Graphics meuGrafico){
repaint();
}
}
</syntaxhighlight>
 
== CommandListener ==
 
Agora entraremos na parte interativa onde o usuário pode interagir com as funções do celular através do teclado ou da caneta digital.
 
=== Estrutura básica do CommandListener ===
 
Antes de trabalharmos para receber comandos, na nossa classe Midlet precisamos implementar a classe CommandListener.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet implements CommandListener{
Display meuDisplay = Display.getDisplay(this);
 
public void startApp() {
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
</syntaxhighlight>
 
Agora vamos inserir o método '''commandAction()''' que iremos usar diretamente para manipular as ações do teclado, esse método deverá sempre ter 2 parâmetros, o primeiro é o objeto da classe Command (que veremos logo após) e o outro é o objeto Displayable.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet implements CommandListener{
Display meuDisplay = Display.getDisplay(this);
 
public void startApp() {
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command pegarComando, Displayable pegarDisplay){
}
}
</syntaxhighlight>
 
=== Criando um comando ===
 
Para criar um comando primeiro precisamos intanciar uma variável do tipo '''Command'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet implements CommandListener{
Display meuDisplay = Display.getDisplay(this);
 
Command meuComando;
 
public void startApp() {
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command pegarComando, Displayable pegarDisplay){
}
}
</syntaxhighlight>
 
Agora vamos criar o objeto Command, para isso vamos usar como parâmetro respectivamente: 1º o texto que será exibido na tela, 2º o tipo de comando e 3º a prioridade do comando.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet implements CommandListener{
Display meuDisplay = Display.getDisplay(this);
 
Command meuComando = new Command("OK", Command.OK, 0);
 
public void startApp() {
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command pegarComando, Displayable pegarDisplay){
}
}
</syntaxhighlight>
 
=== Detectando a ação de um comando ===
 
Agora vamos para a parte prática, vamos detectar uma ação de comando pelo teclado do celular, já temos o objeto Command criado, agora vamos criar uma condição caso ele seja apertado.
 
Como vimos anteriormente é dentro do método '''commandAction()''' que fazemos os trabalhos com comandos, é através dos dos atributo do tipo Command que vamos fazer a comparação com o objeto Command externo que criamos, e vamos exibir uma mensagem no console.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet implements CommandListener{
Display meuDisplay = Display.getDisplay(this);
 
Command meuComando = new Command("OK", Command.OK, 0);
 
public void startApp() {
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command pegarComando, Displayable pegarDisplay){
if(pegarComando == meuComando){
System.out.println("Pressionou o botão OK");
}
}
}
</syntaxhighlight>
 
Agora calma, AINDA não vai acontecer nada quando apertarmos o botão, para isso precisamos criar a tela que irá "escutar" o comando que iremos colocar, podemos fazer a tela com qualquer objeto tipo Alert, TextBox, etc... no nosso caso vamos usar um simples Form.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet implements CommandListener{
Display meuDisplay = Display.getDisplay(this);
 
Command meuComando = new Command("OK", Command.OK, 0);
Form meuForm = new Form("Título do formulário");
 
public void startApp() {
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command pegarComando, Displayable pegarDisplay){
if(pegarComando == meuComando){
System.out.println("Pressionou o botão OK");
}
}
}
</syntaxhighlight>
 
Agora dentro do método '''startApp()''' vamos adicionar o comando à tela do Form através do método '''addCommand()'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet implements CommandListener{
Display meuDisplay = Display.getDisplay(this);
 
Command meuComando = new Command("OK", Command.OK, 0);
Form meuForm = new Form("Título do formulário");
 
public void startApp() {
meuForm.addCommand(meuComando);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command pegarComando, Displayable pegarDisplay){
if(pegarComando == meuComando){
System.out.println("Pressionou o botão OK");
}
}
}
</syntaxhighlight>
 
Agora vamos adicionar o "escutador" no Form, para detectar se pressionamos ou não algum botão.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet implements CommandListener{
Display meuDisplay = Display.getDisplay(this);
 
Command meuComando = new Command("OK", Command.OK, 0);
Form meuForm = new Form("Título do formulário");
 
public void startApp() {
meuForm.addCommand(meuComando);
meuForm.setCommandListener(this);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command pegarComando, Displayable pegarDisplay){
if(pegarComando == meuComando){
System.out.println("Pressionou o botão OK");
}
}
}
</syntaxhighlight>
 
Por fim, colocamos normalmente o método '''setCurrent()''' da classe '''Display'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet implements CommandListener{
Display meuDisplay = Display.getDisplay(this);
 
Command meuComando = new Command("OK", Command.OK, 0);
Form meuForm = new Form("Título do formulário");
 
public void startApp() {
meuForm.addCommand(meuComando);
meuForm.setCommandListener(this);
meuDisplay.setCurrent(meuForm);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command pegarComando, Displayable pegarDisplay){
if(pegarComando == meuComando){
System.out.println("Pressionou o botão OK");
}
}
}
</syntaxhighlight>
 
== Form ==
 
Vamos agora aprender a fazer Forms (formulários), são dentro das forms que podemos inserir vários ítens de uma aplicação.
 
=== Inserindo um simples Form ===
 
Vamos ver como inserir um simples form numa aplicação, primeiro criamos o objeto Form.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet {
Display meuDisplay = Display.getDisplay(this);
Form meuForm;
 
public void startApp() {
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
</syntaxhighlight>
 
Agora vamos inicializar o formulário com o construtor, como parâmetro vamos colocar a String que será exibida na tela.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet {
Display meuDisplay = Display.getDisplay(this);
Form meuForm = new Form("Título do formulário");
 
public void startApp() {
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
</syntaxhighlight>
 
Agora vamos usar o método '''setCurrent()''' da classe '''Display''' entrando o nosso formulário como parâmetro para exibir o formulário na tela.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet {
Display meuDisplay = Display.getDisplay(this);
Form meuForm = new Form("Título do formulário");
 
public void startApp() {
meuDisplay.setCurrent(meuForm);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
</syntaxhighlight>
 
=== Inserindo ítens no Form ===
 
Como vimos, objetos Form podem conter vários ítens, aqui veremos que o construtor do Form pode conter outros parâmetros, vejamos agora cada um deles.
 
==== ChoiceGroup ====
 
==== CustomItem ====
 
==== DateField ====
 
==== Gauge ====
 
==== ImageItem ====
 
==== Spacer ====
 
==== StringItem ====
 
==== TextField ====
 
== GameCanvas ==
 
O Canvas foi uma classe criada para o tratamentos de eventos de baixo nível, que durande o Midp1.0 foi muito usada na produção de jogos, a partir da versão Midp2.0, o J2ME apresentou uma nova classe, a GameCanvas com ações mais voltadas para a manipulação de jogos.
 
=== Iniciando um GameCanvas ===
 
Primeiramente vamos importar o pacote que contém a classe GameCanvas.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.game.*;
</syntaxhighlight>
 
Agora vamos criar a classe MeuGameCanvas, extendendo a classe GameCanvas.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.game.*;
 
public class MeuGameCanvas extends GameCanvas{
}
</syntaxhighlight>
 
Uma classe que extende o GameCanvas precisa obrigatoriamente de um construtor.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.game.*;
 
public class MeuGameCanvas extends GameCanvas{
public MeuGameCanvas(){
}
}
</syntaxhighlight>
 
Agora precisamos obrigatoriamente instanciar a classe superior GameCanvas dentro do construtor, usaremos o argumento true (se quisermos herdar os métodos da classe Canvas) ou false (se quisermos usar apenas os métodos da classe GameCanvas.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.game.*;
 
public class MeuGameCanvas extends GameCanvas {
public MeuGameCanvas(){
super(false);
}
}
</syntaxhighlight>
 
=== Utilizando Canvas no GameCanvas ===
 
Do mesmo modo que a classe Canvas, na classe GameCanvas podemos usar o método '''paint()''' (que na GameCanvas é public) para exibir algo na tela. Vamos primeiramente inserir o pacote que contém a classe Canvas.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.*;
 
public class MeuGameCanvas extends GameCanvas {
public MeuGameCanvas(){
super(false);
}
 
public void paint(Graphics meuGrafico){
}
}
</syntaxhighlight>
 
Agora vamos criar o método '''paint()'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.*;
 
public class MeuGameCanvas extends GameCanvas {
public MeuGameCanvas(){
super(false);
}
 
public void paint(Graphics meuGrafico){
}
}
</syntaxhighlight>
 
Agora vamos desenhar um retângulo na tela.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.*;
 
public class MeuGameCanvas extends GameCanvas {
public MeuGameCanvas(){
super(false);
}
 
public void paint(Graphics meuGrafico){
meuGrafico.drawRect(10, 20, 100, 200);
}
}
</syntaxhighlight>
 
Também podemos implementar outros métodos da classe Canvas como o '''keyPressed()''' (como public).
 
=== Estrutura básica do GameCanvas ===
 
Vimos que podemos fazer tudo que fazíamos no Canvas dentro do GameCanvas, mas vamos ver agora que o GameCanvas não trabalha somente "reinventando a roda", ele possui um tratamento diferente que se assemelha mais as várias APIs de criação de jogos que existem por ai, não vamos trabalhar com um método padrão, e sim com loops que irão fixar a tela, até quando uma condição faça com que o loop pare.
 
Bom, primeiramente agora que não temos mais o método paint() que era inicializado automaticamente, vamos agora usar outro método que também é chamado automaticamente, ele está dentro da interface '''Runnable''', vamos implementar na classe.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.*;
 
public class MeuGameCanvas extends GameCanvas implements Runnable {
public MeuGameCanvas(){
super(false);
}
}
</syntaxhighlight>
 
Agora devemos obrigatoriamente incluir dentro da nossa classe o método '''run()''' da interface '''Runnable''' que é o método que é chamado automaticamente, será dentro dele que iremos incluir todas as ações da classe.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.*;
 
public class MeuGameCanvas extends GameCanvas implements Runnable {
public MeuGameCanvas(){
super(false);
}
public void run(){
}
}
</syntaxhighlight>
 
Agora vamos instanciar um objeto da classe '''Thread''', ele será o controlador que irá iniciar a nossa classe.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.*;
 
public class MeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
 
public MeuGameCanvas(){
super(false);
}
public void run(){
}
}
</syntaxhighlight>
 
Devemos agora iniciar o objeto thread dentro do construtor da classe, como parâmetro vamos usar o this da classe GameCanvas.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.*;
 
public class MeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
 
public MeuGameCanvas(){
super(false);
meuThread = new Thread(this);
}
public void run(){
}
}
</syntaxhighlight>
 
Já temos tudo pronto, agora por último vamos iniciar a o objeto Thread que criamos utilizando o método '''start()''' dentro do construtor.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.*;
 
public class MeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
 
public MeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
}
}
</syntaxhighlight>
 
=== Exibindo algo no GameCanvas ===
 
Agora com a estrutura básica do nosso GameCanvas pronta, precisamos criar um objeto do tipo '''Graphics''' dentro da nossa classe GameCanvas.
 
<syntaxhighlight lang="java" enclose="div">
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(){
}
}
</syntaxhighlight>
 
Agora dentro criaremos o loop principal dentro do método '''run()''', primeiramente vamos criar uma variavel booleana, para criar a condição do jogo.
 
<syntaxhighlight lang="java" enclose="div">
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;
}
}
</syntaxhighlight>
 
Agora vamos criar o loop com um comando while que irá comparar a variavel booleana que criamos.
 
<syntaxhighlight lang="java" enclose="div">
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){
}
}
}
</syntaxhighlight>
 
Por fim dentro do loop vamos chamar o método '''flushGraphics()''' que irá desenhar o gráfico na tela do celular.
 
<syntaxhighlight lang="java" enclose="div">
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){
flushGraphics();
}
}
}
</syntaxhighlight>
 
Agora como exemplo vamos exibir um retângulo na tela através do objeto do tipo Graphics.
 
<syntaxhighlight lang="java" enclose="div">
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){
meuGrafico.drawRect(10, 20, 100, 200);
flushGraphics();
}
}
}
</syntaxhighlight>
 
=== Controlando a velocidade do aplicativo ===
 
Agora que fizemos a exibição precisamos controlar a velocidade de atualização do loop, isso porque do jeito que está o aplicativo irá rodar mais rápido em celulares com melhor hardware e mais lentos em celulares com pior hardware.
 
Para isso primeiramente precisamos criar um '''try-catch-finally''' dentro do loop principal.
 
<syntaxhighlight lang="java" enclose="div">
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{
}catch (Exception minhaExcessao){
minhaExcessao.printStackTrace();
}finally{
}
}
}
}
</syntaxhighlight>
 
Agora, como devemos sempre pintar a tela a cada loop colocamos o '''flushGraphics()''' dentro do '''finally'''.
 
<syntaxhighlight lang="java" enclose="div">
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{
}catch (Exception minhaExcessao){
minhaExcessao.printStackTrace();
}finally{
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora dentro do '''try''' vamos utilizar o método '''sleep()''' da classe '''Thread''' e entrar como parâmetro o tempo em milisegundos que a aplicação deve esperar para chamar o próximo loop, nesse caso iremos esperar 50 milisegundos (o que dá 20 quadros por segundo) que é mais ou menos a taxa de atualização da tela da maioria dos celulares.
 
<syntaxhighlight lang="java" enclose="div">
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 minhaExcessao){
minhaExcessao.printStackTrace();
}finally{
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora por último colocaremos um simples retângulo para andar na tela, para isso criaremos uma variável '''int''' auxiliar que irá encrementar-se a cada loop, e depois usaremos essa variável em um parâmetro do método '''drawRect()'''.
 
<syntaxhighlight lang="java" enclose="div">
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(){
int auxiliar = 0;
boolean fimDeJogo = false;
while(fimDeJogo == false){
try{
meuGrafico.drawRect(auxiliar, 0, 10, 20);
meuThread.sleep(50);
}catch (Exception minhaExcessao){
minhaExcessao.printStackTrace();
}finally{
auxiliar++;
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Você pode mudar a taxa de atualização na tela (método sleep()) e verá que o retângulo irá se mover com diferentes velocidades.
 
=== Controles no GameCanvas ===
 
No Canvas tratávamos separadamente a parte dos comandos e a parte dos gráfico, agora no GameCanvas podemos tratar dessas coisas tudo no mesmo loop, vamos ver agora que essa parte será tratada de uma forma bem diferente e muito mais simples.
 
Primeiramente dentro do '''run()''' vamos criar uma variável que tem que ser do tipo '''int''' que irá receber os controles.
 
<syntaxhighlight lang="java" enclose="div">
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;
int tecla;
 
while(fimDeJogo == false){
try{
meuGrafico.drawRect(10, 20, 100, 200);
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrace();
}finally{
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora dentro do loop principal vamos checar se alguma tecla foi pressionada através do método '''getKeyStates()'''.
 
<syntaxhighlight lang="java" enclose="div">
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;
int tecla;
 
while(fimDeJogo == false){
try{
tecla = getKeyStates();
meuGrafico.drawRect(10, 20, 100, 200);
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrace();
}finally{
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora vamos criar uma condição caso uma tecla específica seja apertada, nesse caso vamos usar a tecla FIRE e desenhar outro retângulo na tela caso ela seja apertada, note que agora vamos usar a constante '''FIRE_PRESSED'''.
 
<syntaxhighlight lang="java" enclose="div">
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;
int tecla;
 
while(fimDeJogo == false){
try{
tecla = getKeyStates();
if(tecla == FIRE_PRESSED){
meuGrafico.drawRect(20, 40, 80, 100);
}
 
meuGrafico.drawRect(10, 20, 100, 200);
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrace();
}finally{
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
=== Imagens no GameCanvas ===
 
Vamos agora ver como carregar uma imagem no GameCanvas, isso pode se aplicar ao carregamento de outros arquivos também.
 
Primeiramente dentro do método '''run()''' vamos colocar um try-catch.
 
<syntaxhighlight lang="java" enclose="div">
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(){
try{
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrace();
}
 
boolean fimDeJogo = false;
while(fimDeJogo == false){
try{
meuThread.sleep(50);
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrace();
}finally{
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora dentro do vamos instanciar o objeto '''Image''' na classe MeuGameCanvas.
 
<syntaxhighlight lang="java" enclose="div">
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{
meuThread.sleep(50);
}catch(Exception ex){
ex.printStackTrace();
}
 
boolean fimDeJogo = false;
while(fimDeJogo == false){
try{
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrace();
}finally{
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Depois vamos iniciar o objeto '''Image''' dentro do try no método '''run()'''.
 
<syntaxhighlight lang="java" enclose="div">
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.printStackTrace();
}
 
boolean fimDeJogo = false;
while(fimDeJogo == false){
try{
meuThread.sleep(50);
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrace();
}finally{
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora normalmente dentro do loop do jogo colocamos a imagem para ser exibida.
 
<syntaxhighlight lang="java" enclose="div">
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.printStackTrace();
}
 
boolean fimDeJogo = false;
while(fimDeJogo == false){
try{
meuGrafico.drawImage(minhaImagem, 30, 40, Graphics.LEFT|Graphics.TOP);
meuThread.sleep(50);
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrace();
}finally{
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
== Instalação ==
 
# Para começar a desenvolver aplicativos em J2ME você primeiro precisa ter instalado no computador o J2SE, para baixa-lo clique [http://java.sun.com/javase/downloads/index.jsp aqui].
# Após instalado o J2SE você irá baixar o J2ME clicando [http://java.sun.com/javame/downloads/index.jsp aqui].
# Após instalado o J2SE e o J2ME você já pode começar a programar suas applets.
# Para instalar a IDE NetBeans com o Mobility Pack clique [http://www.netbeans.org/downloads/index.html aqui].
# Para instalar a IDE Eclipse com a ferramenta Pulsar para desenvolvimento para celular clique [http://www.eclipse.org/downloads/packages/pulsar-mobile-java-developers/galileor aqui].
 
== 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 ===
 
Vamos começar utilizando a mesma estrutura do GameCanvas.
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
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.
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
Agora vamos instanciar a variável do tipo '''TiledLayer'''.
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
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.
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
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.
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
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'''.
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
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[]).
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
=== Sprite ===
 
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.
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
Agora vamos instanciar a variável do tipo '''Sprite'''.
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
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.
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
=== LayerManager ===
 
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.
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
Agora para começarmos a controlar a exibição de Tiles e Sprites primeiramente devemos instanciar uma variável do tipo '''LayerManager'''.
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
Agora dentro do '''run()''' vamos criar o objeto do tipo '''LayerManager'''
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
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.
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
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.
 
<syntaxhighlight lang="java" enclose="div">
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();
}
}
}
}
</syntaxhighlight>
 
=== Colisão ===
 
== M3G ==
 
Vamos agora iniciar o estudo do pacote M3G, é esse pacote que trabalha com a parte de gráficos em 3D no J2ME, para um bom uso é necessário que se tenha um bom conhecimento no Canvas e no GameCanvas.
 
# [[== M3G/No Canvas|No Canvas]] ==
# [[== M3G/No GameCanvas|No GameCanvas]] ==
# [[== M3G/Modificando objetos 3D|Modificando objetos 3D]] ==
# [[== M3G/Criando objetos primitivos|Criando objetos primitivos]] ==
# [[== M3G/Colisões|Colisões]] ==
 
== M3G/Colisões ==
 
Colisões podem parecer simples em 2D, mas são um pouco mais complicadas no mundo em 3D, vamos ver aqui como fazer colisões da câmera para as meshes do cenário.
 
==== Checando colisões ====
 
Vamos ver como checar colisões, primeiramente devemos criar um objeto do tipo '''RayIntersection''', é ele que vai armazenar todos os dados da colisão.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
RayIntersection meuRayIntersection;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrance();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora vamos criar 2 arrays de float, um irá pegar a posição X, Y, Z da câmera, o outro irá pegar a oriêntação da câmera. Essas variáveis devem ser obrigatoriamente iniciadas.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
RayIntersection meuRayIntersection;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
 
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrance();
}
 
float[] translacaoCamera = {0.0f, 0.0f, 0.0f}
float[] orientacaoCamera = {0.0f, 0.0f, 0.0f, 0.0f}
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora vamos criar uma variável booleana para checar se houve uma colisão, vamos coloca-la inicialmente como false.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
RayIntersection meuRayIntersection;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrance();
}
 
float[] translacaoCamera = {0.0f, 0.0f, 0.0f}
float[] orientacaoCamera = {0.0f, 0.0f, 0.0f, 0.0f}
boolean colisao = false;
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora dentro do loop principal, vamos usar os métodos '''getTranslation()''' e '''getOrientation()''' para armazenar nas variáveis translacaoCamera e rotacaoCamera, os atributos da nossa câmera.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
RayIntersection meuRayIntersection;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrance();
}
 
float[] translacaoCamera = {0.0f, 0.0f, 0.0f}
float[] orientacaoCamera = {0.0f, 0.0f, 0.0f, 0.0f}
boolean colisao = false;
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
 
minhaCamera.getTranslation(translacaoCamera);
minhaCamera.getOrientation(orientacaoCamera);
 
meuGrafico3D.render(meuMundo);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora vamos testar a colisão através do método '''pick()''', que terá como enrada os seguintes valores:
# escopo - sempre será -1
# posição X - a posição X da câmera que foi pega no getTranslation()
# posição Y - a posição Y da câmera que foi pega no getTranslation()
# posição Z - a posição Z da câmera que foi pega no getTranslation()
# orientação X - a orientação X da câmera que foi pega no getOrientation()
# orientação Y - a orientação Y da câmera que foi pega no getOrientation()
# orientação Z - a orientação Z da câmera que foi pega no getOrientation()
# RayIntersection - o objeto RayIntersection que criamos anteriormente
Esse método '''pick()''' irá retornar a condição true ou false para a nossa variável booleana colisao;
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
RayIntersection meuRayIntersection;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrance();
}
 
float[] translacaoCamera = {0.0f, 0.0f, 0.0f}
float[] orientacaoCamera = {0.0f, 0.0f, 0.0f, 0.0f}
boolean colisao = false;
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
 
minhaCamera.getTranslation(translacaoCamera);
minhaCamera.getOrientation(orientacaoCamera);
colisao = meuMundo.pick(-1,
translacaoCamera[0],
translacaoCamera[1],
translacaoCamera[2],
orientacaoCamera[1],
orientacaoCamera[2],
orientacaoCamera[3],
meuRayIntersection);
 
meuGrafico3D.render(meuMundo);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora, vamos criar um '''if'' para caso a colisão seja verdadeira mostrar uma mensagem no console.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
RayIntersection meuRayIntersection;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrance();
}
 
float[] translacaoCamera = {0.0f, 0.0f, 0.0f}
float[] orientacaoCamera = {0.0f, 0.0f, 0.0f, 0.0f}
boolean colisao = false;
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
 
minhaCamera.getTranslation(translacaoCamera);
minhaCamera.getOrientation(orientacaoCamera);
colisao = meuMundo.pick(-1,
translacaoCamera[0],
translacaoCamera[1],
translacaoCamera[2],
orientacaoCamera[1],
orientacaoCamera[2],
orientacaoCamera[3],
meuRayIntersection);
if (colisao == true){
System.out.println("Colisão verdadeira");
}
 
meuGrafico3D.render(meuMundo);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
== M3G/Criando objetos primitivos ==
 
Além de poder carregar objetos externos você também pode criar objetos primitivos usando os recursos do próprio M3G.
 
=== Criando uma câmera ===
 
Apesar do arquivo .m3g ter a facilidade de se poder criar a própria câmera, ela pode apresentar alguns tipos de dificuldade em relação ao aspecto de tela de cada celular, que pode deixar o gráfico exibido no celular "esticado" tanto horizontalmente quanto verticalmente. Para resolver isso é recomendável criar uma própria câmera definindo os aspectos de cada celular.
 
Para fazer isso crie um arquivo .m3g em algum editor externo, mas lembre-se de NÃO colocar uma câmera no arquivo, já que essa nós vamos criar manualmente. Com o arquivo criado vamos carrega-lo normalmente como fizemos anteriomente, adicionar no objeto '''World''', e renderiza-lo normalmente.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrance();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora, como vamos manipular a câmera manualmente vamos criar um objeto do tipo '''Camera'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrance();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora dentro do construtor vamos inicializar a câmera.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = new Camera();
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrance();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora vamos usar o método '''setPerspective()''' para ajustar os atributos da câmera, o primeiro atributo será o ângulo de visão em graus (60 é a angulação padrão), o próximo campo será o aspecto da tela que será a largura da tela dividida pela autura, o terceiro campo é a distância em que a cena começará a ser renderizada (deve ser obrigatoriamente maior que zero), e por último é a distância máxima da renderização (o horizonte).
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo = (World) meuObjeto3D[0];
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrance();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora vamos adicionar o nosso objeto do tipo Camera para o mundo 3D, para isso vamos usar o método '''addChild()''' e entrar a nossa câmera como parâmetro.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas() throws Exception {
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo = (World) meuObjeto3D[0];
meuMundo.addChild(minhaCamera);
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrance();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Por último agora que adicionamos a câmera ao mundo 3D, vamos dizer ao mundo 3D que queremos que essa câmera seja a câmera ativa, através do método '''setActiveCamera()''' entrando como parâmetro o nome da câmera.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas() throws Exception {
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo = (World) meuObjeto3D[0];
meuMundo.addChild(minhaCamera);
meuMundo.setActiveCamera(minhaCamera);
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrance();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
=== Criando um triângulo ===
 
Vamos começar criando o mais simples dos polígonos, o triângulo, primeiramente na nossa classe vamos colocar o que aprendemos anteriormente.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo.addChild(minhaCamera);
meuMundo.setActiveCamera(minhaCamera);
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
==== VertexArray ====
 
O objeto do tipo '''VertexArray''' (array de vértices) é o tipo de objeto genérico que pode guardar coisas como a posição dos vértices, normais, texturas, etc...
 
===== Vértices =====
 
Primeiramente vamos criar um array do tipo '''short''' que irá armazenar os vértices X, Y e Z (nessa ordem) do nosso triângulo.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo.addChild(minhaCamera);
meuMundo.setActiveCamera(minhaCamera);
 
short[] vetorVertices = {-1, 0, -1, -1, 0, 1, 1, 0, -1}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Sabemos que o VertexArray pode guardar coisas como a posição dos vértices, normais, texturas, etc... no nosso caso iremos criar um objeto para armazenar a posição dos vértices. Como parâmetros do construtor iremos entrar:
# O número de vértices do VertexArray (como faremos um triângulo então teremos 3 vértices)
# O número de componentes por vértice (nesse caso são 3, os eixos X, Y e Z).
# O tamanho em bytes de cada componente (nesse caso 2, pois um short ocupa 2 bytes). OBS: O tamanho máximo é 2.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo.addChild(minhaCamera);
meuMundo.setActiveCamera(minhaCamera);
 
short[] vetorVertices = {-1, 0, -1, -1, 0, 1, 1, 0, -1}
VertexArray arrayDePosicoes = new VertexArray(3, 3, 2);
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Criamos o array dos vértices e criamos também o objeto do tipo VertexArray. Agora iremos colocar o array ''vetorVertices'' que criamos dentro do objeto VertexArray para isso iremos usar o método '''set()''' onde iremos entrar 3 parâmetros:
# O primeiro vértice do vetor vertices (nesse caso e quase sempre será zero)
# O número de vértices do VertexArray (como faremos um triângulo então teremos 3 vértices).
# O vetor de vértices (o que criamos ''short[] vertices'').
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo.addChild(minhaCamera);
meuMundo.setActiveCamera(minhaCamera);
 
short[] vetorVertices = {-1, 0, -1, -1, 0, 1, 1, 0, -1}
VertexArray arrayDePosicoes = new VertexArray(3, 3, 2);
arrayDePosicoes.set(0, 3, vetorVertices);
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
===== Normais =====
 
A exemplo do anterior primeiramente criamos um array do tipo '''short''' que agora irá armazenar a posição das noemais de cada vértice (127-padrão, 0-sem normal, -127-invertido) nesse caso como fizemos um triângulo plano vamos setar a normal padrão para o eixo Y (virado para cima).
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo.addChild(minhaCamera);
meuMundo.setActiveCamera(minhaCamera);
 
short[] vetorVertices = {-1, 0, -1, -1, 0, 1, 1, 0, -1}
VertexArray arrayDePosicoes = new VertexArray(3, 3, 2);
arrayDePosicoes.set(0, 3, vetorVertices);
 
short[] vetorNormais = {0, 127, 0, 0, 127, 0, 0, 127, 0}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora vamos criar o objeto '''VertexArray''' com os mesmos atributos no construtor (número de vertices do VextexArray, o numero de componentes de cada vértice, o tamanho em bytes de cada componente).
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo.addChild(minhaCamera);
meuMundo.setActiveCamera(minhaCamera);
 
short[] vetorVertices = {-1, 0, -1, -1, 0, 1, 1, 0, -1}
VertexArray arrayDePosicoes = new VertexArray(3, 3, 2);
arrayDePosicoes.set(0, 3, vetorVertices);
 
short[] vetorNormais = {0, 127, 0, 0, 127, 0, 0, 127, 0}
VertexArray arrayDeNormais = new VertexArray(3, 3, 2);
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
E por fim, chamar novamente o método '''set()''' com os mesmos atributos (índice do primeiro vértice, o numero de vértice do VertexArray, o vetor de vértices).
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo.addChild(minhaCamera);
meuMundo.setActiveCamera(minhaCamera);
 
short[] vetorVertices = {-1, 0, -1, -1, 0, 1, 1, 0, -1}
VertexArray arrayDePosicoes = new VertexArray(3, 3, 2);
arrayDePosicoes.set(0, 3, vetorVertices);
 
short[] vetorNormais = {0, 127, 0, 0, 127, 0, 0, 127, 0}
VertexArray arrayDeNormais = new VertexArray(3, 3, 2);
arrayDeNormais.set(0, 3, vetorNormais);
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
===== Textura* =====
 
Por último vamos agora criar um vetor para as texturas.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo.addChild(minhaCamera);
meuMundo.setActiveCamera(minhaCamera);
 
short[] vetorVertices = {-1, 0, -1, -1, 0, 1, 1, 0, -1}
VertexArray arrayDePosicoes = new VertexArray(3, 3, 2);
arrayDePosicoes.set(0, 3, vetorVertices);
 
short[] vetorNormais = {0, 127, 0, 0, 127, 0, 0, 127, 0}
VertexArray arrayDeNormais = new VertexArray(3, 3, 2);
arrayDeNormais.set(0, 3, vetorNormais);
 
short[] vetorTexturas = {1, 0, 0, 0, 1, 1}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Vamos também criar o objeto do tipo '''VextexArray''' utilizando os mesmos atributos anteriores (número de vertices do VextexArray, o numero de componentes de cada vértice, o tamanho em bytes de cada componente).
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo.addChild(minhaCamera);
meuMundo.setActiveCamera(minhaCamera);
 
short[] vetorVertices = {-1, 0, -1, -1, 0, 1, 1, 0, -1}
VertexArray arrayDePosicoes = new VertexArray(3, 3, 2);
arrayDePosicoes.set(0, 3, vetorVertices);
 
short[] vetorNormais = {0, 127, 0, 0, 127, 0, 0, 127, 0}
VertexArray arrayDeNormais = new VertexArray(3, 3, 2);
arrayDeNormais.set(0, 3, vetorNormais);
 
short[] vetorTexturas = {1, 0, 0, 0, 1, 1}
VertexArray arrayDeTexturas = new VertexArray(2, 2, 2);
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
E por fim chamamos o método '''set()''' com os mesmos atributos (índice do primeiro vértice, o numero de vértice do VertexArray, o vetor de vértices).
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo.addChild(minhaCamera);
meuMundo.setActiveCamera(minhaCamera);
 
short[] vetorVertices = {-1, 0, -1, -1, 0, 1, 1, 0, -1}
VertexArray arrayDePosicoes = new VertexArray(3, 3, 2);
arrayDePosicoes.set(0, 3, vetorVertices);
 
short[] vetorNormais = {0, 127, 0, 0, 127, 0, 0, 127, 0}
VertexArray arrayDeNormais = new VertexArray(3, 3, 2);
arrayDeNormais.set(0, 3, vetorNormais);
 
short[] vetorTexturas = {1, 0, 0, 0, 1, 1}
VertexArray arrayDeTexturas = new VertexArray(2, 2, 2);
arrayDeTexturas.set(0, 2, vetorTexturas);
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
==== Vertex buffer* ====
 
Criamos os arrays dos vértices, das normais e das texturas, agora precisamos agrupar esses arrays em um único buffer, por isso agora iremos criar um objeto do tipo '''VertexBuffer'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo.addChild(minhaCamera);
meuMundo.setActiveCamera(minhaCamera);
 
short[] vetorVertices = {-1, 0, -1, -1, 0, 1, 1, 0, -1}
VertexArray arrayDePosicoes = new VertexArray(3, 3, 2);
arrayDePosicoes.set(0, 3, vetorVertices);
 
short[] vetorNormais = {0, 127, 0, 0, 127, 0, 0, 127, 0}
VertexArray arrayDeNormais = new VertexArray(3, 3, 2);
arrayDeNormais.set(0, 3, vetorNormais);
 
short[] vetorTexturas = {1, 0, 0, 0, 1, 1}
VertexArray arrayDeTexturas = new VertexArray(2, 2, 2);
arrayDeTexturas.set(0, 2, vetorTexturas);
 
VertexBuffer meuVertexBuffer = new VertexBuffer();
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora para colocar o array de posições que criamos anteriormente vamos usar o método '''setPositions()''' da classe VertexBuffer, como parâmetros entraremos o objeto VertexArray, a escala (tamanho) do objeto e por fim o parâmetro null.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
minhaCamera = new Camera();
minhaCamera.setPerspective(60.0f, (float)getWidth()/(float)getHeight(), 1.0f, 100.0f);
meuMundo.addChild(minhaCamera);
meuMundo.setActiveCamera(minhaCamera);
 
short[] vetorVertices = {-1, 0, -1, -1, 0, 1, 1, 0, -1}
VertexArray arrayDePosicoes = new VertexArray(3, 3, 2);
arrayDePosicoes.set(0, 3, vetorVertices);
 
short[] vetorNormais = {0, 127, 0, 0, 127, 0, 0, 127, 0}
VertexArray arrayDeNormais = new VertexArray(3, 3, 2);
arrayDeNormais.set(0, 3, vetorNormais);
 
short[] vetorTexturas = {1, 0, 0, 0, 1, 1}
VertexArray arrayDeTexturas = new VertexArray(2, 2, 2);
arrayDeTexturas.set(0, 2, vetorTexturas);
 
VertexBuffer meuVertexBuffer = new VertexBuffer();
meuVertexBuffer.setPositions(arrayDePosicoes, 1.0f, null);
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
== M3G/Modificando objetos 3D ==
 
Vamos entrar agora na parte de modificação dos objetos .m3g carregados no J2ME, vamos utilizar isso através do objeto for tipo '''World''' que criamos, na verdade esse objeto servirá como uma ponte de ligação entre o programador e os nódulos do objeto 3D em si.
 
==== Translação de um objeto ====
 
Vamos inicialmente aprender como translatar um nódulo do objeto 3D, quando se fala em translação você deve pensar em um movimento giratório que a Terra faz no sol, no mundo 3D não é bem assim, na verdade a translação nada mais é que a posição dos eixos x, y, z dentro do espaço.
 
Primeiramente vamos translatar a câmera que você criou e armazenou no arquivo .m3g, para isso vamos criar um objeto do tipo '''Camera()''' e inicializa-lo.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Criamos a variável minhaCamera, mas nenhuma câmera foi colocada lá, agora vamos fazer isso através do nosso objeto do tipo '''World''', utilizando o método '''getActiveCamera()'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora com a câmera armazanada vamos movimenta-la, para isso só precisamos pegar emprestado da classe '''World''' o método '''setTranslation()''' que irá receber 3 variáveis float, que serão respectivamente o eixo x, y e z.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
} catch (Excepetion minhaExcessao) {
minhaExcessao.printStackTrace();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
minhaCamera.setTranslation(1.0f, 3.0f, 2.0f);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
==== Pegando a translação de um objeto ====
 
Vamos ver agora como pegar a translação (posição dentro do mundo) de um objeto, vamos usar o mesmo exemplo anterior.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
minhaCamera.setTranslation(1.0f, 3.0f, 2.0f);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Vamos pegar a posição X, Y e Z da câmera, para isso vamos inicialmente criar um array float de 3 posições chamado '''posicaoCamera[]''', e inicia-lo com 0.
 
<syntaxhighlight lang="java" enclose="div">
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}
 
boolean gameOver = false;
float[] posicaoCamera = {0.0, 0.0, 0.0};
 
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
minhaCamera.setTranslation(1.0f, 3.0f, 2.0f);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora dentro do loop principal vamos usar o método '''getTranslation()''' e entrar como parâmetro a variável float que criamos que vai pegar os 3 atributos X, Y e Z nessa ordem, como saída vamos dar um '''System.out.println()''' para exibir cada posição.
 
<syntaxhighlight lang="java" enclose="div">
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}
 
boolean gameOver = false;
float[] posicaoCamera = {0.0, 0.0, 0.0};
 
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
minhaCamera.setTranslation(1.0f, 3.0f, 2.0f);
minhaCamera.getTranslation(posicaoCamera);
System.out.println(posicaoCamera[0]);
System.out.println(posicaoCamera[1]);
System.out.println(posicaoCamera[2]);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
==== Orientação de um objeto ====
 
Vamos agora ver como orientar (rotacionar) um objeto 3D, vamos fazer como anteriormente, carregar o objeto, coloca-lo no objeto World e colocar a câmera na classe Camera.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
 
ClasseMeuCanvas(){
super(false)
meuThread = new Thread(this);
meuThread.start();
}
 
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Vamos agora utilizar o método '''setOrientation()''' e entrar como parâmetro respectivamente o angulo, o componente de roatação X, o componente de roatação Y e o componente de roatação Z. Esses componentes de rotação se colocados como 0 não irão alterar o eixo de rotação.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
 
ClasseMeuCanvas(){
super(false)
meuThread = new Thread(this);
meuThread.start();
}
 
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
minhaCamera.setOrientation(10, 1, 2, 0);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
No exemplo a câmera irá girar 10 graus no eixo X, 20 graus no eixo Y, e 0 graus no eixo Z.
 
==== Pegando a orientação de um objeto ====
 
Vamos ver agora como pegar a orientação de um objeto, vamos usar o mesmo exemplo anterior.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
if (meuMundo != null) {
minhaCamera.setOrientation(10.0f, 0.0f, 1.0f, 2.0f);
meuGrafico3D.render(meuMundo);
}
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Vamos pegar a rotação X, Y e Z da câmera, para isso vamos inicialmente criar um array float agora de 4 posições chamado orientacaoCamera[], e inicia-lo com 0.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}
 
boolean gameOver = false;
float[] orientacaoCamera = {0.0, 0.0, 0.0, 0.0};
 
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
if (meuMundo != null) {
minhaCamera.setOrientation(10.0f, 0.0f, 1.0f, 2.0f);
meuGrafico3D.render(meuMundo);
}
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora dentro do loop principal vamos usar o método '''getOrientation()''' e entrar como parâmetro a variável float que criamos que vai pegar os 4 atributos, como saída vamos dar um System.out.println() para exibir cada um.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}
 
boolean gameOver = false;
float[] orientacaoCamera = {0.0, 0.0, 0.0, 0.0};
 
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
if (meuMundo != null) {
minhaCamera.setOrientation(10.0f, 0.0f, 1.0f, 2.0f);
minhaCamera.getOrientation(orientacaoCamera);
System.out.println(orientacaoCamera[0]);
System.out.println(orientacaoCamera[1]);
System.out.println(orientacaoCamera[2]);
System.out.println(orientacaoCamera[3]);
meuGrafico3D.render(meuMundo);
}
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
==== Pegando um objeto específico ====
 
O World no M3G pode conter várias câmeras, meshes, luzes, etc, vamos ver aqui como pegar cada um desses objetos. Primeiramente é bom no seu editor 3D nomear cada objeto com um número, quando esse arquivo for salvo ficará mais fácil de você pegar a identificação do objeto através de um número inteiro.
 
Primeiramente vamos pegar os exemplos anteriores.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
if (meuMundo != null) {
meuGrafico3D.render(meuMundo);
}
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora vamos criar o objeto '''Node''', que é o objeto que pode pegar a referência de uma câmera, mesh, luz, etc...
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
Node meuNode;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
if (meuMundo != null) {
meuGrafico3D.render(meuMundo);
}
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora vamos usar o método '''getChild()''' no objeto '''World''' e entrar como parâmetro a idêntificação do objeto selecionado.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
Node meuNode;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}
meuNode = meuMundo.getChild(1);
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
if (meuMundo != null) {
meuGrafico3D.render(meuMundo);
}
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora usamos normalmente os métodos para modificar o Node, nesse caso vamos move-lo usando '''translate()'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
Camera minhaCamera = new Camera();
Node meuNode;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
minhaCamera = meuMundo.getActiveCamera();
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}
meuNode = meuMundo.getChild(1);
 
boolean gameOver = false;
while(gameOver == false){
try {
meuGrafico3D.bindTarget(meuGrafico);
if (meuMundo != null) {
meuNode.translate(0.0f, 0.0f, 0.1f);
meuGrafico3D.render(meuMundo);
}
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
==== Animando um objeto 3D ====
 
Você colocou um objeto 3D para ser mostrado no seu aplicativo, mas se você criou um objeto animado deve ter notado que o objeto não expressou nenhum quadro da animação. Para fazer isso vamos usar o método '''animate()''' da classe '''World''' e receber como parâmetro, uma variavel '''int''' que irá incrementar a cada frame.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
 
public ClasseMeuCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
 
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrace();
}
 
int frame = 0;
 
boolean gameOver = false;
while(gameOver == false){
try{
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcessao) {
minhaExcessao.printStackTrace();
}finally{
meuGrafico3D.releaseTarget();
flusGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora vamos chamar o método '''animate()''' e como parâmetro colocar uma variavel para a contagem do frame para a animação do objeto.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
 
public ClasseMeuCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
 
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrace();
}
 
int frame = 0;
 
boolean gameOver = false;
while(gameOver == false){
try{
meuGrafico3D.bindTarget(meuGrafico);
meuMundo.animate(frame);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrace();
}finally{
meuGrafico3D.releaseTarget();
frame++;
flushGraphics()
}
}
}
}
</syntaxhighlight>
 
== M3G/No Canvas ==
 
=== Preparando um gráfico no Canvas ===
 
Primeiramente dentro da nossa classe de Canvas vamos incluir o pacote M3G que tem todas as classes e métodos para se trabalhar com gráficos 3D.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
</syntaxhighlight>
 
Vamos agora criar normalmente nossa classe de Canvas.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends Canvas {
}
</syntaxhighlight>
 
Agora colocaremos o método '''paint()''' dentro da nossa classe de Canvas.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends Canvas {
public void paint(Graphics meuGrafico){
}
}
</syntaxhighlight>
 
E dentro do método '''paint()''' colocaremos o método '''repaint()'''.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends Canvas {
public void paint(Graphics meuGrafico){
repaint();
}
}
</syntaxhighlight>
 
=== Iniciando o gráfico 3D no Canvas ===
 
Até agora fizemos todo o preparativo para receber um gráfico canvas 2D, vamos agora iniciar um objeto do tipo '''Graphics3D''' com o método '''getInstance()''' dentro da nossa classe de Canvas.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends Canvas {
Graphics3D meuGrafico3D = Graphics3D.getInstance();
 
public void paint(Graphics meuGrafico){
repaint();
}
}
</syntaxhighlight>
 
Agora iniciaremos o nosso gráfico 3D dentro do método '''paint()''', para isso vamos usar o método '''bindTarget()''' da classe '''Graphics3D''', e vamos usar como parâmetro o objeto da classe '''Graphics'''.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends Canvas {
Graphics3D meuGrafico3D = Graphics3D.getInstance();
 
public void paint(Graphics meuGrafico){
meuGrafico3D.bindTarget(meuGrafico);
repaint();
}
}
</syntaxhighlight>
 
Agora vamos terminar o processo de renderização do gráfico com o método '''releaseTarget()''' da classe '''Graphics3D''', esse método deverá estar sempre APÓS a chamada do método '''bindTarget()'''.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends Canvas {
Graphics3D meuGrafico3D = Graphics3D.getInstance();
 
public void paint(Graphics meuGrafico){
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.releaseTarget();
repaint();
}
}
</syntaxhighlight>
 
=== Exibindo um objeto em 3D no Canvas ===
 
Vamos agora ver como exibir um objeto já criado, primeiro crie o seu objeto em 3D em algum programa a sua escolha depois salve o seu arquivo na mesma pasta do arquivo ClasseMeuCanvas.java. O processo é um pouco parecido com o de exibição de uma imagem na tela.
 
Agora primeiramente vamos incluir o pacote '''java.io''' que contém o tratamento de exceção.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
import java.microedition.m3g.*;
</syntaxhighlight>
 
Agora vamos criar uma variável do tipo '''Object3D[]'''.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends Canvas {
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
 
public void paint(Graphics meuGrafico){
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.releaseTarget();
repaint();
}
}
</syntaxhighlight>
 
Agora vamos criar o construtor da classe '''ClasseMeuCanvas''' jogando a exceção IOException que é necessário para inciarmos o nosso objeto.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends Canvas {
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
 
ClasseMeuCanvas() throws IOException {
}
public void paint(Graphics meuGrafico){
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.releaseTarget();
repaint();
}
}
</syntaxhighlight>
 
Agora vamos inicializar o nosso objeto '''meuObjeto3D''' dentro do construtor, usando a classe '''Loader''' com o método '''load()''' que irá receber como parâmetro o endereço da localização do arquivo 3D que vamos carregar.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends Canvas {
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
 
ClasseMeuCanvas() throws IOException {
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
}
public void paint(Graphics meuGrafico){
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.releaseTarget();
repaint();
}
}
</syntaxhighlight>
 
Agora poderíamos estar prontos para mostrar o objeto 3D na tela, mas calma, não é possível exibir objetos do tipo '''Object3D''' na tela, por isso devemos converter o nosso objeto '''meuObjeto3D''' para um tipo aceito para a renderização, nesse caso o tipo será da classe '''World''' que irá renderizar tudo dentro do nosso arquivo .m3g de uma vez, e que futuramente também será usado para modificar os atributos do arquivo .m3g. Por isso vamos primeiramente criar a nossa variável do tipo '''World'''.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends Canvas {
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
 
ClasseMeuCanvas() throws IOException {
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
}
public void paint(Graphics meuGrafico){
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.releaseTarget();
repaint();
}
}
</syntaxhighlight>
 
Agora dentro do construtor após a inicialização do objeto '''meuObjeto3D''' vamos converter o tipo '''Object3D[]''' para o tipo '''World'''.
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends Canvas {
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
 
ClasseMeuCanvas() throws IOException {
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
}
public void paint(Graphics meuGrafico){
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.releaseTarget();
repaint();
}
}
</syntaxhighlight>
 
Agora sim, podemos exibir o objeto que criamos na tela, para isso dentro do método '''paint()''', no espaço entre os métodos '''bindTarget()''' e '''releaseTarget()''' ficará todas as ações do módulo 3D. Para isso vamos usar nosso objeto da classe '''Graphics3D()''' e entrar o método '''render()''' que irá receber como parâmetro o nosso objeto do tipo '''World''' (que convertemos previamente).
 
<syntaxhighlight lang="java" enclose="div">
//arquivo ClasseMeuCanvas.java
import java.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
public class ClasseMeuCanvas extends Canvas {
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
 
ClasseMeuCanvas() throws IOException {
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
}
public void paint(Graphics meuGrafico){
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuGrafico3D.releaseTarget();
repaint();
}
}
</syntaxhighlight>
 
== M3G/No GameCanvas ==
 
=== Preparando um gráfico no GameCanvas ===
 
Inicializamos a ClasseMeuGameCanvas do mesmo jeito que fazemos com o GameCanvas normal, extendendo o GameCanvas, implementando o Runnable e colocando os objetos e métodos necessários.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
boolean gameOver = false;
while(!gameOver){
try{
meuThread.sleep(50);
}catch(Exception minhaExcessao){
minhaExcessao.printstackTrace();
}finally{
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
=== Iniciando um gráfico 3D no GameCanvas ===
 
Vimos que a parte de inicialização do gráfico é igual a parte 2D, agora vamos criar o gráfico 3D em si, para isso vamos criar um objeto do tipo Graphics3D.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
boolean gameOver = false;
while(!gameOver){
try{
meuThread.sleep(50);
}catch(Exception minhaExcessao){
minhaExcessao.printStackTrace();
}finally{
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora nessa parte vamos fazer um pouco diferente do que em relação ao Canvas normal, para iniciar o gráfico 3D dentro do GameCanvas devemos obrigatoriamente criar um '''try-catch-finally''' dentro do método '''run()''', nesse caso agora como a cada loop vamos sempre chamar o método '''flushGraphics()''' vamos coloca-lo dentro do '''finally'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
boolean gameOver = false;
while(!gameOver){
try {
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace)();
} finally {
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora podemos chamar os métodos padrões do '''Graphics3D''', primeiramente dentro do '''try''' vamos chamar o gráfico3D para inicializar o gráfico através do método '''bindTarget()'''
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
boolean gameOver = false;
while(!gameOver){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace)();
} finally {
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora vamos chamar o método '''releaseTarget()''' para soltar o gráfico 3D e deixar o programa correr normalmente, mas atente que faremos isso sempre dentro do '''finally''', caso o programa não consiga inicializar o gráfico 3D.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
boolean gameOver = false;
while(!gameOver){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
=== Exibindo um objeto em 3D no GameCanvas ===
 
Vamos agora ver como exibir um objeto criado externamente dentro do GameCanvas, primeiro crie normalmente um objeto .m3g em algum editor externo (não se esqueça de colocar a câmera e a luz) e salve na mesma pasta da sua classe.
 
Agora vamos importar primeiramente o pacote '''java.io''' para o projeto.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
</syntaxhighlight>
 
Agora vamos criar a variável do tipo '''Object3D[]'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
 
public ClasseMeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
boolean gameOver = false;
while(!gameOver){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora dentro do método '''run()''', mas antes do loop vamos criar um '''try-catch'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
 
public ClasseMeuGameCanvas() throws Exception {
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
} catch(Exception minhaExcessao) {
minhaExcecao.printStackTrace();
}
 
boolean gameOver = false;
while(!gameOver){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora vamos criar a variável do tipo '''Object3D[]'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
 
public ClasseMeuGameCanvas() throws Exception {
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
} catch(Exception minhaExcessao) {
minhaExcecao.printStackTrace();
}
 
boolean gameOver = false;
while(!gameOver){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Como sabemos, não se pode manipular objetos diretamente pelo '''Object3D[]''', temos que criar outro objeto do tipo '''World'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
 
public ClasseMeuGameCanvas() throws Exception {
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
} catch(Exception minhaExcessao) {
minhaExcecao.printStackTrace();
}
 
boolean gameOver = false;
while(!gameOver){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrace();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora dentro do '''try-catch''' vamos converter o nosso objeto do tipo '''Object3D[]''' para o tipo '''World'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
 
public ClasseMeuGameCanvas() throws Exception {
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
} catch(Exception minhaExcessao) {
minhaExcecao.printStackTrace();
}
 
boolean gameOver = false;
while(!gameOver){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
Agora vamos colocar o nosso World para ser renderizado no nosso gráfico 3D, vamos colocar o método '''render()''' dentro do '''run()''' logo após o '''bindTarget()'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;
 
public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Graphics3D meuGrafico3D = Graphics3D.getInstance();
Object3D[] meuObjeto3D;
World meuMundo;
 
public ClasseMeuGameCanvas() throws Exception {
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
try{
meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
meuMundo = (World) meuObjeto3D[0];
} catch(Exception minhaExcessao) {
minhaExcecao.printStackTrace();
}
 
boolean gameOver = false;
while(!gameOver){
try {
meuGrafico3D.bindTarget(meuGrafico);
meuGrafico3D.render(meuMundo);
meuThread.sleep(50);
} catch (Exception minhaExcecao) {
minhaExcecao.printStackTrance)();
} finally {
meuGrafico3D.releaseTarget();
flushGraphics();
}
}
}
}
</syntaxhighlight>
 
== Primeira aplicação ==
 
Neste artigo você irá aprender a criar a sua primeira classe para J2ME.
 
=== Importando ===
 
Para começarmos a fazer a nossa primeira aplicação (midlet) em J2ME vamos primeiramente importar a classe '''MIDlet''' para o nosso projeto.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
</syntaxhighlight>
 
=== Criando a classe ===
 
Agora iremos criar a classe principal da nossa aplicação, ela irá extender a classe MIDlet, lembrando que o nome da classe sempre deverá ser o mesmo do arquivo .java.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
 
public class MinhaClasse extends MIDlet {
}
</syntaxhighlight>
 
=== Métodos padrões ===
 
O ciclo de vida de uma aplicação para celular é sempre composta por 3 métodos '''startApp()''', '''pauseApp()''' e '''destroyApp(boolean unconditional)''', vamos inseri-los dentro da nossa classe.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
 
public class MinhaClasse extends MIDlet {
public void startApp() {
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
</syntaxhighlight>
 
O método '''startApp()''' funciona como o método '''main()''' no J2SE, ou seja, todas as instruções de execução ficarão dentro dele. Você também deve especificar o nome da MIDlet que contém os métodos de execução nas propriedades do projeto.
 
=== Execução dos métodos ===
 
Vamos agora mostrar a execução dos métodos através do console, para isso iremos usar normalmente o '''System.out.println()''' do pacote padrão do Java.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
 
public class MinhaClasse extends MIDlet {
public void startApp() {
System.out.println("Executando startApp");
}
public void pauseApp() {
System.out.println("Executando pauseApp");
}
public void destroyApp(boolean unconditional) {
System.out.println("Executando destroyApp");
}
}
</syntaxhighlight>
 
Você deve ter notado que foram executados apenas os métodos '''startApp()''' e '''destroyApp()''', o '''pauseApp()''' não foi executado porque precisa de uma chamada especial para ser feita, como por exemplo uma ligação que o celular recebe enquanto o aplicativo está rodando.
 
=== Display ===
 
O objeto Display é o controlador do que é mostrado no dispositivo, ele está dentro do pacote '''javax.microedition.lcdui'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet {
Display meuDisplay;
 
public void startApp() {
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
</syntaxhighlight>
 
Para criar fisicamente o objeto vamos chamar o método estático '''getDisplay()'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet {
Display meuDisplay = Display.getDisplay(this);
 
public void startApp() {
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
</syntaxhighlight>
 
=== Olá mundo ===
 
Fizemos várias coisas no projeto do programa, mas ainda não exibimos nada na tela, agora é a hora, nós vamos exibir a mensagem em um Form que é fácil de implementar, primeiro vamos instanciar o objeto Form.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet {
Display meuDisplay = Display.getDisplay(this);
Form meuForm;
 
public void startApp() {
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
</syntaxhighlight>
 
Agora vamos dar atributos ao objeto '''meuForm''', nesse caso ele só tem um atributo que é a String de texto que será exibida na tela.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet {
Display meuDisplay = Display.getDisplay(this);
Form meuForm = new Form("Título do Form. Olá mundo!");
 
public void startApp() {
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
</syntaxhighlight>
 
Agora finalmente vamos exibir a mensagem na tela, para isso dentro do método '''startApp''' vamos colocar o objeto display, chamar o seu método '''setCurrent()''', e colocar como atributo o objeto da classe '''Form'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class MinhaClasse extends MIDlet {
Display meuDisplay = Display.getDisplay(this);
Form meuForm = new Form("Título do Form. Olá mundo!");
 
public void startApp() {
meuDisplay.setCurrent(meuForm);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
</syntaxhighlight>
 
== Redes ==
 
Vamos agora ver como trabalhar com redes para troca de dados no J2ME, podemos trabalhar com conexões de HTTP, Socket e Datagram. Para rodar os exemplos precisaremos na maioria dos casos de 2 midlets rodando ao mesmo tempo, e também precisaremos implementar loops que irão checar a chegada de novas informações.
 
Para iniciar, podemos usar normalmente a classe que criamos do GameCanvas e importando o pacote '''javax.microedition.io'''.
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
 
public class MeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
 
public MeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
boolean fim = false;
while(fim == false){
flushGraphics();
}
}
}
</syntaxhighlight>
 
Primeiramente dentro do '''run()''' vamos instanciar um objeto do tipo '''Connector''', vamos também inicia-lo com conteúdo vazio (null).
 
<syntaxhighlight lang="java" enclose="div">
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
 
public class MeuGameCanvas extends GameCanvas implements Runnable {
Thread meuThread;
 
public MeuGameCanvas(){
super(false);
meuThread = new Thread(this);
meuThread.start();
}
public void run(){
Connection meuConnection = null;
 
boolean fim = false;
while(fim == false){
flushGraphics();
}
}
}
</syntaxhighlight>
 
== Criando arquivos M3G no Blender ==
 
Neste tutorial vamos ver como criar um arquivo .m3g utilizando o Blender, um software gratuito de modelagem 3D.
 
=== O programa ===
 
Você pode baixar e instalar gratuitamente a versão completa do Blender em seu site oficial [http://www.blender.org/ www.blender.org].
 
=== Blender Export for J2ME ===
 
A partir da versão 2.48 o Blender passou a vir com um exportador para o J2ME, para exportar seu objeto clique '''File -> Export -> M3G (.m3g, java) -> OK'''. Aparecerá uma janela com os seguintes atributos:
 
* Texturing
** Enabled - Permite a exportação de texturas
** External - Referencia arquivos externos para texturas
* Lightning
** Enabled - Permite a exportação de luz
** Ambient Light - Insere um objeto de luz extra para luz ambiente
* Mesh Options
** Autoscalling - Usa precisão máxima para posição de vértices
** Persp. Correcti - Coloca uma flag de correção de perspectiva
** Smooth Shading - Coloca uma flag de sombreamento suave
* Posing
** All Armature Ac - Exporta todas as ações para armaduras
* Export
** As Java Source - Exporta a cena como um código fonte em Java
** M3G Version 2.0 - Arquivo M3G versão 2.0
** Game Physics - Inclui informações de física de jogo para NOPE na exportação
** O3D As JS - Gera um código em HTML e JavaScript que mostra a cena atual com o Google O3D API em um Browser
** O3D As O3DTGZ
 
== Ligações externas ==
 
* [http://java.sun.com/javame/index.jsp Site da Sun]
* [http://java.sun.com/products/sjwtoolkit/download.html Download do Wireless Toolkit]
* [http://download.netbeans.org/netbeans/6.0/final/ NetBeans 6.0 IDE]
* [http://www.m3gexporter.com/ M3G Exporter para 3D Studio Max]
* [http://www.m3gexport.com/ M3G Exporter para Maya]
* [http://www.nelson-games.de/bl2m3g/default.html M3G Exporter para Blender]
* [http://www.gimp.org/ GIMP]
* [http://www.anvilstudio.com/ Anvil Studio]
* [http://www.blender.org/ Blender]
 
{{Esboço}}
{{AutoCat|Java|Programação}}
{{Ficha do livro
|Etapa = 6
|Nível educacional 1 =
|Tema 1 = <!-- Antes de preencher este campo, opine na [[Wikilivros Discussão:Biblioteca#Proposta]] -->
|CDD 1 = 005
|CDU 1 =
|CBC 1 =
}}
 
[[en:J2ME Programming]]