在运行时旋转俄罗斯方块
Rotate tetris blocks at runtime
我有一个类tetronimo
(俄罗斯方块),它有四个QRect
类型(分别命名为first
, second
, third
, fourth
)。我使用build_tetronimo_L
类型函数来绘制每个tetronimo。
它们在一个特定的方向上构建了四方块,但是在俄罗斯方块中,你应该能够旋转四方块,我试图通过旋转四方块的每个方块来旋转一个四方块。
我发现下面的公式适用于特定正方形的每个(x, y)坐标。
newx = cos(angle) * oldx - sin(angle) * oldy
newy = sin(angle) * oldx + cos(angle) * oldy
现在,QRect
类型的Qt似乎只有一个setCoords
函数,它取左上角和右下角各自正方形的点的(x, y)坐标。
我这里有一个例子(它似乎不能产生正确的结果)旋转我的四重音中的前两个正方形。
谁能告诉我我应该如何正确旋转这些方块,使用运行时旋转计算?
void tetromino::rotate(double angle) // angle in degrees
{
std::map<std::string, rect_coords> coords = get_coordinates();
// FIRST SQUARE
rect_coords first_coords = coords["first"];
//top left x and y
int newx_first_tl = (cos(to_radians(angle)) * first_coords.top_left_x) - (sin(to_radians(angle)) * first_coords.top_left_y);
int newy_first_tl = (sin(to_radians(angle)) * first_coords.top_left_x) + (cos(to_radians(angle)) * first_coords.top_left_y);
//bottom right x and y
int newx_first_bl = (cos(to_radians(angle)) * first_coords.bottom_right_x) - (sin(to_radians(angle)) * first_coords.bottom_right_y);
int newy_first_bl = (cos(to_radians(angle)) * first_coords.bottom_right_x) + (sin(to_radians(angle)) * first_coords.bottom_right_y);
//CHANGE COORDINATES
first->setCoords( newx_first_tl, newy_first_tl, newx_first_tl + tetro_size,newy_first_tl - tetro_size);
//SECOND SQUARE
rect_coords second_coords = coords["second"];
int newx_second_tl = (cos(to_radians(angle)) * second_coords.top_left_x) - (sin(to_radians(angle)) * second_coords.top_left_y);
int newy_second_tl = (sin(to_radians(angle)) * second_coords.top_left_x) + (cos(to_radians(angle)) * second_coords.top_left_y);
//CHANGE COORDINATES
second->setCoords(newx_second_tl, newy_second_tl, newx_second_tl - tetro_size, newy_second_tl + tetro_size);
first
和second
为QRect
类型。rect_coords
就是一个struct
,里面有四个int
,用来存储方块的坐标。
第一个平方和第二个平方的计算是不同的,因为我一直在尝试弄清楚它。
我希望有人能帮我弄清楚这个问题。(是的,我可以做得更简单,但我正试图从中吸取教训)
这看起来更像是一个数学问题而不是一个编程问题。只要代入90度这样的值就能算出来。对于90度,一个点(x,y)被映射到(-y, x).你可能不想绕着原点旋转,而是绕着某个枢轴点c.x, c.y旋转。为此,你需要先平移,然后旋转,然后再平移:
(x,y) := (x-c.x, y-c.y) // translate into coo system w/ origin at c
(x,y) := (-y, x) // rotate
(x,y) := (x+c.x, y+c.y) // translate into original coo system
在旋转之前,你必须进行平移,使工件位于原点的中心:
- 将block居中为
0, 0
- 旋转
- 再次将块的中心转换为
x, y
如果你旋转而不平移,你将始终围绕0, 0
旋转,但由于该块不是居中的,它将围绕中心旋转。设置块居中非常简单:
- 对于每一个点,计算
X
和Y
的中位数,设为m - 将
m.X
和m.Y
减去所有点的坐标 - 再次添加
m.X
和m.Y
到点数
当然你可以使用线性代数和vector * matrix
乘法,但是可能太多了:)
翻译
假设有一个坐标为A(3,5) B(10,15)
的线段。如果你想绕着它的中心旋转,我们首先把它平移到原点。让我们计算mx
和my
:
mx = (10 - 3) / 2
my = (15 - 5) / 2
现在我们计算A1
和B1
点来平移这段,使其以原点为中心:
A1(A.X - mx, A.Y - my)
B1(B.X - mx, B.Y - my)
现在我们可以执行A1
和B1
的旋转(你知道怎么做)。然后我们必须再次转换到原始位置:
A = (rotatedA1.X + mx, rotatedA1.y + my)
B = (rotatedB1.X + mx, rotatedB1.y + my)
如果没有2分,你有n
分,你当然要为n
分做任何事情。
你可以使用Qt图形视图为你做所有的几何计算。
或者你只是想学习基本的线性几何变换?那么读数学课本可能比写代码更合适。
- OpenGL只是渲染一个黑色的方块
- 如何打印空心方块?
- 使用 FreeType 和 SDL2 渲染文本会生成白色方块而不是字符
- C 中俄罗斯农民算法中的整数溢出
- 如何用更少的代码在俄罗斯方块中绘制块
- D3D11:渲染(深度)到纹理会导致红色方块,正常渲染有效
- SFML雪碧白色方块
- 为什么 SFML 加载的是白色方块而不是纹理
- 没有数组的俄罗斯方块旋转
- SFML中的白色方块,角色和纹理存储在不同的对象中
- 俄罗斯农民乘法算法的时间复杂度.
- 俄罗斯方块移动2D阵列
- 俄罗斯方块对象模型在C++
- 为什么渲染引擎将图像细分为小方块
- C++扫雷检查相邻方块并添加提示
- 选择一个随机方块并生成一个随机数
- C++在俄罗斯方块这样的游戏中设置帧速率
- 使用valgrind读取大小为1的俄罗斯方块无效
- 在运行时旋转俄罗斯方块
- 如何在c++中显示《俄罗斯方块》中的桶呢?