# einfache Simulation von Gravitation



## jeipack (1. März 2009)

Hi
Ich möchte gerne einen einfachen Gravitationseinfluss eines Planeten auf ein Schiff simulieren.
Input ist:
- x,y des Schiffes
- x,y des Planeten
- Gravitationskonstante des Planeten
Output ist:
- Hinzuzufügende Geschwindigkeit x und y des Schiffes

Die Gravitationskonstante habe ich bis jetzt so benutzt, dass sie die Entfernung angibt in der die Gravitation noch wirkt. Danach wird die Differenz von Gravitationskonstante und Abstand des Schiffes zum Planeten zur aktuellen Beschleunigung des Schiffes hinzugefügt.


```
//Gravitationseinfluss auf Schiff ausüben
				int dif_x=planet.getMidX()-ship.getMidX();
				int dif_y=planet.getMidY()-ship.getMidY();
				
				
				if(dif_x*dif_x+dif_y*dif_y<planet.getGravity()*planet.getGravity()) {
					if(dif_x>1||dif_x<-1) {
						if(dif_x<planet.getGravity()) {
							ship.beeinflusseBeschleunigungX(dif_x);
						} 
					}
					if(dif_y>1||dif_y<-1) {
						if(dif_y<planet.getGravity()) {
							ship.beeinflusseBeschleunigungY(dif_y);
						} 
					}
				}
```
Das ganze funktioniert zwar grundsätzlich. Die Gravitation wirkt sich aber Linear aus und das stimmt so ja nicht wirklich.

Ziel ist, dass das ganze System stimmig ist (es muss nicht 100% realistisch sein) und es schlussendlich einfacher ist in einen Orbit einzuschwenken.


Ich hoffe ihr habt eine Idee wie ich das hinbekomme 

Vielen Dank
jeipack


Edit:
Wenn ich die Gravitationskonstante recht hoch stelle und dif_x und dif_y jeweils noch durch 2.5 Teile kommt es im Moment ganz gut. Über Anregungen würde ich mich trozdem freuen!


----------



## takidoso (2. März 2009)

Hi jeipack,
echt interessantes Thema. Also wenn ich mich recht entsinne gibt es doch die Berechnung des freien Falls. Müsste dass nicht sowas ähnliches  hier sein?
Anderseits hat es ja vermute ich mal ohne Physiker zu sein sowohl mit der Masse des "Planeten" als auch der Masse des "Raumschiffes" zu tun.
vielleicht hilft ja ein wenig googeln 

in diesem Sinne 

Takidoso


----------



## jeipack (2. März 2009)

Hi
Ich habe es inzwischen hinbekommen 
Was ich oben gemacht habe simuliert eher ein Gummiseil zwischen Planeten und dem Schiff.

Also die Masse des Schiffes (sofern ich das noch richtig in Erinnerung habe) ist so klein und kann vernachlässigt werden (Das Schiff würde mit seiner Masse ja den Planeten bewegen und der ist eh fix). Ich habe jetzt also nur eine Gravitationskonstante für jeden Planeten (Entspricht seiner Masse).

Ein "Problem" ist jetzt allerdings noch:
Mit dem Schiff kann man über den Fensterrand fliegen und kommt beim anderen Ende wieder raus. Die Gravitationswirkung hört aber beim Fensterrand auf. Wenn ein Planet nun Nahe an einem Rand plaziert ist, kann man wenn man auf diesen zu fliegt und dann gleich am Rand verschwindet immer mehr beschleunigen.. Wie ich das lösen will weiss ich aber noch nicht. 


Gruss


----------



## takidoso (2. März 2009)

Ich wette das wird ein nettes Spiel 
Wäre doch Lustig wenn Du es zum Spielen irgendwo ins Netz stellst.
Wird das eigentlich etwas für "zukünftige Raumfahrer" Swing-By Manöver zu üben?

Zu Deinen Problem:
Ich nehme an, dass Du das Raumschiff wenn es den Bildschirm verlässt irgendwie mit Modulusfunktion auf die andere Seite des Bildschirm zauberst, oder?
Die Kräfte die auf Dein Schiff wirken müssten vielleicht ähnlich ermittelt werden. Also vielleicht sollte man die Planeten bzw. ihre Gravitationskräfte dann auch irgendwie umgekehrt Modulo-mäßig ermitteln.
Ich nehme an jeder Planet hat seine Kraft in einem größeren konzentrischen Kreis. Du müsstest also die Kreisausschnitte die diese Kraft darstellen modulomäßig ermitteln, so Du merkst, dass der Gravitationskreis den Bildschirm überschreitet.

Mal eine Frage: wie machst Du dass eigetnlich mit der Darstellung des Raumschiffes wenn ein Teil auf dem einen und ein teil auf dem anderen Bildschirmrand liegt?

mit neugierigen Grüßen 

Takidoso


----------



## jeipack (2. März 2009)

