Universidad Tecnológica del estado de Zacatecas.
Unidad Académica de Pinos.
Desarrollo de Aplicaciones III
“Manual para la Creación de una Aplicación Móvil
Tetris”.
Eloy Contreras de Lira.
Luis Ángel Dávila Elías
Desarrollo
Creando el Proyecto
Debemos de crear un proyecto del tipo Java ME y Mobile Application desde Netbeans
Como nombre al proyecto le pondremos "Tetris"
Después que le ponemos el nombre a nuestro proyecto, nos saldrá un formulario como el
que sigue. Y seleccionamos la opción por defecto, debido a que ahí solamente
seleccionamos que tipo de celular vamos a ejecutar la aplicación
Creación de clases
Debemos añadir a nuestro proyecto 5 clases y una imagen donde se va a mostrar las figuras
del Tetris si es que no la conocen (pero es de forma opcional). La distribución de las clases
se mostrara a continuación
3.2.1. Clase Rejilla
Sirve para dibujar el limite donde se van a mostrar las figurar de Tetris.
package TetrisMidlet;
//@author hwongu
public class Rejilla {
static final int VACIA = 0;
static final int BLOQUE = 1;
static final int PIEZA = 2;
private int anchura;
private int altura;
private int[][] celdas;
public Rejilla(int w, int h) {
anchura = w;
altura = h;
celdas = new int[anchura][altura];
initRejilla();
}
public int getAnchura() {
return anchura;
}
public int getAltura() {
return altura;
}
public void assignTipoCelda(int x, int y, int valor) {
celdas[x][y] = valor;
}
public int getTipoCelda(int x, int y) {
return celdas[x][y];
}
public void initRejilla() {
int i, j;
for (i = 0; i < anchura; i++) {
for (j = 0; j < altura; j++) {
celdas[i][j] = VACIA;
}
}
// Añadimos los muros exteriores
for (i = 0; i < anchura; i++) {
//celdas[i][0]=BLOQUE;
celdas[i][altura - 1] = BLOQUE;
}
for (j = 1; j < altura - 1; j++) {
celdas[0][j] = BLOQUE;
celdas[anchura - 1][j] = BLOQUE;
}
}
boolean copiaFiguraEnRejilla(Figura fig) {
Elemento elemento;
boolean valorDevuelto = false;
for (int i = 0; i < fig.cantidadElmentos(); i++) {
elemento = fig.getElementoPos(i);
if (elemento.getFila() + fig.getYOrigen() < 4) {
valorDevuelto = true;
}
celdas[elemento.getColumna() +
fig.getXOrigen()][elemento.getFila() + fig.getYOrigen()] = PIEZA;
}
return valorDevuelto;
}
boolean seChoca(Figura fig, int direccion) {
Elemento elemento;
for (int i = 0; i < fig.cantidadElmentos(); i++) {
elemento = fig.getElementoPos(i);
if (direccion == Figura.ABAJO) {
if (celdas[elemento.getColumna() +
fig.getXOrigen()][elemento.getFila() + fig.getYOrigen() + 1] != VACIA) {
return true;
}
} else if (direccion == Figura.IZQUIERDA) {
if (celdas[elemento.getColumna() + fig.getXOrigen() -
1][elemento.getFila() + fig.getYOrigen()] != VACIA) {
return true;
}
} else if (direccion == Figura.DERECHA) {
if (celdas[elemento.getColumna() + fig.getXOrigen() +
1][elemento.getFila() + fig.getYOrigen()] != VACIA) {
return true;
}
}
}
return false;
}
int primeraFilaLlena(int desdeFila) {
boolean encontrada = false;
while (desdeFila < altura - 1 && !encontrada) {
if (filaLlena(desdeFila)) {
encontrada = true;
} else {
desdeFila++;
}
}
if (encontrada) {
return desdeFila;
} else {
return -1;
}
}
int ultimaFilaVacia(int fvacia) {
boolean encontrada = false;
while ((fvacia < altura - 1) && !encontrada) {
if (!filaVacia(fvacia)) {
encontrada = true;
} else {
fvacia++;
}
}
return fvacia - 1;
}
boolean filaVacia(int fila) {
int i = 1;
boolean vacia = true;
while ((i < anchura - 1) && vacia) {
if (celdas[i][fila] != VACIA) {
vacia = false;
}
i++;
}
return vacia;
}
boolean filaLlena(int fila) {
int i = 1;
boolean llena = true;
while ((i < anchura - 1) && llena) {
if (celdas[i][fila] != PIEZA) {
llena = false;
}
i++;
}
return llena;
}
void eliminarFilasLlenas() {
boolean hayfilasllenas = true;
int filavacia = ultimaFilaVacia(0);
int filallena = 0;
while (hayfilasllenas) {
filallena = primeraFilaLlena(filallena);
if (filallena >= 0 && filallena < altura) {
for (int i = filallena - 1; i >= filavacia; i--) {
if (i == -1) {
for (int j = 0; j < anchura; j++) {
celdas[j][0] = VACIA;
}
} else {
copiarFilas(i, i + 1);
}
}
filavacia++;
filallena++;
} else {
hayfilasllenas = false;
}
}
}
void copiarFilas(int forigen, int fdestino) {
for (int i = 0; i < anchura; i++) {
celdas[i][fdestino] = celdas[i][forigen];
}
}
}
3.2.2. Clase Elemento
Muestra en que posición se encuentra la figura que se esta moviendo o ya esta dentro de la
rejilla.
package TetrisMidlet;
//@author hwongu
public class Elemento {
private int fila;
private int columna;
public Elemento(int f, int c) {
fila = f;
columna = c;
}
public int getFila() {
return fila;
}
public int getColumna() {
return columna;
}
public void setFila(int valor) {
fila = valor;
}
public void setColumna(int valor) {
columna = valor;
}
}
3.2.3. Clase Figura
Esta clase es la encargada de dibujar la figura que deseamos mostrar.
package TetrisMidlet;
import java.util.Vector;
//@author hwongu
public class Figura {
static final int IZQUIERDA = 0;
static final int DERECHA = 1;
static final int ABAJO = 2;
static final int ARRIBA = 3;
static java.util.Random rand = new java.util.Random();
private Vector elements;
private int xorigen;
private int yorigen;
public Figura(int fila0, int fila1, int fila2, int fila3) {
elements = new Vector();
agregarFigura(0, fila0);
agregarFigura(1, fila1);
agregarFigura(2, fila2);
agregarFigura(3, fila3);
}
public static Figura nuevaFigura() {
Figura fig = null;
int tipoFigura = rand.nextInt(7);
if (tipoFigura == 0) {
fig = new Figura(
0x0000,
0x0FF0,
0x0FF0,
0x0000);
} else if (tipoFigura == 1) {
fig = new Figura(
0x0F00,
0x0F00,
0x0FF0,
0x0000);
} else if (tipoFigura == 2) {
fig = new Figura(
0x00F0,
0x00F0,
0x0FF0,
0x0000);
} else if (tipoFigura == 3) {
fig = new Figura(
0x0000,
0x0F00,
0xFFF0,
0x0000);
} else if (tipoFigura == 4) {
fig = new Figura(
0x0F00,
0x0F00,
0x0F00,
0x0F00);
} else if (tipoFigura == 5) {
fig = new Figura(
0x0F00,
0x0FF0,
0x00F0,
0x0000);
} else if (tipoFigura == 6) {
fig = new Figura(
0x00F0,
0x0FF0,
0x0F00,
0x0000);
}
fig.xorigen = 3;
fig.yorigen = 0;
return fig;
}
private void agregarFigura(int fila, int valor) {
if ((valor & 0xF000) > 0) {
elements.addElement(new Elemento(fila, 0));
}
if ((valor & 0x0F00) > 0) {
elements.addElement(new Elemento(fila, 1));
}
if ((valor & 0x00F0) > 0) {
elements.addElement(new Elemento(fila, 2));
}
if ((valor & 0x000F) > 0) {
elements.addElement(new Elemento(fila, 3));
}
}
public int cantidadElmentos() {
return elements.size();
}
public Elemento getElementoPos(int pos) {
return (Elemento) elements.elementAt(pos);
}
public int getXOrigen() {
return xorigen;
}
public int getYOrigen() {
return yorigen;
}
public void mueve(int direccion) {
int c, d, i, j;
if (direccion == ABAJO) {
yorigen++;
;
} else if (direccion == IZQUIERDA) {
xorigen--;
} else if (direccion == DERECHA) {
xorigen++;
}
}
public void rotar(Rejilla rej) {
Elemento elemento;
int x, y, i;
boolean sepuederotar = true;
Vector newelements = new Vector();
i = 0;
while (i < cantidadElmentos() && sepuederotar) {
elemento = getElementoPos(i);
x = elemento.getColumna();
y = elemento.getFila();
if (rej.getTipoCelda(y - 1 + getXOrigen(), -x + 3 +
getYOrigen()) != Rejilla.VACIA) {
sepuederotar = false;
} else {
newelements.addElement(new Elemento(-x + 3, y - 1));
}
i++;
}
if (sepuederotar) {
elements = newelements;
}
}
}
Clase Mueve
Esta clase es la encargada de mover la figura, acá utilizamos hilos para si es que
en algún caso ustedes quieren agregar la opción de pausa lo puedan
implementar, también en esta clase se muestra la velocidad con la cual bajan las figuras, les
dejo para su investigación para que puedan subirle el nivel de velocidad conformen ganen
en el juego.
package TetrisMidlet;
//@author hwongu
public class Mueve implements Runnable {
private int delay;
private boolean continuar = true;
private boolean suspendFlag = true;
private TetrisMidlet tetrisMidlet;
public Mueve(TetrisMidlet tetris, int nivel) {
tetrisMidlet = tetris;
delay = actualizaRetardo(nivel);
Thread t = new Thread(this);
t.start();
}
public void run() {
try {
while (continuar) {
synchronized (this) {
while (suspendFlag) {
wait();
}
}
Thread.sleep(delay);
if
(!tetrisMidlet.getRejilla().seChoca(tetrisMidlet.getFigura(),
Figura.ABAJO)) {
tetrisMidlet.getFigura().mueve(Figura.ABAJO);
if (tetrisMidlet.getCanvas() != null) {
tetrisMidlet.getCanvas().repaint();
}
} else {
boolean valor =
tetrisMidlet.getRejilla().copiaFiguraEnRejilla(tetrisMidlet.getFigura());
tetrisMidlet.getRejilla().eliminarFilasLlenas();
if (tetrisMidlet.getCanvas() != null) {
tetrisMidlet.getCanvas().repaint();
}
if (!valor) {
tetrisMidlet.nuevaFigura();
} else {
System.out.println("He llegado al final");
continuar = false;
}
}
}// end while(continuar)
} catch (InterruptedException e) {
System.out.println("Hilo MueveSerpiente interrumpido");
}
}
// Detiene momentaneamente la ejecución de la hebra, haciendo que la
Figura actual
//quede parada.
synchronized public void suspender() {
tetrisMidlet.getCanvas().repaint();
suspendFlag = true;
}
//Reanuda el movimiento de la hebra. La Figura actual vuelve a
moverse.
public synchronized void reanudar() {
tetrisMidlet.getCanvas().repaint();
suspendFlag = false;
notify();
}
//Termina la ejecución de la hebra.
public void parar() {
continuar = false;
}
//Nos dice si la hebra está o no parada.
synchronized public boolean getParado() {
return suspendFlag;
}
//La siguiente función actualiza el retardo que espera la hebra
//para mover la Figura actual. El nivel más lento será
//el 0 (retardo 700) y el más rápido el 10 (retardo 50)
private int actualizaRetardo(int nivel) {
if (nivel > 10) {
nivel = 10;
} else if (nivel < 0) {
nivel = 0;
}
return (400 - (nivel * 35));
}
}
3.2.5. Clase MiCanvas
Clase donde se mostraran todos los elementos del tetris
package TetrisMidlet;
import javax.microedition.lcdui.*;
// @author hwongu
public class MiCanvas extends Canvas implements CommandListener {
private TetrisMidlet tetris;
private Command exitCommand;
private int anchoCelda = -1;
public MiCanvas(TetrisMidlet t) {
try {
setCommandListener(this);
exitCommand = new Command("Exit", Command.EXIT, 1);
addCommand(exitCommand);
this.tetris = t;
} catch (Exception e) {
e.printStackTrace();
}
}
public void dibujaRejilla(Graphics g) {
int i, j;
Rejilla rejilla = tetris.getRejilla();
int xoffset = (getWidth() - rejilla.getAnchura() * anchoCelda) /
2;
for (i = 0; i < rejilla.getAnchura(); i++) {
for (j = 0; j < rejilla.getAltura(); j++) {
if (rejilla.getTipoCelda(i, j) == Rejilla.BLOQUE) {
g.setColor(0, 0, 0);
g.drawRect(xoffset + i * anchoCelda, j * anchoCelda,
anchoCelda,
anchoCelda);
} else if (rejilla.getTipoCelda(i, j) == Rejilla.PIEZA) {
g.setColor(255, 255, 0);
g.fillRect(xoffset + i * anchoCelda, j * anchoCelda,
anchoCelda,
anchoCelda);
g.setColor(255, 0, 0);
g.drawRect(xoffset + i * anchoCelda, j * anchoCelda,
anchoCelda,
anchoCelda);
}
}
}
}
// Dibuja la Figura fig en el Graphics g pasado como par´ametro
// (normalmente el asociado a este Canvas)
// @param fig la Figura a dibujar
// @param g el Graphics donde se dibujar´a
public void dibujaFigura(Figura fig, Graphics g) {
if (fig != null) {
Elemento elemento;
Rejilla rejilla = tetris.getRejilla();
int xoffset = (getWidth() - rejilla.getAnchura() *
anchoCelda) / 2
+ fig.getXOrigen() * anchoCelda;
int yoffset = fig.getYOrigen() * anchoCelda;
for (int i = 0; i < fig.cantidadElmentos(); i++) {
elemento = fig.getElementoPos(i);
g.setColor(255, 255, 0);
g.fillRect(xoffset + elemento.getColumna() * anchoCelda,
yoffset + elemento.getFila() * anchoCelda,
anchoCelda,
anchoCelda);
g.setColor(255, 0, 0);
g.drawRect(xoffset + elemento.getColumna() * anchoCelda,
yoffset + elemento.getFila() * anchoCelda,
anchoCelda,
anchoCelda);
}
}
}
public void paint(Graphics g) {
if (anchoCelda == -1) {
anchoCelda = Math.min(getWidth() /
tetris.getRejilla().getAnchura(),
(getHeight() - 10) /
tetris.getRejilla().getAltura());
}
g.setColor(255, 255, 255);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(0, 0, 0);
g.translate(0, 12);
dibujaRejilla(g);
dibujaFigura(tetris.getFigura(), g);
g.translate(0, -12);
}
protected void keyPressed(int keyCode) {
if (keyCode == getKeyCode(LEFT)) {
if (!tetris.getRejilla().seChoca(tetris.getFigura(),
Figura.IZQUIERDA)) {
tetris.getFigura().mueve(Figura.IZQUIERDA);
if (tetris.getCanvas() != null) {
tetris.getCanvas().repaint();
}
}
} else if (keyCode == getKeyCode(RIGHT)) {
if (!tetris.getRejilla().seChoca(tetris.getFigura(),
Figura.DERECHA)) {
tetris.getFigura().mueve(Figura.DERECHA);
if (tetris.getCanvas() != null) {
tetris.getCanvas().repaint();
}
}
} else if (keyCode == getKeyCode(UP)) {
tetris.getFigura().rotar(tetris.getRejilla());
if (tetris.getCanvas() != null) {
tetris.getCanvas().repaint();
}
} else if (keyCode == getKeyCode(DOWN)) {
if (!tetris.getRejilla().seChoca(tetris.getFigura(),
Figura.ABAJO)) {
tetris.getFigura().mueve(Figura.ABAJO);
if (tetris.getCanvas() != null) {
tetris.getCanvas().repaint();
}
}
}
}
protected void keyReleased(int keyCode) {
}
protected void keyRepeated(int keyCode) {
}
protected void pointerDragged(int x, int y) {
}
protected void pointerPressed(int x, int y) {
}
protected void pointerReleased(int x, int y) {
}
public void commandAction(Command command, Displayable displayable) {
if (command == exitCommand) {
javax.microedition.lcdui.Display.getDisplay(tetris).setCurrent(tetris.get
Form());
}
}
}
Dibujando el Midlet
El Midlet esta conforma por Alert y por un Form, en este ultimo es donde se mostrara la
opciones si vamos a jugar, ver el score, etc. Debemos elaborar el siguiente diseño
splashAlert
El "splashAlert" solo nos muestra una bienvenida al juego, el "okCommand" que se
adiciona debe de dirigir hacia el form para que se muestre el formulario. Su diseño es el
siguiente
form
El "form" tiene el siguiente diseño
Para realizar este diseño nos vamos a los elementos o el apartado que dice paleta ahí
añadimos la opción de choice group
Después le damos clic derecho dentro de este y nos vamos a propiedades
Dentro de propiedades elegimos la opción de de Type y elegimos la opción de Exclusive
Debemos de codificar el "okCommand1" para eso hacemos clic derecho en el
"okCommand1" y seleccionamos la opción "Go to source" y dentro de ese evento ponemos
el siguiente código
public void commandAction(Command command, Displayable displayable) {
// write pre-action user code here
if (displayable == form) {
if (command == exitCommand) {
// write pre-action user code here
exitMIDlet();
// write post-action user code here
} else if (command == okCommand1) {
// write pre-action user code here
// write post-action user code here
//Para q valla al boton
if (choiceGroup.getSelectedIndex() == 0) {
System.out.println("Ha seleccionado Jugar");
javax.microedition.lcdui.Display.getDisplay(this).setCurrent(this.miCanva
s);
inicializaJuego();
mueve.reanudar();
} else if (choiceGroup.getSelectedIndex() == 1) {
System.out.println("Ha seleccionado Opciones");
} else if (choiceGroup.getSelectedIndex() == 2) {
System.out.println("Ha seleccionado Ver records");
}
}
} else if (displayable == splashAlert) {
if (command == okCommand) {
// write pre-action user code here
switchDisplayable(null, getForm());
// write post-action user code here
}
}
// write post-action user code here
}
Ahora solo ay que correrlo y estará listo
Top Related