JavaFX - привязка к CenterX / CenterY, обнаружение столкновений на основе текущего положения объектов - PullRequest
0 голосов
/ 03 марта 2019

У нас есть проблема с тем, что позиция Круга становится отрицательной (если она относительна, так что это имеет смысл), однако я предполагаю, что CenterX / Y всегда будет основываться на его текущем местоположении на сцене (JavaFX).Однако всякий раз, когда я добавляю слушателя для этого, круг помещается в недопустимом месте.Даже когда несколько строк устанавливают его положение и обновляют его одинаково, я уже слушаю его свойства X и Y (заметьте, я прокомментировал эти вещи)

Код Ball.java:

метод bounce:

  /**
 * To be documented
 * @param Vector 
 * @param Vector
 */
public void bounce(Vector y, Vector x)
{
    // Get vector between two points of the side
    dest = new Vector(y.getX() - x.getX(), y.getY() - x.getY());
    Vector n1 = new Vector(-dest.getY(), dest.getX());
    n1 = n1.getUnitVector();

    Vector yCopy = new Vector(y.getX(), y.getY());

    // Vector between pall and a point
    dest = new Vector(y.getX(), y.getY());
    dest.setX(dest.getX() - this.getX());
    dest.setY(dest.getY() - this.getY());

    double distanceToLine = dest.getDotProduct(n1);
    System.out.println("Distance toline: " + distanceToLine);
    if (distanceToLine > Constants.BALL_RADIUS || distanceToLine + Constants.BALL_RADIUS < Constants.BALL_RADIUS)
    {
        System.out.println("X-X: " + x.getX() + ", Y-X: " + y.getX() + " X-Y: " + x.getY() + ", Y-Y: " + y.getY());

        Vector nextLocation = new Vector(this.getCenterY(), this.getCenterY());

        Vector speed = new Vector(this.speedX, this.speedY);
        nextLocation.add(speed);
        // Distance from next location to the side
        y.subtract(nextLocation);
        dest = new Vector(y.getX(), y.getY());
        double nextDistToLine = dest.getDotProduct(n1);
        double time = (Constants.BALL_RADIUS - distanceToLine) / (nextDistToLine - distanceToLine);
        // If the ball will be next to line within update
        System.out.println("Debug time: "+ time);
        if (time > 0 && time <= 1000)
        {
            Vector moveToLine = new Vector(this.goalSpeedX, this.goalSpeedY);
            moveToLine.multiply(time);

            moveToLine.add(new Vector(this.getCenterX(), this.getCenterY()));
            System.out.println("Time passed: X-X: " + x.getX() + ", Y-X: " + yCopy.getX() + " X-Y: " + x.getY() + ", Y-Y: " + y.getY());
            if (x.getX() == yCopy.getX())
            {
                System.out.println("XX CONFIRMED: XX : " + x.getX() + " YX: " + y.getX());
                if (moveToLine.getY() >= x.getY() - Constants.BALL_RADIUS && moveToLine.getY() <= y.getY() + Constants.BALL_RADIUS || (moveToLine.getY() >= y.getY() - Constants.BALL_RADIUS && moveToLine.getY() <= x.getY() + Constants.BALL_RADIUS))
                {
                    System.out.println("Move2Line-Y: " + moveToLine.getY() + " ");
                    this.add(moveToLine.getX(), moveToLine.getY());
                    this.goalSpeedX = -this.goalSpeedX;

                    System.out.println("Bounce: moveToLine: getY() - Y");
                }
            }
            else if (x.getY() == yCopy.getY())
            {
                System.out.println("YY CONFIRMED: XX : " + x.getX() + " YX: " + yCopy.getX());
                if (moveToLine.getX() > x.getX() - Constants.BALL_RADIUS && moveToLine.getX() < y.getX() + Constants.BALL_RADIUS || (moveToLine.getX() > y.getX() - Constants.BALL_RADIUS && moveToLine.getX() < x.getX() + Constants.BALL_RADIUS))
                {
                    this.add(moveToLine.getX(), moveToLine.getY());
                    this.goalSpeedX = -this.goalSpeedX;

                    System.out.println("Bounce: moveToLine: getX() - X");
                }
            }
        }
    }
}

