# Problem mit Thread.sleep()



## FloOo (22. Feb 2009)

Hallo,
ich unternehme gerade den Versuch ein simples 2D RPG zu konstruieren .. es funktioniert soweit auch eigentlich alles wie ich es mir vorstelle, das einzige problem ist die geschwindigkeit meines charakters bzw des spiels!
Diese ist entweder zu langsam oder zu schnell! 

in meiner hauptschleife habe ich natürlich zu erst UPDATEWORLD() dann PAINTWORLD() und dann eine kleine Pause mit try{Thread.sleep(GAME_PAUSE);} catch (InterruptedException e) {} eingebaut, weil das spiel sonst zu schnell ist! es liegt also nicht daran das das spiel zu hohe anforderungen an den rechner hätte^^

mit dieser pause ist es jetzt aber zu langsam .. ich hab zwar gerade mal 10 ms eingegeben aber es ist mir zu langsam und wenn ich die zahl auf 5 oder eine zahl unter 10 wähle bleibt alles gleich auser ich gehe über 10 .. dann wirds natürlich langsamer! 

ich finde das sehr seltsam weil ich schon öfters solche pausen gemacht habe und da konnte ich auch werte unter 10 eingeben! 

hat jemand eine idee an was es liegt?

greetz flo


----------



## andre111 (22. Feb 2009)

Schau dir dazu mal das Tutorial von Quaxli an (in Grafik- und Spieleprogrammierung -> Tutorials). Da ist das alles genau beschrieben.


----------



## FloOo (23. Feb 2009)

ja danke, das tut kenne ich .. hab es mal überflogen und habe schon mal so ein ähnliches gemacht! 
ich finde aber nicht wirklich die lösung meines problems ... ist aber nicht schlimm ... ich versuche etwas anderes


----------



## manuche (23. Feb 2009)

Das Problem was du dir selbst gebaut hast besteht darin, dass die Bewegung von der zeit abhängen, die der Thread für einen Durchlauf  benötigt... Wenn du es auf einem schlechten Rechner spielst dann werden deine Männchen sich zu langsam bewegen! Andernfalls werden sie sich natürlich zu schnell auf einem sehr guten Rechner bewegen! Logisch oder?
Guck dir nochmal quaxlis Tutorial an und lies es komplett und überflieg es nicht nur!!!


----------



## XyMorgan (1. Mrz 2009)

Hi,

das Einfachste, und CPUunabhängig:

Pack deine beiden Methoden in eine Zeitgesteuerte abfrage:

[HIGHLIGHT="Java"]private long currentTs = System.currentTimeMillis;
private long waitTime = 1000; //(1 sekunde warten)[/HIGHLIGHT]
in der Hauptschleife dann:

[HIGHLIGHT="Java"]....
if (currentTs + waitTime <= System.currentTimeMillis()) {
  UPDATEWORLD();
  PAINTWORLD();
  currenTs = System.currentTimeMillis();
}[/HIGHLIGHT]
...

das ist dann unabhängig von der CPU Geschwindigkeit.
Und sollte das sich Zeitlich nicht genau genug timen lassen, weil
die Auflösung von currentTime zu ungenau ist, dann nimm System.nanoTime().
Aber dran denken das du dann nicht mit milli, sondern nano arbeitest. 

//Martin.


----------



## manuche (1. Mrz 2009)

Das Problem bei der Methode ist allerdings, dass du immer eine gewissen Zeit einfach nicht wahrnimmst...
currentTs + waitTime wird in den meisten Fällen größer sein also die aktuelle Systemzeit! Diese paar ms fallen vllt nicht direkt auf... Wenn dein System mal nen kleinen Hänger hat wird es allerdings recht große Auswirkungen haben!
Nimm die Methode aus quaxlis Tutorial...


----------



## XyMorgan (2. Mrz 2009)

manuche hat gesagt.:


> Das Problem bei der Methode ist allerdings, dass du immer eine gewissen Zeit einfach nicht wahrnimmst...
> currentTs + waitTime wird in den meisten Fällen größer sein also die aktuelle Systemzeit! Diese paar ms fallen vllt nicht direkt auf... Wenn dein System mal nen kleinen Hänger hat wird es allerdings recht große Auswirkungen haben!
> Nimm die Methode aus quaxlis Tutorial...



Bei den ms stimme ich Dir zu, jedoch bei nanos gibt es eigentlich keine Latenz. 
Für die häufigsten Timingsituationen reicht aber die ms Varianten voll und ganz aus. Das einzige Problem das auftreten kann, ist, dass evtl. die Ausführung des Codes im Timing länger dauert als die Triggerzeit. Aber ein Programm, das sagen wir mal 5 Minuten (übertrieben) dauert kann ich auch nicht alle 2 Minuten ausführen. (Ausser als Kaskade) 

Ausserdem kann man je nach Anwendungsfall natürlich auch vor der Ausführung des Codes den Zeitstempel aktualisieren.

Genauer als über (dank der neuen Auflösung beim Java-Timer) nanos kannst du nicht Timen in Java. Und einfacher zu verstehen/anzuwenden gehts glaub ich kaum. Und btw. wenn Dein System nen hänger hat, dann kann Du da sowieso nichts machen, dann bekommst egal mit welchem Timing ne Latenz rein.

//Martin.


----------



## manuche (3. Mrz 2009)

Ich glaub du hast mich nicht ganz verstanden....
Es ist ungünstig zu sagen, dass etwas nach einer bestimmten Zeit geupdatet werden soll!


```
private long currentTs = System.currentTimeMillis;
private long waitTime = 1000; //(1 sekunde warten)
...
if (currentTs + waitTime >= System.currentTimeMillis()) { //Hab mal richtigerweise die Abfrage überarbeitet ;)
  UPDATEWORLD();
  PAINTWORLD();
  currenTs = System.currentTimeMillis();
}
```
Wenn jetzt currentTs + waitTime größer als System.currentTimeMillis() ist fehlt dir beim UPDATEWORLD was... Und zwar genau die Differenz System.currentTimeMillis() - (currentTs + waitTime)! Da in UPDATEWORLD höchst wahrscheinlich die Bewegungen und Animationen ausgeführt werden kann das bei einem hänger fatale Auswirkungen haben... Wobei fatal relativ zu sehen ist! Bei einem RPG wird es geringer ins Gewicht fallen als bei Shootern o.ä. wo es um Kollisionen geht!
Der Gedanke dahinter ist, dass eine Figur eine Geschwindigkeit hat und die Bewegung in Abhängigkeit von der Zeit geschehen soll und nicht wann sich wieder bewegt werden darf...
z.B. Figur bewegt sich in einer sek 10 px nach rechts... wenn der letzte Schleifendurchlauf ne halbe sek gedauert hat bewege dich auch nur halb soviel nach rechts!
Bei der Lösung oben würde sich die Figur in 1,00005sek 10px nach rechts bewegen und bei einem hänger womöglich in 1,999998sek...

daher:

```
while (true){
  ...
  long actTime = System.currentTimeMillis() ;
  updateWorld (actTime - zeitLetzterSchleifendurchlauf)
  paintWorld (actTime - zeitLetzterSchleifendurchlauf)
  ...
}
```


----------

