Bomberman: Bewegung der Spielfigur in windows viel schneller

Status
Nicht offen für weitere Antworten.
M

MaN_

Gast
Hi,

Ich programmier momentan an nem Bomberman-clone. Jetzt habe ich gerade festgestellt, dass die Bewegung auf meinem Windows Laptop einiges schneller ist als auf meinem Desktop mit Linux (Kubuntu).

Hier der Thread der die gedrückten tasten aus dem boolean Array bCursorKey[] ausliest und der Figur übergiebt.

Code:
for (int i = 0; i < 4; i++)
{
	if (bCursorKey[i])
	{					
		switch (i)
		{
		case 0:
			man.moveMan(Man.LEFT);
			break;
		case 1:
			man.moveMan(Man.UP);
			break;
		case 2:
			man.moveMan(Man.RIGHT);
			break;
		case 3:
			man.moveMan(Man.DOWN);
			break;
		}
		
		try{Thread.sleep(50);} catch (InterruptedException e){}	
	}
}

Die moveMan Methode:
Code:
/** speichert die Richtung in eine LinkedBlockingQueue **/
public void moveMan(int dir)
{
	queue.add(dir);
}

und hier der Thread der dann die LinkedBlockingQueue ausliest und die Befehle an die Methode move übergibt, der dann die Figur an der neuen stelle zeichnet.

Code:
public void run()
{
	while(!bStopRequested)
	{
		try 
		{
			move(queue.take());
		}
		catch (InterruptedException e) 
		{
			e.printStackTrace();
		} 
	}
}

Ich denke mal das die 50ms (im ersten code-teil) ausreichen sollte das ganze zu zeichnen. bei 100ms ist es auf dem Desktop noch viel langsamer... Kann es sein das die Sleep-Methode so ungenau ist das sie auf dem Laptop einiges kürzer wartet?
Bei 150 Schritten ist der Laptop ca 30 Schritte vorraus.

Am Prozessor oder Ram kann es nicht liegen. der Desktop hat nen 3800+ und 2GB Ram der Laptop nur nen Centrino 1,6 und 512MB Ram.
Das einzige wäre die Grafikkarte. im Desktop steckt ne Geforce 4 TI 4400 und im Laptop ne Radeon 9700 Mobility. Also könnte die Zeichenoperation auf dem Laptop deswegen schneller passiert sein. Aber da der Unterschied bei 100ms noch viel höher ist, glaub ich eher das es am sleep liegt.

Habt ihr mir ein Tipp das ganze gleichschnell hinzubekommen? Im Singleplayer ist das natürlich egal aber im Multiplayer
ist das ja schon ein bisschen unfair...

Ich hoffe ihr versteht mein Problem :)

Gruß
MaN
 

Tobias

Top Contributor
Das von sleep() sogar eine Variante gibt, die Nanosekunden-genau sein soll, kann ich mir Ungenauigkeiten an dieser Stelle kaum vorstellen. Lass in mal was auf die Konsole schreiben, wenn eine InterruptedException fliegen sollte, vielleicht verhält sich ja an der Stelle etwas unterschiedlich...

mpG
Tobias
 
S

SlaterB

Gast
Im Multiplayer musst du so oder so die Zeit vereinheitlichen,
mit einem einfachen Mittel wird das viel genauer:

statt hardkodiert 50 ms zu warten (und vielleicht noch zusätzliche 20 ms weil ein anderer Thread was macht +5-15ms reine Baerbeitungszeit)
setzt du dir feste Intervalle,
nächster Schritt zu Systemzeit 5535333.300
übernächster Schritt zu Systemzeit 5535333.350
Schritt 3 zu Systemzeit 5535333.400

das sleep ist dann Zielzeit - aktuelle Zeit,
so kannst du minimale externe Einflüsse sehr genau ausgleichen,

wenn du feststellst, dass mehrere Schritte übersprungen wurden, kannst du gesondert reagieren
 

Chris_1980

Bekanntes Mitglied
Ich hab allerdings auch das Gefühl das Thread.sleep superungenau ist.
Ich hab das anhand von System.nanoTime gemessen, wie lang er denn nun wirklich wartet... und bei gewollten 10ms hat er immer im Wechsel n paar durchläufe 7ms gewartet, dann wieder n paar durchläufe 15ms.
Allerdings niemals exakt 10.
Ist jetzt schwer zu sagen, welche Methode ungenau ist, Thread.sleep oder System.nanoTime, ider gar beides :? ...
wobei ich ja schon ganz schwer auf ersteres tippe. :meld:
 

Illuvatar

Top Contributor
Mir kam Thread.sleep unter Windows auch schon oft äußerst ungenau vor - nie wirklich gemessen, aber Thread.sleep(5000) sind bei mir höchstens 4 Sekunden!

