Monday, October 7, 2019

java - Tetris - Rotations using Linear Algebra (Rotation Matrices)


I'm making Tetris in Java and am at the point of rotations... Originally I was hardcoding each rotation:


if (direction.equals("right")) {
if (shape.equals("Bar")) {
if (rotationsCounter == 0) {
currXs[0] += 1;
currYs[0] += -1;

currXs[1] += 0;
currYs[1] += 0;


currXs[2] += -1;
currYs[2] += 1;

currXs[3] += -2;
currYs[3] += 2;

rightRotate1 = new int[] {currXs[0], currYs[0], currXs[1], currYs[1], currXs[2], currYs[2], currXs[3], currYs[3]};
}
if (rotationsCounter == 1) {

etc...

Then, I have this to set the correct coordinates based on what the rotated counter is


   if (direction == "right") {
if (shape == "Bar") {
if (rotationsCounter == 0) {
pieceRotations = rightRotate1;
}
if (rotationsCounter == 1) {
pieceRotations = rightRotate2;

}
if (rotationsCounter == 2) {
pieceRotations = rightRotate3;
}
if (rotationsCounter == 3) {
pieceRotations = rightRotate0;
}
}
}
if (direction == "left") {

if (shape == "Bar") {
if (rotationsCounter == 0) {
pieceRotations = leftRotate3;
}
if (rotationsCounter == 3) {
pieceRotations = leftRotate2;
}
if (rotationsCounter == 2) {
pieceRotations = leftRotate1;
}

if (rotationsCounter == 1) {
pieceRotations = leftRotate0;
}
}
}
return pieceRotations;

But found that was a very tedious way to go...


People suggested I use rotation matrices in Linear Algebra.


So I tried rotating 1 coordinate in a Tetris piece just to see if I was doing it correctly... the point (1, 1) seems to rotate just fine...



enter image description here


So then I thought that the way to rotate the whole block was to get all the coordinates of each tile in a Piece (4 tiles, 16 coordinates), and rotate each one... but I was wrong.


enter image description here


So my questions is...


In the first picture, I choose (1, 1) as my rotation axis... How do I move the rest of the coordinates in relation to that point?


Thanks!



Answer



This answer still ignores the attempt to use matrix rotation, but I realized that there was a simple yet general solution.


First, assuming that the shape is encoded as coordinates of blocks in a grid, you have an arbitrary shape containing blocks with coordinates in the X and Y axes from 0 to n, where n+1 is the maximum size of a block (traditional Tetris shapes would fit a 4x4 grid). The classic Tetris bar (vertical) would be (1,0), (1,1), (1,2) (1, 3).


To rotate this shape, no matter what the form or size, you simply swap and invert axes.



enter image description here


To rotate clockwise, for every block in the shape, the new block's X would be the previous Y, and the new block's Y would be the inverse of X (n-x). The example rotated bar (now horizontal) would be (0, 2), (1, 2), (2, 2), (3, 2)


To rotate counter-clockwise, the new block's X is the inverse of the old block's Y and the new block's Y is the old block's X.


To put it more clearly:



  • Clockwise- x2 = y1 && y2 = n-x1

  • Counter - x2 = n-y1 && y2 = x1


This can be done easily in a single method, the two rotations are independent of previous rotations (you could keep rotating clockwise indefinitely and cycle through the same 4 shapes), the code is simple and easy-ish to understand, and it is general enough to apply to any 2D shape composed of blocks. In fact, this is general enough that you could easily rotate even a user-generated shape, let alone any custom shapes you create yourself.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...