# Asteroid unschöne Bewegung



## raven (18. Mrz 2009)

Hallo...
Ich habe mal wieder eine Frage an euch. Ich versuche mich gerade an einem Asteroid-Clone, jedoch sieht die Bewegung meines Raumschiff so unschön aus...
Und zwar beim beschleunigen ist alles OK, nachdem ich das Raumschiff gedreht habe und erneut beschleunige will. Fährt es gleich in die Richtung. Ist es im Weltraum nicht so, das das Raumschiff erstmal Gegenschub(hoffe ihr wisst was ich meine) ausübt und auch ein wenig von der eigentlich geplanten Flugbahn abkommt...

Die Bewegung habe ich Moment so gelöst

```
public void move() {
		if(forward) {
			if(v < vMax)
				v = v + a;
		}

		if(backward) {
			if(v > -vMax)
				v = v - a;
		}

		if(!forward && !backward) {
			if(v < 0)
				v = v + 0.01F;
			if(v > 0)
				v = v - 0.01F;
		}

		if(right) {
			alpha = alpha + rv;
		}
		if(left) {
			alpha = alpha - rv;
		}

		impuls();
	}

	public void impuls() {
		if(!right && !left) {
			vx = (float)(Math.cos(Math.toRadians(alpha)) * v);
			vy = (float)(Math.sin(Math.toRadians(alpha)) * v);
		}
		x = x + vx;
		y = y + vy;
	}
```

Hoffe ihr wisst wie ich es meine...

mfg raven


----------



## 0x7F800000 (18. Mrz 2009)

nichts für ungut, aber in einem solchen spiel Koordinaten in Polardarstellung abzuspeichern ist krank^^ :autsch: 
Schreib das alles in normale Kartesische rechteckige Koordinaten um, dann läuft's von selbst... 
(Den Winkel für die Orientierung des schiffes mitzuspeichern ist zwar unnötig, aber hier grad noch so akzeptabel. Für die Position, geschwindigkeit und beschleunigung solltest du mit einer normalen "Vector2D"-Klasse rechnen, ob aus irgendeinem package oder selbstgeschrieben ist egal)


----------



## Developer_X (18. Mrz 2009)

ich glaub die wissen net was du meinst, das gibts doch auch als Online Game,
stell hier mal den Link rein, damit die Sehen was du und ich meinen....


----------



## 0x7F800000 (18. Mrz 2009)

Ich geh mal davon aus, dass sowas hier gemeint ist:
Vectoroids - Miniclip Games - Play Free Games
Wie gesagt: polarkoordinaten haben da überhaupt nichts verloren...


----------



## Marco13 (18. Mrz 2009)

Polarkoordinaten sehe ich da auch nicht - dieses sin/cos-Gedengel ist wohl nur, um die Geschwindikeitsänderung in die entsprechende (Blick)Richtung hinzukriegen (ob man den Drehwinkel speichert oder die Blickrichtung ist ja wurscht ...). Allerdings scheint dort nur die Position verändert zu werden, und nicht die Geschwindigkeit (bzw. der Impuls).


----------



## raven (18. Mrz 2009)

Ja genau so was, halt also 360 Grad Drehung usw... wenn ich das jetzt richtig verstanden habe, soll ich mein Schiff nicht einfach so drehen, sonder die Drehung über Vektoren berechnen...

EDIT:
Hat jemand von euch ne Seite wo die Berechnung erklärt wird, oder zum Beispiel wie es anhand so eines Spiels erläutert wird... ich kann mir bis jetzt noch nichts darunter vorstellen... wie ich das Schiff anders drehen soll...


----------



## 0x7F800000 (18. Mrz 2009)

1) Position als p=(px,py) abspeichern
2) Geschwindigkeit als v=(vx,vy) abspeichern
3) Meinetwegen drehung als alpha aus [0,2PI] abspeichern. Bitte, tue der Welt eine gefallen, und lasse diesen ganzen 

```
toDegrees(fromDegrees(toRadians(myAngleInSomeFuckedUpFormat))))
```
-Mist weg, und speichere direkt alles im schönen vorfaktor unbehafteten Bogenmaß.
4) Betrag der beschleunigung irgendwo als konstante definieren

