Tutorial – Como hacer un Tetris
Las piezas son definidas por una constate. Esta constante no será un array por cada ficha sino que será un array por todas las fichas pero no de una dimensión sino de dos dimensiones. Con el primer Ãndice indicaremos que pieza queremos seleccionar y con el segundo el casillero dentro de la pieza.
Ahora bien ¿Qué hace la clase Piece? Si bien la forma de todas las piezas se encuentran descritas en una constante, debe existir un objeto que almacene cierta información adicional. En principio podrÃamos pensar que con almacenar el número de pieza serÃa suficiente pero luego tendrÃamos que lidiar con el modo en el cual deberÃamos implementar la rotación.
Para implementar la rotación deberemos trabajar con el array de la pieza y modificarlo según el tipo de rotación (horaria o antihoraria). Por lo tanto, el objeto pieza almacenará una copia de la pieza (originalmente tomado de la constante) que modificará según la necesidad, aplicando rotaciones.

Notar como se modifica la ubicación de los elementos cuando realizamos una rotación antihoraria de la matriz.
Ahora nos resta determinar que columna/fila va a parar a que columna/fila para este tipo de rotación. Para esto basta con analizar el ejemplo suministrado y con asà podremos establecer cual es la cuenta que deberemos realizar, veamos:

Como se puede apreciar en la tabla anterior, lo que en la primer columna son filas, en la segunda columna terminan siendo filas, por lo que ya poseemos la primer relación:
COL_ROT = FILA
Ahora nos resta calcular cual es la fila en la cual termina cada elemento, analizando un poco el ejemplo suministrado podremos inferir que:
FILA_ROT = 2 – COL
Donde el 2 en realidad el tamaño de lado menos 1, por lo que de un modo más general podremos establecer que:
FILA_ROT = TAM – 1 – COL
Y para el caso de la rotación horaria, procederemos de modo análogo y obtendremos:
COL_ROT = TAM – 1 – ROW
FILA_ROT = COL
Por lo tanto, el algoritmo que deberemos utilizar para realizar la rotación de la matriz consistirá en recorrerla toda y copiar un elemento desde una columna/fila determinada por los Ãndices de la iteración hacia una columna/fila determinada por la cuenta que realizaremos según lo calculado.
Ej:
| void Piece::RotateCW()
| {
| int ncol, nrow;
| unsigned char newPiece[MAX_PIECE_SIZE*MAX_PIECE_SIZE];
|
| // Roto la pieza
| for (int row=0; row<_size; row++)
| for (int col=0; col<_size; col++)
| {
| ncol = _size-1-row;
| nrow = col;
| newPiece[ncol + nrow * _size] = _data[col + row * _size];
| }
|
| // Copio la pieza temporal a la definitiva
| memcpy((void *) _data, (const void *) newPiece, _size * _size * sizeof(unsigned char));
| }
Notar que el movimiento se realiza hacia un array temporal pero luego es copiado al original de la ficha.
Interactuando con el tablero
En la implementación del juego tenemos sólo una ficha (dos si contamos la ficha preview que podrÃamos o no utilizar). Cuando debamos seleccionar una ficha para dejarla caer desde el borde superior del tablero, estaremos verificando en cada chequeo de reglas si la misma colisiona o no contra otra ficha o contra algún extremo del tablero.
A grandes rasgos podrÃamos establecer que cuando la ficha no colisiona contra nada dentro del tablero, la posición hacia la cual deseamos moverla es válida y podremos actualizar, definitivamente, la posición de la misma.
En un determinado momento la ficha colisionará contra otra ficha o contra el borde inferior del tablero; llegada esta situación se procederá a “estampar” la ficha en el tablero, es decir que se copiará la información que describe la ficha en el array que representa el tablero (en la posición que quedó, claro).
Luego el objeto ficha se reutilizará, seleccionando otra cualquier (al azar) y volviéndola a lanzar desde el borde superior del tablero.
Colisión con tablero
Ahora bien ¿Cómo es esto de colisionar contra el tablero? El objeto ficha, además de la forma de la misma, poseerá la posición en columna y fila que posee la misma dentro del tablero. Esta información la utilizaremos cuando debamos realizar la verificación, veamos el código para entenderlo un poco mejor:
| bool BoardMap::CollideWith(Piece & piece)
| {
| for (int row=0; row<piece._size; row++)
| for (int col=0; col<piece._size; col++)
| {
| // Verifico que la pos. del mapa a afectar esté dentro del mismo
| if (piece._col+col >= COLS || piece._col+col < 0)
| {
| // Me estoy yendo del mapa por la derecha o por la izquierda
| if (piece._data[col + row * piece._size] != 0)
| return true;
| }
| else if (piece._row+row >= ROWS || piece._row+row < 0)
| {
| // Estoy tocando el piso del mapa o
| // estoy por encima del mapa -> ¿Este es un caso posible?
| if (piece._data[col + row * piece._size] != 0)
| return true;
| }
| else if (_map[piece._col+col][piece._row+row] != 0 &&
piece._data[col + row * piece._size] != 0)
| // Una parte de la pieza toca otra pieza del mapa
| return true;
| }
|
| return false;
| }
Como se puede apreciar en el listado anterior, realizamos una iteración por todas las posiciones de la ficha (NO por todo el tablero) mediante dos bucles anidados. Por cada posición de la ficha debemos verificar:
. No quedar fuera del tablero por izquierda ni por derecha.
. No quedar fuera del tablero por abajo o por arriba.
. No quedar superpuesto a otra ficha ya colocada en el tablero.





Comentarios (5)



Justo lo que necesitaba. Hace poco que estoy con la programacion de juegos.
Muy interesante el tutorial.
Saludos
espero que haya mas tutoriales de este tipo (con el motor de zakengine, claro) para que nos ayuden a nosotros, los que estamos en los primeros pasos en el desarrollo de juegos y a veces caemos en un pozo imposible de salir.
Yo debo el tetris todavÃa porque no sé por donde empezar, esto puede ser el hilo que buscaba
[...] A traves de fuzzyGameDev encontramos una guÃa de implementación de tetris basada en el lenguaje C++,y aunque se utilize una librerÃa grafica especifica se puede entender el concepto facilmente. Enlace al articulo [...]
[...] GuÃÂa de implementación para Tetris A traves de fuzzyGameDev encontramos una guÃÂa de implementación de tetris basada en el lenguaje C++,y aunque se utilize una librerÃÂa grafica especifica se puede entender el concepto facilmente. Enlace al articulo [...]
Muy bueno el tutorial de tetris, recien empiezo con la programacion de juegos en c++, antes me dedicaba al querido div games estudio.