Objekt mit cos/sin verschieben

Status
Nicht offen für weitere Antworten.

raven

Bekanntes Mitglied
Hallo,

Ich sitze nun schon nach einiger Zeit an meinem Problem und rätsle wie ich es lösen kann. In meinen Spiel in dem man einen Panzer fährt, kann man mit den Pfeiltasten die Fahrtrichting(360 Crad) ändern und man kann auch schon in die dem entsprechende Richtung fahren, nur wenn ich die Fahrtgeschwindigkeit gering halte, sieht es flüssig aus, aber die Richung stimmt ganz. Wenn ich die Geschwindigkeit hoch habe, stimmt die Fahrtrichtung aber ist halt nicht so flüssig. Kuckt es euch erst einmal selber an.

So rechne ich die Richtung aus
Code:
speedX = (int)(Math.cos(Math.toRadians(angle)) * speed);
speedY = (int)(Math.sin(Math.toRadians(angle)) * speed);

So steure ich ihn:
Code:
public void keyPressed (KeyEvent k) {
		int key = k.getKeyCode ();
		switch (key) {
			case KeyEvent.VK_LEFT:
				player.angle = player.angle - 1;
				break;
			case KeyEvent.VK_RIGHT:
				player.angle = player.angle + 1;
				break;
			case KeyEvent.VK_UP:
				player.xPos = player.xPos + (int)player.speedX;
				player.yPos = player.yPos + (int)player.speedY;
				break;
		}
	}

und hier könnt ihr euch angucken wie es aussieht, wenn die Richtung nicht so ganz stimmt.

Klickt hier

Hoffe ihr seht was ich mein, fahrt einfach mal nen bissl rum.
 

Campino

Top Contributor
Ich gehe mal davon aus, dass du anschließend das x des Panzers um speedX und das y des Panzers um speedY änderst? Ist doch klar das das bei hohen Tempi ruckelt, da macht der Panzer ja große Sprünge statt kleiner Schritte...

Du könntest eventuell mit math.round() echt runden, statt einfach zu casten, vllt. hilft das etwas...aber richtig weg bekommst du es nicht.
 

0xdeadbeef

Top Contributor
Nebenbei bemerkt tabelliert man Winkelfunktionen und dergleichen üblicherweise für Spiele. Das zur Echtzeit zu berechnen ist relativ "teuer" und bringt keinen ernsthaften Vorteil. Wenn man Platz sparen will, braucht man ja eigentlich nur von 0 bis PI/2 zu speichern und kann dann den Rest (inklusive des Kosinus) daraus ableiten.
 

raven

Bekanntes Mitglied
Campino hat gesagt.:
Ich gehe mal davon aus, dass du anschließend das x des Panzers um speedX und das y des Panzers um speedY änderst? Ist doch klar das das bei hohen Tempi ruckelt, da macht der Panzer ja große Sprünge statt kleiner Schritte...

Du könntest eventuell mit math.round() echt runden, statt einfach zu casten, vllt. hilft das etwas...aber richtig weg bekommst du es nicht.

Du hast recht, so mache ich es. Und du glaubst wirklich das das runden was ausmachen würde, da passiert doch genau das gleiche.

// Edit

Hab es gerade mal mit dem round probiert. ändert sich nichts. Wenn ich die Geschwindigkeit auf 5/6 setzte gehts ja, dann stimmt die Richtung ja im groben über ein, aber er macht zu große sprünge, ist ja auch klar, aber bei kleineren Geschwindigkeiten, stimmt die Richtung wieder nicht, was ihr ja oben seht.

Wie realisieren andere sowas in einem Space Invader, ist ja das gleiche Prinzip, wenn man es so nimmt. Da funktioniert es doch auch einmanfrei, hat jemand eine Idee. mfg
 

EgonOlsen

