Noch nie gescriptet? Der Guide Scripting für Einsteiger auf visionaire-studio.net zeigt an einem kleinen Beispiel, wann sich Lua lohnt und wie du deine ersten Skripte schreibst.

Visionaire Studio bringt eine eigene Skriptumgebung mit. Sie besteht aus Lua und dem Visionaire-Objektmodell. Über das Objektmodell greifst du bequem auf die Datenstruktur von Visionaire zu. Fast alles in Visionaire ist ein Objekt (zum Beispiel Szene, Charakter, Interface), und du kannst jedes davon per Skript auslesen und verändern.


Lua

Visionaire Studio verwendet derzeit Lua in Version 5.4.

Wenn du mehr über die Sprache lernen möchtest, hilft dir die offizielle Dokumentation auf der Lua-Website oder eines dieser Tutorials:


Eine Einführung in Lua von unserem Community-Mitglied AFRLme findest du auch hier im Wiki:


Das Visionaire-Objektmodell

Jedes Visionaire-Projekt wird in einer hierarchischen Datenstruktur gespeichert. Jedes Objekt dieser Datenstruktur ist ein „VisionaireObject“ (TVisObj). Alle Objekte desselben Typs (zum Beispiel Szenen oder Buttons) liegen in einer gemeinsamen Tabelle (zum Beispiel „Scenes“ oder „Buttons“).

Auf die Eigenschaften eines Objekts greifst du über die Felder zu, die für die jeweilige Tabelle festgelegt sind. Ein Feld kann einen einzelnen Wert enthalten (zum Beispiel eine Zahl oder einen Text), eine Tabelle mit Werten, einen Link auf ein anderes VisionaireObject oder eine Liste solcher Links. Alle Objekte und ihre Felder sind unter Datenstrukturen beschrieben. Die verschiedenen Feldtypen findest du weiter unten.


Auf Objekte und Felder zugreifen

Die Tabellen der Datenstruktur sind global verfügbar. Objekte in den Tabellen sprichst du meist über ihren Namen an, du kannst aber auch den Index der Tabelle verwenden. Das Objekt „game“ steht in keiner Tabelle, sondern ist direkt verfügbar.

-- Examples of accessing a VisionaireObject by (a unique) name
local char = Characters["hero"]
local coins = Values["coins"]

-- The following syntax is also possible, but be aware that it only works for object names which don't contain
-- special characters or whitespaces (only A-Z, a-z, 0-9 and underscore allowed) and start with a letter
local char = Characters.hero

-- Access a VisionaireObject by table index: get the first object in the "Characters" table
local char = Characters[1]


Auf die Eigenschaften eines Objekts greifst du über seine Felder zu:

-- Example of accessing a property of a VisionaireObject
local char = Characters["hero"]
local pos = char.Position

-- This leads to the same result
local pos = Characters["hero"].Position

-- Get the integer value ("Int" field) of the "Value" object called "coins"
local num_coins = Values["coins"].Int

-- The "game" object is directly accessible
local scr_pos = game.ScrollPosition


Sind in einer Eigenschaft andere VisionaireObjects verknüpft, kannst du den vollständigen Objektpfad angeben. Das hilft besonders, wenn Objektnamen nicht eindeutig sind und du sie nicht allein über den Namen erreichst:

-- Let's say each character has a value property called "coins"; it is not possible to use 'Values["coins"]'
-- because the name is not unique; now access the different values by using the object path
local hero_num_coins = Characters["hero"].Values["coins"].Int
local villain_num_coins = Characters["villain"].Values["coins"].Int
local cur_num_coins = game.CurrentCharacter.Values["coins"].Int

-- Object paths can be even longer
local door_state = Scenes["kitchen"].Objects["door"].Conditions["door_closed"]

-- If the condition name "door_closed" is unique in the project, the following leads to the same result
local door_state = Conditions["door_closed"]


Einen Feldwert zu schreiben ist genauso einfach. Allerdings lassen sich nicht alle Felder der Datenstruktur per Skript ändern. Welche es sind, steht unter Datenstrukturen:

-- Lower the brightness of a scene to 80%
Scenes["kitchen"].Brightness = 80

-- Make the villain the playable character
game.CurrentCharacter = Characters["villain"]

-- Set a condition to true
Conditions["door_closed"].Value = true

-- Change the integer value of a "Value" object
Characters["hero"].Values["coins"].Int = 47


Felder, die jedes VisionaireObject hat

