En la última entrega, dábamos prácticamente por terminado nuestro Tetris. Con el bucle de juego, ya era posible hacer que las piezas bajaran, así como moverlas. También las líneas completas eran eliminadas del tablero, con el siguiente código en showFrame():
showFrame: () => {
// más cosas...
let millis = performance.now() - game.startTime;
if ( millis >= 10 ) {
game.pushPieceDownTime += 1;
// más cosas...
if ( game.piece.row != 0 ) {
let newScore = 0;
game.portPieceToBoard();
newScore = game.calculateScore();
if ( newScore > 0 ) {
game.score += newScore;
pScore.innerText = "" + game.score;
}
// Prepare the board
let filledRows = game.chkFilledRows();
game.board.removeRows( filledRows );
game.board.insertEmptyRows( filledRows );
} else {
game.stopGame();
}
game.chooseNewPiece();
}
}
En la parte del comentario // Prepare the board, lo que hacemos es tomar los índices de aquellas filas que están llenas con trozos de fichas (su contenido es 1 en todas las celdas), y después llamar a Board.removeRows() para que las elimine. Entonces rellenamos con filas vacías por la parte delantera del tablero (la parte superior), de manera que el nivel de fichas "baja" tanto como filas hayamos eliminado.
De la modificación a continuación es de donde viene el nombre Insertrix: vamos a añadir filas "basura" en parte, además de seguir rellenando con filas vacías la parte superior. Estas filas "basura" serán filas que contendrán ceros y unos al azar. Hay algunos Tetris que, además de acelerar el tiempo de bajada de cada pieza, hacen esto para hacerte perder cuando ya llevas mucho tiempo jugando. En esta versión, la velocidad no va a variar, pero pueden introducirse muchas más filas "basura" que una fila cada cierto tiempo.
En concreto, vamos a introducir filas "basura" cuando llegue el momento de bajar el tablero el mismo número de filas que las que se han eliminado. Vamos a meter la mitad más uno de filas vacías, y el resto con filas basura. El algoritmo es el siguiente. Sabemos el número de filas total a rellenar porque tenemos la longitud del vector de índices de filas a eliminar, filledRows.length. Así, si calculamos la mitad sin redondear, tomando la parte entera: let numTrashRows = parseInt( filledRows.length / 2 ), tendremos exactamente la mitad o la mitad menos uno en numTrashRows, si filledRows.length es impar. Este se hace así para favorecer al usuario.
Por ejemplo, si el usuario elimina una fila, la mitad exacta de la divisón por dos es 0, por lo que se introducen 0 filas basura, y 1 fila vacía.
El código es el siguiente:
showFrame: () => {
// más cosas...
let millis = performance.now() - game.startTime;
if ( millis >= 10 ) {
game.pushPieceDownTime += 1;
// más cosas...
if ( game.piece.row != 0 ) {
let newScore = 0;
game.portPieceToBoard();
newScore = game.calculateScore();
if ( newScore > 0 ) {
game.score += newScore;
pScore.innerText = "" + game.score;
}
// Prepare the board
let filledRows = game.chkFilledRows();
let numTrashRows = parseInt( filledRows.length / 2 );
game.board.removeRows( filledRows );
game.board.insertEmptyRows( filledRows.length - numTrashRows );
game.board.appendTrashRows( numTrashRows );
} else {
game.stopGame();
}
game.chooseNewPiece();
}
}
Ya solo queda añadir al tablero tantas filas basura como nos digan, con el método Board.appendTrashRows(n: Integer). Podemos generar un número entero aleatorio entre 0 y 1 con Math.random() * 2, siempre que lo corrijamos con Math.floor().
class Board {
// Más cosas...
appendTrashRows(numRows)
{
for(let i = 0; i < numRows; ++i) {
this.#board.push( Array.from( { length: this.cols }, () => Math.floor( Math.random() * 2 ) ) );
}
}
}
En lugar de #board.unshift() utilizamos #board.push(), pues lo que queremos es añadir filas al final. El método estático Array.from(), toma un Array ya existente, y lo modifica con la lambda que le pasemos, su segundo parámetro. En este caso, lo que hacemos es crear un objeto que tiene la propiedad length, lo cual a ojos de Array.from(), lo transforma en un array. Después, la lambda se aplica para cada elemento, con lo que se asigna un valor aleatorio entre 0 y 1.
¡Y ya está! Nuestro juego está listo. Arriba puedes ver cómo al eliminar dos filas, se ha añadido una fila "basura". La partida solo termina cuando una pieza ya no tiene sitio para caer, y se queda "enganchada" en la parte superior. No hay estrés por tener que mover las piezas cada vez más rápido. ¿Te animas a una partida a Insertrix?

Top comments (0)