==> Mit nanoTime oder currentTimeMillis arbeiten
 
G

Guest

Gast
SlaterB hat gesagt.:
Im Multiplayer musst du so oder so die Zeit vereinheitlichen,
mit einem einfachen Mittel wird das viel genauer:

statt hardkodiert 50 ms zu warten (und vielleicht noch zusätzliche 20 ms weil ein anderer Thread was macht +5-15ms reine Baerbeitungszeit)
setzt du dir feste Intervalle,
nächster Schritt zu Systemzeit 5535333.300
übernächster Schritt zu Systemzeit 5535333.350
Schritt 3 zu Systemzeit 5535333.400

das sleep ist dann Zielzeit - aktuelle Zeit,
so kannst du minimale externe Einflüsse sehr genau ausgleichen,

wenn du feststellst, dass mehrere Schritte übersprungen wurden, kannst du gesondert reagieren


ich hab jetzt mal den ersten code-Schnippsel umgeschrieben und so ist es einiges genauer, doch jetzt ist der Desktop ein kleines bisschen schneller

Code:
for (int i = 0; i < 4; i++)
{
	if (bCursorKey[i])
	{	
		long time = System.currentTimeMillis();
		long nextTime = time + 50;
		
		switch (i)
		{
		case 0:
			man.moveMan(Man.LEFT);
			break;
		case 1:
			man.moveMan(Man.UP);
			break;
		case 2:
			man.moveMan(Man.RIGHT);
			break;
		case 3:
			man.moveMan(Man.DOWN);
			break;
                                    }
		
		while(System.currentTimeMillis()<nextTime);
		//try{Thread.sleep(50);} catch (InterruptedException e){}	
	}
}

wie soll ich das dann aber im Netzwerk sinvoll machen? alle 50ms übers netzwerk den impuls fürs weitergehen senden? der würde dann ja auch überall zeitversetzt ankommen.
 

Illuvatar

Top Contributor
Dennoch ist das sinnvollste, solche Berechnungen auf dem Server zu machen. Aber ich würde hier keinen "Impuls zum Weitergehen" senden, sondern auf dem Server alles berechnen, und den Clients immer nur senden, wo alle Spielfiguren sind - die Clients sagen dem Server dafür, in welche Richtung sie gerade gehen wollen.
Ich weiß ja nicht, ob du dein Spiel "groß rausbringen" willst - aber solange du den Client irgendsowas berechnen lässt, können immer die Clients dekompiliert, verändert und wieder kompiliert werden - Cheaterparadies ;)
Und das ist genau der Punkt - das was Cheater ausnutzen können, kann - und wird - eben auch versehentlich geschehen.

Edit: Was ich noch sagen wollte: Sowas wie deine Zeile 25 ist... nicht so gut ;) Dadurch verbraucht das Programm 100% der CPU. Mach vielleicht lieber
Code:
      long diff = nextTime - System.currentTimeMillis();
      while(diff >= 0){
            try{Thread.sleep(Math.max(diff / 2, 10);} catch (InterruptedException e){interrupt();}
      }
 
M

MaN_

Gast
ok das mit den Berechnungen am Server durchführen lassen leuchtet mir ein. Das muss ich unbedingt noch einbauen.

aber dein Code-Snipet versteh ich net ganz... Müsste man nicht in der while schleife diff einen Wert geben, denn sonst wird ja nur einmal diff initialisiert und bleibt dann in der whileschleife hängen. Und wieso übergibst du der Methode sleep Math.max(diff/2,10) und nicht nur diff/2?
 

Illuvatar

Top Contributor
Öh ja, das erste stimmt, man müsste diff in der while-Schleife immer neu berechnen lassen.

Das mit dem Math.max mache ich, weil hier im Forum mal einer rausgefunden hat: Wenn man Thread.sleep mit zu kleinen Werten aufruft (10 ist schon hart an der Grenze), kann das die Windows-Systemuhr verstellen. Frag mich bitte nicht warum - mit dem max stell ich eben sicher, dass der Wert nicht zu klein wird.
 

Wildcard

Top Contributor
Illuvatar hat gesagt.:
Wenn man Thread.sleep mit zu kleinen Werten aufruft (10 ist schon hart an der Grenze), kann das die Windows-Systemuhr verstellen.
Das kann auch bei zu häufigen Aufrufen von System.currentTimeMillis passieren.
Ist AFAIK ein Bug in der Windows API.
 
S

SlaterB

Gast
> long time = System.currentTimeMillis();
> long nextTime = time + 50;

> while(System.currentTimeMillis()<nextTime);

neben der schon erwähnten 100%-CPU-Last ist das immer noch falsch

nextTime darf nicht von der vorherigen Zeit direkt abhängen,
sondern:

long time = System.currentTimeMillis();
long nextTime = getNextTargetTime(time);


Thread.sleep(nextTime-System.currentTimeMillis());


getNextTargetTime liefert einen festen Slot,
zu 454340566 -> 454340600
zu 454340576 -> 454340600
zu 454340596 -> 454340650 (weil 4 ms zu kurz wären)
zu 454340606 -> 454340650

usw., das kann natürlich berechnet werden, aber nicht stur 50ms drauf,
gerade dann gleichst du ja externe Pausen (andere Windows-Threads) NICHT aus

-------

das hilft nun aber nur, wenn man gleiche Zeitintervalle haben will und ein Auslassen egal ist
(etwa zur Bildschirmaktualisierung einer Bewegung, die man zu einem beliebigen Zeitpunkt berechnen kann, z.B. eine Uhr-Anzeige),


möchtest du dagegen gleich viele Schritte (z.B. Figurbewegungen),
dann wäre es ja fatal, einen Slot zu überspringen,

dann würde ich beim Festellen von Abweichungen das Warteintervall anpassen,
-> anderes Programm hat drei Schritte Vorsprung bzw. nach normaler Rechnung sollte zu dieser Zeit im Singleplayer schon 3 Schritte mehr gemacht werden?,
dann die nächsten 15 Intervalle nur 40ms statt 50 ms warten,

aber das klingt ganz schön abenteuerlich, wahrscheinlich sollte man bei solchen Problemen ganz anders anfangen ;)
ich rede auch nur theoretisch daher
 

