Schalter und Variablen im RPG Maker MV

Wenn man den RPG Maker MV nutzt wird man feststellen, dass im Event-Editor unter anderem die Begriffe Schalter, Variablen und Selbstschalter auftauchen. Gemeinsam ist diesen drei Konstrukten, dass in ihnen Daten gespeichert werden können. Je nach Anwendungszweck sollte man hier das am besten passende Konstrukt wählen. Grundsätzlich unterscheiden sich die drei Konstrukte in ihrem Gültigkeitsbereich. Schalter und Variablen gelten global und können aus jedem beliebigen Event heraus ausgelesen und verändert werden. Die Selbstschalter hingegen sind nur im Kontext des aktuellen Events gültig.

Der Event-Editor des RPG Maker MV

Neben dem Gültigkeitsbereich gibt es noch einen Unterschied in den Werten, welche Schalter und Variablen abbilden können. Schalter können nur zwei Werte (EIN und AUS) speichern. Sie sind damit mit einem boolean-Datentyp vergleichbar. Daneben gibt es Variablen; diese speichern eine Ganzzahl. Sie sind damit mit einem Integer-Datentyp zu vergleichen. Bei der Arbeit mit den globalen Schaltern und Variablen sollte darauf geachtet werden, das die Nutzung der jeweiligen Variablen dokumentiert wird, da diese leider nicht benannt werden können. Stattdessen besteht ihre Bezeichnung aus einer Nummer z.B. 0001.

RPG Maker MV Autorun-Event nur einmal ablaufen lassen

Beim RPG Maker MV gibt es Events. Mit diesen Events kann das Spiel gestaltet werden. Für ein Intro-Event stand ich nun vor dem Problem, dass das Event nur einmal ausgeführt werden sollte. Bei mir wiederholte sich das Event allerdings ständig. Da es sich um ein Autorun-Event handelte, startete dieses beim Betreten des Raumes jedes Mal von Neuem. Die Möglichkeit das Event über den entsprechenden Event-Befehl zu löschen funktionierte in diesem Fall ebenfalls nicht. Das Löschen eines Events kann nur dann genutzt werden, wenn der Spieler nicht während des Events auf eine andere Karte transferiert wird.

Seite 1 des Events

Die Lösung für dieses Problem ist relativ einfach. Auf der ersten Seite des Events erstellt man das eigentliche Event. Als Auslöser wird hierfür Autorun gewählt. Am Ende des Events wird der Selbstschalter A auf EIN gesetzt. Anschließend wird eine zweite Seite erstellt. Auf dieser Seite kann der Auslöser ebenfalls auf Autorun gestellt werden; es ist allerdings nicht zwingend nötig. Wichtig ist hingegen, dass die Bedingung Selbstschalter ausgewählt wird und mit dem Selbstschalter A verknüpft wird.

Seite 2 des Events

Bei der Ausführung des Events führt dies nun dazu, dass sobald der Selbstschalter A gesetzt ist, statt der ersten Seite des Events, die zweite Seite ausgeführt wird. Da diese keine Befehle enthält ist das Event damit beendet. Theoretisch kann man so in einem Event eine ganze Kaskade von fortschreitenden Eventteilen schaffen. Der Hintergrund hier ist das die Eventseiten dafür gedacht sind ein Event unter unterschiedlichen Bedingungen anders zu gestalten. Die Dokumentation des RPG Maker MV erklärt das Ganze so:

[Event Pages] are responsible for this. Event pages [conditionally] determine the contents of events. You can have one event with up to 20 event pages, and specify different images, triggers, and what processes are run for each. In other words, you can [conditionally] choose from 20 different events for one map event.

Threadsichere Event unter C#

Events unter C# sind so eine Sache. Im Normalfall funktionieren sie ohne Probleme. Spannend wird das ganze wenn man Events in einer Anwendung zwischen verschiedenen Threads verschicken möchte. Dabei kann es nämlich passieren das Events verloren gehen weil sie nicht empfangen werden. Abhilfe schafft hier die Klasse “ThreadSafeEvent”:

public class ThreadSafeEvent
{
  EventHandler internalEventHandler;
  readonly object internalEventHandlerLock=new object();

  public event EventHandler Event
  {
    add
    {
      lock(internalEventHandlerLock)
      {
        internalEventHandler+=value;
      }
    }
    remove
    {
      lock(internalEventHandlerLock)
      {
        internalEventHandler-=value;
      }
    }
  }

  public virtual void Fire(object sender, EventArgs e)
  {
    EventHandler handler;

    lock(internalEventHandlerLock)
    {
      handler=internalEventHandler;
    }

    if(handler!=null)
    {
      handler(sender, e);
    }
  }
}