Bekanntes Mitglied
0xdeadbeef hat gesagt.:
Nebenbei bemerkt tabelliert man Winkelfunktionen und dergleichen üblicherweise für Spiele. Das zur Echtzeit zu berechnen ist relativ "teuer" und bringt keinen ernsthaften Vorteil. Wenn man Platz sparen will, braucht man ja eigentlich nur von 0 bis PI/2 zu speichern und kann dann den Rest (inklusive des Kosinus) daraus ableiten.
So teuer ist das auf heutigen CPUs auch nicht mehr. Wenn man es nicht für hunderte von Entitäten/Frame durchführt, ist es kein Problem. An der Stelle würde ich wirklich als allerletztes was drehen.
 

EgonOlsen

Bekanntes Mitglied
Das Problem dürfte sein, dass du die Position als int speicherst. Damit verlierst du bei jeder Addition den Nachkommaanteil der Richtung und das summiert sich auf zu einer falschen Richtung.
Speicher die Position entweder als float/double oder von mir aus auch als int, aber dann als Fixedpoint, indem du sie z.B.*256 abspeicherst. Aber ich würde es einfach mit float machen. Dann sollte das passen.

Edit: Gilt natürlich auch für den Speed selber. Also alles als Gleitkomma machen und vor dem Zeichnen erst zu int casten.
 

raven

Bekanntes Mitglied
So hab nun alles auf Float abgeändert und es macht sich schon ein klein bisschen bemerkbar, doch es ist noch nicht so wie in den obrigen Spiel. In meinem Spiel fährt man ja ein Panzer, und bekanntlich sind Panzer ja nicht die schnellsten Fahrzeuge, und sie sollen im Spiel auch nicht so schnell sein.

Hier könnt ihr mein Spiel ncohmal sehen, so schnell sollen sie in etwa sein. Wie kann ich die Richtung noch genau machen und wie mache ich es das die Bewegung nicht ganz so abgehackt ist?

http://toni90.to.funpic.de/TankWar_0_1.jar

mfg
 

raven

Bekanntes Mitglied
Hier hast du den Code meiner Player Klasse, sprich dem Panzer.

Code:
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;

public class Player {

	public Background bg;
	public PlayerKey playerKey;

	public Image tank;

	public float xPos;
	public float yPos;
	public float speedX;
	public float speedY;
	public float speed = 3.0F;
	
	public int width = 35;
	public int height = 20;
	public int angle = 45;

	public Player(Background bg, Image tank, int xPos, int yPos) {
		this.bg = bg;
		this.tank = tank;
		this.xPos = xPos;
		this.yPos = yPos;

		playerKey = new PlayerKey(this);
	}

	public void paint(Graphics2D g2D) {
		g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		AffineTransform at = new AffineTransform();
		at.rotate(Math.toRadians(angle), xPos+width/2, yPos+height/2);

		g2D.setTransform(at);

		g2D.setColor(Color.gray);
		g2D.fill(new Rectangle2D.Float(xPos, yPos, width, 5));
		g2D.fill(new Rectangle2D.Float(xPos, yPos+15, width, 5));
		
		g2D.setColor(new Color(92, 65, 35));
		g2D.fill(new Rectangle2D.Float(xPos+3, yPos+2, width-6, height-4));

		g2D.setColor(new Color(128, 103, 59));
		g2D.fill(new Rectangle2D.Float(xPos+12, yPos+5, 13, 10));
		g2D.fill(new Rectangle2D.Float(xPos+25, yPos+9, 15, 2));
	}

	public void calculation() {
		speedX = Math.round((Math.cos(Math.toRadians(angle)) * speed));
		speedY = Math.round((Math.sin(Math.toRadians(angle)) * speed));
	}
}

Der Thread den du mir gegeben hast, entspricht nicht ganz meinem Problem.(Ich hab ihn mir durchgelesen) In ihm geht es um die CPU Auslastung, was bei mir kein Problem, oder noch nicht darstellt. Die Richtung ist für mich noch nicht ganz perfekt,man sieht manchmal, wenn man ungefähr im Winkel von 65/70 Crad ist, das es noch leicht schif fährt, um dies auszubessern erhöhe ich die Geschwindigkeit, dann ist die Richtung perfekt, nur leider, wird dabei mein Panzer in großen Scritten gesetzt und es sieht nicht mehr so aus als ich fahren würde.


