Vorwort:
Nun, in der Hoffnung ein wenig mein Motivationstief was das Makern angeht zu überwinden habe ich mich entschlossen endlich mal mein aktuelles Hauptskript zu veröffentlichen. Es ist zwar noch lange nicht fertig, aber es sollte relativ bugfrei sein und auch wenn viele Funktionen noch nicht eingebaut sind ist es dennoch in einem Zustand, den ich durchaus als "benutzbar" bezeichnen würde.
Was ist das MGK eigentlich?
MGK ist die Abkürzung für "Magic GUI Kit" und ist eben genau das, ein GUI-Kit. Ein GUI-Kit ist eine Sammlung von Klassen und Funktionen, die das Erstellen von GUIs (Graphical User Interfaces - Grafisches Benutzerinterface) erleichtern. Das MGK ist ein eben solches Kit für den RPG-Maker XP. Im Gegensatz zu den normalen Standardinterfaces, die in einem XP-Spiel auftauchen ist das MGK auf mausgesteuerte Interfaces ausgelegt. Eine Steuerung über die Tastatur sowie das Erstellen von Hotkeys ist zwar geplant aber steht relativ weit unten auf meiner Prioritätenliste.
Im Moment besitzt das MGK die Möglichkeit Fenster, Labels, mehrzeiligen Text, Icons und Buttons zu erstellen. Das besondere ist dabei, daß das komplette GUI in einer XML-Datei definiert wird, die das Skript einfach einlädt. Das erlaubt nicht nur das editieren von Interfaces ohne im Ruby-Code rumzusuchen, was zB. für Übersetzungen eine enorme Hilfe ist, sondern Interfaces lassen sich so auch viel einfacher austauschen. In der XML-Datei schreibt man einfach WAS man haben möchte und innerhalb des Spieles sagt man dem Skript nur noch welche XML-Datei es laden soll.
Widgets und Outlets - Das Konzept:
Ein GUI ist im Prinzip nichts weiter als eine zusammenhängende Sammlung von sogenannten Widgets. Ein Widget ist ein eigenständiges Objekt, das einen bestimmten Zweck innerhalb einer GUI übernimmt. Das MGK kennt bisher folgende Typen von Widgets:
1. Window
Das Fenster ist eines der wichtigsten Elemente eines Benutzerinterfaces, denn bisher ist es nur möglich innerhalb eines Fenster Informationen anzuzeigen.
2. Label
Ein Label ist ein Element, das einen einzeiligen Text enthält. Es wird an einer bestimmten Stelle auf einem Fenster positioniert. Ein Label kann sich automatisch der benötigten Länge des Textes anpassen, sowie von einem einfarbigen Rand umgeben werden.
3. Text
Ähnlich wie ein Label dient das Text-Widget dazu Text in einem Fenster anzuzeigen. Anders als das Label enthält das Text-Widget dabei beliebig viele Zeilen Text. Man kann sowohl den Text als ganzes ändern, als auch einzelne Zeilen. Automatischer Zeilenumbruch ist noch nicht eingebaut.
4. Button
Das einzige Widget, das auf Interaktivität ausgelegt ist. Ein Button ist im Grunde nur ein Labelwidget, das von Hause aus auf die Mausposition reagiert.
5. Icon
Das einzige vollkommen ungeteste Widget in der Sammlung, sollte aber aufgrund seiner geringen Komplexität keine Fehler verursachen. Mit diesem Widget ist es möglich eine als "Icon" importierte Bilddatei auf dem Fenster anzuzeigen.
Ein GUI besteht aus beliebig vielen Widgets, wobei jedes Widget weitere Widgets enthalten kann. So enthält die GUI ein Window-Widget, welches wiederrum dann Labels und Buttons enthält.
Jedes Widget kann Outlets enthalten. Ein Outlet ist eine Funktion, die dem Widget-Objekt eigen ist. Bei bestimmten Ereignissen, wie dem Klicken der Maus, werden bestimmte Outlets aufgerufen. So wird bei einem Linksklick der Maus das Outlet "OnClick" des Widgets aufgerufen, auf dem sich der Mauscursor befindet. Sollte das Widget kein entsprechendes Outlet besitzen geht der Aufruf an das nächsthöhere Widget (zB das Window-Widget) weiter. Über solche Outlets interagiert das Interface mit dem Benutzer.
Die Demo:
Da das MGK zum Lesen der XML-Datein einen externen XML-Parser (rexml) benutzt verzichte auf das Posten des Codes, sondern gebe stattdessen nur den Link zu einer kleinen Demo. In der Demo wurde das Titelmenü mit dem MGK erstellt (title.xml), der Lade-Punkt wurde dabei durch den Musik-Punkt ersetzt. Ihr könnt dort mit einem Linksklick die Hintergrundmusik starten und mit einem Rechtsklick wieder stoppen.
Auf der Startmap sorgt der gute Aluxes für ein kleines Testinterface (test.xml) während der zweite NPC alle Interfaces löscht.
Zum Einbauen in das eigene Projekt muss zuerst die rexml-Bibliothek eingebunden werden und das MGK mit einem Maus-Skript verbunden werden. Wie das geht könnt ihr im "main"-Skript nachgucken.
Alle MGK-Skripte haben ein "MGK" vor ihrem Namen, zusätzlich dazu sind das Mausskript (oder ein anderes) sowie die beiden obersten Skripte notwendig. Die beiden obersten Skripte sind Ergänzungen zur Ruby-Standardbibliothek und zur RGSS-Bibliothek, die ich innerhalb das MGK benutze.
Falls ihr wissen wollt welche XML-Elemente die Widgets lesen und verarbeiten guckt in den Skripten einer Widget-Klasse in den Aufruf "MGK.registerWidget". "hooverPic" und "sound" beim Button werden allerdings noch nicht unterstützt.
Da Ruby case-sensitive ist, müssen die Elemente auch genau so formuliert werden wie sie dort angegeben sind. Sobald ich raushabe wie, versuche ich das zu ändern.
Genug geschwafelt:
Download: MGK - Beta
Das englische XP-RTP wird für die Demo benötigt.
Falls Fragen, Fehler oder sonstiges auftauchen, bitte posten =).
Edit:
So, die versprochene Dokumentation über die XML-Tags. Spielt mit dem Zeugs rum, wenn etwas nicht funktioniert sagt es mir. Über Bugreporte freue ich mich in der Tat.
Welche XML-Tags versteht das MGK?
Eine Einführung zu XML generell spare ich mir, sie würde auch sicherlich den Rahmen sprengen. Wer mit XML nichts anfangen kann soll Google oder Wikipedia befragen.
Ich gebe hier mal eine kurze Beispieldatei:
Code:
<gui>
<name>TestGUI</name>
<widget>
<type>Window</type>
<name>TestWindow</name>
<x>10</x>
<y>20</y>
<z>800</z>
<width>100</width>
<height>64</height>
<widget>
<type>Button</type>
<name>End</name>
<x>0</x>
<y>0</y>
<z>801</z>
<width>100</width>
<height>32</height>
<caption>Spiel beenden</caption>
<outlet>
<name>OnClick</name>
<text>MGK.killGUI; $scene = nil</text>
</outlet>
</widget>
</widget>
</gui>
Wir erstellen hier zuerst eine GUI, die wir "TestGUI" nennen. Innerhalb dieser GUI wird ein Widget vom Typ "Window" erstellt und innerhalb dieses Widget dann wiederrum ein anderes Widget vom Typ Button. Dieses Button-Widget erhält dann noch ein Outlet namens "OnClick", dies ist das Outlet, das ausgeführt wird wenn jemand auf den Button klickt.
Anbei eine Auflistung aller XML-Tags die das MGK versteht:
<gui>
Elterntag: Keiner
Untertags: <name>, <widget>
Der gui-Tag ist der Wurzel- oder Roottag der XML-Datei. Streng genommen ist es eigentlich egal welchen Tag man als Roottag verwendet, aber in späteren Versionen wird das MGK eventuell nur XML-Dateien als GUI lesen, die auch mit <gui> beginnen.
<widget>
Elterntag: <gui> oder <widget>
Untertags: <name>, <widget>, <type>, <outlet> (Weitere je nach typ)
Der Widget-Tag beschreibt ein Widget. Der Widget-Tag muss entweder unterhalb des gui-Tag oder unterhalb eines anderen Widget-Tags definiert sein, je nachdem ob das Widget an oberster Stelle der Hierarchie stehen soll, oder zu einem anderen Widget gehören soll.
<outlet>
Elterntag: <widget>
Untertags: <name>, <text>
Der Outlettag erzeugt ein Outlet für das zugehörige Widgetobjekt.
<name>
Elterntag: <gui>, <widget> oder <outlet>
Untertags: Keine
Der Nametag gibt der GUI, dem Widget oder dem Outlet einen eindeutigen Namen. Innerhalb einer GUI oder eines Widget kann es jeden Namen nur einmal geben. Es findet keine Überprüfung statt, wird ein Name doppelt verwendet wird das ältere Objekt dieses Namens mit dem neueren überschrieben.
<type>
Elterntag: <widget>
Untertags: Keine
Gibt den Typ des Widget an. Mögliche Werte sind:
Window/Windows, Label, Button, Text, Icon
<x> <y> <z> <width> <height>
Elterntag: <widget>
Untertags: Keine
Alle bisherigen Widgets nehmen einen rechteckigen Raum auf dem Screen ein. Mit diesen Tags wird die Position sowie Größe des Widgets bestimmt. Die X- und Y-Werte sind dabei relativ zum jeweiligen Bezugssystems, das entweder das direkt übergeordnete Widget ist, oder der Screen, sofern das Widget direkt unterhalb der GUI steht. Die Z-Werte sollten optimalerweise bei 800 beginnen und steigen wenn das Widget eine Ebene tiefer erstellt wurde.
<caption>
Elterntag: <widget>
Untertags: Keine
Dieser Tag funktioniert für Label- und Button-Widgets und gibt den String an, der auf diesen Widgets angezeigt wird. Wird dieser Tag weggelassen zeigen die Widgets ihre Namen an.
<text>
Elterntag: <outlet> oder <widget>
Untertags: Keine
Ist dieser Tag unter einem outlet-Tag aufgeführt so enthält der den Ruby-Code der bei Aufruf des Outlets ausgeführt wird.
Ist der Elterntag ein Widget-Tag vom Typ Text, so wird innerhalb dieses Tags der Text bestimmt, den das Textwidget zu Beginn anzeigen soll. Sollte der Text mit einem Zeilenumbruch beginnen wird dieser entfernt, ansonsten wird der Text nur an expliziten Zeilenumbrüchen umgebrochen.
<colorRed> <colorBlue> <colorGreen>
Elterntag: <widget>
Untertags: Keine
Mit diesen drei Tags können die Farbwerte für die Schriftfarbe des Widgets festgelegt werden. Bisher reagieren nur Label- und Buttonwidgets auf diese Tags. Werden diese Tags weggelassen wird in der Standardfarbe geschrieben (Weiß).
<fontName>
Elterntag: <widget>
Untertags: Keine
Ändert bei Label- und Buttonwidgets die Schriftart.
<fontSize>
Elterntag: <widget>
Untertags: Keine
Ändert bei Label- und Buttonwidgets die Schriftgröße.
<showBorder>
Elterntag: <widget>
Untertags: Keine
Mögliche Werte sind "true", "false" oder eine Zahl (0 für false, alles andere für true). Bestimmt ob das Label-, Button- oder Textwidget von einem dünnen weißen Rand umgeben sein soll.
<file>
Elterntag: <widget>
Untertags: Keine
Gibt bei einem Icon-Widget den Dateinamen des verwendeten Bildes an. Das Bild muss dabei als "Icon" importiert worden sein.
#{datei}
Mit diesem "Tag" kann der Inhalt einer anderen Datei in die XML-Datei eingefügt werden bevor diese in eine GUI umgewandelt wird.
Das sind bisher alle verstandenen Tags. Zu sagen ist nur, daß der text-Tag bei outlets demnächst durch einen "code"-Tag ersetzt wird. Die bisherigen Tags für Schriftformatierungen sind auch nur temporär eingebaut. Ich plane ein Formatierungssystem mit externen Dateien und ids ähnlich wie CSS mit HTML funktioniert.