Also Swing-By Manöver funktionieren schon gut  
Vorallem hab ich jetzt noch den vermeindlich letzen Bug in der Gravitation gefunden (Hab vergessen lag mitzurechnen).


Ans Onlinestellen hab ich auch schon gedacht.. mal schauen..
Am anderen Ende des Bildschirms wieder aufzutauchen ist recht simpel:

```
public void move(long delta) {
		x += (delta * dx) / 1000;
		y += (delta * dy) / 1000;

		//falls wir ausserhalb des Bildes sind tauchen wir am anderen ende wieder auf ;)
		if(x<0) {
			x+=windowx;
		} else if(x>windowx) {
			x-=windowx;
		}
		if(y<0) {
			y+=windowy;
		} else if(y>windowy) {
			y-=windowy;
		}
	}
```

Schönen Abend
und falls mal was online geht post ichs hier 

cheers


----------



## takidoso (3. März 2009)

jeipack hat gesagt.:


> Also Swing-By Manöver funktionieren schon gut
> Vorallem hab ich jetzt noch den vermeindlich letzen Bug in der Gravitation gefunden (Hab vergessen lag mitzurechnen).


jetzt musst Du mir nur noch erklären was lag heißt bzw. bedeutet.

Bezogen auf Deinen Algorithmus für das Verlassen und Wiedereintreten des Bildschirms, ist nett und einfach, bedeutet aber auch, dass Dein Raumschiff plötzlich den Bildschirm verlässt und plötzlich wieder eintritt, oder? Ich hätte sonst angenommen dass ein Teil des raumschiffes an dem einen ende und der andere teil auf  dem anderen Ende des Bildschirms zeitweise zusehen sei.
Wäre natürlich gruselig komplizierter gewesen.

prost


----------



## jeipack (3. März 2009)

Morgen


> Ich hätte sonst angenommen dass ein Teil des raumschiffes an dem einen ende und der andere teil auf dem anderen Ende des Bildschirms zeitweise zusehen sei.
> Wäre natürlich gruselig komplizierter gewesen.


Also das reine Zeichnen wäre nicht so kompliziert. Aber die Grafik ist im Moment ans Schiff gekoppelt, somit hätte ich auf einmal mehr Schiffe auf die eine Gravitation wirkt ^^.

Lag (kennt man doch vom Onlinegamen ;-] ):
Ich berechne alle 20ms alles neu (Gravitationseinfluss, Schiffsbeschleunigung -> Schiffsbewegung) und zeichne das dann auf dem Spielfeld. Wenn diese Berechnung nun lange dauert dann rechne ich bei der Schiffsbewegung die Verzügerung(=lag) mit. Also wenn es z.B. 5ms gedauert hat dann ist die Bewegung=Bewegung*(25ms/20ms). Das mitzurechnen hatte ich bei der Gravitation vergessen.

PS: Hab das am anderen Bildschirmende auftauchen rausgenommen. Mein Ziel ist es nun das ganze Zoombar und Scrollbar zu machen..


----------



## takidoso (3. März 2009)

Hi,
bezüglich Scrollen und Zoomen kann ich Dir was Nettes wenn auch Simples anbieten...
Ich benutze es für ein Risiko inspiriertes Brettspiel:

```
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2006</p>
 * <p>Company: </p>
  * @version 1.0
 */

public class ScalingPanel extends JPanel implements MouseWheelListener
{
    

	private BorderLayout        m_borderLayout1  = new BorderLayout();
    private JSlider             m_zoomSlider     = new JSlider();
    private JScrollPane         m_scrollPanel    = new JScrollPane();
    private ScalablePanel       m_scalablePanel;

    public ScalingPanel()
    {
        try
        {
            jbInit();
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
    }

    private void jbInit() throws Exception
    {
        this.setLayout(m_borderLayout1);
        m_zoomSlider.setOrientation(JSlider.VERTICAL);
        m_zoomSlider.addChangeListener(new javax.swing.event.ChangeListener()
        {
            public void stateChanged(ChangeEvent e)
            {
                zoom();
            }
        });
        this.add(m_zoomSlider, BorderLayout.WEST);
        this.add(m_scrollPanel,  BorderLayout.CENTER);
        m_zoomSlider.setMaximum(500);
        m_zoomSlider.setMinimum(5);
    }

    public  void zoom()
    {
    	if (m_scalablePanel!=null)
    	{
    		double zoomFaktor = (double)m_zoomSlider.getValue()/(double)100;
    		m_scalablePanel.setScaling(zoomFaktor);
    		Dimension d = m_scalablePanel.getPreferredSize();
    		m_scrollPanel.getVerticalScrollBar().setMaximum(d.width);
    		m_scrollPanel.getHorizontalScrollBar().setMaximum(d.height);
    	}
    }


    public ScalablePanel getScalablePanel()
    {
    	return m_scalablePanel;
    }

    public void setScalablePanel(ScalablePanel scalabePanel)
    {
    	if (m_scalablePanel!=null)
    	{
    		m_scalablePanel.removeMouseWheelListener(this);
    	}
    	m_scalablePanel = scalabePanel; 
    	m_scrollPanel.getViewport().add(m_scalablePanel, null);
    	
    	m_scalablePanel.addMouseWheelListener(this);
    	
    	zoom();
    }
    
    /** 
	 * @see java.awt.event.MouseWheelListener#mouseWheelMoved(java.awt.event.MouseWheelEvent)
	 */
	public void mouseWheelMoved(MouseWheelEvent e)
	{
		m_zoomSlider.setValue(m_zoomSlider.getValue()+e.getWheelRotation()*10);
		
	}
}
```


