1

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);
    }
} 
rdelfin
  • 819
  • 2
  • 13
  • 31
  • 2
    Are you sure the aspect ratio on the monitor/LCD/yadda is 1:1? – Tony Ennis May 17 '12 at 23:56
  • I don't know what your output display is. But back in the day (/waves cane) pixels weren't square. They were rectangular. We had to apply a scaling factor to an axis to make a mathematically correct circle into a visually correct circle. I have no idea if this is your problem; if it is, you'll never solve it by looking at your code. – Tony Ennis May 18 '12 at 01:09
  • If you're sure this isn't your problem, post your code. But you can probably tell immediately where the problem lies by displaying the X and Y coords where either X or Y are 0; the other value should be well known. For example, a circle with a radius of 2 would have (0,2), (2,0), (0,-2), (-2,0) for the 4 positions. – Tony Ennis May 18 '12 at 01:11
  • I have the full planet class up, incase you need to check it, and no, i am sure that the problem is not because of the pixel ratio. It is 1:1 – rdelfin May 18 '12 at 01:44
  • How are you drawing the circle? In swing, java draws circles not around the middle of it, but by the top left corner, much like a square, is it possible your equation is fine but the position of the circle is off by this? Try drawing a single dot and see if it still does it? – dann.dev May 18 '12 at 03:11
  • The circle draws itself just like in swing – rdelfin May 18 '12 at 03:24

2 Answers2

3

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.

Image of how Swing draws.

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
dann.dev
  • 2,406
  • 3
  • 20
  • 32
  • I thought of that which is why in position.x = ((Math.cos(orbitAngle) * orbitDistance) + orbitCenter.x); and position.y = ((Math.sin(orbitAngle) * orbitDistance) + orbitCenter.y); I added the OrbitCenter.x and .y – rdelfin May 18 '12 at 03:37
  • Sorry my maths is a bit rusty, but I don't see what the orbit center has to do with anything. The issue I'm saying is that the image is being drawn at it's top corner, so the top corner is following the orbit, not the center of the planet which is what I think you want – dann.dev May 18 '12 at 03:42
  • Try altering your code to not clear the screen each time and see how the planet travels around the center – dann.dev May 18 '12 at 03:43
  • Oh, that. I also changed the draw method so that the position.x and the orbitCenter.y are the actual centers of the objects. You can see it in the draw – rdelfin May 18 '12 at 03:46
  • Thanks. I just discovered that it follows a circular pattern but it is off as you said for some reason even if I took it into account. I will revise the code again. It seems like it is a circular orbit, just off to the top left corner – rdelfin May 18 '12 at 03:52
  • Also. I thought I edited that piece of code for position. Thank you – rdelfin May 18 '12 at 03:53
  • 1
    No worries, those kind of errors are the worse, where you've found them, edited them, but then not saved, or accidentally copied back over it, you search everywhere but there and slowly go insane! – dann.dev May 18 '12 at 03:59
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.

Animation Test

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I tried resizing the applet to 800 by 800 and the error remains. The planet still colides with the central planet on only one side. Also, why should a constant value (the distance from the sun to the planet) be related with the width-height ratio of the applet? – rdelfin May 18 '12 at 01:57
  • I see the expected result in `AnimationTest`. The parametric equation assumes a unit circle, and you have to transform the coordinates from Cartesian to screen. What applet? Can you edit your question to include an [sscce](http://sscce.org/)? – trashgod May 18 '12 at 02:19
  • I would like to post the whole code but the base for the code (what makes the applet be an applet) is a class called AppletCore that I have inside a .jar file. I could send it to you as is seems that I cannot add an atachment – rdelfin May 18 '12 at 02:35
  • ok, I added a download link to the jar and the complete, compilable example. I tried making it as short as posible but this is it. – rdelfin May 18 '12 at 02:42