在运行时旋转tetris块

时间:2011-10-28 17:31:18

标签: c++ qt graphics rotation coordinates

我有一个类tetronimo(一个俄罗斯方块),有四种QRect类型(名为firstsecondthird,{{1} } 分别)。我使用fourth类型函数绘制每个tetronimo

这些tetronimo在某个方向上构建,但是在俄罗斯方块中你应该能够旋转tetronimo,我试图通过旋转tetronimo的每个方格来旋转tetronimo。

我发现以下公式适用于特定方块的每个(x,y)坐标。

  

newx = cos(角度)* oldx - sin(角度)* oldy

     

newy = sin(角度)* oldx + cos(角度)* oldy

现在,build_tetronimo_L类型的Qt似乎只有一个QRect函数,它采用左上角相应方格的右下角。

我在这里有一个例子(似乎没有产生正确的结果)在我的tetronimo中旋转前两个方格。

任何人都可以告诉我如何使用运行时轮换计算正确旋转这些方块?

setCoords

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); firstsecond类型。 QRect只是rect_coords,其中包含四个struct,用于存储正方形的坐标。

第一个正方形和第二个正方形计算是不同的,因为我正在试图解决它。

我希望有人可以帮我解决这个问题吗?

(是的,我可以做得更简单,但我正试图从中学习)

3 个答案:

答案 0 :(得分:3)

这似乎更像是一个数学问题,而不是一个编程问题。只需插入角度为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

答案 1 :(得分:1)

在旋转之前,你必须翻译以使作品在原点居中:

  1. 将您的区块翻译为0, 0
  2. 旋转块
  3. 再次将块的中心翻译为x, y
  4. 如果旋转而不进行平移,则会始终围绕0, 0旋转,但由于该块未居中,因此将围绕中心旋转。使块块居中很简单:

    1. 对于每个点,计算XY的中位数,让我们称之为m
    2. m.Xm.Y减去所有点的坐标
    3. 旋转
    4. 再次将m.Xm.Y添加到积分中。
    5. 当然你可以使用线性代数和vector * matrix乘法,但也许它太多了:)


      <强>翻译

      假设我们有一个坐标为A(3,5) B(10,15)的细分。 如果你想围绕它的中心旋转它,我们首先将它翻译成我们的原点。我们来计算mxmy

      mx = (10 - 3) / 2
      my = (15 - 5) / 2
      

      现在我们计算点A1B1翻译片段,使其以原点为中心:

      A1(A.X - mx, A.Y - my)
      B1(B.X - mx, B.Y - my)
      

      现在我们可以执行A1B1 (您知道如何)的轮播。 然后我们必须再次翻译到原来的位置:

      A = (rotatedA1.X + mx, rotatedA1.y + my)
      B = (rotatedB1.X + mx, rotatedB1.y + my)
      

      如果您有n分,而不是两分,那么您当然可以为n点做一切。

答案 2 :(得分:0)

您可以使用Qt Graphics View为您完成所有几何计算。

或者您只是想学习基本的线性几何变换?然后阅读数学教科书可能比编码更合适。