5

I'm making a game where the player will (on release of mouseclick) shoot a "star" in a certain direction at an initial speed determined by how far he dragged the mouse before releasing. I have a "planet" (stationary circle) on the canvas that I want to exert a gravitational pull on the moving planet. I believe I'm using the right formulas for gravitational force and such, and I have it partially working - the planet affects the planet's trajectory up until a certain point, when the star seems to endlessly speed up and stop changing direction based on it's angle to the star. Any advice? (I know that stars aren't supposed to orbit planets, it's the other way around. I coded the whole thing with the names interchanged so forgive that).

main class:

    import acm.graphics.GCompound;
    import acm.graphics.GImage;
    import acm.graphics.GLabel;
    import acm.graphics.GLine;
    import acm.graphics.GMath;
    import acm.graphics.GObject;
    import acm.graphics.GPen;
    import acm.graphics.GPoint;
    import acm.graphics.GRect;
    import acm.graphics.GOval;
    import acm.graphics.GRectangle;
    import acm.program.GraphicsProgram;
    import acm.util.RandomGenerator;
    import java.awt.Color;
    import java.awt.event.MouseEvent;
    import java.util.*;

    public class Space extends GraphicsProgram {
      public static int APPLICATION_WIDTH = 1000;
      public static int APPLICATION_HEIGHT = 1000;
      private int size = 15;
      public static double pMass = 1000;
      public static int sMass = 20;
      public static double G = 200;
      private RandomGenerator rand = new RandomGenerator();
      GOval planet, tempstar;
      shootingStar star;
      GLine line;
      double accel, xAccel, yAccel, xspeed, yspeed, angle;


      public void init(){
        planet = new GOval(APPLICATION_WIDTH/2, APPLICATION_HEIGHT/2, 30, 30);
        planet.setFilled(true);
        planet.setFillColor(rand.nextColor());
        add(planet);

      }


      public void mousePressed(GPoint point) {
        // draw a line
        tempstar = new GOval(point.getX() - size/2, point.getY() - size/2, size, size);
        tempstar.setFilled(true);
        tempstar.setColor(rand.nextColor());
        add(tempstar);
        line = new GLine(tempstar.getX() + size/2, tempstar.getY() + size/2, 
    point.getX(), point.getY());                             
        add(line);
        line.setVisible(true);
      }

      public void mouseDragged(GPoint point) {
        line.setEndPoint(point.getX(), point.getY());
      }

      public void mouseReleased(GPoint point){
        xspeed =            
    -.05*GMath.cosDegrees(getAngle(line))*GMath.distance(line.getStartPoint().getX(),         
    line.getStartPoint().getY(), line.getEndPoint().getX(), line.getEndPoint().getY());
        yspeed = 
    .05*GMath.sinDegrees(getAngle(line))*GMath.distance(line.getStartPoint().getX(), 
    line.getStartPoint().getY(), line.getEndPoint().getX(), line.getEndPoint().getY());
        System.out.println(xspeed + " " + yspeed);
        star = new shootingStar(xspeed, yspeed, this);
        if(xspeed != 0)
          add(star, tempstar.getX(), tempstar.getY());
        new Thread(star).start();
        remove(tempstar);
        remove(line);

      }

      private double getAngle(GLine line) {
        return GMath.angle(line.getStartPoint().getX(), line.getStartPoint().getY(), 
                           line.getEndPoint().getX(), line.getEndPoint().getY());
      }


      public void checkPlanet(){
        accel = .06*GMath.distance(star.getX(), star.getY(), planet.getX(), 
    planet.getY());
        angle = correctedAngle(GMath.angle(planet.getX(), planet.getY(), star.getX(), 
    star.getY()));       
        xAccel = accel*GMath.cosDegrees(GMath.angle(planet.getX(), planet.getY(), 
    star.getX(), star.getY()));
        yAccel = accel*GMath.sinDegrees(GMath.angle(planet.getX(), planet.getY(), 
    star.getX(), star.getY()));

        double newX = xspeed - xAccel*.01;
        double newY = yspeed + yAccel*.01;

        xspeed = newX + xAccel*Math.pow(.01, 2)/2;
        yspeed = newY + yAccel*Math.pow(.01, 2)/2;

        star.setSpeed(xspeed, yspeed);


      }

      public double correctedAngle(double x) {
        return (x%360.0+360.0+180.0)%360.0-180.0;
    }
    }