Die folgenden Felder hat jedes VisionaireObject. Sie lassen sich nur lesen (außer „name“, das du mit der Methode „setName“ ändern kannst):

  • id: Die interne ID des Objekts (Ganzzahl).
  • name: Der interne Name des Objekts aus dem Editor (Text). Nicht zu verwechseln mit der Eigenschaft „Name“ (mit großem „N“), die es bei manchen Objekten gibt und die den mehrsprachigen Namen im Spiel enthält.
  • parent: Gibt das übergeordnete Objekt zurück (TVisObj).
  • tableId: Die ID der Datenstruktur-Tabelle, zu der das Objekt gehört (Ganzzahl).


Feldtypen

Die Feldtypen der Datenstruktur entsprechen diesen Lua-Typen:

Feldtyp Lua-Typ/Struktur Beschreibung
t_bool boolean true oder false
t_int number Ganzzahl
t_float number Kommazahl
t_string string
t_path string Dateipfad
t_point table x (int) x-Koordinate
y (int) y-Koordinate
t_rect table x (int) x-Koordinate der linken oberen Ecke
y (int) y-Koordinate der linken oberen Ecke
width (int) Breite des Rechtecks
height (int) Höhe des Rechtecks
t_sprite table path (str) relativer Pfad zur Bilddatei
position (t_point) Versatz des Sprites, wenn es in einer Animation verwendet wird
transparency (int)
transpcolor (int) Transparenzfarbe
pause (int) Pause in Millisekunden, wenn das Sprite in einer Animation verwendet wird
t_text table text (str)
sound (str) Dateipfad zu einer Sounddatei für diesen Text
language (int) ID der Sprache dieses Textobjekts
t_link string ein Link auf ein VisionaireObject (TVisObj); beim Lesen bekommst du das Objekt zurück, beim Setzen übergibst du ein Objekt
t_links table eine Liste von Links auf VisionaireObjects (TVisObj), die du über Nummern und über die Namen der Objekte durchlaufen kannst
t_vint table Tabelle mit Ganzzahlen
t_vfloat table Tabelle mit Kommazahlen
t_vstring table Tabelle mit Texten
t_vpath table Tabelle mit t_path-Einträgen
t_vpoint table Tabelle mit t_point-Einträgen
t_vrect table Tabelle mit t_rect-Einträgen
t_vsprite table Tabelle mit t_sprite-Einträgen
t_vtext table Tabelle mit t_text-Einträgen


Die alte Langschreibweise

Empfohlen ist die Schreibweise aus dem Abschnitt „Auf Objekte und Felder zugreifen“. Es gibt aber noch einen zweiten Weg, VisionaireObjects anzusprechen. Er stammt aus den Anfängen der Skripte in Visionaire, und du triffst ihn noch in älteren Skriptbeispielen an. Man nennt ihn die „Langschreibweise“, im Gegensatz zur viel einfacheren Kurzschreibweise von oben.

Mit dem globalen Befehl getObject holst du dir ein VisionaireObject, mit den Objektbefehlen liest und setzt du seine Felder:

-- Example of accessing a VisionaireObject by (a unique) name
local char = getObject("Characters[hero]")

-- Example of accessing a VisionaireObject by passing a tuple:
-- get the object with id=1 from the table with id=0 (characters table).
local char = getObject("(0,1)")

-- Note that in the object path, VisionaireObject names need to be prefixed with the (singular) table name
local door_state = getObject("Scenes[kitchen].SceneObjects[door].ObjectConditions[door_closed]")

-- If you want to get/set a field you need the appropriate object method and have to use the field constants.
-- A field constant starts with a "V" followed by the field name (including the aforementioned table prefix)
local is_closed = door_state:getBool(VConditionValue)
door_state:setValue(VConditionValue, true)


Ein Skript anlegen

Skriptbereich

Skripte legst du im Bereich „Skripte“ des Editors an. Für jedes Skript legst du über die Option oberhalb des Skripteditors fest, ob es ein Definitionsskript oder ein Ausführungsskript ist (siehe Bild). Ein Definitionsskript läuft automatisch beim Spielstart, ein Ausführungsskript muss ausdrücklich aufgerufen werden.

In deinen Aktionen nutzt du Skripte über die Aktionsteile „Call script“ und „Execute a script“. Beim ersten wählst du eines deiner Ausführungsskripte aus, beim zweiten gibst du direkt Lua-Code ein. Mit dem Aktionsteil „If Lua result“ baust du eine Wenn/Sonst-Abfrage mit Lua-Code. Außerdem kann eine Lua-Abfrage Teil einer kombinierten Bedingung sein.