Projekt:Adventure 2.0/Autoren-Handbuch/Scripting-Anleitung

aus Kamelopedia, der wüsten Enzyklopädie
Zur Navigation springen Zur Suche springen

Bei Fragen oder Problemen am besten an Kamel:J* wenden, der das hier alles verbockt hat.


Im Adventure2 gibt es 2 Arten von Unterseiten: Die Spielseiten und die Item-Seiten:

Spiel- und Item-Seiten

Die Spielseiten werden (mehr oder weniger fortlaufend) durchnummeriert. Bitte die Vorlage:Adventure2/Seite verwenden! Das Bild sollte 550x300px groß sein, oder zumindest das richtige Seitenverhältnis haben. Mit Hilfe der imagemap-Extension können da drin auch gleich Bereiche definiert werden, mit denen man später irgendwas anstellen können soll. Dabei werden einfach die Links so gesetzt, dass sie nicht auf eine Wikiseite zeigen, sondern stattdessen mit "#" beginnen, gefolgt von irgendeinem Bezeichner. Wie auch sonst fast für alles, sind als einzige Zeichen für den Bezeichner die Kleinbuchstaben und der Unterstrich erlaubt.

Ein guter Online-Editor für das Zeug ist [1]. Den Code findet man dann unten auf der Seite (ganz einfach bei "Code" aufklappen - ich habs da zuerst übersehen).

Die Itemseiten heißen einfach "item/" gefolgt vom Namen des Items in Kleinbuchstaben. Auch auf die Itemseite gehört ein Bild (50x50 Pixel oder wenigstens quadratisch, wenn's geht transparent). Bitte die Vorlage:Adventure2/Item verwenden! Auf beiden Seitenarten können hinter dem Bild Ereignisse (sog. Events) festgelegt werden, die steuern, wie sich der Spieler durch's Adventure bewegen kann. Ereignisse sollten immer auf der Seite platziert werden, zu der sie gehören. Ereignisse auf Spielseiten können nur aufgerufen werden, wenn der Spieler sich auf der entsprechenden Seite befindet, Ereignisse auf Itemseiten nur dann, wenn der Spieler das Item besitzt.

Ereignisse

Die Ereignisse Werden mit der Vorlage:A2Event eingebunden. Da hinein kommt dann der Text für die Ereignis-Definition in der extra dafür entwickelten Mini-Programmiersprache A2l. Beim Drücken auf Vorschau und nach dem Abspeichern wird der Programmcode auf der entsprechenden Spiel- oder Itemseite ausgegeben. Wenn alles geklappt hat, steht dort der Code genau so wie er eingegeben wurde. Wenn etwas schief gegangen ist, malt der Parser die Zeile rot an und schreibt drunter, was das Problem ist. Der Pfeil ↑ zeigt dabei (meistens) auf das erste fehlerhafte Wort.

Ereignisse in A2l

Das Grundgerüst eines Ereignisses sieht etwa so aus:

event [name];
  on <trigger>;
 [if <condition>;]
 [do <action>;]
  end.

Die spitzen und eckigen Klammern gehören nicht wirklich da hin: die spitzen (<>) signalisieren einen Platzhalter, die eckigen ([]) bedeuten, dass der Inhalt darin auch weggelassen werden kann, wenn er nicht gebraucht wird.

Event-Name

Man darf jedem Event einen Namen geben. Das ist vor allem nützlich, um anderen sagen zu können, um welches Event es geht, oder für die Fehlersuche. Der Eventname darf aus beliebigen Kleinbuchstaben und Unterstrichen bestehen.

Trigger

Es können ein oder mehrere Trigger definiert werden, die festlegen, was der Auslöser für das Ereignis sein soll. Möglich sind dabei:

enter(<page>)
ausgelöst beim Betreten einer Seite oder beim Laden eines Spielstands
leave(<page>)
ausgelöst vor dem Verlassen einer Seite - Vorsicht, vielleicht noch mit Nebeneffekten verbunden
click(<region>)
ausgelöst beim Klicken auf eine Region auf der Spielseite
hier ohne das "#"-Zeichen)
activate(<item>)
ausgelöst beim Klicken auf ein Item
combine(<item1>, <item2>)
ausgelöst, wenn Item1 auf Item2 gezogen wird
drag&drop). Hier ist es oft sinnvoll auch combine(<item2>, <item1>) zu verwenden, so dass man auch mit dem anderen Item anfangen kann
apply(<item>, <region>)
ausgelöst, wenn das Item auf eine Bildregion gezogen wird
add(<item>)
ausgelöst beim Hinzufügen des Items zum Inventar
remove(<item>)
ausgelöst beim Entfernen des Items aus dem Inventar

