【问题标题】:Java - Rotating a Polygon around its centerJava - 围绕其中心旋转多边形
【发布时间】:2014-04-21 11:23:29
【问题描述】:

我正在尝试根据给定的 theta 变量围绕自己的中心点旋转多边形。它似乎有点工作,但有一些大问题。它以我不理解的越来越快的速度旋转。多边形本身在旋转时也会缩小尺寸,直到点相互移动。

这是我的代码的主要旋转部分。

public void Rotate(double dTheta)
{
    this.theta += dTheta;

    for(int i = 0; i < body.npoints; i++)
    {
        body.xpoints[i] = 
                (int) (body.getBounds2D().getCenterX() + (body.xpoints[i] - body.getBounds2D().getCenterX()) * 
                        Math.cos(theta) - (body.ypoints[i] - body.getBounds2D().getCenterY()) * Math.sin(theta));

        body.ypoints[i] = 
                (int) (body.getBounds2D().getCenterY() + (body.xpoints[i] - body.getBounds2D().getCenterX()) * 
                        Math.sin(theta) + (body.ypoints[i] - body.getBounds2D().getCenterY()) * Math.cos(theta));
    }
}

“body”对象是一个多边形,每帧以 60 FPS 的速率绘制。

当用户按下空格键时,theta 变量增加了 Math.PI / 180 倍。

我使用的相当大的数学运算是我在网上找到的,它应该根据弧度角和锚点旋转一个点。

“身体”多边形本身由点 (-16, 0)、(16, -16) 和 (16, 16) 组成。 'body' Polygon 最初放置在位置 (100, 100),除了旋转之外不会从那里平移。

非常感谢您对此问题的任何帮助,在此先感谢您。

【问题讨论】:

  • 你在使用像 Slick2D 或 lwjgl 这样的框架吗?使用 Slick2D 只需两条简单的线
  • 其实我正在创建自己的游戏引擎。我使用的唯一外部库是 JNativeHook 来处理鼠标和键盘输入(它有助于消除键等的多操作系统错误)。我使用 JPanel 的绘制方法和一个强制转换的 Graphics2D 对象来完成我所有的绘图。

标签: java graphics geometry 2d game-engine


【解决方案1】:

好吧,当我从一个不好的角度解决问题时,我觉得这么快寻求帮助有点无能。

我通过将原始多边形的点存储在两个名为 xpoints 和 ypoints 的 int 数组中来解决我的问题。这些点一旦加载就永远不会改变,它们与多边形的位置无关,而是与多边形中心周围的点的位置相关,而多边形中心可以在任何给定时刻发生变化。

我所做的是在每一帧循环遍历所有这些点,并使用 AffineTransform 类以 (0, 0) 为中心获取每个点的旋转实例。然后,我从这些旋转点构造了一个 Polygon 对象,并根据玩家的 x 和 y 位置(它们是我的类中存储的变量)对其进行平移。

这是我使用的代码段。

public void DoFrame(Graphics2D g)
{
    // Increment x by the dx factor
    x += dx * game.GetDeltaTime();
    // Increment y by the dy factor
    y += dy * game.GetDeltaTime();

    // Reset the body polygon
    body.reset();
    // Loop through all of the reference polygon points
    for(int i = 0; i < xpoints.length; i++)
    {
        // Create a placeholder array for the two points
        double[] pt = {xpoints[i], ypoints[i]};
        // Rotate the points around a center (0, 0)
        AffineTransform.getRotateInstance(theta, 0, 0).transform(pt, 0, pt, 0, 1);
        // Add the rotated point to the body
        body.addPoint((int) pt[0], (int) pt[1]);
    }
    // Translate the body based on x and y coordinates
    body.translate((int) x, (int) y);
}

这将根据原始传递点的中心粗略显示一个旋转的多边形,但请注意,使用的中心不是完美的中心,而是取决于构造函数调用时点的定位。

【讨论】:

  • 我并没有试图理解算法,但我会说这个 - 你写的大多数 cmets 根本没有用。它们使代码混乱,并且所有信息都是重复的,因此现在您每次都必须在两个地方而不是一个地方更改它。代码应该足够有表现力,这样就不需要 cmets。我建议你阅读 Clean Code 一书中关于 cmets 的章节。
【解决方案2】:

您并没有按照您的想法应用旋转变换。因为您首先修改x,并使用修改后的值来计算y。保存x 的副本。

【讨论】:

  • 顺便说一句,保留整个原始多边形的副本并以增加的角度旋转它会更安全。否则,舍入误差会随着时间的推移而累积。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-30
  • 2013-12-18
  • 2014-02-08
  • 1970-01-01
  • 2018-05-17
相关资源
最近更新 更多