```
public static double ACCELERATION=123.456;
```
5) Rictungsänderung des schiffes auch als konstante abspeichern

```
public static double ROTATION=0.01;
```
6) Reaktion auf tasten:
Rechts: alpha-=ROTATION
Links: alpha+=ROTATION
Oben: : 

```
//Beschleunigung berechnen
a=(ax,ay)=ACCELERATION*(Math.cos(alpha),Math.sin(alpha))

...

//geschwindigkeit ändern
v+=a*dt //wobei "dt" entweder die zeit des letzten durchlaufs des gameloops oder einfach kleine konstante ist
//bewegen
x+=v*dt
```
Beim Druck des pfeilchens nach unten zeigt der beschleunigungsvektor einfach in die entgegengesetzte richtung:

```
//Beschleunigung berechnen
a=(ax,ay)=-ACCELERATION*(Math.cos(alpha),Math.sin(alpha))

...
//geschwindigkeit ändern
v+=a*dt //wobei "dt" entweder die zeit des letzten durchlaufs des gameloops oder einfach kleine konstante ist
//bewegen
x+=v*dt
```
Sonst noch Fragen...?


----------



## raven (18. Mrz 2009)

Ok danke erstmal... aber ich verstehe folgende Zeilen noch nicht

a=(ax,ay)=ACCELERATION*(Math.cos(alpha),Math.sin(alpha))

mfg raven


----------



## 0x7F800000 (18. Mrz 2009)

das ist kein javacode, sondern einfach nur als "pfeilchenrechung" hingeschrieben.
sinus ist sinus
kosinus ist kosinus
* ist die multiplikation
(x,y) ist ein tupel mit 2 koordinaten, dafür solltest du dir eine Vector2d-Klasse basteln...


----------



## raven (18. Mrz 2009)

```
if(forward) {
			a.setLocation(ACCELERATION*Math.cos(alpha), ACCELERATION*Math.sin(alpha));
			
			if(v.getX()+v.getY() < vMax)
				v.setLocation(v.getX()+a.getX()*1.00F, v.getY()+a.getY()*1.00F);
			
			p.setLocation(p.getX()+v.getX()*0.05F, p.getY()+v.getY()*0.05F);
			
		}
```

hab das jetzt so hin gebaut, aber der Flieger fliegt nicht in die gewünschte Richtung...
wie ne vectort2d klasse... warum brauch ich dafür ne extra klasse...


----------



## Marco13 (18. Mrz 2009)

_4) Betrag der beschleunigung irgendwo als konstante definieren
...
5) Rictungsänderung des schiffes auch als konstante abspeichern
_
... vorrausgesetzt, sie SIND wirklich konstant (und es gibt nicht irgendwelche "booster", die die Beschleunigung erhöhen) dann sollten sie auch *final* sein. Final oder nicht public static.

_wie ne vectort2d klasse... warum brauch ich dafür ne extra klasse... _

Man _braucht_ die natürlich nicht - aber es ist viel bequemer und sauberer. Die Klasse könnte dann praktische Methoden anbieten (add, scale, normalize, rotate...), damit man solches Gewurste

```
a.setLocation(ACCELERATION*Math.cos(alpha), ACCELERATION*Math.sin(alpha));
			
			if(v.getX()+v.getY() < vMax)
				v.setLocation(v.getX()+a.getX()*1.00F, v.getY()+a.getY()*1.00F);
			
			p.setLocation(p.getX()+v.getX()*0.05F, p.getY()+v.getY()*0.05F);
vx = (float)(Math.cos(Math.toRadians(alpha)) * v);
			vy = (float)(Math.sin(Math.toRadians(alpha)) * v);
```
hübscher schreiben kann, z.B. als

```
direction.rotate(alpha);
a.scaleAdd(speed, direction);
p.scaleAdd(0.05f, v);
```
usw. 

Das macht es viiieel einfacher und sauberer, den zeitlichen Verlauf von
position
geschwindigkeit
beschleunigung
(was ja alles 2D-Vektoren SIND) in der Form hinzuschreiben, die "näher" an dem ist, was du hoffentlich schon als Bleistifgekritzel auf einem Blatt Papier vor dir liegen hast....


----------



## raven (19. Mrz 2009)