Die Platzhalter sind durch die Namen der Items/Seiten/Regionen zu ersetzen. Es können auch mehrere Trigger, per Komma getrennt, angegeben werden; das Ereignis tritt dann bei jedem der angegebenen Trigger ein.

Condition

Manchmal sollen bestimmte Voraussetzungen erfüllt sein, damit das Ereignis auch tatsächlich durch den Trigger ausgelöst wird. Das können sein:

page(<page>) oder page(@<pageclass>)
der Spieler muss sich auf der angegebenen Seite aufhalten
have(<item>) oder have(:<itemclass>)
der Spieler muss das angegebene Item im Inventar haben
any(...)
wahr wenn irgendeine der durch Komma getrennten Bedingungen wahr ist
all(...)
wahr wenn alle der durch Komma getrennten Bedingungen wahr sind
not(...)
wahr wenn die Bedingung innen falsch ist und anders herum

Wenn keine Bedingung gebraucht wird, kann sie weggelassen werden.

Action

Das was dann passieren soll, wird durch eine oder mehrere, mit Komma getrennte, Aktionen angegeben:

goto(<page>)
Auf eine andere Spielseite wechseln
add(<item>)
Ein Item hinzufügen
remove(<item>)
Ein Item entfernen
print("<text>") oder print('<text>')
Text ausgeben. Für wörtliche Rede kannst du die deutschen Anführungszeichen innendrin verwenden (die findest du rechts in den Klick-Sonderzeichen)
Beispiel: do print("Dort steht: „Eintritt strengstens erlaubt.“");
setTimeout(<sekunden>)
Starte den Timer und führe alle Aktionen die danach kommen erst aus, wenn der Timer durchgelaufen ist. Wenn der Timer vorher gestoppt wird oder die Seite verlassen wird, werden die Dinge danach nicht ausgeführt.
Es kann immer nur ein Timer laufen. Wenn schon ein Timer läuft, macht setTimeout(…) gar nix. Der Timer wird unten rechts in der Ecke dem Spieler angezeigt.
Beispiel: do setTimeout(20), print("Dieser Text wird erst nach 20 Sekunden ausgegeben");
clearTimeout()
Den Timer abbrechen
showOverlay() und hideOverlay(<overlay>)
Overlays anzeigen oder ausblenden. [] Absatz zu Overlays)
ask("<Frage?>", <sect>="<text>", …)
Frage den Benutzer was er tun will, oder bau einen Dialog zusammen: Hinter der Frage können mehrere mit Komma getrennte Optionen angegeben werden. <sect> gibt den Namen für die Option an <text> ist der Text, der dem Benutzer für die Option angezeigt wird. Die Namen können dann mit click(…) benutzt werden wie Bildregionen. Statt der doppelten können auch hier wieder einfache Anführungszeichen verwendet werden.
Beispiel: do ask("Was möchtest du malen?", optkamel="Ein Kamel natürlich!", optoase="Eine Oase.");

Die Aktion kann weggelassen werden, was allerdings nicht so richtig viel Sinn macht (dann lieber weg mit dem ganzen Ereignis).

Testen

Ob der eigene Code zumindest syntaktisch okay ist, kann man schon in der Vorschau sehen. Wenn einfach nur der Code (mit Zeilennummern) angezeigt wird, ist alles gut gegangen; wenn eine Zeile rot markiert wurde, hat der Parser dich nicht verstanden. Schau dir in dem Fall die Fehlermeldung an (steht in blauem Text unter der roten Zeile) und korrigiere deinen Code.

Anschließend kannst du dir dann anschaun, wie sich deine Seiten und Dinge im Adventure verhalten. Dazu benutzt du am besten die Debug-Version, da kannst du dann nämlich direkt auf bestimmte Spielseiten springen oder Items laden. Außerdem kannst du dort im Event-Log sehen, welche Trigger ausgeführt wurden (schwarz) und welche Events dadurch ausgelöst wurden (grün) bzw. aufgrund nicht erfüllter Bedingungen nicht ausgelöst wurden (rot+kursiv).

Kommentare

Code kann kommentiert werden, so dass andere Autoren wissen warum da irgendwas so gemacht wurde, wie es gemacht wurde. Kommentare sind im C/C++-Style, das heißt an beliebiger Stelle entweder // Kommentar (bis zum Ende der Zeile) oder /* Kommentar */ (geht auch innerhalb einer Zeile oder über mehrere Zeilen).

Für Fortgeschrittene

Seiten- und Itemklassen

Ich benutze hier einfach mal ein Beispiel:

Manchmal hat man Seiten oder Items die sich aus irgendeinem Grund ähnlich verhalten. Geht man etwa in einen dunklen Raum wird es dann hell, wenn man ein Licht dabei hat - egal ob Fackel oder Taschenlampe. Dafür kann man dann den Items Fackel und Taschenlampe eine gemeinsame Klasse zuweisen, indem man auf die Itemseiten schreibt:

item;
  provides :light;
  end.

Weitere Klassen würde man einfach mit Komma getrennt dahinter schreiben. Die Itemklasse kann man dann auf der entsprechenden Spielseite in der Condition mit have(:light) abfragen.

Andersherum gibt es natürlich auch bestimmte Items, die sich in bestimmten Umgebungen anders verhalten - z.B. kann man unterwasser die Fackel nicht anmachen. Dafür kommt dann auf die Spielseite:

page;
  provides @underwater;
  end.

Die lässt sich dann in der Condition auf der Itemseite mit page(@underwater) wieder abfragen.

Auch die remove-Funktion unterstützt die Angabe einer Klasse - in dem Fall werden dann alle Elemente entfernt, die auf die Klasse passen: z.B: remove(:light);

In den meisten Triggern lassen sich ebenfalls Klassen verwenden. Um das triggernde Item zu entfernen kann in der Action die Syntax remove(${<triggerfunktion><index>}) verwendet werden - <triggerfunktion> ist dann add/remove/activate etc. und index die Nummer des Operanden (eigentlich immer 1, außer bei combine, da ist auch die 2 möglich). Passt die angegebene Triggerfunktion nicht, dann passiert einfach stattdessen nichts. Beispiel:

event;
  on activate(:light);
  if page(4);
  do remove(${activate1}), print("Du versuchst Licht zu machen, aber im Dunkeln ist das extrem schwierig. Deine Lampe fällt dir dabei auf den Boden und geht kaputt.");
 end.

Overlays

Overlays ermöglichen das hinzufügen und wegnehmen von Objekten auf einer Seite - das können Gegenstände sein, oder aber irgendwas ganz anderes. Warum das nötig ist zeigt folgendes Beispiel: In einem Raum sollen 6 Gegenstände vom Spieler in beliebiger Reihenfolge aufgenommen werden können. Wenn man das versucht, mit einzelnen Seiten umzusetzen braucht man eine für jede Kombination von noch vorhandenen Gegenständen: also 2^6 = 64. Damit das nicht sein muss, platziert man alle Gegenstände mit Overlays auf der Seite. Es werden dann nur so viele Overlays benötigt, wie Gegenstände auf der Seite sind.

Overlays werden mit der Vorlage:Adventure2/Overlay eingefügt:

{{Adventure2/Seite
 |bild=...
 |bereiche=
...
 |overlays=
{{Adventure2/Overlay|<id>|<css>|<content>}}
 |left= |right= |up= |down=
 |code=
...
}}

Der Parameter <id> steht für den Namen des Overlays, <css> für die css-Angaben: hier sollten mindestens left (oder right) und top (oder bottom) gesetzt werden, vielleicht auch noch display: none. <content> ist der Inhalt des Overlays. Beispiel:

{{Adventure2/Overlay|hammer|right:70px; bottom: 0px; display: none;|[[Datei:Hammer.png|link=]]}}

Das Bild:Hammer.png enthält dann den anzuzeigenden Inhalt, d.h. hier den Hammer, so wie er im Bild dargestellt werden soll, natürlich mit transparentem Hintergrund. Da für jedes Overlay auch ein Klick-und-drop-Bereich definiert wird, sollten keine breiten transparenten Ränder usw. im Bild sein und der Bereich auch nicht unnötig mit width oder height groß gemacht werden.

Für Overlays gibt es zwei eigene Aktionen: showOverlay(<id>) und hideOverlay(<id>), mit denen sich Overlays anzeigen oder verstecken lassen.

Ist display:none nicht gesetzt, so wird das Item beim Betreten der Seite angezeigt, ansonsten nicht. Wenn beides möglich sein soll (z.B. je nachdem, ob der Spieler das Item schon im Inventar hat), kann man display:none zunächst setzen, und wenn nötig, das Overlay beim Betreten der Seite einblenden:

event enter;
  on enter(30);
  if not(have(hammer));
  do showOverlay(hammer);
  end.

Am Rande sei noch bemerkt, dass sich mit Overlays, etwa zusammen mit Widgets, auch andere Dinge realisieren lassen, wie z.B. Eingabefelder.

Links

[] Debug-Version, Seiten- und Itemübersicht
Siehe auch.png Siehe auch:  Items-Bilder, Seiten-Bilder
[] zum Autorenhandbuch | zur Projektseite