Нужна помощь в понимании математического Java метода - PullRequest
0 голосов
/ 25 марта 2020

Я сейчас работаю над переделкой игры 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, другими словами? Я не являюсь носителем английского языка sh.

Заранее спасибо! Каждый ответ очень ценится!

С уважением, Стремящийся разработчик

Ответы [ 2 ]

2 голосов
/ 25 марта 2020

Он использует радианы, потому что Math.cos() ожидает, что его аргумент будет в радианах.

Но на самом деле, использование sin и cos для поворота сетки с шагом 90 градусов слишком сложное и довольно хрупкое, потому что тригонометрия В функциях c используется математика с плавающей запятой, которая не гарантирует точных результатов, что может вызвать проблемы, поскольку (int) всегда округляется, поэтому 0.99999999999999 станет 0 или -0.0000000000001 станет -1.

К счастью, есть более простой способ вращать вещи с шагом 90 градусов. Чтобы выяснить, как, нарисуйте на листе бумаги обычную координатную сетку (ось X направлена ​​вправо, а ось Y направлена ​​вверх), а затем возьмите этот лист и поверните его на 90 градусов по часовой стрелке. Теперь ось X будет указывать вниз, а ось Y будет направлена ​​вправо. То есть вращение заставляло оси менять положение, а одна ось проходила в обратном направлении. Иными словами, мы можем повернуть на 90 градусов по часовой стрелке, поменяв значения x и y и поменяв знак 1:

int newx = oldy;
int newy = -oldx;

Теперь ваш случай немного сложнее, потому что вы не вращаетесь вокруг источника система координат, но средняя точка плитки. Компенсируя это, формула для поворота на 90 градусов по часовой стрелке принимает вид:

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

, а для поворота на 90 градусов против часовой стрелки:

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

Поэтому самое простое решение - забыть обо всем этом грех и так далее и просто напиши

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];
    }
}
1 голос
/ 25 марта 2020

Поворот объектов в 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.cos и Math.sin принять в качестве аргумента и угол в радианах.

...