首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >俄罗斯方块旋转算法

俄罗斯方块旋转算法
EN

Stack Overflow用户
提问于 2008-10-24 14:49:54
回答 15查看 72.9K关注 0票数 48

表示和旋转俄罗斯方块游戏的最好的算法(和解释)是什么?我总是发现作品的旋转和表示方案令人困惑。

大多数俄罗斯方块游戏似乎在每次旋转时都使用天真的“重做块数组”:

http://www.codeplex.com/Project/ProjectDirectory.aspx?ProjectSearchText=tetris

但是,有些使用预置的编码数字和位移位来表示每个部分:

http://www.codeplex.com/wintris

有没有一种方法可以用数学来做到这一点(不确定在基于电池板的电路板上是否有效)?

EN

回答 15

Stack Overflow用户

发布于 2008-10-24 14:55:08

形状的数量是有限的,所以我会使用一个固定的表格,不进行计算。这样可以节省时间。

但也有旋转算法。

选择一个中心点并旋转pi/2。

如果一个块从(1,2)开始,它将顺时针移动到(2,-1),(-1,-2)和(-1,2)。将此应用于每个块,该块将被旋转。

每个x都是前一个y,每个y都是前一个x。这给出了以下矩阵:

代码语言:javascript
复制
[  0   1 ]
[ -1   0 ]

对于逆时针旋转,请使用:

代码语言:javascript
复制
[  0  -1 ]
[  1   0 ]
票数 32
EN

Stack Overflow用户

发布于 2011-11-15 12:02:41

当我试图弄清楚旋转如何在我的俄罗斯方块游戏中工作时,这是我在堆栈溢出时发现的第一个问题。尽管这个问题很古老,但我认为我的输入将帮助其他人尝试通过算法解决这个问题。首先,我不同意硬编码和旋转会更容易。Gamecat的答案是正确的,但我想详细说明一下。下面是我用Java解决旋转问题的步骤。

  1. 对于每个形状,确定其原点的位置。我使用来自this page的图表上的点来指定我的原点。请记住,根据您的实现,您可能需要在用户每次移动块时修改原点。
  2. Rotation假定原点位于点(0,0),因此您必须先平移每个块,然后才能旋转。例如,假设您的原点当前位于点(4,5)。这意味着在旋转形状之前,每个块必须在x坐标中平移-4,在y坐标中平移-5,以相对于(0,0)。
  3. 在Java语言中,典型的坐标平面从左上角的点(0,0)开始,然后向右和向下递增。为了在我的实现中补偿这一点,我在旋转之前将每个点乘以-1。
  4. 这里是我用来计算逆时针旋转后新的x和y坐标的公式。有关这方面的更多信息,我可以查看Rotation Matrix上的维基百科页面。x‘和y’是新的坐标:

x‘=x* cos(PI/2) -y* sin(PI/2)和y’=x* sin(PI/2) +y* cos(PI/2)。

  • 对于最后一步,我只是以相反的顺序完成了步骤2和3。因此,我再次将结果乘以-1,然后将这些块转换回其原始coordinates.

下面是为我工作的代码(用Java),让我了解如何在您的语言中做到这一点:

代码语言:javascript
复制
public synchronized void rotateLeft(){

    Point[] rotatedCoordinates = new Point[MAX_COORDINATES];

    for(int i = 0; i < MAX_COORDINATES; i++){

        // Translates current coordinate to be relative to (0,0)
        Point translationCoordinate = new Point(coordinates[i].x - origin.x, coordinates[i].y - origin.y);

        // Java coordinates start at 0 and increase as a point moves down, so
        // multiply by -1 to reverse
        translationCoordinate.y *= -1;

        // Clone coordinates, so I can use translation coordinates
        // in upcoming calculation
        rotatedCoordinates[i] = (Point)translationCoordinate.clone();

        // May need to round results after rotation
        rotatedCoordinates[i].x = (int)Math.round(translationCoordinate.x * Math.cos(Math.PI/2) - translationCoordinate.y * Math.sin(Math.PI/2)); 
        rotatedCoordinates[i].y = (int)Math.round(translationCoordinate.x * Math.sin(Math.PI/2) + translationCoordinate.y * Math.cos(Math.PI/2));

        // Multiply y-coordinate by -1 again
        rotatedCoordinates[i].y *= -1;

        // Translate to get new coordinates relative to
        // original origin
        rotatedCoordinates[i].x += origin.x;
        rotatedCoordinates[i].y += origin.y;

        // Erase the old coordinates by making them black
        matrix.fillCell(coordinates[i].x, coordinates[i].y, Color.black);

    }
    // Set new coordinates to be drawn on screen
    setCoordinates(rotatedCoordinates.clone());
}

这个方法就是将形状向左旋转所需要的全部,它比为每个形状定义每次旋转要小得多(取决于您的语言)。

票数 30
EN

Stack Overflow用户

发布于 2008-10-24 15:17:38

这就是我最近在一个基于jQuery/CSS的俄罗斯方块游戏中做的。

计算出积木的中心(用作枢轴点),即积木形状的中心。称之为(px,py)。

组成积木形状的每一块砖都将围绕该点旋转。对于每一块砖,您可以应用以下计算...

其中每个砖的宽度和高度是q,砖的当前位置(左上角)是(x1,y1),新砖位置是(x2,y2):

代码语言:javascript
复制
x2 = (y1 + px - py)

y2 = (px + py - x1 - q)

要旋转相反方向,请执行以下操作:

代码语言:javascript
复制
x2 = (px + py - y1 - q)

y2 = (x1 + py - px)

此计算基于2D仿射矩阵变换。如果你对我是如何做到这一点感兴趣的,请告诉我。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/233850

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档