Pertinent parts of shootingStar class:

     public void run() {
        // move the ball by a small interval
        while (alive) {
        oneTimeStep();
        }
      }

      // a helper method, move the ball in each time step
      private void oneTimeStep() {
        game1.checkPlanet();
        shootingStar.move(xSpeed, ySpeed);
        pause(20); 
      }

      public void setSpeed (double xspeed, double yspeed){
        xSpeed = xspeed;;
        ySpeed = yspeed;

      }
    }

EDIT:

Current Main Class Method:

    public void checkPlanet(){
        double xDistance = star.getX() - planet.getX();
        double yDistance = star.getY() - planet.getY();
        double distance = Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2));
        accel = G*pMass/Math.pow(distance, 2);

        xAccel = accel * xDistance/distance;
        yAccel = accel * yDistance/distance;

          xspeed += xAccel;

         yspeed += yAccel;

       star.setSpeed(xspeed, yspeed);

    }

Current Star class Method:

    public void run() {
        while (alive) {
          oneTimeStep();
        }
      }

      private void oneTimeStep() {
        game1.checkPlanet();
        shootingStar.move(xSpeed, ySpeed);
        pause(20); 
      }

      public void setSpeed (double xspeed, double yspeed){
        xSpeed = xspeed;;
        ySpeed = yspeed;

      }
    }
lorddarkangel
  • 212
  • 3
  • 21
user1811903
  • 51
  • 1
  • 3
  • After a whole day of reading TDWTF, eventually stopping at [this](http://thedailywtf.com/Articles/Divine-by-Zero.aspx), I momentarily felt obligated to ask whether you wanted to simulate the gravitational pull or just the math behind it. – Theodoros Chatzigiannakis Dec 31 '12 at 18:28

2 Answers2

1

Wow, that's a lot more effort than what you "HAVE" to do.

If the thing is on the board calculate it's distance from the object. If it's farther away than D do nothing. If it's D away then it's within the objects gravitational pull. Just add a small amount of velocity to it pointing at the object. Let's say it was 1000 X away and 500 z away. Just do something simple like divide by 100, and add that to the objects velocity so it moves 10 x and 5 y towards the object. Each time you update add the velocity again.

You'll probably want a maximum velocity also. This is a LOT easier to calculate works well, and will give you effects like in the game STAR CONTROL where there's a planet, or the ships gravitationally pull towards each other a tiny bit. I did this with 10 planets and a star, and the user could basically do lunar lander with each planet. It was a blast but I never turned it into a real game. This has the advantage of being rockingly fast to calculate. There some edge conditions like if you make the map a torus so they warp through the sides of the map, but basically it's all just simple addition and subtraction.

It's GOOD enough for a game. You're not making a simulator. You're making a game.

ggb667
  • 1,881
  • 2
  • 20
  • 44
0

I am not sure, but try to change the part where you calculate the xAccel and yAccel values to something like this.

xDistance = XComponentObject1 - XComponentObject2; 

yDistance = YComponentObject1 - YComponentObject2;

(xDistance and yDistance can have negative values)

Distance = sqrt( xDistance^2 + yDistance^2 );

gConstant = constant Value for gravitational strenght in your world;

MassObject1 = some Mass;

MassObject2 = some other Mass;

Accel = gConstant*MassObject1*MassObject2 / (Distance^2 );

''NOW COMES THE IMPORTANT PART''

xAccel = Accel * xDistance/Distance;

yAccel = Accel * yDistance/Distance;

I think your whole yadayada with sine and cosine creates a whole bunch of hard-to-trackdown-errors.

paradigmatic
  • 40,153
  • 18
  • 88
  • 147
N_las
  • 1
  • Thanks - this definitely works more efficiently than what I had going on. The same problem still seems to be there though - how do I account for the fact that as the star is drawn into the planet's gravitational field, it should be (and does) accelerating. As it gets "pushed out" the other side (given it doesn't collide with the planet), it should then decelerate. My star's speed endlessly increases. – user1811903 Nov 09 '12 at 16:15
  • That sounds like a sign-error to me. What exactly do you do with the Acceleratien values afterwards? I don't understand the sense of your code. Just try: ' NewXspeed = OldXspeed + xAccel*timefactor; ' NewYspeed = OldYspeed + yAccel*timefactor; ' – N_las Nov 10 '12 at 10:06
  • updated question with current code - still having two problems: the gravitational field is working in the opposite direction - all objects are being pushed AWAY from the center planet, and 2) the stars don't do a complete orbit - it's more of a partial orbit where they just get faster and faster until they're going in a straight line. any advice? thank you very much! – user1811903 Nov 12 '12 at 07:07
  • regarding your first problem: just use a negative Value for your gravitational constant. – N_las Nov 14 '12 at 12:09