Java 游戏物体旋转,使之成为椭圆而不是圆形

Java 游戏物体旋转,使之成为椭圆而不是圆形,java,animation,rotation,trigonometry,Java,Animation,Rotation,Trigonometry,我有一个用java制作的简单游戏动画。它由三颗围绕一个轴旋转的行星组成。每个行星都是该类行星的一个实例,它们都有一个更新方法,每次运行该方法时,轨道的旋转角度都会增加,并且位置会根据角度和一些预定变量(如距离太阳的距离)进行更新。从这里,你可以用简单的三角法确定行星的位置。在这种情况下: Sin(angle) = op/hyp = y/distance therefore Sin(angle)*hyp = op Cos(angle) = ady/hyp = x/distance therefo

我有一个用java制作的简单游戏动画。它由三颗围绕一个轴旋转的行星组成。每个行星都是该类行星的一个实例,它们都有一个更新方法,每次运行该方法时,轨道的旋转角度都会增加,并且位置会根据角度和一些预定变量(如距离太阳的距离)进行更新。从这里,你可以用简单的三角法确定行星的位置。在这种情况下:

Sin(angle) = op/hyp = y/distance
therefore
Sin(angle)*hyp = op

Cos(angle) = ady/hyp = x/distance
therefore
Cos(angle)*hyp = ady
式中,假设值是到太阳的距离,副边和副边分别是x值和y值。我想这会管用的,直到我试过为止。它给了我一个椭圆旋转。以下是更新行星旋转轨道中心和太阳中心位置的代码:

position.x = ((Math.cos(orbitAngle) * orbitDistance) + orbitCenter.x);
position.y = ((Math.sin(orbitAngle) * orbitDistance) + orbitCenter.y);
有什么不对劲吗

编辑:

我通过将一个对象的中心放置在轨道中心指定的位置来实现这个问题

以下是行星级的完整代码:

public class Planet
{
    protected Image image;

    protected Vector2 position;
    protected final Vector2 orbitCenter;
    protected float rotation;
    protected Vector2 imageSize;

    protected final float rotationSpeed;
    protected final float orbitDistance;

    protected float orbitAngle;
    protected final float orbitAngleSpeed;

    public Planet(Image image, float orbitDistance, float rotationSpeed, Vector2 orbitCenter, float orbitAngleSpeed)
    {
        this.image = image;
        this.position = new Vector2(orbitCenter.x, orbitCenter.y - orbitDistance);
        this.orbitCenter = orbitCenter;
        this.rotation = 0;
        this.imageSize = new Vector2(image.getWidth(null), image.getHeight(null));
        this.rotationSpeed = rotationSpeed;
        this.orbitDistance = orbitDistance;
        this.isMouseOver = false;
        this.isPressed = false;
        this.orbitAngle = 0;
        this.orbitAngleSpeed = orbitAngleSpeed;
    }

    public void Update()
    {
        orbitAngle += orbitAngleSpeed;
        if(orbitAngle > Math.PI * 2)
            orbitAngle %= Math.PI * 2;

        position.x = ((Math.cos(orbitAngle) * orbitDistance) + orbitCenter.x);
        position.y = ((Math.sin(orbitAngle) * orbitDistance) + orbitCenter.y);
    }

    public void Draw(Graphics2D g)
    {
        g.rotate(rotation, position.x + imageSize.x / 2, position.y + imageSize.y / 2);
        g.drawImage(image, (int)position.x, (int)position.y, null);
        g.rotate(-rotation, position.x + imageSize.x / 2, position.y + imageSize.y / 2);
    }
}
这是测试行星类的类。您可以从这里下载它需要工作的jar:foxtailgames.net/AppletSource.jar。下面是tester类,您可能需要导入一些东西,但如果您在eclipse或netbeans中进行导入,它将为您提供导入:

public class PlanetTest extends AppletCore
{
    public void resizeScreen() {resize(800, 800);}

    Image center;
    Planet p;