Möchte man nun z.B. der Klasse “Entries” eine solches Event hinzufügen, so sieht das ganze wie folgt aus:

public ThreadSafeEvent EntrySelected=new ThreadSafeEvent();

Nun kann das Event gefeuert werden, das ganze wird mittels der “Fire” Methode bewerkstelligt. Dieser übergibt man den Sender und zusätzliche Argumente in Form eines “EventArgs” bzw. einer davon abgeleiteten Klasse.

EntrySelected.Fire(this, new EntryEventArgs(entry));

Jede Klasse welche das Event nun empfangen möchte hängt sich an das entsprechende Event.

Entries entries=new Entries();
Entries.EntrySelected.Event+=OnEntrySelected;

...

private void OnEntrySelected(object sender, EventArgs e)
{
  EntryEventArgs args=(EntryEventArgs)e;
  Console.WriteLine(args.Entry);
}

Und schon haben wir in unserer Anwendung ein sauberes und threadsicheres Eventsystem.

C# in Depth

Auf der Suche nach ein paar C#/CLR Interna bin ich auf die Webseite “C# in Depth” gestoßen, wobei man sagen muss das es sich dabei vorrangig um ein Buch handelt bzw. um die Webseite zum gleichnamigen Buch handelt. Aber auch die Webseite gibt einige sehr interessante Informationen von sich, welche man vor allem in der “Articles” Sektion findet. So lege ich jedem, der sich für das Thema interessiert, den Artikel Delegates und Events ans Herz. Es gibt dort definitiv die eine oder andere Erleuchtung ;) Die Webseite ist dabei unter http://csharpindepth.com zu finden.

MooTools und benutzerdefinierte Events

Bei MooTools handelt es sich um ein Framework mit welchem man sehr schön Klassen basierte Strukturen in JavaScript abbilden kann. Bei der Definition von benutzerdefinierten Events ist die Dokumentation leider etwas dünn, so das ich dort etwas probieren musste, bis ich zum richtigen Ergebnis gekommen bin.

Gegeben sei dabei ein Projekt mit einer “index.html” Datei sowie der JavaScript Datei “explosive.js” welche die Klasse “Explosive” enthält. Die Klasse sieht dabei im Quelltext so aus:

var Explosive = new Class({
       Implements: [Events],

       tntequivalent: 0,

       //Constructor
       initialize: function(equivalent) {
         this.tntequivalent = equivalent;
       },

       //Methods
       detonate: function(){
         this.fireEvent('explode');
       },

       detonateWithInfo: function(){
         this.fireEvent('explode', this.tntequivalent);
       }
});

In dieser Klasse gibt es die Eigenschaft “tntequivalent” welche die Sprengkraft unser Bombe definiert und im Konstruktor gesetzt wird. Die Funktionen “detonate” und “detonateWithInfo” zünden die Bombe und senden das Event “explode” wahlweise mit der Informationen über die Sprengkraft.

Die dazu passende “index.html” sieht dabei so aus:

<!DOCTYPE html>
<html>
  <head>
    <title>Mootools Event Test</title>
    <meta charset="utf-8" />
    <script type="text/javascript" src="mootools-core-1.4.5-full-nocompat.js"></script>
    <script type="text/javascript" src="explosive.js"></script>
  </head>
  <body>
    <script type="text/javascript">
      function onExplode(object)
      {
        if(object==null)
        {
          alert("Bomb is exploded.");
        }
        else
        {
          alert("Bomb is exploded, with " + object + " tons of TNT equivalent.");
        }
      }

      var bomb = new Explosive(100);
      bomb.addEvent('explode', onExplode);
    </script>

    <form>
      <input type="button" value="Detonate bomb" onClick="bomb.detonate();">
      <input type="button" value="Detonate bomb with info" onClick="bomb.detonateWithInfo();">
    </form>
  </body>
</html>

Hier wird im JavaScript-Bereich der Klasse eine Funktion “onExplode” angelegt, welche das Event am Ende entgegennehmen soll. Darunter wird eine Instanz der Klasse “Explosive” mit dem Namen “bomb” angelegt. Dieser Instanz sagen wir das dass Event “explode” an die Funktion “onExplode” weitergereicht werden soll.

Nun werden noch zwei Buttons definiert, welche die auslösenden Funktionen aufrufen. Einmal wird die Funktion “onExplode” mit einem Parameter und einmal ohne aufgerufen. In diesem Parameter steckt in diesem Fall die Sprengkraft der Bombe, so das diese mit ausgegeben werden kann. Und schon ist man mit seinem ersten Event fertig.

Weitere Informationen gibt es unter:
http://de.wikipedia.org/wiki/MooTools