/ ** * Унаследовано от суперкласса (GameObject) для вызова в GameLoop * @param deltaTime Время дельты в миллисекундах с момента последнего обновления * @TODO: если координата Y ниже 0, пользователь потерялball * / @Override публичное обновление void (double deltaTime) {if (isFalling) this.speedY + = Constants.BALL_GRAVITY;

    this.speedY += approach(this.goalSpeedY, this.speedY, deltaTime * 30);
    this.speedX += approach(this.goalSpeedX, this.speedX, deltaTime * 30);

    add(Math.min(Constants.MAX_BALL_SPEED, this.speedX), Math.min(Constants.MAX_BALL_SPEED, this.speedY));
    this.centerX.set(getCenterX() + Math.min(Constants.MAX_BALL_SPEED, this.speedX));
    this.centerY.set(getCenterY() + Math.min(Constants.MAX_BALL_SPEED, this.speedY));

    System.out.println(this.toString());
    if (this.getCenterX() > Constants.VECTOR_TOP_RIGHT.getX())
    {
        bounce(Constants.VECTOR_TOP_RIGHT, Constants.VECTOR_BOT_RIGHT);
        System.out.println("Over X treshold: " + this.getX());
    }
    else if (this.getCenterX() < Constants.VECTOR_TOP_LEFT.getX())
    {
        bounce(Constants.VECTOR_BOT_LEFT, Constants.VECTOR_TOP_LEFT);
        System.out.println("Under X treshold: " + this.getX());
    }
    else if (this.getCenterY() > Constants.VECTOR_TOP_RIGHT.getY())
    {
        bounce(Constants.VECTOR_TOP_LEFT, Constants.VECTOR_TOP_RIGHT);
        System.out.println("Crossed Y treshold: " + this.getY());
    }
    else if (this.getCenterY() < Constants.VECTOR_BOT_LEFT.getY())
    {
        bounce(Constants.VECTOR_BOT_RIGHT, Constants.VECTOR_BOT_LEFT);
        System.out.println("Below Y treshold: " + this.getY());
    }
}

Другой класс (GameHandler, но таймер определенно работает, и у нас естьотладка в течение нескольких часов)

    /**
 * Called by AnimationTimer in GameLoop
 * @param time Milliseconds since last update
 */
public void update(double deltaTime) {
    if (this.state == GameState.PLAYING) {
        //System.out.println("GameLoop: Update time: " + deltaTime + " ms");
        this.ball.update(deltaTime);
        for(Wall wall : walls)
        {
            wall.update(deltaTime);
        }
    }
}

/** This breaks the Circle class for some reason?
   *balltest.centerXProperty().bind(gameHandler.getBall().getCenterXProperty());
   *balltest.centerYProperty().bind(gameHandler.getBall().getCenterYProperty());
    */

Результаты отладки:

[Ball: X = 0.0, Y = -848.2400000000009; CenterX = 0.0, CenterY = -848.2400000000009; SpeedX = 0.0SpeedY: -1.8410000000000015] Расстояние Toline: 52.9675209999059 XX: 0.0, YX: 19095.45300000002 XY: -775.0, YY: 17460.445000000018 Время отладки: 0.03929486679040967 Время прошло: XX: 0.0, YX: 19095.45300000002 XY: YY: -Y18310,52600000002 Ниже Y Treshold: -848,2400000000009 [Бал: Х = 0.0, Y = -850,0830000000009; CenterX = 0,0, CenterY = -850,0830000000009; SpeedX = 0.0SpeedY: -1,8430000000000015] Расстояние toline: +54,2459571676045 XX: 0,0, YX: 19943,69300000002 XY: -775.0, YY: 18310.52600000002 Время отладки: 0.04134649528251092 Пройденное время: XX: 0.0, YX: 19943.69300000002 XY: -775.0, YY: 19162.45200000002 Ниже порога Y: -850.0830000000009

* 1019проблемы обнаружения могут быть связаны с тем фактом, что мы основываем наше обнаружение на координатах X / Y шара.Я думаю, что они относительно того, где изначально был создан Круг, потому что его координаты могут быстро стать отрицательными, что усложняет обработку столкновений.

Мы думали, что, возможно, использование привязки к CenterX / Y вместо X / YProperty решит нашпроблемы.Однако, если мы сделаем это (даже комментируя предыдущий код, установив X / Y), он сделает круг в верхнем левом углу.Даже если впоследствии мы вручную установим его положение, оно все равно прослушивается.

Кто-нибудь испытывал то же самое или знал о возможном решении?Мы знаем, что мы можем реструктурировать наши классы (например, помещая больше этих вещей в основной класс), чтобы облегчить решение этой проблемы.Однако нам нужна объектно-ориентированная структура, и мы не будем использовать ярлыки.Для справки, вот изображение нашей текущей настройки пакета: Предложения приветствуются!

Current package and class structure is appreciated! Java is not the programming language we use the most, and this is for educational purposes only.

...