Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rotating cordinates around pivot? (tetris)

I'm attempting to design my very own tetris clone but have run into a little problem with shape rotations. I have a 2 dimensional array representing a 10 x 20 game grid and individual shape objects which when initialised contain coordinates of where on the grid the shape will start falling from. So for example, when the user moves the shape down each coordinate's y value gets decremented and this change is reflected on the grid.

What I can't seem to figure out is an efficient way to handle shape rotations using this implementation. Is there any way to maybe use a matrix these coordinates around a designated pivot?

Any suggestions will be greatly appreciated,

Thank you.

like image 644
101010110101 Avatar asked Dec 14 '22 02:12

101010110101


2 Answers

If classic rotation matrices work, will depend on the rotation system you want to use. I will use SRS as an example.

The rotation matrix for counter-clockwise rotation around the origin is:

[0 -1]
[1  0]

Now, suppose you have a list of coordinates [(0, 1), (1, 1), (2, 1), (3, 1)] representing the I-block in its initial position:

 0123
0....
1####
2....
3....

Note that I don't use a cartesian coordinate system, but the usual screen coordinates, starting in the top left. To rotate the block properly, you first have to account for the flip of the y-axis. The rotation matrix then becomes:

[ 0 1]  ->  x_new = y_old
[-1 0]  ->  y_new = -x_old

Next, to rotate around a pivot-point, before rotating, you have to shift the coordinates so that the pivot-point becomes the origin (called sb below) and shift them back after rotating (called sa below):

x_new = sa_x + (y_old - sb_x)
y_new = sa_y - (x_old - sb_y)

Normally you would have sb = sa, but for tetris blocks the pivot-point is sometimes on the grid between two cells (for I- and O-blocks) and sometimes at the center of a cell (for all other blocks).

It turns out that

sa_x = 0
sb_x = 0
sa_y = 1
sb_y = me - 2

where me is the maximum extent (i.e. 2, 3, or 4) of the block to rotate, works for all blocks. So to sum up, you get:

x_new = y_old
y_new = 1 - (x_old - (me - 2))

Clockwise rotation is similar, but if you cache the coordinates for all for block orientations you will only need one direction.

For other rotation systems other values of the shift variables might work, but you might have to shift the piece again, depending on the current orientation of the block (compare SRS rotation to DTET rotation of the I-block, to see what I mean).

like image 83
mdm Avatar answered Feb 01 '23 02:02

mdm


Sure, look up "affine transform". But in your case what you've got is exactly four possible rotations of an object in discrete angles -- there's no 70.3° rotation, it's just 0, 90°, 180°, 270°. So why not precompute?

like image 29
Crashworks Avatar answered Feb 01 '23 03:02

Crashworks