# "Rebuffen" - Messen der Zeit eines Timers



## xyss (12. Sep 2014)

Hallo Javacommunity,

ich bin aktuell dabei ein Spiel zu programmieren, und so wie man es aus manchen Spielen kennt, kann der Spieler auch sogenannte Buffs erhalten, sprich, Fähigkeiten (z.B. erhöhte Laufgeschwindigkeit) über Zeit. Das tue ich aktuell über die in Java vorhandene Klasse Timer.

Nehmen wir Mal das Beispiel von oben: Erhöhte Laufgeschwindigkeit
Wenn der Buff aktiviert wird, passiert folgendes: Laufgeschwindigkeit wird erhöht, der Timer gestartet, und die Laufgeschwindigkeit wird danach wieder verringert.

Code:
[Java]
	private void runBuffTimer(){
		if (activate && !buffActive){
			buffActive = true;
			handleBuffActivation(); //Aktiviert die Fähigkeit des Buffs
			buffTimer = new Timer();
	        TimerTask task = new TimerTask() {
	            @Override
	            public void run() {
	            	handleBuffDeactivation(); //Deaktiviert die Fähigkeit des Buffs
	            	activate = false;
	            	buffActive = false;
	            }
	        };
	        buffTimer.schedule(task, duration); 
		}
	}
[/Java]

Die boolean-Variablen dienen dazu, dass nicht ein und der selbe Buff mehrmals aktiviert wird (und dann "gleichzeitig" wirkt).

Mein Problem ist nun das sogenannte "rebuffen", also das überschreiben des Buffs, durch einen besseren.
Beispiel:
Wenn es nun nur den Buff gibt:
- Laufgeschwindigkeit +5 für 5 Sekunden

Der Spieler hat den Buff (5 Sekunden), dieser läuft aber schon seit 3 Sekunden, also sind nur noch 2 Sekunden übrig. Wenn der Spieler nun den Buff nochmal erhält, soll der alte überschrieben werden, also wieder bei 5 Sekunden Laufzeit sein.

Ein etwas komplexeres Beispiel:
- Laufgeschwindigkeit +5 für 3 Sekunden
- Laufgeschwindigkeit +5 für 5 Sekunden
- Laufgeschwindigkeit +5 für 7 Sekunden

Der Spieler hat den 2. Buff (5 Sekunden), erhält nun den 1. Buff (3 Sekunden). Falls der 2. Buff nur noch weniger als 3 Sekunden Laufzeit hat, wird der 2. Buff durch den 1. überschrieben, ansonsten nicht. Danach erhält er den 3. Buff (7 Sekunden). Da dieser länger anhält als die anderen, überschreibt er den aktuellen Buff.

Mein Problem ist also konkret, dass ich nicht weiß, wie ich bei einem Timer überprüfen kann, wie lange dieser schon läuft, da ich bei den Buffs entscheiden muss, welcher der beiden zu dem aktuellen Zeitpunkt länger aktiv ist.


----------



## turtle (12. Sep 2014)

> wird der 2. Buff durch den 1. überschrieben,


Das ist ein Problem, denn meines Wissens kannst du einen Thread nicht überschreiben.

Der Thread startet und beendet sich irgendwann. Dazwischen ist es ja so, das du da nicht eingreifen kannst. Selbst stoppen kannst du ihn nicht, es sei denn, der Thread "überwacht" das und reagiert entsprechend.

Am Beispiel des Abbrechens sieht der Code in der Run-Methode dann meistens so aus:

```
public void run() {
 while ( ! isInterrupted() ) {
}
}
```

So könntest du Variable von aussen setzen, die der Thread ebenfalls überwacht und entsprechend reagiert. Dies ist aber komplex weil du ja mehrere paralelle laufende Threads hast und die Zugriffe synchronisiert werden müssen.


----------



## Joose (12. Sep 2014)

Was wäre du für jeden Spieler einen Thread zur Verfügung stellst.
Dieser Thread macht nichts anderes als zu überwachen ob ein neuer Buff einen alten überschreiben soll, soll ein Buff auslaufen/deaktiviert werden usw.
Und dieser Thread prüft einfach jede Sekunde die Liste an Buffs durch (bzw. auch neue)


----------



## xyss (16. Sep 2014)

Das mit dem überwachen habe ich implementiert, funktioniert gut  

Für das "unterbrechen" bzw überschreiben eines Buffs, habe ich die in Java vorhandene Klasse Timer verwendet, und mit hilfe von timer.cancel() und timer.purge() den Timer unterbrochen, und danach einen neuen gestartet.

Danke euch beiden


----------

