Tetris 2d array logic

I am trying to write Tetris in JS with matrices instead of sprites. In principle, it is better to render 2d arrays.

I rotate the block by transferring its matrix data and then changing the rows. But since the width and height of the block do not completely fill this 4x4 matrix, rotation causes the block to move, instead of rotating in place.

I don’t see this, I have already spent more than two days trying to get such a simple game as Tetris, working by restarting from scratch a couple of times. I need help, I really want to be able to program games, and the only thing that worked out for me was tic tac toe. Which I spent more time than I should.

Here is the full js code. Clicking on the canvas rotates the piece.

var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
canvas.width = 400;
canvas.height = 600;

// game object
var G = {};
var current = 0;
var x = 0;
var y = 0;

//GRID
G.grid = [];
G.gridColumns = 10;
G.gridRows = 15;
for (var i = 0; i < G.gridColumns; i++) {
  G.grid[i] = [];
  for (var j = 0; j < G.gridRows; j++) {
    G.grid[i][j] = 0;
  }
}

// Array with all different blocks
G.blocks = [];
//block constructor
function block() {};
G.blocks[0] = new block();
G.blocks[0].matrix = [
  [1, 0, 0, 0],
  [1, 1, 0, 0],
  [0, 1, 0, 0],
  [0, 0, 0, 0]
];
G.blocks[0].width = 2;
G.blocks[0].height = 3;

function transpose(m) {
  // dont understand this completely, but works because j<i
  for (var i = 0; i < m.matrix.length; i++) {
    for (var j = 0; j < i; j++) {
      var temp = m.matrix[i][j];
      m.matrix[i][j] = m.matrix[j][i];
      m.matrix[j][i] = temp;
    }
  }
}

function reverseRows(m) {
  for (var i = 0; i < m.matrix.length; i++) {
    m.matrix[i].reverse();
  }
}

function rotate(m) {
  transpose(m);
  reverseRows(m);
}

function add(m1, m2) {
  for (var i = 0; i < m1.matrix.length; i++) {
    for (var j = 0; j < m1.matrix[i].length; j++) {
      m2[i + x][j + y] = m1.matrix[i][j];
    }
  }
}

function draw(matrix) {
  for (var i = 0; i < matrix.length; i++) {
    for (var j = 0; j < matrix[i].length; j++) {
      if (matrix[i][j] === 1) {
        ctx.fillRect(j * 20, i * 20, 19, 19);
      }
    }
  }
  ctx.strokeRect(0, 0, G.gridColumns * 20, G.gridRows * 20);
}


window.addEventListener("click", function(e) {
  rotate(G.blocks[current]);
});

function tick() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  add(G.blocks[current], G.grid);
  draw(G.grid);
}
setInterval(tick, 1000 / 30);
<canvas id="c"></canvas>
Run codeHide result

, , . :)

+4
2

, , , 4 . , . Z/S 3x3. .

, , (2, 2), (1, 1) ( , 0). C - , .

[x][ ][ ][ ][ ]      [ ][ ][X][X][ ]
[X][X][ ][ ][ ]      [ ][X][X][ ][ ]
[ ][X][C][ ][ ]  =>  [ ][ ][C][ ][ ]
[ ][ ][ ][ ][ ]      [ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ]      [ ][ ][ ][ ][ ]

, :

[x][ ][ ]      [ ][X][X]
[X][C][ ]  =>  [X][C][ ]
[ ][X][ ]      [ ][ ][ ]
+2

, , . , "I":

. X . .        . . . .        . . X .        . . . .
. X . .   =>   X X X X   =>   . . X .   =>   . . . .
. X . .        . . . .        . . X .        X X X X
. X . .        . . . .        . . X .        . . . .

, 3- 4- 1- 2-. , . , (5x4), , .

, , , , , "", . , . 4x4.

, .

, , . . , , , , .

" ", 'on', "", , .

, S:

X . . .     1 0 0 0
X X . .  =  1 1 0 0  =  1000110001000000 (in binary)  =  0x8C40 (in hexadecimal)
. X . .     0 1 0 0
. . . .     0 0 0 0

. X X .     0 1 1 0
X X . .  =  1 1 0 0  =  0110110000000000 (in binary)  =  0x6C00 (in hexadecimal)
. . . .     0 0 0 0
. . . .     0 0 0 0

. , "S" :

[ 0x8C40, 0x6C00, 0x8C40, 0x6C00 ]

, - :

var shape = [
  [ 0x4640, 0x0E40, 0x4C40, 0x4E00 ], // 'T'
  [ 0x8C40, 0x6C00, 0x8C40, 0x6C00 ], // 'S'
  [ 0x4C80, 0xC600, 0x4C80, 0xC600 ], // 'Z'
  [ 0x4444, 0x0F00, 0x4444, 0x0F00 ], // 'I'
  [ 0x44C0, 0x8E00, 0xC880, 0xE200 ], // 'J'
  [ 0x88C0, 0xE800, 0xC440, 0x2E00 ], // 'L'
  [ 0xCC00, 0xCC00, 0xCC00, 0xCC00 ]  // 'O'
];

, ? matrix[y][x] :

for (var y = 0; y < 4; y++) {
  for (var x = 0; x < 4; x++) {
    if (shape[s][r] & (0x8000 >> (y * 4 + x))) {
      ctx.fillRect(x * 20, y * 20, 19, 19);
    }
  }
}

Demo

.

var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
canvas.width = 100;
canvas.height = 100;

var shape = [
  [ 0x4640, 0x0E40, 0x4C40, 0x4E00 ], // 'T'
  [ 0x8C40, 0x6C00, 0x8C40, 0x6C00 ], // 'S'
  [ 0x4C80, 0xC600, 0x4C80, 0xC600 ], // 'Z'
  [ 0x4444, 0x0F00, 0x4444, 0x0F00 ], // 'I'
  [ 0x44C0, 0x8E00, 0xC880, 0xE200 ], // 'J'
  [ 0x88C0, 0xE800, 0xC440, 0x2E00 ], // 'L'
  [ 0xCC00, 0xCC00, 0xCC00, 0xCC00 ]  // 'O'
];

var curShape = 0, curRotation = 0;
draw(curShape, curRotation);

function draw(s, r) {
  ctx.fillStyle = 'white';
  ctx.fillRect(0, 0, 100, 100);
  ctx.fillStyle = 'black';

  for (var y = 0; y < 4; y++) {
    for (var x = 0; x < 4; x++) {
      if (shape[s][r] & (0x8000 >> (y * 4 + x))) {
        ctx.fillRect(x * 20, y * 20, 19, 19);
      }
    }
  }
}

function next() {
  curShape = (curShape + 1) % 7;
  draw(curShape, curRotation);
}

function rotate() {
  curRotation = (curRotation + 1) % 4;
  draw(curShape, curRotation);
}
<canvas id="c"></canvas>
<button onclick="rotate()">Rotate</button>
<button onclick="next()">Next shape</button>
Hide result
+2

Source: https://habr.com/ru/post/1649187/


All Articles