// edit

Der andere Code ist nicht wichtig für dieses Problem.
 

EgonOlsen

Bekanntes Mitglied
Doch sicher. Weil das das ist, was du auf die Position addierst, wenn ich mich recht entsinne. D.h. wenn da 1.4 rauskommt, dann addierst du mit round() nur 1. D.h. nach 100 Durchläufen stehst du bei 100 statt bei 140. Wenn du "speed" erhöhst, wird es übrigens deswegen etwas besser, weil du die verlorene Genauigkeit durch das round() damit prozentual aufs Endergebnis gesehen etwas kompensierst.
 

0xdeadbeef

Top Contributor
EgonOlsen hat gesagt.:
So teuer ist das auf heutigen CPUs auch nicht mehr. Wenn man es nicht für hunderte von Entitäten/Frame durchführt, ist es kein Problem. An der Stelle würde ich wirklich als allerletztes was drehen.
Ich sagte "relativ" teuer und das ist es immer noch und wird es auch immer sein im Vergleich zu einem Tabellenzugriff. Außerdem macht er ja sonst nicht viel, also ist es auch bezogen auf die Laufzeit des Algorithmus' teuer.
Wie auch immer, ich komme halt noch aus einer Zeit, in der man keine Ressourcen verschwendet hat und muß auch beruflich noch darauf achten, keine Multiplikation umsonst auszuführen - Fließkommaberechnungen und trigonometrische Funktionen sind da eh außen vor.
 
G

Guest

Gast
0xdeadbeef hat gesagt.:
Wie auch immer, ich komme halt noch aus einer Zeit, in der man keine Ressourcen verschwendet hat und muß auch beruflich noch darauf achten, keine Multiplikation umsonst auszuführen - Fließkommaberechnungen und trigonometrische Funktionen sind da eh außen vor.
Ich weiß, ich habe deine Homepage gelesen. Wir sind ein Jahrgang, d.h. ich "komme auch aus dieser Zeit" (C64 in Assembler und so)... :wink: Und ich mache auch noch heute Lookup-Tabellen, aber für diese Anwendung würde ich sie nicht machen. Lookup ist auf einem P4 etwa 4mal schneller. Nur zählt das erst wirklich, wenn man 1000e davon ausführt.
 

raven

Bekanntes Mitglied
EgonOlsen hat gesagt.:
Wenn du "speed" erhöhst, wird es übrigens deswegen etwas besser, weil du die verlorene Genauigkeit durch das round() damit prozentual aufs Endergebnis gesehen etwas kompensierst.

Das war mir klar, das wollte ich euch ja die ganze Zeit irgendwie sagen, Aber mein problem ich die Geschwindigkeit nicht so hoch stellen, weil ich das nicht so schön finde.[/quote]

Ich sagte "relativ" teuer und das ist es immer noch und wird es auch immer sein im Vergleich zu einem Tabellenzugriff. Außerdem macht er ja sonst nicht viel, also ist es auch bezogen auf die Laufzeit des Algorithmus' teuer.
Wie auch immer, ich komme halt noch aus einer Zeit, in der man keine Ressourcen verschwendet hat und muß auch beruflich noch darauf achten, keine Multiplikation umsonst auszuführen - Fließkommaberechnungen und trigonometrische Funktionen sind da eh außen vor.

Also bist du der Meinung ich kann das Problem nicht ohne enormen Aufwand lösen. Aber ich will es unedingt so haben, sonst hat das ganze Game kein sinn, wenn sich der Panzer nichtrichtig lenken lässt.

mfg
 

LoN_Nemesis

Bekanntes Mitglied
Nein X_Master, die letzten Beiträge haben sich nur mit der Frage beschäftigt ob man jedesmal den Sinus ausrechnen sollten oder besser eine Tabelle bereithält, in der man alle benötigten Werte dort einträgt und dann nur nachschauen muss.