Inanis

Mitglied
Tag Man_,

versuch doch mal wesentlich mehr Grafik auf den Screen zu spucken, dann merkst ja auch, obs
an der Grafikkarte liegen koennte.

Falls dass das Problem ist, schlage ich dir vor nachzusehen, ob deine Grafikkarte unter Linux ordentlich
unterstuetzt wird. Ansonsten halt nen entsprechenden Driver installieren, was ja heutzutage kein Problem
mehr darstellt, auch wenn sich viele Hardware-Hersteller noch gegen Linux straeuben.
Mit nem frischen Java solltest du dann unter Linux ein recht performantes Spiel bekommen. Ansonsten helfen
eventuell Flags fuer opengl-support.

Bei mir laufen auf derselben Maschine auf der ich ein Linux und ein Windows XP laufen habe, die Javaspiele unter
Linux performanter als unter Windows. Da erkennt man halt wieder das Ressourcenmanagement.
 
G

Guest

Gast
Hi,

Also meine Treiber sind richtig installiert, läuft ja sogar XGL mit beryl drauf. Ich denke mal es liegt an der Grafikkarte. Der Unterschied zwischen Radeon 9700 und Geforce 4 TI ist halt doch recht arg... Aber es funktioniert jetzt auch eingermaßen!
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Java Bomberman Probleme java.lang.NullPointerException Spiele- und Multimedia-Programmierung 1
YangLee Ausgabe von einer Bewegung bei mehrzeiligen Strings Spiele- und Multimedia-Programmierung 1
D Arrays auf Bewegung prüfen (2048) Spiele- und Multimedia-Programmierung 1
Furtano Vektoren für Bewegung für eine 2D-Simulation Spiele- und Multimedia-Programmierung 3
K Bewegung falsch Spiele- und Multimedia-Programmierung 6
J Spielprogrammierung mit bewegung und kollision Spiele- und Multimedia-Programmierung 24
B Webcam Bewegung markieren Spiele- und Multimedia-Programmierung 3
R Asteroid unschöne Bewegung Spiele- und Multimedia-Programmierung 13
G Bewegung eines Grafikobjektes Spiele- und Multimedia-Programmierung 7
F Probleme bei Bewegung Spiele- und Multimedia-Programmierung 7
T Flüssige Bewegung Spiele- und Multimedia-Programmierung 7
U Freie Bewegung Realisierung Spiele- und Multimedia-Programmierung 13
F Brauche Hilfe bei Bewegung eines Rechtecks [Applet] Spiele- und Multimedia-Programmierung 5
F Bewegung/Kollision von Objekten auf Tastendruck Spiele- und Multimedia-Programmierung 6
S gekillte Spielfigur Spiele- und Multimedia-Programmierung 5
M Fehlende Spielfigur auf neuer Landschaft Spiele- und Multimedia-Programmierung 2
A Spielfigur mit vielen Aktionen Spiele- und Multimedia-Programmierung 7
F RPG - Spielfigur soll sich nicht frei bewegen können. Anregugen wären gerne gesehen^^ Spiele- und Multimedia-Programmierung 13
J Fehlverhalten einer Spielfigur Spiele- und Multimedia-Programmierung 7
A Spielfigur steuern Spiele- und Multimedia-Programmierung 8
G Bewegungen von Spielfigur Spiele- und Multimedia-Programmierung 2

Ähnliche Java Themen

Neue Themen


Oben