| Name | Teil | Von |
|---|---|---|
| Ein Verb-Coin-Interface mit Inventar in der Bildschirmmitte einrichten (im Stil von MI3) | Teil 2 von 2 | Einzelkämpfer |
Dieses Tutorial beschreibt, wie du ein Verb-Coin-Interface zusammen mit einem Inventar in der Bildschirmmitte einrichtest, ganz ähnlich wie im Adventure The Curse of Monkey Island (MI3) von 1997. Wir bauen die Steuerung von MI3 nicht in allen Details nach, der Grundmechanismus ist aber derselbe.
Das Tutorial hat 2 Teile:
- Teil 1 behandelt die Grundlagen: das Coin-Interface und das Inventar. Dort wird nicht geskriptet, alles läuft über die Einstellungen und das Aktionssystem von Visionaire.
- Teil 2 (diese Seite) vervollständigt den Aktionstext, denn am Ende von Teil 1 haben wir gesehen, dass er noch nicht wie gewünscht funktioniert. Außerdem bringt er mehr Abwechslung bei den Befehlen, denn in MI3 hängen die Befehle vom Objekt ab: Der Papagei auf der Münze kann zum Beispiel „Reden“, „Essen“ oder „Pusten“ bedeuten. Dafür brauchen wir etwas Lua und ein bisschen Tüftelei.
Die Projektdateien kannst du unten auf beiden Tutorialseiten herunterladen. Die meisten Grafiken hat Esmeralda für ihr Menü-Tutorial erstellt.
Teil 1 // Teil 2
Was zu tun ist (1)
Wir machen da weiter, wo Teil 1 aufgehört hat. Der Aktionstext funktioniert beim Ziehen nicht richtig. Das ist kein Wunder, denn unser Standardbefehl "walk", mit dem Items gezogen werden, hat in den Befehlseigenschaften weder einen Namen noch ein Bindewort („... mit ...“). Meist ist das völlig in Ordnung, aber wir wollen satzartige Aktionstexte, also müssen wir den Aufbau etwas ändern.
Wir können den Standardbefehl nicht einfach "Use" nennen, sonst stünde das beim Herumlaufen ständig da. Und wir können auch nicht den normalen Befehl "Use" zum Ziehen von Items nutzen, weil wir ihn weiterhin auf Items anwenden wollen. Diese Anforderungen kommen sich in die Quere (glaub mir, ich habe es ausprobiert, es klappt nicht). Außerdem ändern wir unsere drei Befehle später ohnehin noch.
Die Lösung ist ein fünfter Befehl, der nur zum Ziehen von Items dient.
Einen neuen Befehl zum Ziehen anlegen
- Füge dem Interface "Coin" einen neuen Button mit dem Namen "use_drag" hinzu.
- Wähle in den Button-Eigenschaften als Button-Typ „Befehls-Button“.
- Trage in den Befehlseigenschaften als Namen "Use" ein, setze den Cursor "arrow" und hake „Items können mit diesem Befehl gezogen werden“ an.
- Stelle den Befehlstyp auf „Kombinierter Befehl“ und trage als Bindewort "with" ein.
Lass die Option zum Ziehen auch beim Befehl "walk" angehakt. Warum, erkläre ich später.
Befehl zum Ziehen aktivieren und deaktivieren
Der Befehl "use_drag" hat nur einen Zweck: Items aus dem Inventar ziehen. Er muss also im Inventar aktiv sein und außerhalb inaktiv, außer er zieht gerade ein Item heraus. Schauen wir, wo wir dafür den Zieh-Befehl bzw. den Standardbefehl setzen müssen.
Inventar ein- und ausblenden
- Füge in der globalen Aktion für den Rechtsklick diese Aktionsteile hinzu:
- Direkt unter „Sekundäres Interface einblenden“ fügst du Befehl setzen mit dem Befehl "use_drag" ein.
- Direkt über „Inventar ausblenden“ fügst du Befehl setzen mit „Standardbefehl“ ein.
Das Inventar schließt sich auch, wenn der Cursor es verlässt. Hier müssen wir unterscheiden, ob er es einfach verlässt oder ein Item herauszieht. Im zweiten Fall dürfen wir den Standardbefehl nicht setzen.
- Öffne in den Interface-Einstellungen von "Inventory" die „Aktion beim Verlassen“ und hänge diese Aktionsteile an:
- Wenn Lua-Ergebnis: trage
return game.UsedItem:isEmpty()ein. Die folgenden Aktionsteile laufen nur, wenn gerade kein Item gezogen wird. - Befehl setzen: wähle „Standardbefehl“.
- Ende Wenn
Aktionen der Münze
- Öffne in den Einstellungen des Interface "Coin" die „Aktion beim Verlassen“ und hänge diese Aktionsteile an:
- Wenn Bedingung: wähle die Bedingung "inventory_visible" und „true“. Die folgenden Aktionsteile laufen nur, wenn das Inventar sichtbar ist.
- Befehl setzen: wähle "use_drag".
- Ende Wenn
- Öffne die Aktion für „Linke Maustaste gehalten (Taste losgelassen)“ und füge direkt unter „Hauptinterface ausblenden“ diese Aktionsteile ein:
- Wenn Bedingung: wähle die Bedingung "inventory_visible" und „true“. Die folgenden Aktionsteile laufen nur, wenn das Inventar sichtbar ist.
- Befehl setzen: wähle "use_drag".
- Ende Wenn
- Öffne die Aktion für „Linke Maustaste gehalten (Taste gedrückt)“ und füge diese Aktionsteile hinzu:
- Wenn Lua-Ergebnis: trage
return game.UsedItem:isEmpty()ein. Die Münze erscheint dann nur, wenn kein Item gezogen wird. Das ist ohnehin sinnvoll und löst nebenbei das Problem, den richtigen Befehl zu setzen.
- Ende Wenn
Item auf Item ziehen
Nach einer erfolgreich ausgeführten Aktion wird automatisch der Standardbefehl gesetzt. Ziehen wir im Inventar ein Item auf ein anderes, muss aber "use_drag" aktiv bleiben, weil das Inventar offen bleibt. Leider lässt sich eine erfolgreiche Ausführung nicht global erkennen. Es hat sich aber gezeigt, dass es reicht, Linksklicks allgemein abzufangen: Klickt der Spieler im Inventar mit der linken Maustaste, wird der Zieh-Befehl gesetzt, außer die Münze ist sichtbar.
- Öffne die Aktion für „Linke Maustaste“ und füge diese Aktionsteile hinzu:
- Wenn Bedingung: wähle die Bedingung "inventory_visible" und „true“.
- Wenn Bedingung: wähle die Bedingung "interface_visible" und „false“.
- Befehl setzen: wähle "use_drag".
- Ende Wenn
- Ende Wenn
- Füge genau dieselben Aktionsteile auch in die globale Aktion „Doppelklick“ ein. Das ist nötig, weil die Aktion für Item auf Item auch per Doppelklick ausgelöst wird. Eine gemeine Falle.
Gezogenes Item per Rechtsklick loslassen
Jetzt kommt eines dieser fiesen Probleme, die man leicht übersieht.
Ein Rechtsklick löst ein gezogenes Item vom Cursor und bricht den Vorgang ab, ohne eine Aktion auszuführen. Das ist in Visionaire fest eingebaut und lässt sich nicht ändern (vielleicht doch, aber ich wüsste nicht wie, und eigentlich wollen wir es auch gar nicht ändern). Solange der Cursor noch im Inventar ist, macht das nichts. Klicken wir aber rechts, nachdem wir das Item aus dem Inventar gezogen haben, verschwindet das Item zwar wie erwartet, "use_drag" bleibt aber aktiv, weil keine Aktion ausgeführt wurde. Außerhalb des Inventars nützt dieser Befehl nichts, wir müssen stattdessen den Standardbefehl aktivieren.
Auch hier lässt sich nicht direkt erkennen, wann ein gezogenes Item losgelassen wurde. Und die globale Rechtsklick-Aktion hilft nicht, weil sie in diesem Fall gar nicht ausgeführt wird. Also tüfteln wir mit Lua.
- Lege ein neues Lua-Skript mit dem Namen "mouse_events" an.
- Achte darauf, dass die Option „Definitionsskript“ angehakt ist, und füge diesen Code ein:
function onMouseEvent(eventType, mousePosition)
if eventType == eEvtMouseRightButtonUp then
if not game.UsedItem:isEmpty() then
if Conditions["inventory_visible"].Value == false then
game.ActiveCommand = Buttons["walk"]
end
end
end
end
registerEventHandler("mouseEvent", "onMouseEvent")
Die letzte Zeile registriert einen Event-Handler für Mausereignisse. Bei jeder Mausbewegung, jedem Klick und jedem Scrollen wird also die Funktion "onMouseEvent" aufgerufen. Das ist eine eigene Funktion, in der wir tun können, was wir wollen. Wichtig: Dieses Mausereignis kommt, bevor Visionaire irgendetwas anderes tut. Unsere Funktion läuft also, bevor der Visionaire-Player das gezogene Item loslässt.
- Die Zeile mit
if eventType...prüft die Mausaktion; wir wollen nur beim Rechtsklick etwas tun. - Die Zeile mit
if not game...prüft, ob gerade ein Item gezogen wird. - Die Zeile mit
if Conditions...prüft, ob das Inventar gerade ausgeblendet ist. - Die Zeile mit
game.ActiveCommand...setzt den Standardbefehl.
Nicht wichtig, aber interessant: Falls du dich fragst, warum der Standardbefehl "walk" weiterhin Items ziehen darf ... Sobald unser Skript oben beim Rechtsklick den Standardbefehl setzt, würde das gezogene Item schon losgelassen, wenn der Standardbefehl es nicht halten könnte. Das Loslassen stand ohnehin bevor, scheint also keinen großen Unterschied zu machen. Wenn der Visionaire-Player dann aber weitermacht und kein Item mehr loszulassen ist, führt er die globale Rechtsklick-Aktion aus und öffnet das Inventar. Das wollen wir hier nicht. War nicht interessant? Tut mir leid, jetzt ist es zu spät, es nicht gelesen zu haben.
Was zu tun ist (2)
Jetzt der letzte Schritt dieses Tutorials. Wie gesagt hängen die Befehls-Buttons in MI3 vom Zusammenhang ab. Das Symbol Hand steht zum Beispiel je nach Objekt für „Nehmen“, „Drücken“ oder „Benutzen“.
Um das nachzubauen, legen wir Befehls-Buttons für alle möglichen Befehle an und aktivieren nur die, die zum aktuellen Objekt passen. „Ansehen“ bleibt der einzige Befehl für das Auge, für Hand und Mund kommen aber einige neue Befehle hinzu.
Weitere Befehle hinzufügen
- Lege im Coin-Interface zwei Werte an, "which_hand_command" und "which_mouth_command", beide mit dem Wert 1. Sie bestimmen, welcher der Hand- und welcher der Mund-Befehle gerade aktiv ist.
- Benenne den Befehl "use" in "hand_1_use" um. Er wird unser erster Hand-Befehl und ist damit standardmäßig aktiv.
- Verknüpfe in den Button-Eigenschaften den Wert "which_hand_command" mit der Prüfung „= 1“.
- Dupliziere den Button "hand_1_use" zweimal und nenne die Kopien "hand_2_take" und "hand_3_push". Beim Duplizieren werden alle Einstellungen mitkopiert, auch Bild und Objektbereich. Das spart dir viel Arbeit.
- Stelle in den Button-Eigenschaften der neuen Buttons die Prüfung auf „= 2“ bzw. „= 3“.
- Gib den neuen Buttons in den Befehlseigenschaften die Namen "Take" bzw. "Push".
- Wiederhole das alles für die Mund-Buttons und verknüpfe sie mit dem Wert "which_mouth_command". Aus "talk" wird "mouth_1_talk", die anderen Buttons heißen "mouth_2_eat", "mouth_3_drink", "mouth_4_blow" und "mouth_5_bite".
Befehle aktivieren und deaktivieren
Wie schalten wir nun bestimmte Befehle je nach angeklicktem Objekt ein oder aus? Die Idee: Wir geben dem Objekt einen Wert "set_hand" und/oder "set_mouth" und setzen ihn auf die Nummer des gewünschten Befehls. Für den Pilz in unserer Projektdatei legen wir also einen Wert "set_hand" mit dem Inhalt 2 an. Öffnen wir die Münze dann auf dem Pilz, heißt der Hand-Befehl „Take“ statt „Use“. Nicht jedes Objekt braucht diese Werte: Fehlt der Wert, gilt der Standardbefehl, also "Use" bzw. "Talk".
Damit das funktioniert, brauchen wir noch ein Skript:
- Lege ein neues Lua-Skript mit dem Namen "set_coin" an.
- Nimm den Haken bei „Definitionsskript“ heraus und füge diesen Code ein:
if game.SavedObject ~= nil then
if game.SavedObject.Values["set_hand"] ~= nil then
Values["which_hand_command"].Int = game.SavedObject.Values["set_hand"].Int
else
Values["which_hand_command"].Int = 1
end
if game.SavedObject.Values["set_mouth"] ~= nil then
Values["which_mouth_command"].Int = game.SavedObject.Values["set_mouth"].Int
else
Values["which_mouth_command"].Int = 1
end
end
- Die Zeile mit
if game.SavedObject ~=...prüft, ob überhaupt ein Objekt zum Ausführen gespeichert wurde. - Der folgende If-Block sucht am Objekt nach einem Wert "set_hand" und setzt "which_hand_command" auf diesen Wert, falls es ihn gibt. Fehlt "set_hand", wird der Standardwert 1 (Befehl "Use") gesetzt.
- Der untere Codeblock macht dasselbe für die Mund-Befehle.
Dieses Skript müssen wir direkt vor dem Anzeigen der Münze aufrufen:
- Öffne die Aktion für „Linke Maustaste gehalten (Taste gedrückt)“ und füge direkt unter „Objekt speichern“ diesen Aktionsteil ein:
- Skript aufrufen: wähle das Skript "set_coin".
So arbeitest du mit den Befehlen
Einfacher geht es kaum. Soll auf dem Pilz statt "Use" der Befehl "Take" gelten, gib dem Pilzobjekt einen Wert "set_hand" mit dem Inhalt 2. Lege dann eine Aktion vom Typ „Befehl auf Objekt ausgeführt“ an und wähle den Befehl "hand_2_take". Du kannst "set_hand" sogar zur Laufzeit ändern, wenn ein Objekt im Spielverlauf unterschiedlich behandelt werden soll.
In der Projektdatei habe ich diese Beispielaktionen eingebaut:
- Mit dem Hand-Befehl kannst du den Pilz „nehmen“.
- Mit dem Mund-Befehl kannst du versuchen, den aufgesammelten Pilz im Inventar zu „essen“.
- Du kannst versuchen, den Gnom zu „nehmen“. Danach versuchst du beim nächsten Hand-Befehl, ihn zu „schubsen“.
Sind wir jetzt fertig?
Ich denke schon.
Teil 1 // Teil 2
Ressourcen
| Name | Beschreibung |
|---|---|
| vistut_verb_coin_interface_and_inventory.zip | Projektdateien zu diesem Tutorial (erstellt mit Visionaire Studio 5.1.9.2) |