Das was du vorhast sollte auf jeden Fall gehen, sicher ist irgendwo noch ein kleiner Fehler drin.

Kannst du das .jar File mal so ändern, dass man es mit einem Doppelklick starten kann? Dann schaue ich es mir mal an.
 

LoN_Nemesis

Bekanntes Mitglied
Also ich hab mir deinen Code jetzt nochmal angeschaut und ich würde das anders machen.

Ich würde dem Panzer einen Richtungsvektor geben. Dieser gibt (wie der Name schon sagt) an in welche Richtung der Panzer fährt. Das sollte einfach ein Einheitsvektor sein. Durch die aktuelle Position des Panzers und diesen Richtungsvektor kannst du dann eine Gerade berechnen. Auf dieser Gerade bewegt sich der Panzer dann, wenn du ihn gerade ausfahren lässt; wie weit wird durch den speed bestimmt.

Wenn der Spieler dann die Nach-Rechts oder die Nach-Links Taste drückt, dann rotierst du den Richtungsvektor.

Bin mir ziemlich sicher, dass es so geht und denke auch, dass ist das Standardvorgehen in vielen Spielen.


Edit: Eh ok im Grunde machst du das ja ähnlich, dein Richtungsvektor ist speedX und speedY. Hm..

Habs nun mal ausgeführt, ich sehe das Problem nicht? Wieso soll die Richtung bei langsamer Bewegung nicht stimmen? Mir kommt das richtig vor?
 

raven

Bekanntes Mitglied
Das Problem siehst du besonders gut, wenn du den Panzer in den Winkel von ca. 70 Crad setzt. Die Cradzahl kannst du auf der Konsole sehen. dort wird sie ausgegeben.

Ich würde dem Panzer einen Richtungsvektor geben. Dieser gibt (wie der Name schon sagt) an in welche Richtung der Panzer fährt. Das sollte einfach ein Einheitsvektor sein. Durch die aktuelle Position des Panzers und diesen Richtungsvektor kannst du dann eine Gerade berechnen. Auf dieser Gerade bewegt sich der Panzer dann, wenn du ihn gerade ausfahren lässt; wie weit wird durch den speed bestimmt.

Ich verstehe dein System nicht ganz so. Extra ein Vector erstellen um die beiden Variablen (xSpeed, ySpeed) zu speichern????

mfg
 

EgonOlsen

Bekanntes Mitglied
Ähhh...was ist nun mit dem round()? Haste das mal entfernt? Dann sollte es doch eigentlich passen, wenn du nicht noch irgendwo anders wild rundest oder abtrennst, wo es nicht sein sollte.
 

LoN_Nemesis

Bekanntes Mitglied
Und was bedeuten die Ausgaben X und Y auf der Konsole? Sind das speedX und speedY? Wenn ja, dann sind es immer noch int Werte und keine Floats.

Code:
case KeyEvent.VK_UP:
            player.xPos = player.xPos + (int)player.speedX;
            player.yPos = player.yPos + (int)player.speedY;
            break;

Hast du das mittlerweile auch korrigiert und den (int) cast weggemacht? Wenn deine Koordinaten alle floats sind, dann solltest du gar nicht mehr runden ausser beim Zeichnen.
 

raven

Bekanntes Mitglied
LoN_Nemesis hat gesagt.:
Und was bedeuten die Ausgaben X und Y auf der Konsole? Sind das speedX und speedY? Wenn ja, dann sind es immer noch int Werte und keine Floats.

Code:
case KeyEvent.VK_UP:
            player.xPos = player.xPos + (int)player.speedX;
            player.yPos = player.yPos + (int)player.speedY;
            break;

Hast du das mittlerweile auch korrigiert und den (int) cast weggemacht? Wenn deine Koordinaten alle floats sind, dann solltest du gar nicht mehr runden ausser beim Zeichnen.