    public void LoadContent()
    {
        p = new Planet(loadImage("images/GameMenuCircles/Planet1.png"), 100f, 0.02f, new Vector2(400, 400), 0.005f);
        center = loadImage("images/GameMenuCircles/Center.png");
    }

    public void Update(GameTime gameTime)
    {
        p.Update();
    }

    public void Draw(Graphics2D g, GameTime gameTime)
    {
        g.drawImage(center, 400 - center.getWidth(null)/2, 400 - center.getWidth(null)/2, null);
        p.Draw(g);
        g.setColor(Color.green);
        g.drawLine(400, 400, 500, 400);
        g.drawLine(400, 400, 400, 500);
        g.drawLine(400, 400, 300, 400);
        g.drawLine(400, 400, 400, 300);
        g.setColor(Color.white);
    }
} 

您可以将您的结果与使用相同结果的结果进行比较。因为轨道半径是封闭面板尺寸的函数,所以只有当w等于h时,轨道才是圆形的。调整框架大小,或将其设置为“高=宽”,以查看效果


您可以将您的结果与使用相同结果的结果进行比较。因为轨道半径是封闭面板尺寸的函数,所以只有当w等于h时,轨道才是圆形的。调整框架大小,或将其设置为“高=宽”,以查看效果


您的旋转在上面设置为0,所以我假设您目前没有旋转图片。我认为正在发生的是,你正在制造的轨道圈是好的,但是你正在绘制的行星的位置是错的

下面是Swing如何绘制圆的图像,因此您所经历的重叠就是因为这个

您需要调整绘制圆的位置,调整宽度的一半,使其位于轨道中心上方

编辑:您已经更改了一些代码,但需要更改的是行星的绘制方法:

public void Draw(Graphics2D g) {
        g.rotate(rotation, position.x + imageSize.x / 2, position.y + imageSize.y / 2);
        g.drawImage(image, (int)position.x, (int)position.y, null); //here
        g.rotate(-rotation, position.x + imageSize.x / 2, position.y + imageSize.y / 2);
    }
这一行需要:

g.drawImage(image, (int)position.x - imageSize.width, (int)position.y - imageSizee.height, null); //here

您的旋转在上面设置为0,所以我假设您目前没有旋转图片。我认为正在发生的是,你正在制造的轨道圈是好的,但是你正在绘制的行星的位置是错的

下面是Swing如何绘制圆的图像,因此您所经历的重叠就是因为这个

您需要调整绘制圆的位置,调整宽度的一半,使其位于轨道中心上方

编辑:您已经更改了一些代码,但需要更改的是行星的绘制方法:

public void Draw(Graphics2D g) {
        g.rotate(rotation, position.x + imageSize.x / 2, position.y + imageSize.y / 2);
        g.drawImage(image, (int)position.x, (int)position.y, null); //here
        g.rotate(-rotation, position.x + imageSize.x / 2, position.y + imageSize.y / 2);
    }
这一行需要:

g.drawImage(image, (int)position.x - imageSize.width, (int)position.y - imageSizee.height, null); //here

你确定显示器/LCD/yadda上的纵横比是1:1吗?我不知道你的输出显示是什么。但在过去,像素不是正方形的。它们是长方形的。我们必须对轴应用比例因子,才能将数学上正确的圆变成视觉上正确的圆。我不知道这是否是你的问题;如果是,你永远不会通过查看你的代码来解决它。如果你确定这不是你的问题,请发布你的代码。但是,您可以通过显示X和Y坐标立即知道问题所在,其中X或Y为0;另一个值应该是众所周知的。例如,半径为2的圆的4个位置为0,2,2,0,0,-2,-2,0。我有完整的行星等级,以防您需要检查。不,我确信问题不是因为像素比率。现在是1:1,你怎么画圆的?在swing中,java不是在它的中间画圆,而是在左上角画圆,很像一个正方形,你的等式可能是正确的,但圆的位置由此偏离了吗?试着画一个单点,看看它是否还能画出来?你确定显示器/LCD/yadda上的纵横比是1:1吗?我不知道你的输出显示是什么。但在过去,像素不是正方形的。它们是长方形的。我们必须对轴应用比例因子,才能将数学上正确的圆变成视觉上正确的圆。我不知道这是否是你的问题;如果是,你永远不会通过查看你的代码来解决它。如果你确定这不是你的问题,请发布你的代码。但是,您可以通过显示X和Y坐标立即知道问题所在,其中X或Y为0;另一个值应该是众所周知的。例如,半径为2的圆的4个位置为0,2,2,0,0,-2,-2,0。我有完整的行星等级,以防您需要检查。不,我确信问题不是因为像素比率。现在是1:1,你怎么画圆的?我
n swing,java不是在它的中间画圆,而是在左上角画圆,很像一个正方形,你的方程可能很好,但是圆的位置被这个偏移了吗?试着画一个点,看看它是否还能画出来?我试着将小程序的大小调整到800乘800,错误依然存在。这颗行星仍然只在一边与中心行星共线。还有,为什么太阳到行星的距离这个常量值应该与小程序的宽高比相关呢?我在AnimationTest中看到了预期的结果。参数方程假定为单位圆,必须将坐标从笛卡尔坐标变换为屏幕坐标。什么小程序?你能编辑你的问题来包含一个吗?我想发布整个代码,但是代码的基础是一个名为AppletCore的类,它包含在一个.jar文件中。我可以将它发送给您,因为我似乎无法添加atachmentok,我添加了jar的下载链接和完整的可编译示例。我试着使它尽可能短,但就是这样。我试着将小程序的大小调整到800乘800,错误仍然存在。这颗行星仍然只在一边与中心行星共线。还有,为什么太阳到行星的距离这个常量值应该与小程序的宽高比相关呢?我在AnimationTest中看到了预期的结果。参数方程假定为单位圆,必须将坐标从笛卡尔坐标变换为屏幕坐标。什么小程序?你能编辑你的问题来包含一个吗?我想发布整个代码,但是代码的基础是一个名为AppletCore的类,它包含在一个.jar文件中。我可以将它发送给您,因为我似乎无法添加atachmentok,我添加了jar的下载链接和完整的可编译示例。我试着使它尽可能短,但就是这样。我想到了这就是为什么在position.x=Math.cosorbitAngle*orbitDistance+orbitCenter.x;和position.y=Math.sinorbitAngle*轨道距离+轨道中心.y;我加上了轨道中心.x和.y抱歉,我的数学有点生疏,但我不知道轨道中心与任何事情有什么关系。我想说的问题是,图像是在它的上角绘制的,所以上角是沿着轨道,而不是行星的中心,这就是我想你想要改变你的代码,每次都不清除屏幕,看看行星是如何围绕中心运行的哦,那就是。我还更改了绘制方法,使position.x和orbitCenter.y是对象的实际中心。你可以在绘图中看到它不用担心,那些错误更糟糕,在你找到它们,编辑它们,但没有保存,或者不小心复制回来的地方,你到处搜索,但是那里,慢慢地变得疯狂!我想到了这一点,这就是为什么在position.x=Math.cosorbitAngle*orbitDistance+orbitCenter.x;和position.y=Math.sinorbitAngle*轨道距离+轨道中心.y;我加上了轨道中心.x和.y抱歉,我的数学有点生疏,但我不知道轨道中心与任何事情有什么关系。我想说的问题是,图像是在它的上角绘制的,所以上角是沿着轨道,而不是行星的中心,这就是我想你想要改变你的代码,每次都不清除屏幕,看看行星是如何围绕中心运行的哦,那就是。我还更改了绘制方法,使position.x和orbitCenter.y是对象的实际中心。你可以在绘图中看到它不用担心,那些错误更糟糕,在你找到它们,编辑它们,但没有保存,或者不小心复制回来的地方,你到处搜索,但是那里,慢慢地变得疯狂!