Spiele-App BUMM Teil 6: Countdown

Für viele ist das BUMM-Spiel zu leicht. Wir machen es jetzt schwieriger. Der Spieler soll für jede Entscheidung nur noch wenige Sekunden Zeit haben. Braucht er zu lange, hat er verloren. Wir bauen dazu einen CountDownTimer ein.
Schau dir auch die anderen Teile dieser Serie an, da haben wir gezeigt, wie man dieses Spiel gestaltet und den Code schreibt.
Keine Lust alles nachzubauen? Du kannst auch den Quellcode des Spiels herunterladen. Da fehlen nur noch die Sounds und eben der Countdown aus diesem Video. Klicke hier, um zum Download zu kommen.
Konstante definieren
Zunächst müssen wir eine Konstante erzeugen, die angibt wie lange der Nutzer Zeit hat eine Entscheidung zu treffen. Das ganze geben wir in Sekunden an. Mein Vorschlag wäre, dass der Nutzer 3 Sekunden Zeit hat, um den jeweils nächsten Button zu drücken.
public final static int TIMEOUT = 3;
CountDownTimer initialisieren
Als nächstes brauchen wir einen CountDownTimer. Der sorgt dafür, dass wir herunterzählen können. Dazu hat er im wesentlichen zwei Methoden, die wir implementieren müssen. Die eine wird im Sekundentakt aufgerufen, die andere wenn der Countdown abgelaufen ist, also nach 3 Sekunden.
Dazu deklarieren wir den CountdownTimer oben in der MainActivity.
CountDownTimer countDownTimer;
Und dann schreiben wir eine initCountDown Methode, um den CountDownTimer einzurichten.

Was passiert hier? Wir instanziieren ein neues Objekt vom Typ CountDownTimer und übergeben dabei zwei Argumente. Das erste Argument gibt an, wie lange der Countdown insgesamt laufen soll. Dafür haben wir ja unsere Konstante definiert, die nehmen wir. Wichtig ist, dass wir die Konstante noch mit 1000 multiplizieren müssen, denn der CountDownTimer möchte es in Millisekunden angegeben haben. Das zweite Argument gibt an, alle wieviel Sekunden bzw. Millisekunden heruntergezählt werden soll. Damit jede Sekunde gezählt wird, müssen wir also 1 reinschreiben, wieder multipliziert mit 1000. Oder einfach gesagt: Wir schreiben 1000.
Android Studio erzeugt auch gleich die zwei Methoden, die wir noch implementieren müssen. Die eine heißt „onTick“, die jede Sekunde aufgerufen wird. Die andere heißt „onFinish“, die am Ende des Countdowns aufgerufen wird, also nach 3 Sekunden. Um onTick kümmern wir uns in einem anderen Video. Die könnte man dazu nutzen, irgendwo sichtbar den Countdown runterzählen zu lassen. Und die onFinish-Methode delegieren wir an eine neue Methode, die wir „onTimeout“ nennen. Das machen wir, damit unser Code übersichtlich bleibt.
Nicht vergessen: initCountDown müssen wir in onCreate aufrufen, also beim Starten der App. So sieht die onCreate-Methode dann aus:

Game Over
Nach 3 Sekunden soll das Spiel beenden, wenn der Spieler zu langsam war und keine Entscheidung getroffen hat. Dazu erstellen wir eine neue Methode, die wir „showGameOver“ nennen.

Hier steht der Code aus der onError-Methode. Es ist egal, ob das Spiel beendet, weil der Countdown abgelaufen ist, oder weil der Nutzer einen Fehler gemacht hat. In beiden Fällen passiert das gleiche. Daher rufen wir showGameOver sowohl in onTimeout als auch in onError auf.
Die onTimeout-Methode sieht so aus:

Die onError-Methode sieht genauso aus:

Damit der Nutzer auch wirklich weiß, warum das Spiel nach 3 Sekunden plötzlich verloren ist und beendet wurde, wollen wir ihm noch einen fetten roten Text in der Mitte der App anzeigen. Dazu öffnen wir unsere strings.xml Datei (res/values/strings) und erstellen einen neuen Text.
<string name="timeout" translatable="false">TIMEOUT</string>
Und diesen Text setzen wir in die Mitte der App, also in die numberView, wo normalerweise die aktuelle Zahl steht. Das ganze machen wir in der onTimeout-Methode, noch bevor wir showGameOver aufrufen.

Countdown starten
Soweit so gut. Wir haben den Countdown eingerichtet und definiert, was passieren soll, wenn er abläuft. Wir dürfen aber nicht vergessen den Countdown auch zu starten. Er soll immer dann neu gestartet werden, wenn der Nutzer einen Button klickt, und zwar den richtigen. Das heißt auch, dass der Countdown zu Beginn des Spiels noch nicht läuft. Er läuft erst, nachdem der Nutzer das erste Mal auf + getippt hat.
Am Besten ist es also, wenn wir den CountDown in der onCorrect-Methode starten, und zwar dort in der letzten Zeile. Das geht so:
countDownTimer.start();
Countdown stoppen
Der Countdown wird immer neu gestartet, wenn der Nutzer den richtigen Button tippt. Aber was passiert, wenn der Nutzer mitten im Spiel die App beendet? Dann würde der Countdown im Hintergrund noch weiterlaufen. Und nach 3 Sekunden würde das Handy den Sound abspielen und den Game-Over-Toast anzeigen. Das wäre verwirrend für den Nutzer. Wir sollten deswegen den CountDownTimer stoppen, wenn die App beendet wird.
Da unsere MainActivity von der AppCompatActivity erbt, gibt es schon eine Methode, die wir hier nutzen bzw. überschreiben können. Die heißt „onStop“. Sie wird immer aufgerufen, wenn die App gestoppt/beendet wird.
Um eine Methode zu überschreiben, musst du sie neu implementieren. Tippe einfach onStop. Es erscheint eine Auswahl an Vorschlägen. Wähle die onStop-Methode aus und drücke Enter.

Android Studio erzeugt die Methode. Das Schlüsselwort „@Override“ zeigt dir an, dass diese Methode schon existiert (und zwar in der AppCompatActivity) und von dir überschrieben wird.
In onStop stoppen wir den CountDownTimer, indem wir cancel aufrufen.

Das war’s schon! Wenn dir das Spiel immer noch zu leicht vorkommt, setz doch mal die Konstante auf 2 oder auf 1 Sekunde. 😉