Den hatte ichganz vergessen. Hab ihn jetzt weggemacht. Funktioniert jetzt.
Hier seht ihr die aktuelle version nochmal. http://toni90.to.funpic.de/bin/TankWar_0_1.jar

Ja X und Y Ausgaben sind speedX und speedY.

mfgWeiß auch nicht warum er bei speedX eine Kommastelle und bei SpeedY immer genau eine ganze Zahl ausgibt. HAt mich auch selber schon gewundert.
 

Campino

Top Contributor
Du musst in der manifest-datei noch die main-Class eintragen...dann lässt das ganze sich per Doppelklick starten...
 

raven

Bekanntes Mitglied
So hab jetzt wie gewünscht die Manifest Datei abgeändert.

http://toni90.to.funpic.de/TankWar_0_1.jar

Müsste jetzt gehen, Hab auch gleich mal die Steuerung(So wie sich halt nen Panzer/Auto in real steurn lässt) eswas verändert, sagt mal wie ihr sie findet. Funktioniert jetzt alles. Großes DANK an alle die mir geholfen habe. Das einzigste was jetzt noch fehlerhaft ist, seit ich die neue Steuerung habe, das diverse Panzerteile manchmal ein bisschen daneben gezeichnet werden. Aber das Problem denke ich liegt, dann auch an meiner Zeichenmethode.
 

raven

Bekanntes Mitglied
So hab nun noch einiges abgeändert. Die Steuerung liegt jetzt auf den Numernblock. Mit 4, 5, 6, 8 steuert man den Panzer und mit 7 und 9 kann man das Panzerrohr drehen. Als nächstes machen ich die Schüsse und dann werde ich versuchen es Netzwerkfähig zu machen.

Nochmals Danke für eure Hilfe.

