Libgxd:将对象旋转到移动到另一点所需的角度

huangapple go评论80阅读模式
英文:

Libgxd: Rotate an object to angle necessary to move to another point

问题

好的,这是您提供的内容的翻译:

好的,所以我尝试了许多不同的方法,最终找到了一个有时可以正常工作的方法。想法是让蜜蜂精灵朝着花朵精灵移动,到目前为止,我已经完成了以下几件事:

  1. 蜜蜂可以根据移动速度向左或向右旋转。
  2. 蜜蜂可以朝着旋转的方向移动(通过使用角度的正弦和余弦)。
  3. 蜜蜂有时能够到达花朵,有时不能(通常在这种情况下花朵离蜜蜂很近)。

这是一个正常工作的示例:

Libgxd:将对象旋转到移动到另一点所需的角度

蜜蜂向右转,并最终达到它在条件中寻找的角度,然后直线(无意冒犯),朝花朵飞去。

另一方面,当花朵离蜜蜂的起始点(屏幕中间)更近时:

Libgxd:将对象旋转到移动到另一点所需的角度

它会绕过花朵的右侧,然后进入窗口底部。

这是蜜蜂类的代码:

// 这里是您的代码,请注意这部分没有翻译。

我一直在尝试调试的主要函数是updateRotationAngle(float deltaTime)

提前感谢您的任何帮助。

英文:

Ok, so I have tried many different approaches and I have landed with one that works some of the time. The idea is to get a bee sprite to move toward a flower sprite, here are the things I have accomplished with this so far:

  1. Bee can rotate to the left or right based on a movement speed
  2. Bee can move in the direction that it is rotated (by using the sin and cos of angle)
  3. Bee is sometimes able to make it to the flower and sometimes not (usually the flower is very close when this happens)

This is the working example:

Libgxd:将对象旋转到移动到另一点所需的角度

The bee turns to the right and eventually hits the angle it is looking for in the condition and makes a beeline (no pun intended), for the flower.

On the other hand, when the flower is closer to the bees starting point (the middle of the screen):

Libgxd:将对象旋转到移动到另一点所需的角度

It goes around the right side of the flower and down into the bottom of the window.

Here is the code for the bee class:

public class Bee {
    public Vector2 position;
    public Sprite sprite;
    public float topSpeed = 300f;
    public float xSpeed = 0f;
    public float ySpeed = 500f;
    public float rotationSpeed = 200f;
    public float rotationAngle = 360f;
    public float moveAngle;
    public Vector2 flowerPosition;
    public boolean collided = false;

    public Bee(Texture img, Vector2 flowerVector) {
        sprite = new Sprite(img);
        sprite.setScale(2);
        position = new Vector2(Gdx.graphics.getWidth()/2f - sprite.getWidth(),
                Gdx.graphics.getHeight()/2f - sprite.getHeight());
        flowerPosition = flowerVector;
    }

    public Rectangle getBoundingBox() {
        return sprite.getBoundingRectangle();
    }

    public void updateCollided(boolean collidedBool) {
        collided = collidedBool;
    }

    public boolean beeHittingRightWall() {
        return position.x + sprite.getWidth() > Gdx.graphics.getWidth();
    }

    public boolean beeHittingLeftWall() {
        return position.x < 0;
    }

    public boolean beeHittingTopWall() {
        return position.y + sprite.getHeight() > Gdx.graphics.getHeight();
    }

    public boolean beeHittingBottomWall() {
        return position.y < 0;
    }

    public void updateBeeCoordinates(float deltaTime) {
        position.x += deltaTime * xSpeed;
        position.y += deltaTime * ySpeed;
    }

    public void checkBeeHittingBorders() {
        if(beeHittingRightWall()) {
            position.x -= sprite.getWidth();
        }
        if(beeHittingLeftWall()) {
            position.x += sprite.getWidth();
        }
        // Check if bee is hitting top and bottom walls
        if(beeHittingTopWall()) {
            position.y -= sprite.getHeight();
        }
        if(beeHittingBottomWall()) {
            position.y += sprite.getHeight();
        }
    }

    // gets quadrant of coordinate
    public float getCoordinateQuadrantMinuend(float x, float y) {
        float yAxis = Gdx.graphics.getWidth() / 2f;
        float xAxis = Gdx.graphics.getHeight() / 2f;

        if(x > yAxis && y > xAxis) {
            return 90f;
        }
        else if(x > yAxis && y < xAxis) {
            return 180f;
        }
        else if(x < yAxis && y < xAxis) {
            return 270f;
        }
        else {
            return 360f;
        }
    }

    // gets the angle bee needs to be rotated to, to move to a certain coordinate
    public float getPathfindingRotationAngle(float x1, float y1, float x2, float y2) {
        float c = (y2 - y1) / (x2 - x1);
        float minuend = getCoordinateQuadrantMinuend(x1, y1);

        return minuend - MathUtils.atanDeg(c);
    }

    public float targetAngle() {
        return 360 - getPathfindingRotationAngle(flowerPosition.x, flowerPosition.y, position.x, position.y);
    }

    public void moveForward(float deltaTime) {
        if(!collided) {
            moveAngle = targetAngle();
            updateBeeCoordinates(deltaTime);
            checkBeeHittingBorders();
        }
    }

    public void rotateLeft(float deltaTime) {
        rotationAngle += deltaTime*rotationSpeed;
        if(rotationAngle > 360) {
            rotationAngle -= 360;
        }
    }