Könntet ihr mir noch ein aller letztes mal helfen... Mein Schiff fliegt hin wo es will ohne ersehbaren Grund... Ich habe auch schon die Werte der Beschleunigung und des Drehwinkels geändert. Ohne Erfolg... Könnt ihr mir sagen was ich falsch mache?

Hier die die Klasse des Schiffes...

```
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.Graphics;

public class Ship implements KeyListener {

	private Main main;

	private boolean forward;
	private boolean backward;
	private boolean right;
	private boolean left;

	private Point p;
	private Point v;
	private Point a;

	private double ACCELERATION = 1.00F;
	private double ROTATION = 2.00F;

	private int w = 24;
	private int h = 20;
	private int vMax = 1000;
	private int alpha;

	public Ship(Main main, int x, int y) {
		this.main = main;
		this.p = new Point(x, y);
		this.v = new Point(0, 0);
		this.a = new Point(0, 0);
		main.frame.addKeyListener(this);
	}

	protected void paint(Graphics2D g2d) {
		double x = p.getX();
		double y = p.getY();
		AffineTransform rotation = new AffineTransform();
		rotation.rotate(Math.toRadians(alpha), x, y);
		g2d.setTransform(rotation);

		g2d.setColor(Color.white);
		g2d.draw(new Line2D.Double(x+w/2, y, x-w/2, y-h/2));
		g2d.draw(new Line2D.Double(x-w/2, y-h/2, x-w/2, y+h/2));
		g2d.draw(new Line2D.Double(x-w/2, y+h/2, x+w/2, y));

	}

	public void move() {
		if(right) {
			alpha += ROTATION;
		}
		if(left) {
			alpha -= ROTATION;
		}

		if(forward) {
				a.setLocation(ACCELERATION*Math.cos(alpha), ACCELERATION*Math.sin(alpha));

				v.setLocation(v.getX()+a.getX()*0.60F, v.getY()+a.getY()*0.60F);
			System.out.println(v.getX()+"/"+v.getY());
			p.setLocation(p.getX()+v.getX()*0.05F, p.getY()+v.getY()*0.05F);
			
		}

		if(!forward && !backward) {
			if(v.getX()+v.getY() < 0)
				v.setLocation(v.getX()+100.00F, v.getY()+100.00F);
			if(v.getX()+v.getY() > 0)
				v.setLocation(v.getX()-1000.00F, v.getY()-1000.00F);
		}

		
	}

	public void keyPressed (KeyEvent k) {
		int key = k.getKeyCode();
		switch(key) {
			case KeyEvent.VK_NUMPAD8:
				forward = true;
				break;
			case KeyEvent.VK_NUMPAD5:
				backward = true;
				break;
			case KeyEvent.VK_NUMPAD6:
				right = true;
				break;
			case KeyEvent.VK_NUMPAD4:
				left = true;
				break;
		}
	}

	public void keyReleased (KeyEvent k) {
		int key = k.getKeyCode();
		switch(key) {
			case KeyEvent.VK_NUMPAD8:
				forward = false;
				break;
			case KeyEvent.VK_NUMPAD5:
				backward = false;
				break;
			case KeyEvent.VK_NUMPAD6:
				right = false;
				break;
			case KeyEvent.VK_NUMPAD4:
				left = false;
				break;
		}
	}

	public void keyTyped(KeyEvent e) {  }
}
```

Ich wäre sehr dankbar, wenn ihr mir helfen könntet... ich weiß echt nicht mehr weiter...
mfg raven


----------



## Marco13 (19. Mrz 2009)

Was auch immer mit

```
if(v.getX()+v.getY() < 0)
				v.setLocation(v.getX()+100.00F, v.getY()+100.00F);
			if(v.getX()+v.getY() > 0)
				v.setLocation(v.getX()-1000.00F, v.getY()-1000.00F);
```
Erreicht werden soll: Es sieht komisch aus...


----------



## raven (19. Mrz 2009)

das war nur von einem Test, was ich noch nicht auskommentiert hatte.... wie auch immer habe durch Zufall das Problem gefunden... 
hab gemerkt das sin() bzw. cos() ein wert in Bogenmaß erwarten... und ich hatte einfach nur den Winkel alpha rein geschrieben...
funktioniert alles perfekt.. danke an euch noch mal alle...

mfg raven


----------

