-1

我目前正在重新制作游戏 2048,但我不知道如何旋转图块。现在我决定看看 GitHub,看看其他人是如何解决这个问题的。

我正在查看的 git 项目:https ://github.com/michaelzherdev/2048/blob/master/src/com/mzherdev/Game.java

我不明白的方法:

private Cell[] rotate(int angle) {
    Cell[] tiles = new Cell[4 * 4];
    int offsetX = 3;
    int offsetY = 3;
    if(angle == 90) {
        offsetY = 0;
    } else if(angle == 270) {
        offsetX = 0;
    }

    double rad = Math.toRadians(angle);
    int cos = (int) Math.cos(rad);
    int sin = (int) Math.sin(rad);
    for(int x = 0; x < 4; x++) {
        for(int y = 0; y < 4; y++) {
            int newX = (x*cos) - (y*sin) + offsetX;
            int newY = (x*sin) + (y*cos) + offsetY;
            tiles[(newX) + (newY) * 4] = cellAt(x, y);
        }
    }
    return tiles;
}

我想知道是否有人可以帮助我弄清楚他的思维过程以及他为什么使用弧度。

换句话说,有人可以解释他对 offsetX 和 y 的含义吗?我不是以英语为母语的人。

提前致谢!每个答案都非常感谢!

真诚的,一个有抱负的开发者

4

2 回答 2

2

他使用弧度是因为Math.cos()期望它的参数是弧度。

但实际上,使用 sin 和 cos 以 90 度为增量旋转网格过于复杂,而且非常脆弱,因为三角函数使用浮点数学,不能保证返回准确的结果,这可能会导致问题,因为(int)总是向下舍入,所以0.99999999999999会成为0-0.0000000000001将成为-1

幸运的是,有一种更简单的方法可以以 90 度的增量旋转物体。要弄清楚如何做,请在一张纸上绘制通常的坐标网格(x 轴向右延伸,y 轴向上延伸),然后抓住这张纸并顺时针旋转 90 度。现在,x 轴将指向下方,y 轴将指向右侧。也就是说,旋转导致轴交换位置,并且一个轴反向延伸。换句话说,我们可以通过交换 x 和 y 值并翻转 1 的符号来顺时针旋转 90 度:

int newx = oldy;
int newy = -oldx;

现在,您的情况有点复杂,因为您不是围绕坐标系的原点而是围绕瓷砖的中点旋转。对此进行补偿,顺时针旋转 90 度的公式变为:

int newx = oldy;
int newy = 3 - oldx;

逆时针旋转 90 度:

int newx = 3 - oldy;
int newy = oldx;

所以最简单的解决方案是忘记所有这些 sin 和 cos 的东西,简单地写

for (int x = 0; x < 4; x++) {
    for (int y = 0; y < 4; y++) {
        int newx;
        int newy;
        if (clockwise) {
            newx = oldy;
            newy = 3 - oldx;
        } else {
            newx = 3 - oldy;
            newy = oldx;
        }
        rotatedTile[newx][newy] = tile[x][y];
    }
}
于 2020-03-25T18:45:12.607 回答
1

在 JavaFX 中旋转对象非常简单 - 只需调用setRotate(double angle),如下例所示:

public void start(Stage ps) throws Exception {
    Button square = new Button();
    square.setOnAction(e -> {
        square.setRotate(square.getRotate() + 90);
    });

    VBox container = new VBox(square);

    ps.setScene(new Scene(container, 100, 100));
    ps.show();
}

Math.cosMath.sin以弧度作为参数和角度。

于 2020-03-25T18:30:57.037 回答