    public void rotateRight(float deltaTime) {
        rotationAngle += 360 - deltaTime*rotationSpeed;
        if(rotationAngle > 360) {
            rotationAngle -= 360;
        }
    }

    public void updateRotationAngle(float deltaTime) {
        float myAngle = targetAngle();
        if(rotationAngle > myAngle) {
            rotateRight(deltaTime);
        }
        if(rotationAngle < myAngle) {
            rotateLeft(deltaTime);
        }
    }

    // This is called update velocity
    // because velocity implies a speed and direction
    // since it is a vector (this function does both of these)
    public void updateVelocity() {
        // Adjust X and Y speeds based on angle

        /*
            looks like this:
                   0
                  360
                   |
             90____|____270
                   |
                   |
                  180
         */

        float xSpeedMultiplier;
        float ySpeedMultiplier;
        if(rotationAngle < 360 && rotationAngle > 180) {
            xSpeedMultiplier = Math.abs(MathUtils.sinDeg(rotationAngle));
        }
        else{
            xSpeedMultiplier = -1 * (MathUtils.sinDeg(rotationAngle));
        }
        ySpeedMultiplier = MathUtils.cosDeg(rotationAngle);


        xSpeed = topSpeed * xSpeedMultiplier;
        ySpeed = topSpeed * ySpeedMultiplier;
    }

    public void Update(float deltaTime) {
        moveForward(deltaTime);
        updateRotationAngle(deltaTime);
        updateVelocity();
    }

    public void Draw(SpriteBatch batch) {
        Update(Gdx.graphics.getDeltaTime());
        sprite.setPosition(position.x, position.y);
        sprite.setRotation(rotationAngle);
        sprite.draw(batch);
    }
}

The main function I have been trying to debug is updateRotationAngle(float deltaTime).

Thank you in advance for any help.

答案1

得分: 1

在你的代码中,我可以看到一个问题是角度比较。在当前角度为1°且目标角度为359°的情况下,蜜蜂将不得不执行几乎整圈的旋转。你应该通过以下公式或类似的方式来计算方向:((myAngle-rotationAngle)%360+360+179)%360-179,然后根据数字是正数还是负数来改变你的方向。

另一件事我注意到你使用了atan函数,我不确定你是否正确执行了象限修正。你可以做的最简单的事情是使用atan2Deg函数,它不需要象限修正。参数将是y2 - y1, x2 - x1。另外,我还看到你试图在updateVelocity中执行一些角度修正,我也不确定是否正确。

英文:

Problematic scenario I can see in yours code is the angle comparison. In the scenario when current angle is 1° and target is 359°, then the bee would have to perform almost whole circle rotation. You should be calcuating the direction by this formula or similar way: ((myAngle-rotationAngle)%360+360+179)%360-179 and then based on the fact if number is positive or negative change your direction.

The other thing I see the use of atan function and I am not sure if you perform the quadrant correction right. The simplest thing you can do is to use atan2Deg function instead which doesn't require quadrant correction. The arguments will be y2 - y1, x2 - x1. Also I can see you are trying to perform some angle correction in updateVelocity, which I am also not sure if is correct.

答案2

得分: 0

好的,我已经翻译了您提供的内容:

我遵循了 Jiří 提到的一些事情,比如将 atanDeg 改为 atan2Deg

我还使用了以下条件来确定蜜蜂应该旋转的方向:((myAngle-rotationAngle)%360+360+179)%360-179,这样做效果很好。我不得不稍微调整 updateRotationAngle 函数,使其能够正常工作,以下是两个函数的工作形式:

getPathfindingRotationAngle

public float getPathfindingRotationAngle(float x1, float y1, float x2, float y2) {
    return MathUtils.atan2Deg((y2 - y1), (x2 - x1));
}

updateRotationAngle

public void updateRotationAngle(float deltaTime) {
    myAngle = targetAngle() + 90;

    if(Math.abs(myAngle - rotationAngle) > 3 && !collided) {
        if (((myAngle - rotationAngle) % 360 + 360 + 179) % 360 - 179 < 0) {
            rotateRight(deltaTime);
        } else {
            rotateLeft(deltaTime);
        }
    }
}

我还从 targetAngle 函数中删除了 360 -

我也不太清楚这个表达式是如何工作的:((myAngle-rotationAngle)%360+360+179)%360-179。如果有人能告诉我,那将会很棒。

非常感谢您的答案。

英文:

Ok I followed some of the things that Jiří said, like changing atanDeg to atan2Deg.

I also used the condition: ((myAngle-rotationAngle)%360+360+179)%360-179 to figure out which direction the bee should rotate, and it worked well. I had to work a little bit to make some tweaks in the updateRotationAngle function for it to work, here are the two functions in working form:

getPathfindingRotationAngle:

public float getPathfindingRotationAngle(float x1, float y1, float x2, float y2) {
    return MathUtils.atan2Deg((y2 - y1), (x2 - x1));
}

updateRotationAngle:

public void updateRotationAngle(float deltaTime) {
    myAngle = targetAngle() + 90;

    if(Math.abs(myAngle - rotationAngle) > 3 && !collided) {
        if (((myAngle - rotationAngle) % 360 + 360 + 179) % 360 - 179 < 0) {
            rotateRight(deltaTime);
        } else {
            rotateLeft(deltaTime);
        }
    }
}

I also removed the 360 - from the targetAngle function.

I also don't really know how this works: ((myAngle-rotationAngle)%360+360+179)%360-179. If someone could let me know that would be wonderful.

Thank you so much for your answer.

huangapple
  • 本文由 发表于 2023年7月14日 09:44:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76684224.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定