在移动和旋转的物体上设置推力位置

时间:2012-04-04 19:44:20

标签: java math rotation 2d trigonometry

我有一艘宇宙飞船,宇宙飞船通过360度空间移动。

宇宙飞船在2d需要推力动画。信任动画需要位于宇宙飞船的底部中间线。我有以下变量。

_Rotation
_Spaceship.width
_Spaceship.height
_Spaceship.Position(x,y)

我已经上传了我的问题图片,以防人们不理解我的错误解释:

http://imgur.com/Lgchc

两个动画都像这样呈现:

this._itemAnimation.render(this.getPosition(), canvas, this._degrees);
this._thrustAnimation.render(this.thrustPosition(), canvas, this._degrees);

到目前为止我已经尝试过但失败了:

_thurstPosition.set(((int)_object_x + Math.cos(_degrees) * _itemAnimation.getWidth() / 2) , 
((int)_object_y + Math.sin(_degrees) * _itemAnimation.getWidth() / 2));

我失败了,有人帮助我。

---更新---

我已经更新了代码,因此可以更好地理解:

    int SpaceshipCenterX = getPosition().x + (_SpaceshipAnimation.getWidth() / 2) - (_thrustAnimation.getWidth() / 2);
    int SpaceshipCenterY = getPosition().y + ((_SpaceshipAnimation.getHeight() / 2) - (_thrustAnimation.getHeight() / 2));

    double OffSetCos = Math.cos(_spaceshipDegrees);
    double OffSetSin = Math.sin(_spaceshipDegrees);

    _thurstPosition.set 
    (
        (int)(SpaceshipCenterX + (SpaceshipAnimation.getWidth() / 2) * OffSetCos)
        ,
        (int)(SpaceshipCenterY + (SpaceshipAnimation.getHeight() / 2) * OffSetSin)
    );

我仍然无法得到太多的工作。它绕着宇宙飞船飞行,但速度非常快,到处闪烁。

---更新2 ---

这几乎可以工作,但它太过分了:

    int xOffset = -1 * (_itemAnimation.getWidth() / 2);
    double DegreeToRadien = Math.toRadians(_degrees);

    _thurstPosition.set
    (
        (int)(((xOffset) * Math.cos(DegreeToRadien)) + getPosition().x),
        (int)(((xOffset) * Math.sin(DegreeToRadien)) + getPosition().y)
    );

3 个答案:

答案 0 :(得分:4)

假设您正在使用此坐标/角度系统:

                90 (pi/2) - Up
                     ^
                     |
Left - 180 (pi) <----|----> 0 - Right
                     |
                     v
            Down - 270 (3pi/2)

你的宇宙飞船在0度向右移动

>[ } 0

然后,对于任何方向,你需要相对地从宇宙飞船的中心平移推力,让我们说我们在x方向上翻译

offset = -1 * width/2;

然后按照宇宙飞船的角度旋转它,最后将其转移到宇宙飞船的位置。

要计算此变换,请按相反的顺序将3个变换写为矩阵并将它们相乘,转换从(0,0)开始的点

   [1 0 spaceshipX] [cos(dir) -sin(dir) 0] [1 0 -width/2] [0]
   [0 1 spaceshipY] [sin(dir)  cos(dir) 0] [0 1     0   ] [0]
   [0 0     1     ] [   0         0     1] [0 0     1   ] [1]

所以这会给你推力的位置

thrustX = (-width/2)cos(dir) + spaceshipX
thrustY = (-width/2)sin(dir) + spaceshipY

所以我想你错过了你需要减去宽度/ 2而不是添加它的事实。

我用正确且更易读的语法编辑了这个。在任何地方使用下划线确实会损害可读性。我假设你有一个宇宙飞船类,宇宙飞船有宽度,高度,x位置,y位置和旋转。你有一个推进器类,它也有宽度,高度,x位置,y位置和旋转。 (他们可以从Sprite抽象类继承)。要设置推进器对象的位置,我们调用thruster.setPosition(x,y);

int xOffset = -1 * (spaceship.width / 2);

thruster.setPosition(
    (int)(((xOffset) * Math.cos(spaceship.rotation)) + spaceship.x), 
    (int)(((xOffset) * Math.sin(spaceship.rotation)) + spaceship.y)
);

希望这能让您明白需要设置哪些值。我不能在没有看到更多代码的情况下破译你的代码,这些变量被声明,它们实际意味着什么。

更新

总结一下,我想你可能已经发现了。 Math.cos和Math.sin要求角度为弧度,而不是度。我在这里给出的解决方案是正确的,我已经展示了如何通过执行矩阵计算来计算任何相对定位的对象的位置。你只需要记住spaceship.rotation必须是弧度,或者你必须将它从度数转换为弧度,然后再传递给Math.cos()或Math.sin()。

int xOffset = -1 * (spaceship.width / 2);
double radians = Math.toRadians(spaceship.rotation);

thruster.setPosition(
    (int)(((xOffset) * Math.cos(radians)) + spaceship.x), 
    (int)(((xOffset) * Math.sin(radians)) + spaceship.y)
);

答案 1 :(得分:1)

你的代码看起来很接近我。您需要注意_degrees的含义。如果_degrees是火箭指向的方向(从+ x轴逆时针方向),那么你需要在那里放一些减号,因为推力位于火箭后部,而不是前方。另外,我认为推力是在火箭的高度端,所以使用getLength而不是getWidth。您可能还需要为推力动画的高度添加一些额外的内容(取决于其锚点的位置)。像

这样的东西
_thurstPosition.set(((int)_object_x - Math.cos(_degrees) * (_itemAnimation.getHeight() / 2 + _thrustAnimation.getHeight() / 2)) , 
((int)_object_y - Math.sin(_degrees) * (_itemAnimation.getHeight() / 2 + _thrustAnimation.getHeight() / 2)));

如果它不是圆形,你还需要设置推力方向。

(我假设_degrees == _Rotation

答案 2 :(得分:0)

double DegreeToRadien = Math.toRadians(_degrees);

    int ObjectXCenter = (int) (_object_x + ((_itemAnimation.getWidth() / 2)) - _thrustAnimation.getWidth() / 2);
    int ObjectYCenter = (int) (_object_y + ((_itemAnimation.getHeight() / 2)) - _thrustAnimation.getHeight() / 2);

    int xOffset = -1 * (_itemAnimation.getWidth() / 2);

    _thurstPosition.set
    (
        (int)(((xOffset) * Math.cos(DegreeToRadien)) + ObjectXCenter), 
        (int)(((xOffset) * Math.sin(DegreeToRadien)) + ObjectYCenter)
    );