J2ME
Introdução
●
MIDP 1.0 x MIDP 2.0
●
GAME API – MIDP 2.0
- facilidade de desenvolvimento ;
- tamanho da aplicação ;
- performance ;
- internacionalização ;
- algoritmos matemáticos prontos e
- padronização.
●
Considerações
- display dos dispositivos ;
- suporte de cor e áudio (som) ;
- tamanho (200K – 500K) ;
- latência de rede e
- billing
Processo Detalhado
●
Concepção
- Desenvolvimento de uma idéia
●
Pré-Produção
- Storyboard
●
Produção
- 2D to 3D (VRML), Arte Final, Trailer,
Avatares
●
Pós-Produção
Elaboração de Imagens 2D /
3D
Avatares
Efeitos Visuais (Imagens,
Ações, Sons)
Algoritmos Aplicados à Jogos
●
Colisão
- Objetos / 2D / 3D / Polígonos . . .
●
Renderização
- Filmes, Texturas, Sombras,
Visões Dimensionais, Movimentos Remotos. .
●
Recursão
- Movimentos, repetições, ações . . .
●
Inteligência Artificial
- Redes Neurais, Fuzzy, Base de Conhecimento, . . .
●
Jogabilidade
Canvas
●
É uma classe para as aplicações que necessitam
manipular eventos de baixo nível e realizar chamadas
para desenhar no Display.
●
A classe Canvas possui métodos para manipular ações
de jogos, eventos de teclas e eventos de ponteiros
(se suportado pelo dispositivo).
●
Como outras subclasses de Displayable, a classe
Canvas permite que a aplicação registre um listener para
comandos.
●
Ao contrário de outras subclasses de Displayable,a
Canvas
GameCanvas
●
É uma classe que estende a classe Canvas
adicionando a capacidade de leitura, a qualquer
momento, da situação das teclas de jogo; e o recurso de
gráfico secundário, evitando que imagens parciais sejam
exibidas durante a composição de cada cena do jogo.
GameCanvas
Layer / LayerManager
●
Layer: representa um elemento visual do jogo, contento
posição espacial, largura, altura e um atributo indicando
se está atualmente visível ou não.
●
LayerManager: gerencia uma sequência de Layers e
permite a definição de uma janela de visualização que
pode ser movida para implementar o scroll de um jogo
(p.ex. clipping).
Layer / LayerManager
Layer / LayerManager
TiledLayer
●
Implementa um mapa de tiles retangulares, ou seja,
uma matriz de células retangulares, onde cada célula
pode ser preenchida com uma pequena imagem (tile).
Essa técnica permite que grandes cenas sejam
compostas a partir de pequenas imagens.
●
Todos os tiles são armazenados em uma única
imagem (TileSet). Cada célula recebe um índice do tile
correspondente.
TiledLayer
TiledLayer
Sprite
●
Implementa uma sequênica de imagens (frames)
que, quando exibidas em uma certa ordem, produzem
uma animação. Todos os possíveis frames devem ser
passados em uma única imagem, no entanto,
algumas transformações, como espelhamento e
rotação, podem ser aplicadas sobre eles, expandindo
as possibilidades de exibição.
Sprite
Exemplo: Step by Step
1
package j2me ;
import javax.microedition.midlet.MIDlet; import javax.microedition.lcdui.Display;
public class GameMIDlet extends MIDlet { MyGameCanvas gCanvas;
public GameMIDlet() {
gCanvas = new MyGameCanvas(); }
public void startApp() {
Display display = Display.getDisplay(this); gCanvas.start();
display.setCurrent(gCanvas); }
public void pauseApp() { }
public void destroyApp(boolean unconditional) { }
Exemplo: Step by Step
2
package j2me ;
import java.util.TimerTask;
public class Clock extends TimerTask { int timeLeft;
public Clock(int maxTime) { timeLeft = maxTime;
}
public void run() { timeLeft--;
}
public int getTimeLeft() { return this.timeLeft; }
Exemplo: Step by Step
3
package j2me ; import java.util.Random; import javax.microedition.lcdui.Image; import javax.microedition.lcdui.game.Sprite; import javax.microedition.lcdui.game.LayerManager;public class CarSprite implements Runnable { public CarSprite(MyGameCanvas parent) {
this.parent = parent;
this.manager = parent.getManager(); }
public void start() { try { carImage = Image.createImage("/j2me/car.png"); } catch(Exception e) { System.err.println(e); return; }
runner = new Thread(this); runner.start();
} . . .
Exemplo: Step by Step
4
. . .
public void run() { try { while(true) { randomCar(); Thread.currentThread().sleep(500); } } catch(Exception e) { System.err.println(e); } } . . .
Exemplo: Step by Step
5
. . .
private void randomCar() {
if(currentCars == MAX_CARS) return;
carSprite = new Sprite(carImage, 10, 10);
int randomCarX =
parent.getRandom().nextInt(parent.GAME_WIDTH);
int randomCarY = (parent.BASE –
parent.getRandom().nextInt(parent.MAX_HEIGHT + 1) - carSprite.getHeight());
if(randomCarX < parent.GAME_ORIGIN_X) randomCarX = parent.CENTER_X;
if(randomCarY < (parent.BASE - parent.MAX_HEIGHT)) randomCarY = parent.CENTER_Y; carSprite.setPosition(randomCarX, randomCarY); manager.insert(carSprite, 0); currentCars++; } . . .
Exemplo: Step by Step
6
. . .
private void randomCar() {
if(currentCars == MAX_CARS) return;
carSprite = new Sprite(carImage, 10, 10);
int randomCarX =
parent.getRandom().nextInt(parent.GAME_WIDTH);
int randomCarY = (parent.BASE –
parent.getRandom().nextInt(parent.MAX_HEIGHT + 1) - carSprite.getHeight());
if(randomCarX < parent.GAME_ORIGIN_X) randomCarX = parent.CENTER_X;
if(randomCarY < (parent.BASE - parent.MAX_HEIGHT)) randomCarY = parent.CENTER_Y; carSprite.setPosition(randomCarX, randomCarY); manager.insert(carSprite, 0); currentCars++; } . . .
Exemplo: Step by Step
7
. . .
public void checkForCollision() { if(manager.getSize() == 2)
return;
for(int i = 0; i < (manager.getSize() - 2); i++) { if(parent.getCoupleSprite().collidesWith( (Sprite)manager.getLayerAt(i), true)) { manager.remove(manager.getLayerAt(i)); currentCars--; carsHit++; } } } . . .
Exemplo: Step by Step
8
. . .
public int getCarsHit() { return carsHit;
}
private Sprite carSprite;
private Image carImage;
private int currentCars;
private MyGameCanvas parent;
private LayerManager manager;
private Thread runner;
private int carsHit;
private static final int MAX_CARS = 20; }
Exemplo: Step by Step
9
package j2me ; import java.util.Timer; import java.util.Random; import javax.microedition.lcdui.Image; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.game.Sprite; import javax.microedition.lcdui.game.GameCanvas; import javax.microedition.lcdui.game.TiledLayer; import javax.microedition.lcdui.game.LayerManager; import java.io.IOException;public class MyGameCanvas
extends GameCanvas implements Runnable {
public MyGameCanvas() { super(true);
} . . .
Exemplo: Step by Step
10
. . .
public void start() { try {
coupleImg = Image.createImage("/j2me/couple2.png"); coupleX = CENTER_X;
coupleY = BASE;
coupleSprite = new Sprite(coupleImg, 10, 10); coupleSprite.defineReferencePixel(
coupleSprite.getWidth()/2, coupleSprite.getHeight());
manager = new LayerManager(); manager.append(coupleSprite); createBackground();
manager.append(background);
carSprite = new CarSprite(this); carSprite.start();
} catch(IOException ioex) { System.err.println(ioex); }
Thread runner = new Thread(this); runner.start();
}
Exemplo: Step by Step
11
. . .
public void run() {
clock = new Clock(30);
new Timer().schedule(clock, 0, 1000); while(!stop) { verifyGameState(); checkUserInput(); updateGameScreen(getGraphics()); try { Thread.currentThread().sleep(30); } catch(Exception e) {} } showGameScore(getGraphics()); } . . .
Exemplo: Step by Step
12
. . .
private void createBackground() throws IOException {
backgroundImg = Image.createImage("/j2me/tiledlayer1.png"); background = new TiledLayer(5, 5, backgroundImg, 32, 32); int[] cells = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
for (int i = 0; i < cells.length; i++) { int column = i % 5;
int row = (i - column)/5;
background.setCell(column, row, cells[i]); }
background.setPosition(GAME_ORIGIN_X, GAME_ORIGIN_Y); }
Exemplo: Step by Step
13
. . .
private void buildGameScreen(Graphics g) { g.setColor(0x000000);
g.drawRect(GAME_ORIGIN_X, GAME_ORIGIN_Y, GAME_WIDTH, GAME_HEIGHT);
g.drawLine(GAME_ORIGIN_X, BASE, GAME_ORIGIN_X + GAME_WIDTH, BASE);
g.drawLine(GAME_ORIGIN_X, BASE - MAX_HEIGHT,
GAME_ORIGIN_X + GAME_WIDTH, BASE - MAX_HEIGHT); showTimeLeft(g);
}
private void verifyGameState() { if(clock.getTimeLeft() == 0) { stop = true; return; } carSprite.checkForCollision(); } . . .
Exemplo: Step by Step
14
. . .
private void checkUserInput() { int keyState = getKeyStates(); calculateCoupleX(keyState); calculateCoupleY(keyState); }
private void updateGameScreen(Graphics g) { g.setColor(0xffffff);
g.fillRect(0, 0, getWidth(), getHeight()); buildGameScreen(g); coupleSprite.nextFrame(); coupleSprite.setRefPixelPosition(coupleX, coupleY); manager.paint(g, 0, 0); flushGraphics(); } . . .
Exemplo: Step by Step
15
. . .
private void showTimeLeft(Graphics g) { int timeLeft = clock.getTimeLeft(); if(timeLeft < 6) { if((timeLeft % 2) == 0) g.setColor(0xff0000); else g.setColor(0x000000); }
g.drawString("Tempo: " + timeLeft + " segundos", 0, 0, 0); g.setColor(0x000000);
}
private void showGameScore(Graphics g) { g.setColor(0xffffff);
g.fillRect(0, CENTER_Y - 20, getWidth(), 40); g.setColor(0x000000); g.drawString("Você bateu em " + carSprite.getCarsHit() + " carros.", CENTER_X, CENTER_Y, Graphics.HCENTER | Graphics.BASELINE); flushGraphics(); } . . .
Exemplo: Step by Step
16
. . .
private void calculateCoupleX(int keyState) { if((keyState & LEFT_PRESSED) != 0) {
coupleX = Math.max( GAME_ORIGIN_X +
coupleSprite.getWidth()/2, coupleX - dx);
}
else if((keyState & RIGHT_PRESSED) != 0) { coupleX = Math.min( GAME_ORIGIN_X + GAME_WIDTH – coupleSprite.getWidth()/2, coupleX + dx);; } } . . .
Exemplo: Step by Step
17
. . .
private void calculateCoupleY(int keyState) { if(up) {
if((coupleY > (BASE - jumpHeight + coupleSprite.getHeight()))) { coupleY -= dy;
} else if(coupleY == (BASE - jumpHeight + coupleSprite.getHeight())) { coupleY += dy; up = false; } } else { if(coupleY < BASE) { coupleY += dy;
} else if(coupleY == BASE) {
int hyper = random.nextInt(MAX_HEIGHT + 1); if(hyper > coupleSprite.getHeight()) jumpHeight = hyper; coupleY -= dy; up = true; } } } . . .
Exemplo: Step by Step
18
. . .
public Sprite getCoupleSprite() { return this.coupleSprite;
}
public LayerManager getManager() { return this.manager;
}
public Random getRandom() { return this.random;
} . . .
Exemplo: Step by Step
19
. . .
public final int CENTER_X = getWidth()/2; public final int CENTER_Y = getHeight()/2;
public static final int GAME_WIDTH = 160; public static final int GAME_HEIGHT = 160;
public final int GAME_ORIGIN_X = (getWidth() - GAME_WIDTH)/2; public final int GAME_ORIGIN_Y = (getHeight() - GAME_HEIGHT)/2;
public final int SECTION_HEIGHT = 64;
public final int BASE = GAME_ORIGIN_Y +
GAME_HEIGHT - SECTION_HEIGHT; public final int MAX_HEIGHT = 32;
private Image coupleImg;
private Sprite coupleSprite; private Image backgroundImg; private TiledLayer background; private int coupleX;
private int coupleY;
Exemplo: Step by Step
20
. . .
private int dx = 1;
private int dy = 1;
private boolean up = true;
private int jumpHeight = MAX_HEIGHT;
public Random random = new Random();
private LayerManager manager;
private CarSprite carSprite;
private Clock clock;
private boolean stop = false;