2012-11-09 7 views
5

Ich mache ein Spiel, wo der Spieler (bei Freigabe von Mausklick) einen "Stern" in einer bestimmten Richtung mit einer Anfangsgeschwindigkeit schießen wird, bestimmt durch, wie weit er die Maus vor dem Loslassen zog. Ich habe einen "Planeten" (stationären Kreis) auf der Leinwand, die ich auf dem bewegten Planeten eine Anziehungskraft ausüben möchte. Ich glaube, ich verwende die richtigen Formeln für die Gravitationskraft und so, und ich habe es teilweise funktioniert - der Planet beeinflusst die Flugbahn des Planeten bis zu einem bestimmten Punkt, wenn der Stern endlos zu beschleunigen scheint und die Richtung basierend auf seinem Winkel zu ändern zum Stern. Irgendwelche Ratschläge? (Ich weiß, dass Sterne Planeten nicht umkreisen sollen, es ist andersherum. Ich habe die ganze Sache mit den Namen vertauscht, also vergib das).Simulieren Sie die Anziehungskraft eines Sterns?

Hauptklasse:

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

Einschlägige Teile shooting Klasse:

 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:

Aktuelle Hauptklasse Methode:

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

    } 

Aktuelle Sterne-Klasse Methode:

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; 

     } 
    } 
+0

Nach einem ganzen Tag des Lesens der TDWTF, die schließlich bei [dieser] anhielt (http://thedailywtf.com/Articles/Divine-by-Zero.aspx), fühlte ich mich augenblicklich verpflichtet zu fragen, ob Sie die Gravitation simulieren wollten ziehen oder nur die Mathematik dahinter. –

Antwort

0

Ich bin nicht sicher, aber versuchen, den Teil zu ändern, in dem Sie die xAccel und yAccel Werte zu so etwas wie dies zu berechnen.

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; 

Ich denke, Ihre ganze yadayada mit Sinus und Kosinus eine ganze Reihe von schwer zu Trackdown-Fehler erzeugt.

+0

Danke - das funktioniert definitiv effizienter als das, was ich gemacht habe.Dasselbe Problem scheint jedoch immer noch da zu sein - wie beziehe ich die Tatsache mit ein, dass der Stern, wenn er in das Gravitationsfeld des Planeten gezogen wird, beschleunigt werden sollte (und wird). Wenn es auf der anderen Seite "herausgedrückt" wird (vorausgesetzt, es kollidiert nicht mit dem Planeten), sollte es dann verlangsamen. Die Geschwindigkeit meines Sterns steigt endlos. – user1811903

+0

Das klingt nach einem Zeichenfehler für mich. Was genau machst du danach mit den Acceleraten-Werten? Ich verstehe den Sinn deines Codes nicht. Probieren Sie es einfach aus: 'NewXspeed = OldXspeed + xAccel * timefactor; 'NewYspeed = OldYspeed + yAccel * Zeitfaktor; ' –

+0

aktualisierte Frage mit dem aktuellen Code - immer noch mit zwei Problemen: das Gravitationsfeld arbeitet in der entgegengesetzten Richtung - alle Objekte werden weg von der Mitte Planeten geschoben, und 2) die Sterne nicht eine komplette Umlaufbahn - es ist mehr von eine Teilbahn, in der sie immer schneller und schneller werden, bis sie geradeaus fahren. irgendein Rat? vielen Dank! – user1811903

1

Wow, das ist viel mehr Aufwand als das, was Sie "HABEN" zu tun.

Wenn das Ding auf dem Brett ist, berechnen Sie den Abstand vom Objekt. Wenn es weiter weg ist als D tue nichts. Wenn es D ist, dann liegt es innerhalb der Gravitationskraft der Objekte. Fügen Sie einfach eine kleine Geschwindigkeit hinzu, die auf das Objekt zeigt. Nehmen wir an, es war 1000 X weg und 500 z weg. Machen Sie einfach etwas Einfaches wie durch 100 dividieren, und fügen Sie das der Objektgeschwindigkeit hinzu, so dass es sich 10 x und 5 y zum Objekt bewegt. Bei jedem Update addieren Sie die Geschwindigkeit erneut.

Sie werden wahrscheinlich auch eine maximale Geschwindigkeit wünschen. Dies ist viel einfacher zu berechnen funktioniert gut, und wird Ihnen Effekte wie im Spiel STAR CONTROL geben, wo es einen Planeten gibt, oder die Schiffe gravitativ aufeinander zu ziehen ein kleines bisschen. Ich habe das mit 10 Planeten und einem Stern gemacht, und der Benutzer könnte grundsätzlich Mondlander mit jedem Planeten machen. Es war eine Explosion, aber ich habe es nie zu einem echten Spiel gemacht. Dies hat den Vorteil, dass es sehr schnell berechnet werden kann. Es gibt einige Randbedingungen, wie wenn Sie die Karte zu einem Torus machen, so dass sie sich durch die Seiten der Karte biegen, aber im Grunde ist alles nur eine einfache Addition und Subtraktion.

Es ist gut genug für ein Spiel. Du machst keinen Simulator. Du machst ein Spiel.

Verwandte Themen