Ich habe einen Timer der alle 1000 Millisekunden (1 Sekunde:
Code:
int period = 1000;
) etwas macht.
Kann ich nun, während der Timer läuft, diese Periode auf z.B. 500 Millisekunden setzen, oder muss ich den Timer beenden und einen neuen erstellen?
int delay =1000;Timer timer =newTimer();
timer.scheduleAtFixedRate(newTimerTask(){publicvoidrun(){//CODE}}, delay, points.getLevelSpeed());
Wie zu sehen ist, hängt die Geschwindigkeit meines Tetrisspiels davon ab, in welchem Level der Spieler ist (
Code:
points.getLevelSpeed();
). Daher kann ich keine feste Zeit für das Umschalten angeben ...
@Michael ...
Ich habe schon gemerkt, dass der Timer wohl nicht wirklich das richtige ist. Allerdings habe ich keine Ahnung, wie die Varianten, die du vorschlägst funktionieren ...
So habe ich das nicht gemeint, meinte nur es gibt auch eine Welt ohne Timer/TimerTask ;-)
Mit TimerTask könnte man das so machen:
Java:
publicstaticvoidmain(String[] args){Timer timer =newTimer();TimerTask task =createNewTask();
timer.schedule(task,0,500);try{Thread.sleep(3000);}//kuenstliche Pause, um das Warten auf Events o.ä. zu simulierencatch(InterruptedException e){e.printStackTrace();}
task.cancel();
timer.purge();
task =createNewTask();
timer.schedule(task,0,100);try{Thread.sleep(3000);}//kuenstliche Pause, um das Warten auf Events o.ä. zu simulierencatch(InterruptedException e){e.printStackTrace();}
timer.cancel();}publicstaticTimerTaskcreateNewTask(){returnnewTimerTask(){publicvoidrun(){doSomething();}};}privatestaticvoiddoSomething(){System.out.println("I have to do something!");}
Die statische Methoden sind nur zur Demo bitte nicht übernehmen, sondern das ganze an einem Objekt realisieren.
Was genau soll diese künstliche Pause simulieren? Was für Events?
Kann ich cancel und purge auch in der run()-Methde aufrufen, um jede Sekunde zu prüfen, ob schon ein neuer Task gestartet werden muss (mit schnellerer Zeit)?
Also das Problem ist ja, dass ich nicht weiss, wann ich die neue Zeit setzen muss. Ich muss also die ganze Zeit prüfen, ob es schon so weit ist ... wie kann ich das erreichen?
Du musst ja aufgrund irgend eines Ereignisse den Task wechseln z.B. Level/Zeit ist um.
Die Verzögerung mit sleep() habe ich reingebaut, damit man bei der Demo auch mitbekommt, dass eine neue TimerTask gestartet wurde, sonst würde ja die erste gestartet und gleich wieder beendet.
Kann ich cancel und purge auch in der run()-Methde aufrufen, um jede Sekunde zu prüfen, ob schon ein neuer Task gestartet werden muss (mit schnellerer Zeit)?
Aber wie überprüfe ich jetzt, ob ich den neuen Task schon setzen muss?
Ich habe es mit einem zweiten Timer versucht, der einfach nur prüft, ob der erste Timer den Task schon wechseln muss. Wenn ja, übernimmt er das gleich. Wenn nicht, tut er nichts.
Das Problem ist allerdings, dass ich innerhalb einer inneren Klasse (TimerTask) nicht auf eine "nicht-finale" (Eclipse) Variable (task) zugreifen kann, um diese zu beenden und neu zu besetzen. Und wenn ich sie final mache, dann ist sie eben final und kann nicht mehr geändert werden ...
Wie lässt sich das umgehen?
Java:
finalTimer timer =newTimer();TimerTask task =createNewTask();
timer.schedule(task,1000, points.getLevelSpeed());Timer proofTimer =newTimer();TimerTask proofTask =newTimerTask(){publicvoidrun(){if(levelSpeed<points.getLevelSpeed()){//Levelspeed wird erhöht
levelSpeed = points.getLevelSpeed();
tetris.newTask =true;}if(tetris.newTask==true){//Neuer Task für ersten Timer muss gesetzt werden
task.cancel();
timer.purge();
task =createNewTask();
timer.schedule(task,1000,100);}}};
Man kann auch ohne anonyme innere Klasse arbeiten ;-) oder in der run() einfach nur eine andere Methode aufrufen (so ähnlich wie in meinem Bsp) die zu einem Objekt gehört, welches auch Zugriff auf die Variable hat.
Deine Methode von oben greift aber auch nicht auf die Variable zu, sondern füllt sie einfach ...
Ich steh auf dem Schlauch. Wie arbeitet man "ohne anonyme Klasse"?
Indem man eine eigene Klasse schreibt, die das benötigte Interface implementiert oder von der Klasse erbt, deren Methode man überschreibt.
Unabhängig davon, hier mal ein Beispiel. Über einen TimerTask (ChangeTask) wird alle 3 sec ein aktiver TimerTask abbgebrochen und ein neuer mit einer kürzeren Periode gestartet.
Okay, ich habs nun geschafft, indem ich die Variable task in meiner main-Klasse für alle Methoden zugänglich gemacht habe (public). Läuft ganz gut. Wahrscheinlich nicht der beste Stil, aber die Hauptsache ist, dass es endlich läuft ...