Caída y acumulación de las fichas

Ahora que ya hemos combinado el tablero y la ficha activa, el siguiente paso va a ser que la ficha caiga y que, al llegar abajo, se acumule sobre el fondo del tablero (y más adelante también sobre restos de otras fichas).

Hacer que la ficha caiga es fácil. Básicamente es lo mismo que mover la ficha hacia abajo, como veníamos haciendo hasta ahora. Sólo que hasta ahora, la ficha se movía hacia abajo si el jugador marcaba hacia abajo con el joystick 2, mientras que ahora la caída va a ser automática, sin intervención del jugador.

Relacionado con la caída, tenemos el estado de la ficha (variable ficha_estado). Hasta ahora no hemos prestado mucha atención a esta variable. A partir de ahora pasa a ser importante:

  • El juego empieza con la ficha en estado FICHA_ESTADO_INACTIVA.
  • Si el estado de la ficha es FICHA_ESTADO_INACTIVA el juego activa una nueva ficha, es decir, la pinta en la parte superior del tablero.
  • Y si el estado de la ficha es FICHA_ESTADO_ACTIVA el juego la hace caer hasta que se acumule en el fondo, donde volverá a pasar a inactiva, reiniciándose el todo proceso.

Los cambios necesarios son:

Ficheros tetris_ficha.h y tetris_ficha.c:

El primer cambio tiene que ver con la función ficha_inicializa(). En las entradas anteriores hemos elegido diferentes inicializaciones, por ejemplo, para pintar la ficha en el centro de la pantalla o en el centro de la parte superior del tablero. A partir de ahora, la función ficha_inciailiza() va a inicializar la ficha de verdad, es decir, va a dar valor inicial cero a todas las variables que controlan la ficha (ficha_tipo, ficha_rotacion, ficha_fila, ficha_columna, etc.). En particular, va a dar valor inicial cero, es decir, FICHA_ESTADO_INACTIVA, a la variable ficha_estado.

El segundo cambio es la nueva función ficha_copia_a_tablero(). Esta función será llamada cuando el juego detecte que la ficha ya no puede bajar más por estar sobre el fondo del tablero (o sobre restos de otras fichas más adelante). En ese momento hay que copiar la ficha activa al tablero, es decir, acumularla.

Esta nueva función es así:

Es decir, tras detectarse que la ficha activa ya no puede caer más, la función ficha_copia_a_tablero() recorre los cuatro bloques de la ficha, calcula la posición (columna, ficha) de cada bloque, y mete el tipo de ficha (ficha_tipo) en la posición equivalente de tablero. En resumen, copia la ficha al tablero.

Fichero tetris_main.c:

En este fichero hay bastantes cambios, ya que el juego se va complicando.

El primer cambio es en el bucle de juego. Antes era así:

Es decir, antes el bucle de juego era actualizar la ficha o, lo que es lo mismo, moverla y rotarla. Ahora pasa a ser así:

Por tanto, ahora el bucle de juego consiste en:

  • Si la ficha está inactiva, la activa.
  • Y si la ficha está activa, actualiza la ficha.

Activar la ficha se hace en la nueva función ficha_activa():

Esta función activa la ficha (ficha_estado = FICHA_ESTADO_ACTIVA) y, además, la coloca en el centro (ficha_c = TABLERO_MAX_C/2) de la parte superior del tablero (ficha_f = 0).

Por su parte, la función que actualiza la ficha ahora se llama ficha_actualiza(). Antes se llamaba actualiza_ficha(). Viene a ser lo mismo; sólo es una unificación de la nomenclatura.

Lo importante es que ahora ficha_actualiza() es así:

Es decir, esta función hace caer la ficha de forma automática, sin intervención del jugador, y luego la mueve, entendiendo por “mover” moverla a derecha o izquierda y rotarla.

La caída se hace con la función ficha_cae(). Y para que la caída no sea muy rápida, ficha_cae() no se llama en cada iteración del bucle de juego, sino cada vez que la variable ret llega a diez. Es decir, se invoca una de cada diez iteraciones del bucle de juego.

Este tipo de retardo es muy diferente al de la función retardo(), porque esta función retarda todo el programa que la llama, por ejemplo, todo el bucle de juego. Sin embargo, el retardo conseguido con la variable ret sólo retarda una función específica, por ejemplo, la caída. Es un retardo selectivo.

Por otro lado, el movimiento se consigue ahora con la función ficha_mueve(), que viene a ser equivalente a la actualiza_ficha() de la entrada anterior, ya que lee el joystick 2 y actúa en consecuencia, moviendo la ficha a derecha o izquierda o rotándola. Ahora ya no se permite el movimiento hacia arriba ni hacia abajo, ya que la caída es automática.

La función ficha_mueve() no tiene nada nuevo que merezca la pena comentar, pero la función ficha_cae() sí:

Es decir, esta función verifica si la ficha puede seguir bajando y:

  • Si todavía puede bajar más, la baja de forma automática, sin intervención del jugador.
  • Si ya no puede bajar más, copia la ficha al tablero con la ya comentada función ficha_copia_a_tablero(), pone la ficha inactiva, de modo que en la siguiente iteración se active otra, y pinta el tablero con las novedades.

Resultado:

El resultado es que ya tenemos un juego bastante completo. Van apareciendo fichas en la parte superior del tablero (todavía no son aleatorias). Las fichas caen y, mientras caen, se pueden mover a izquierda o derecha y rotar. Cuando las fichas llegan al fondo del tablero se acumulan.

No obstante, todavía quedan bastantes detalles que pulir:

  • Que las fichas que surgen sean aleatorias.
  • Que las fichas se pinten en su color mientras caen.
  • Que las fichas no se acumulen sólo sobre el fondo, sino también sobre otras fichas.
  • Que las filas completas se colapsen y otorguen puntos.
  • Que se detecte el final del juego cuando se llena el tablero.
  • Y algunos detalles más.

Todo esto lo iremos viendo en las entradas que siguen.


Código de ejemplo: tetris06.zip

Deja un comentario