Donnerstag, 28. März 2013

Die Auslösung von OnDistant kontrollieren

Voraussetzung: Zone als Kreis sowie "Der Einstieg in lua“
In früheren Tutorials berichte ich über die Möglichkeit bei einer punktförmigen Zone die Ereignisse OnProximity und OnDistant zu nutzen. Dabei kam es zu dem Problem, dass OnDistant bereits beim Start des Spieles ausgelöst wird.
Wie sich mittlerweile herausgestellt hat, wird OnDistant genaugenommen nicht beim Start sondern bei der ersten Aktvierung der Zone ausgelöst. (Beim vergangenen Tutorial waren alle betroffenen Zone von Start an aktiv, deswegen der Trugschluss mit OnStart).

Abbildung 1: Bei der ersten Auslösung wird das OnDistant-Events ignoriert
Eine einfache Abfrage ob wir uns in der Startphase befinden reicht also nicht mehr aus. Statt dessen müssen wir für jede Zone pflegen, ob das OnDistant-Event zum ersten Male ausgeführt wird (nämlich weil wir gerade die Zone zum ersten Mal aktivieren) oder ob der Spieler gerade den Proximity-Bereich verlässt, denn für diese Aktion wollen wir OnDistant ja nutzen. Dazu bauen wir uns ein Array namen OnDistantRegistry auf, dessen key aus dem Zonennamen besteht und als Value nil also nix oder der Booleanwert true möglich sind. Es könnte auch 1 oder "TradisSindDoof" als Wert genommen werden. Wichtig ist, dass der Vergleich OnDistantRegistry[zoneName] == nil fehlschlägt und da Boolean nur zwei Werte (true oder false) annehmen kann, verbrauchen wir auch nicht viel Speicher für unsere Registry.
In der Methode skipOnDistantEvent geben wir so true zurück, wenn die Methode zum ersten Mal mit diesem Zonennamen aufgerufen wird, ansonsten false.

Abbildung 2: Zu Beginn des OnDistant-Events fragen wir ab, ob wir abbrechen sollen oder ob der Code ausgeführt wird.
Sobald wir für eine Zone ein OnDistant-Event nutzen wollen, fragen wir zu Beginn ab, ob wir die Befehlsfolge des Events abarbeiten oder ob wir mit return abbrechen. 'Abbrechen' bezieht sich aber nur auf das OnDistant-Event nicht auf das Spiel selbst. Dieser Code muss auch nur in den OnDistant-Events eingesetzt werden, die auch wirklich genutzt werden.
Einen Hacken gibt es aber trotzdem bei dieser Lösung: Die fehlerhafte Auflösung des Events bei Aktivierung erfolgt nur, wenn der Spieler sich nicht in der Zone befindet. Sollte eine Zone aktiviert werden in deren onProximity Bereich der Spieler steht (Zufällig beim Start des Spieles, zwei Zonen überlappen sich, Zonenaktivierung durch Timer oder onClick-Events) so hat dies zur Folge, dass beim ersten Verlassen, besser gesagt Distanzieren von der Zone, die Abarbeitung ausfällt, da es für die Registry der erste Aufruf ist. Aber diese Fälle sind im Normalfall nicht zu erwarten und da dann auch das onProximity-Event nicht immer zuververlässig funktionert, kann der Fehler behoben werdene, indem der Spieler einmal raus und wieder rein in den Proximity-Bereich rennt.

Abbildung 3: Die globalen Events werden immer von den Zonen spezifischen ausgeführt
Diese Möglichkeit der Überprüfung ob das Event ausgeführt werden darf oder nicht, umfasst leider in dieser Form nicht die globalen Events, die automatisch für jede Zone ausgeführt werden sollen. Das liegt daran, dass globale Events ein Kunstgriff von Urwigo sind.
Abb. 3 zeigt die Umsetzung im von Uwrigo erzeugten lua Code. Dabei wird für jedes Event die currentZone definiert (deswegen können wir auch beim Aufruf der Prüfmethode auf die Variable zurückgreifen), dann die Methode mit der globalen Eventdefinition aufgerufen und zum Schluss der Zonenspezifische Code eingefügt. Zeile 352 und 353 sowie 362 und 363 werden automatisch von Urwigo erzeugt.
Man kann jedoch in der globalen Definition (da wo z.Zt lediglich "Globales OnDistant ausgeloest" steht) eine ähnliche Abhandlung wie in skipOnDistantEvent einbauen, nämlich if onDistantRegistry[currentZone] == nil then return end. Wichtig ist hier keine boolean Wert zu setzen ansonsten würde der nächste Aufruf (Zeile 354 bzw. 364) als zweiter Aufruf für die Zone erkannt und true zurückgeliefert.

Ich habe noch ein wenig mit Closures herum experimentiert um den skip-Check komplett in den global Event Teil zu schieben. Leider habe ich noch keine Möglichkeit gefunden, wie man in lua mehrere Methoden mittels return abbrechen kann. Also a() ruft b() auf und ein "return(2)" oder so ähnlich in b soll nicht nur die Methode b verlassen, sondern auch zum Abbruch der Methode a führen. Falls hier jemand weiter weiß, bin ich um einen Tipp sehr dankbar.

Keine Kommentare:

Kommentar veröffentlichen