Tutorial – Como hacer un Tetris

Sin embargo vale una aclaraci贸n importante: nuestra ficha – que la trabajamos como si fuese un array de dos dimensiones cuadrado – posee una forma irregular. Por lo tanto, no todos los elementos de este array ficha es realmente ficha 驴Complicado? con el siguiente gr谩fico queda un poco m谩s claro que queremos decir:

tetris-fig8

En la figura anterior, la ficha parece quedar fuera del tablero pero realmente no es as铆 ya que la parte que queda fuera no es parte real de la ficha.

Es por eso que la condici贸n de chequeo de bordes posee dentro otro condicional.

Estampando la ficha en el tablero

Estampar la ficha en el tablero es bastante simple. Bastar谩 con recorrerla, de un modo muy similar al que lo hicimos en la verificaci贸n de colisi贸n, y copiar el elemento de la ficha sobre el elemento del tablero (que obtendremos realizando una cuenta en donde interviene la posici贸n de la ficha) cuando esta no sea cero (parte no real de la ficha).


| void BoardMap::StampPiece(Piece & piece)
| {
| for (int row=0; row<piece._size; row++)
| for (int col=0; col<piece._size; col++)
| {
| if (piece._col+col >= 0 && piece._col+col < COLS &&
| piece._row+row >= 0 && piece._row+row < ROWS &&
| piece._data[col + row * piece._size] != 0)
| _map[piece._col+col][piece._row+row] = piece._data[col + row * piece._size];
| }
|
| piece.SetVisible(false);
| }

Verificaci贸n de l铆nea

La verificaci贸n de una l铆nea completa es algo realmente trivial, ya que simplemente deberemos recorrer el tablero y verificar que la l铆nea activa posea elementos distintos a cero en todo su recorrido.

M谩s complicado ser谩 eliminar la l铆nea del tablero, aunque no demasiado, veamos cu谩l es la idea:

tetris-fig9

Como se puede apreciar en la figura anterior, detectada la l铆nea a eliminar tendremos que copiar una parte del array tablero hacia otra posici贸n del mismo. Tambi茅n podemos observar que parte del tablero permanece inalterado y que debemos modificar la l铆nea superior y fijarla en cero (valor que indica vac铆o en nuestra implementaci贸n).


| void BoardMap::ClearLine(int row)
| {
| // Copio las lineas hacia abajo
| for (int i=row; i>0; i--)
| for (int col=0; col<COLS; col++)
| _map[col][i] = _map[col][i-1];
|
| // Elimino la primer l铆nea
| for (int col=0; col<COLS; col++)
| _map[col][0] = 0;
| }

Para esto bastar谩n dos iteraciones (una para realizar la copia y otra para agregar los ceros).

La l贸gica del juego

Habiendo implementado las funciones m谩s importantes del juego (rotaciones, verificaciones de colisi贸n, etc), nos resta analizar como debe funcionar el juego en s铆 mismo.

La idea aqu铆 ser谩 crear una funci贸n que mueva la ficha activa hacia el borde inferior del tablero e invoque la verificaci贸n de colisiones, estampa al tablero y verificaci贸n de l铆neas armadas.

Esta funci贸n, que ser谩 un m茅todo de la clase GameLogic al que llamaremos CheckRules, no ser谩 invocado en cada frame sino una vez cada N frames – o mejor a煤n – cada N milisegundos.

Luego, la rotaci贸n de la ficha y su desplazamiento forzado a una mayor velocidad hacia abajo se ejecutar谩 cuando el jugador presiona la tecla correspondiente. En el caso del movimiento lateral de la ficha y su rotaci贸n se aplicar谩 s贸lo cuando est谩 sea v谩lida (movemos la ficha, verificamos colisi贸n y si existe una realizamos el movimiento inverso para dejar todo como estaba).

Finalmente, la condici贸n de terminaci贸n es no poder colocar una nueva ficha en el tablero (en la posici贸n inicial colisiona con el tablero).

Conclusi贸n

La manera que este documento explica de realizar un tetris no es la 煤nica ni la mejor. Existen muchas maneras de hacerlo, cada una con su pro y su contra. Un amigo realiz贸 una implementaci贸n con arrays que especifican s贸lo posiciones de las diferentes partes que componen la ficha, de modo que el array es s贸lo de una dimensi贸n y cada elemento es una coordenada; dicha soluci贸n posee la ventaja de no requerir posiciones vac铆as para describir una ficha y casi siempre el array definido tendr谩 menos posiciones. Sin embargo, el armado de la ficha es menos visual y los chequeos son un poco distintos, aunque la idea b谩sica es la misma.

Espero que esta nota haya sido de utilidad. Cualquier duda, vayan a foro.

~fuzzyLogic

Compartir:
  • Twitter
  • Facebook
  • MySpace
  • BarraPunto
  • del.icio.us

Pages: 1 2 3

Comments

  1. Meldron
    February 14th, 2007 | 23:13

    Justo lo que necesitaba. Hace poco que estoy con la programacion de juegos.
    Muy interesante el tutorial.
    Saludos

  2. VCO
    February 15th, 2007 | 10:02

    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

  3. February 19th, 2007 | 18:28

    [...] 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 [...]

  4. July 8th, 2007 | 9:23

    [...] 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 [...]

  5. MDJ
    July 17th, 2007 | 18:31

    Muy bueno el tutorial de tetris, recien empiezo con la programacion de juegos en c++, antes me dedicaba al querido div games estudio.

Leave a reply