【问题标题】:Setting the thrust position on a moving and rotating object在移动和旋转的物体上设置推力位置
【发布时间】:2023-03-07 21:35:01
【问题描述】:

我有一艘宇宙飞船,那艘宇宙飞船在太空中 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)
    );

【问题讨论】:

    标签: java math rotation 2d trigonometry


    【解决方案1】:

    假设您使用的是这个坐标/角度系统:

                    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
    

    所以我想您只是错过了需要减去 width/2 而不是添加它的事实。

    我已使用正确且更易读的语法对其进行了编辑。到处使用下划线确实会损害可读性。我假设你有一个宇宙飞船类,宇宙飞船有一个宽度、高度、x 位置、y 位置和旋转。你有一个推进器类,它也有一个宽度、高度、x 位置、y 位置和旋转。 (它们可以从 Sprite 抽象类继承)。要设置推进器对象的位置,我们调用推进器.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)
    );
    

    【讨论】:

    • 感谢您的回复我已仔细阅读。我已经按照你说的调整了,但还是有问题,现在推力只是出现在一条直线上!在屏幕中间。我用过:int xOffset = (int)_object_x * (_itemAnimation.getWidth() / 2);
    • 我注意到我忘了正确更新最后一行。我已经纠正了。我不太确定您的每个值的含义,因此我也对其进行了更新,使其看起来像您的原始语法。 xOffset 必须是飞船长度的一半。无论旋转如何,该长度都不会改变。它是固定的。我已经更新了答案,希望能清楚地说明需要设置什么。我假设精灵是从中心定位的。
    • 该代码仍然无法正常工作。我已经对我的代码添加了更新,以便更好地理解它?谢谢你顺便帮我。仍然无法正常工作:-/
    • 更新了答案以符合您的问题(弧度/度数问题) - 这是一个容易掉入的陷阱。
    【解决方案2】:

    您的代码看起来很接近我。您需要注意_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

    【讨论】:

    • 我试过你的方法,我得到了一些奇怪的spazzy效果(推力同时出现在很多地方)。 _degrees 是宇宙飞船的当前旋转,我希望我可以同时用于推力和宇宙飞船,对吗?我使用宽度是因为出于某种原因,Android 将侧向的精灵渲染为向上。
    • @OllyDixon 度数需要转换为弧度:Math.toRadians(_degrees)
    【解决方案3】:
    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)
        );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-18
      • 1970-01-01
      • 1970-01-01
      • 2016-04-24
      • 1970-01-01
      相关资源
      最近更新 更多