简体   繁体   English

Java中的2D矢量旋转

[英]2D Vector rotation in Java

I try to make a simple Race-Game. 我尝试做一个简单的竞赛游戏。 For that I got a car with a vector for the position and one for the direction it is facing. 为此,我得到了一辆带有向量的汽车,该向量的位置是矢量,而汽车的方向是矢量。

I have an update and an input method: 我有一个更新和一种输入法:

public void update(double delta) {
    float rotation = 0;
    if(movement.normalized().getY() < 0) {
        rotation = (float) (2*Math.PI - Math.acos(movement.normalized().getX()));
    } else {
        rotation = (float) Math.acos(movement.normalized().getX());
    }

    pos = pos.add(new Vector3f((float) (Math.cos(rotation) * (movement.length() - 2) * delta), (float) (Math.sin(rotation) * (movement.length() - 2) * delta), 0f));

    v1 = new Vertex(new Vector3f((float)(pos.getX() + Math.cos((rotation + basicAngel)) * radius), (float) (pos.getY() + (Math.sin((rotation + basicAngel)) * radius)), 0), new Vector2f(0, 0));
    v2 = new Vertex(new Vector3f((float)(pos.getX() + Math.cos(((2*Math.PI - basicAngel) + rotation)) * radius), (float) (pos.getY() + Math.sin(((2*Math.PI - basicAngel) + rotation)) * radius), 0), new Vector2f(0, 0));
    v3 = new Vertex(new Vector3f((float)(pos.getX() + Math.cos((Math.PI + rotation + basicAngel)) * radius), (float)(pos.getY() + Math.sin((Math.PI + rotation + basicAngel)) * radius), 0), new Vector2f(0, 0));
    v4 = new Vertex(new Vector3f((float)(pos.getX() + Math.cos(((Math.PI - basicAngel) + rotation)) * radius), (float)(pos.getY() + Math.sin(((Math.PI - basicAngel) + rotation)) * radius), 0), new Vector2f(0, 0));
    v5 = new Vertex(new Vector3f((float)(pos.getX() + Math.cos((windowAngel + rotation)) * windowRadius), (float)(pos.getY() + Math.sin((windowAngel + rotation)) * windowRadius), 0), new Vector2f(0, 0));
    v6 = new Vertex(new Vector3f((float)(pos.getX() + Math.cos(((2*Math.PI - windowAngel) + rotation)) * windowRadius), (float)(pos.getY() + Math.sin(((2*Math.PI - windowAngel) + rotation)) * windowRadius), 0), new Vector2f(0, 0));
}

The first if-statement checks whether the y component of the normalized vector below 0 is. 第一个if语句检查归一化向量的y分量是否小于0。
That makes sure that the car rotates below the horizontal axis. 这样可以确保汽车在水平轴以下旋转。
The next line applies the rotation and speed to the position. 下一行将旋转和速度应用于该位置。
The block with v1...v4 calculates the corners of the car to render it. v1 ... v4的块将计算汽车的拐角以进行渲染。
v5 and v6 are the corners of the cars window. v5和v6是汽车窗口的拐角。

public void input() {

    float tempX = movement.normalized().getX();
    float tempY = movement.normalized().getY();
    float tempLength = movement.length();

    if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
        movement = movement.rotate(3);
    }

    if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
        movement = movement.rotate(-3);
    }

    if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
        if (tempLength <= 7) {

            movement.setX((float) (Math.cos(Math.acos(movement.normalized().getX())) * (tempLength + 0.2)));
            movement.setY((float) (Math.sin(Math.acos(movement.normalized().getX())) * (tempLength + 0.2)));

        }
    } else {
        if(tempLength > 2) {

            movement.setX((float) (Math.cos(Math.acos(movement.normalized().getX())) * (tempLength - 0.05)));
            movement.setY((float) (Math.sin(Math.acos(movement.normalized().getX())) * (tempLength - 0.05)));

        }
    }

    if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
        if (tempLength >= 0) {

            movement.setX((float) (Math.cos(Math.acos(movement.normalized().getX())) * (tempLength - 0.2)));
            movement.setY((float) (Math.sin(Math.acos(movement.normalized().getX())) * (tempLength - 0.2)));

        }
    } else {
        if (tempLength < 2) {

            movement.setX((float) (Math.cos(Math.acos(movement.normalized().getX())) * (tempLength + 0.05)));
            movement.setY((float) (Math.sin(Math.acos(movement.normalized().getX())) * (tempLength + 0.05)));

        }
    }

    if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
        reset();
    }
}

The first two if-statements are checking whether the left or right key were pressed. 前两个if语句正在检查是否按下了左键或右键。 If that happened the movement vetor gets rotated. 如果发生这种情况,运动矢量将旋转。 The next two statements are checking the up and down key and appliing the speed to the movement vector by using this formula: 接下来的两个语句是检查向上和向下键,并使用以下公式将速度应用于运动矢量:

x = cos a * (l + speed)
y = sin a * (l + speed)

where a is the angle of the movement vector 其中a是运动矢量的角度
and l is the length of the movement vector l是运动矢量的长度

Everything should work fine and it does, except that it miscalculates sometimes so that the car goes in a different direction as expected. 一切都应该正常运行,但它有时会计算错误,因此汽车会按预期的方向行驶。

Can someone help me finding the mistake? 有人可以帮我发现错误吗?

You can't use acos to get the angle. 您不能使用acos来获取角度。 For example Math.cos(Math.PI*3/4) and Math.cos(Math.PI*5/4) both give you -0.7071. 例如Math.cos(Math.PI * 3/4)和Math.cos(Math.PI * 5/4)都给您-0.7071。 Look at the cosine curve to see why. 查看余弦曲线以了解原因。 To get the angle for a vector use Math.atan2(y,x). 要获取矢量的角度,请使用Math.atan2(y,x)。 Also, why are you converting the vector to an angle and then back to a vector. 此外,为什么还要将向量转换为角度然后再转换为向量。 That is not necessary. 那是没有必要的。 Why don't you use a normalized vector for the direction and a float/double for the speed and multiply that on every update? 为什么不对方向使用归一化向量,对速度使用浮点/双精度并在每次更新时将其乘以?

Or you could do movement = movement.add(movement.normalized().mul(0.2)); 或者你可以做motion = Movement.add(movement.normalized()。mul(0.2));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM