Game object rotation making an eliptical partern instead of circular

五迷三道 提交于 2019-12-14 04:19:57

问题


I have a simple game animation made in java. It is of three planets rotating around an axis. Each planet is an instance of the class Planet and they have an update method which, every time it is run, the orbit's rotation angle increases and the position is updated acording to the angle and a few predetermined variables like distance from the "sun". From here, you can determine the position of the planet with simple trigonometry. In this case:

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

Cos(angle) = ady/hyp = x/distance
therefore
Cos(angle)*hyp = ady

where the hypothenuse is the distance to the sun and the adyacent and oposite sides are the x and y values respectively. I figured this would work, until I tried it out. It gave me an eliptical rotation. Here is the code that updates the planet's rotation (orbit center is the sun's center position):

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

What could be wrong?

EDIT:

I realized this problem by placing an object with its center in the position specified by orbit center

Here is the full code of the planet class:

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);
    }
}

Here is the class that tests the planet class. You can download the jar it needs to work from here: foxtailgames.net/AppletSource.jar. Here is the tester class (you will probably have to import a few things though if you do it in eclipse or netbeans it will give you the imports):

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);
    }
} 

回答1:


Your rotation is set to 0 in the above so i assume you are not rotating the picture at the moment. What i think is happening is the orbit circle you are producing is fine, but the location you are drawing the planet is off.

Below is an image of how Swing would draw the circle, so the overlap you experience is because of this.

You need to adjust the position you draw the circle by how half the width so it sits over the center of the orbit.

EDIT: You've alter some code but what you need to change is the draw method of he planet:

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);
    }

This line needs to be:

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



回答2:


You might compare your result to this AnimationTest that uses the same parametric equation of a circle. Because the orbital radius is a function of the enclosing panel's dimensions, the orbit is circular only when w equals h. Resize the frame, or set HIGH = WIDE, to see the effect.



来源:https://stackoverflow.com/questions/10645032/game-object-rotation-making-an-eliptical-partern-instead-of-circular

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!