【问题标题】:Need help understanding a math related Java method需要帮助理解数学相关的 Java 方法
【发布时间】:2020-07-06 08:23:26
【问题描述】:

我目前正在重新制作游戏 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 的含义吗?我不是以英语为母语的人。

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

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

【问题讨论】:

  • 因为Math.cos()Math.sin() 使用弧度。
  • 看看rotation matrix。您需要弧度,因为 Math.sin()Math.cos() 函数期望角度以弧度为单位。
  • 与旋转无关,您可能需要查看2048FX,如果您想要一个相同的分步教程,请查看此repository。无需旋转...
  • 糟糕的标题。重写以总结您的具体技术问题。

标签: java function javafx methods 2048


【解决方案1】:

他使用弧度是因为 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;

所以最简单的解决办法就是忘掉所有这些罪和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];
    }
}

【讨论】:

    【解决方案2】:

    在 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 采用弧度作为参数和角度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-22
      • 2011-03-14
      • 2012-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多