mfg X_Master
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
G JOGL: per Mausbewegung Objekt verschieben Spiele- und Multimedia-Programmierung 2
G Objekt verschieben Spiele- und Multimedia-Programmierung 6
pcfreak9000 Objekt-Vorlagen Spiele- und Multimedia-Programmierung 0
Arif Maus-Objekt im Player Klasse implementieren !? Spiele- und Multimedia-Programmierung 2
H Objekt der Klasse A in der Klasse B verwenden und manipulieren Spiele- und Multimedia-Programmierung 6
M [JOGL] Maus über einem gezeichnetem Objekt abfragen? Spiele- und Multimedia-Programmierung 5
U Kann nur ein Objekt mit LWJGL rendern Spiele- und Multimedia-Programmierung 2
kaoZ Graphics Objekt liefert null Spiele- und Multimedia-Programmierung 14
E Java3D Objekt skalieren per JSlider/JButton Spiele- und Multimedia-Programmierung 10
D Probleme mit objekt initializirung mit Mouselistener Spiele- und Multimedia-Programmierung 10
S Java3D: Primitives zu einem Objekt kombinieren Spiele- und Multimedia-Programmierung 7
T LWJGL 3D Objekt Collision: Wie? Spiele- und Multimedia-Programmierung 11
S Wie erkennt ein Objekt ein anderes? Spiele- und Multimedia-Programmierung 7
B j3d mehr als ein Objekt rotieren Spiele- und Multimedia-Programmierung 18
G Hindernis vor Objekt erkennen Spiele- und Multimedia-Programmierung 6
W Java3D: Kanten die hinter einem Objekt liegen werden gezeigt Spiele- und Multimedia-Programmierung 2
S Graphics Objekt weiterreichen? Spiele- und Multimedia-Programmierung 4
H Eigenes 3D Objekt Spiele- und Multimedia-Programmierung 20
D 2D Objekt fragmentieren Spiele- und Multimedia-Programmierung 3
V Jogl: Objekt trotz Rotation immer in gleiche Richtung bewegen Spiele- und Multimedia-Programmierung 5
M [J3D]Dynamische Erzeugung vom Objekt Box Spiele- und Multimedia-Programmierung 5
Kr0e OpenGL .. Pixel Buffer Objekt oder Frame Buffer Object? Spiele- und Multimedia-Programmierung 2
B String zu Objekt einer eigenen Klasse casten Spiele- und Multimedia-Programmierung 13
N Objekt entgegengesetzt bewegen Spiele- und Multimedia-Programmierung 8
M BoundingBox ist nicht bündig am Objekt Spiele- und Multimedia-Programmierung 5
K Kanten anzeigen lassen in einem Shape3D-Objekt Spiele- und Multimedia-Programmierung 4
S geladenes Objekt -> Material Zuweisen. Spiele- und Multimedia-Programmierung 4
J Picking Selection auf ein Objekt begrenzen ! Spiele- und Multimedia-Programmierung 6
C Objekt bei Buttonklick zeichnen Spiele- und Multimedia-Programmierung 16
C Objekt zwischen 2 Geraden? Spiele- und Multimedia-Programmierung 3
D 3D Objekt entlang Geraden Spiele- und Multimedia-Programmierung 4
Quaxli Picking: Vom Shape3D zum eigentlichen Objekt Spiele- und Multimedia-Programmierung 2
G Objekt nicht ins negative oder null skalieren Spiele- und Multimedia-Programmierung 2
G Textur laden auf ein eingelesenes 3D Objekt Spiele- und Multimedia-Programmierung 4
I ScaleInterpolator verschiebt Objekt immer in den Ursprung. Spiele- und Multimedia-Programmierung 2
V Objekt per Tastendruck anzeigen/verschwinden lassen? Spiele- und Multimedia-Programmierung 4
G Kein Licht in Box-Objekt Spiele- und Multimedia-Programmierung 2
K Ein 3D-Objekt mit Maus auswählen Spiele- und Multimedia-Programmierung 5
D Alpha Objekt Spiele- und Multimedia-Programmierung 8
H Kompliziertes 3D-Objekt Spiele- und Multimedia-Programmierung 16
G Einen gif oder jpg Datei aus einem Graphics Objekt o. JFrame Spiele- und Multimedia-Programmierung 2
C Wie kann ich ein Objekt auf Tastendruck vor & zurück bew Spiele- und Multimedia-Programmierung 3
M Position der ViewingPlatform als Point3d-Objekt? Spiele- und Multimedia-Programmierung 12
S 3D Objekt erstellen und darstellen Spiele- und Multimedia-Programmierung 4
G RotationInterp. setzt Objekt an Ursprungsposition zurück Spiele- und Multimedia-Programmierung 2
N Shape3D Objekt auf dem Bildschirm zentrieren Spiele- und Multimedia-Programmierung 2
R Java3d ViewingPlatform erst Verschieben und dann RotationsInterpolator Spiele- und Multimedia-Programmierung 0
R Verschieben von Objekten langsam Spiele- und Multimedia-Programmierung 0
A AffineTransform: Nach Drehen verschieben Spiele- und Multimedia-Programmierung 2
X TiledMap "langsam" verschieben Spiele- und Multimedia-Programmierung 8
M J3D gepicktes Primitive verschieben(fix mit Mauszeiger) Spiele- und Multimedia-Programmierung 2
A .jpg-Bild auf andere Position verschieben Spiele- und Multimedia-Programmierung 4
Z Kugeln aufgrund von Daten aus einem Array verschieben Spiele- und Multimedia-Programmierung 2
E Verschieben von Elementen Spiele- und Multimedia-Programmierung 2
R Polygon um double x/y - Werte verschieben Spiele- und Multimedia-Programmierung 2
G Auf Tastendruck bild verschieben Spiele- und Multimedia-Programmierung 5
T Koordinatensystem verschieben? Spiele- und Multimedia-Programmierung 6
B Kugeln verschieben (Vektoren) und Schnitt prüfen Spiele- und Multimedia-Programmierung 12
C Betrachterstandpunkt verschieben Spiele- und Multimedia-Programmierung 7

Ähnliche Java Themen

Neue Themen


Oben