Creando un Tetris con JavaScript II: rotando las piezas
Tags: spanish, gamedev, javascript, tutorial
Published: 2024-06-13 08:06:28

---
title: Creando un Tetris con JavaScript II: rotando las piezas
published: true
series: JavaScript Tetris
description: Insertrix: un tetris ligeramente distinto.
tags: #spanish #gamedev #javascript #tutorial
cover_image: https://upload.wikimedia.org/wikipedia/commons/4/46/Tetris_logo.png
# Use a ratio of 100:42 for best results.
# published_at: 2024-06-13 07:32 +0000
---

En la anterior entrega, explicamos cómo podríamos representar las piezas: básicamente, utilizando matrices con ceros y unos, de manera que un uno representará un cuadrado pintado en pantalla, mientras que un cero representará un hueco vacío. Por ejemplo:

```javascript
class PieceL extends Piece {
    constructor()
    {
        super( [ [ 1, 0 ],
                 [ 1, 0 ],
                 [ 1, 0 ],
                 [ 1, 1 ] ],
               "orange" );
    }
}
```

La clase **Piece** tiene una matriz *shape* en la que se va a guardar la matriz que representará a esa "L". De acuerdo, pero... ¿cómo podemos rotar las piezas?

Las piezas rotarán en el sentido de las agujas del reloj. En realidad, no hay tantas formas distintas por cada pieza: de hecho, la que tendrá más formas distintas serán precisamente la "L" y la "L" inversa.

Hay dos formas de conseguir esto:
1. La genérica: para cada matriz, cambiar filas por columnas. Utiliza poca memoria, aunque necesita mayor complejidad de procesamiento cada vez que se rota.

2. La simple: para cada pieza, guardar las posibles formas que adquiere al rotar. Es necesario guardar un selector con la forma que se está empleando en cada momento. Utiliza más memoria, pero es muy rápido.

| |1| | | |2| | | | |3| | | |4| | 
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|1|0| | |1|1|1| | |1|1| | |0|0|1|
|1|0| | |1|0|0| | |0|1| | |1|1|1|
|1|1| | | | | | | |0|1| | | | | |

En la tabla anterior, podemos ver las distintas formas para la "L" (a partir de la forma 4, se vuelve a la 1). Es la pieza (junto con la "L" inversa) que tiene más formas, cuatro en total. La pieza que tiene menos formas es el cuadrado, que solo tiene una. La "barra" solo tiene dos. A continuación, vemos cómo se definen la "barra" y la "L".

```javascript
class PieceBar extends Piece {
    constructor()
    {
        super( [
                   [ [ 1 ],
                     [ 1 ],
                     [ 1 ],
                     [ 1 ] ],

                   [ [ 1, 1, 1, 1 ] ],
               ],
               "darkcyan" );  // color
    }
}

class PieceL extends Piece {
    constructor()
    {
        super( [
                   [ [ 1, 0 ],
                     [ 1, 0 ],
                     [ 1, 1 ] ],

                   [ [ 1, 1, 1 ],
                     [ 1, 0, 0 ] ],

                   [ [ 1, 1 ],
                     [ 0, 1 ],
                     [ 0, 1 ] ],

                   [ [ 0, 0, 1 ],
                     [ 1, 1, 1 ] ],
               ],
               "orange" );    // color
    }
}
```

En lugar de crear una matriz para una sola forma, crearemos un vector de matrices con las diferentes formas rotando la pieza. A continuación, vemos la clase pieza con el soporte para las distintas formas.

```javascript
class Piece {
    #_shape = null;
    #_color = "black";
    #_height = 1;
    #_width = 1;
    #_row = 0;
    #_col = 0;
    #_shapeNum = 0;
    
    constructor(shapes, color)
    {
        this._row = 0;
        this._col = 0;
        this._height = shapes[ 0 ].length;
        this._width = shapes[ 0 ][ 0 ].length;
        this._shapeNum = 0;
        
        if ( color != null ) {
            this._color = color;
        }
    }
    
    get shape()
    {
        return this._shapes[ this._shapeNum ];
    }

    reset(board_width)
    {
        this._row = 0;
        this._col = parseInt( ( board_width / 2 ) - 1 );
        this._shapeNum = 0;
        this._height = this._shapes[ 0 ].length;
        this._width = this,_shapes[ 0 ][ 0 ].length;
    }
    
    rotate()
    {
        this._shapeNum = ( this._shapeNum + 1 ) % this._shapes.length;
        
        this._height = this._shapes[ this._shapeNum ].length;
        this._width = this._shapes[ this._shapeNum ][ 0 ].length;        
    }
```

Antes teníamos *_shape.length* para calcular la altura de la pieza, y *_shape[ 0 ].length* para calcular el ancho de la misma. Como ahora tenemos una matriz con la secuencia de formas, pasamos a hacer lo mismo, pero con la primera forma: respectivamente *_shape[ 0 ].length* y *_shape[ 0 ][ 0 ].length*. A medida que vamos rotando la pieza (*_shapeNum*), calculamos el alto y el ancho de la forma en concreto en la que estamos, como se puede ver en el método *rotate()*.

En la próxima entrega, veremos cómo representar el tablero del juego.