```
abstract public class ScalablePanel extends JPanel
{
	abstract public void      setScaling(double zoomFactor);
}
```

alles was man zur Benutzung benötigt ist ein Panel, welches von ScalablePanel abgeleitet ist und die abstrakte Routine entsprechend implementiert.

ScalingPanel wird dann wie ein normales Panel z.B. in einem JFrame eingebracht und das von ScalablePanel  abgeleitete Panel in das ScalingPanel gesetzt.
Ist eine ganz nette Möglichkeit. 

Mal 'ne Frage: wenn Du zufällig ein Endlos-Scrollen realisieren willst und dabei Erfolg hast, wäre ich super an Deiner Lösung interessiert.


----------



## jeipack (5. März 2009)

Hi
Ich glaub ich bin dir hier noch eine Antwort schuldig, die letze hab ich im Vorschaumodus geschlossen..

Also die wirklich interessante Funktion:

```
setScaling(double zoomFactor);
```
muss ich noch selber schreiben? ^^

Ich glaube die Klasse ist nicht das richtige für mein Game, aber interessant ist sie auf jedenfall *abspeicher* Danke 



> Mal 'ne Frage: wenn Du zufällig ein Endlos-Scrollen realisieren willst und dabei Erfolg hast, wäre ich super an Deiner Lösung interessiert.


Jo kein Ding. Eine Möglichkeit wäre ja, die x,y Koordinaten jedes Objektes einfach in entgegengesetzer Richtung der Mausbewegung (oder einfach allgemein Scrollbewegung) zu verschieben. So kann theoretisch unendlich weit gescrollt werden. Praktisch kann soweit gescrollt werden bis ein Objekt x oder y ausserhalb des double-Wertebereichs hat.. ^^

Gruss

PS: Hast du meine PM nicht bekommen?


----------



## takidoso (5. März 2009)

jeipack hat gesagt.:


> Hi
> Ich glaub ich bin dir hier noch eine Antwort schuldig, die letze hab ich im Vorschaumodus geschlossen..
> 
> Also die wirklich interessante Funktion:
> ...


ja stimmt!


> Ich glaube die Klasse ist nicht das richtige für mein Game, aber interessant ist sie auf jedenfall *abspeicher* Danke


Es ist nur so eine Art Bedienungsklasse für eine Panel was halt obigefunktion implementiert und von der erwarteten Klasse abgeleitet ist.
Ich dachte schon, dass es nicht das richtige für ein Animiertes Spiel ist, da eignen sich besser Mausgesten fürs Zoomen, auch wenn diese Klasse das Mausrad einbezieht. Eigetnlich müsste Die klasse noch verbessert werden in der Richtung, dass beim Zoomen der Fokus sich an dem Mauszeiger orientiert, was zur Zeit noch nicht der Fall ist.


> Jo kein Ding. Eine Möglichkeit wäre ja, die x,y Koordinaten jedes Objektes einfach in entgegengesetzer Richtung der Mausbewegung (oder einfach allgemein Scrollbewegung) zu verschieben. So kann theoretisch unendlich weit gescrollt werden. Praktisch kann soweit gescrollt werden bis ein Objekt x oder y ausserhalb des double-Wertebereichs hat.. ^^


Ja irgendwie ist mir das klar, aber ich frage mich dauernd wie man das in ein JScrollPanel bzw einen Viewport einbaut. Da ich bei meinem Spielchen halt mich auf JScrollPanel gestüzt hatte, dachte ich, es wäre gut irgendwie da weiter zu machen, habe aber irgendwie noch keinen gescheiten Ansatz. Die paintComponent-Routine dahingehend zu modifizieren, fand ich erstmal nicht so prickelnd, da ich dachte dass muss doch irgendwie mit einem abgeleiteten Viewport gehen 
Eine weitere Schwierigkeit stellt für mich die Möglichkeit dar, dass ein Teil der zu Zeichnenden Objekte sowohl auf der einene als auch auf der anderen Seite des Sichtfenster auftauchen könnten. Eigetnlich könnte ein Objekt auch in allen 4 Ecken auftauchen. Naja irgendwie noch fickelich und auch erstmal bei mir verschoben weil für meine Anwendung dann doch nicht soo furchtbar wichtig.


----------

