logo
Homepage-Sicherheit

Willkommen Gast! Um alle Funktionen zu aktivieren müssen Sie sich Anmelden oder Registrieren.

Mitteilung

Icon
Error

Einloggen


Teilen
Optionen
Ansicht
Gehe zum aktuellsten Beitrag Gehe zum letzten Ungelesenen
Offline MartinRJ Fayray  
#1 Geschrieben : Sonntag, 7. September 2014 07:08:10(UTC)
MartinRJ Fayray

Rang: Ehrenmitglied

Ansehen:

Mitglied seit: 05.09.2014(UTC)
Beiträge: 90
Germany
Wohnort: Tulln und Rostock

Dankte: 6 mal(e)
Hello World

Skripting in Second Life ist überraschenderweise relativ schwierig. Bevor ich nach SL kam, habe ich schon über 10 Jahre lang - zum Teil beruflich - mit den verschiedenartigsten Programmier- und Skriptsprachen zu tun gehabt, und dachte anfangs dass das Schreiben von Skripts in Second Life für mich doch wohl ein Kinderspiel sein müsste.
Ich dachte, dass LSL so ähnlich wie Javascript oder eine der anderen simplen Skriptsprachen funktioniert.
Durch diese Fehlannahmen habe ich erst nach über einem Jahr in SL wirklich angefangen selbst Skripting-Projekte umzusetzen, und habe zum Glück zu Beginn sehr geduldige Kunden gehabt.

Die Skriptsprache von Second Life konzentriert sich sehr auf die speziellen SL-Events und -Funktionen, und ist rund um diese herum konzipiert. Ganz im Gegensatz zu universell einsetzbaren anderen Skriptsprachen wie JS oder VBScript.

Leider hat sie auch viele Macken (fehlerhafte Funktionen, fehlende Funktionalität), die man als professioneller Content-Ersteller kennen muss, oder man muss eben viel Zeit investieren, um das zu verstehen.

LSL (Linden Skripting Language) fällt gleich in drei Kategorien von Programmiersprachen:

  • State-driven
  • Ereignisorientiert
  • Prozedural (in einem gewissen Maß)


State-driven
State-driven bedeutet, dass jeder Code in LSL-Skripts irgend einem Skript-State zugeordnet ist. Mit State (zu Deutsch 'Zustand') ist nicht 'aktiv' oder 'inaktiv' gemeint, sondern jeder State ist im Prinzip ein eigenständiges Skript, und jedes LSL-Skript muss zumindest einen State haben ('default'), kann aber beliebig viele States verwenden, und zwischen diesen hin und her springen.

Zitat:

//--------------------------------------- STATE DEFAULT
default
{
state_entry()
{
if (llListFindList(llGetAgentList(AGENT_LIST_REGION, []), [llGetOwner()]) != -1)
{
state nearby; // Besitzer ist anwesend!
}
}
}

//--------------------------------------- STATE NEARBY
state nearby
{
state_entry()
{
llSay(PUBLIC_CHANNEL, "Owner ist anwesend!");
}
}


Jeder State - außer state default - wird aus dem Schlüsselwort 'state', und dem Namen des neuen States gebildet, z.B.: state nearby.

Man kann in obigem Beispiel-Skript erkennen, dass es in dem Beispiel zwei States gibt: state default, und state nearby. Beim "default"-State, der in allen Skripts vorhanden sein muss, wid das Schlüsselwort 'state' weggelassen (vermutlich damit man weniger schreiben muss).
In dem Skript wird geprüft, ob der Besitzer des Objekts anwesend ist, und wenn ja, wird mit dem Befehl 'state nearby;' sofort in den zweiten State gesprungen. Um das zu verdeutlichen, wird in dem State eine Nachricht im Chat ausgegeben.

LSL-Skripts sind case-sensitive, also eine Variable mit dem Namen meinSKRIPT ist verschieden von einer anderen Variable im selben Skript mit der Bezeichnung meinSkript.
Das gleiche gilt für Funktionsbezeichnungen und States.


Die hier blau gekennzeichneten Teile des Skripts sind Events, die rot gekennzeichneten sind LSL-Funktionen.
Events werden immer dann ausgeführt (teils automatisch), wenn gewisse Ereignisse in Second Life eintreten, z.B. wenn ein User an das Objekt anstößt, wird das collision_start() - Event aufgerufen, und der Code innerhalb dieses Event-Blocks ausgeführt.

LSL-Funktionen wie z.B. llSay() führen verschiedene spezielle Aktionen aus, in diesem Fall wird ein Text im Chat ausgegeben.

Events als auch Funktionen haben in ihrer Syntax gemeinsam, dass sie aus einem Funktionsnamen, und anschließenden Klammern (mit Parameter-Listen) bestehen:
llSay(PUBLIC_CHANNEL, "Owner ist anwesend!");
Rot ist der Funktionsname, und in den Klammern dahinter befinden sich die Parameter (oder auch 'Argumente').
Funktionen und Zuweisungen ( integer a = 3; ) müssen außerdem mit einem Semikolon ; beendet werden.

Dieses Beispiel llSay(PUBLIC_CHANNEL, "Owner ist anwesend!"); enthält als Parameter "PUBLIC_CHANNEL", und den Text der ausgegeben wird.
Public-Channel (oder auch dessen literaler Wert '0') ist der Code für den ganz normalen, öffentlichen Chat-Channel.

Dementsprechend gibt das Beispiel den Text "Owner ist anwesend!" im Chat aus.


Ereignisorientiert (Event-driven)
Event-Driven heißt, dass bestimmte Aktionen erst durch das automatische 'Triggern' von Events gestartet werden.
LSL enthält mehrere Events, z.B. enthält praktisch jedes Skript das state_entry() - Event, welches immer sofort dann ausgeführt wird, wenn das Skript (in-world) abgespeichert wird, und läuft.

So kann man mit dem collision-Event eine Meldung ausgeben, wenn ein Avatar das Prim in dem sich ein Skript befindet berührt (durch dagegen-laufen):

Zitat:

default
{
state_entry()
{
llSay(PUBLIC_CHANNEL, "Skript wurde gestartet!");
}

collision(integer n)
{
llSay(PUBLIC_CHANNEL, "Stups mich nicht!");
}
}


Gibt man dieses Skript nun in ein Prim in Second Life, dann wird das Objekt jedes Mal wenn ein Avatar dagegen rempelt, anfangen zu meckern:
Zitat:
[01:52] Object: Stups mich nicht!


Zur Erklärung: der orange-farben hervorgehobene Text in "collision(integer n)" ist der Standard-Parameter des Collision-Events, und überträgt jedes Mal wenn das Event angestoßen ('getriggert') wird, die Anzahl der Avatare und Objekte die gleichzeitig an das Objekt anstoßen.

Hello World

Bearbeitet vom Benutzer Montag, 29. September 2014 13:43:46(UTC)  | Grund: Nicht angegeben

It is the mark of an educated mind to be able to entertain a thought without accepting it.
Offline MartinRJ Fayray  
#2 Geschrieben : Montag, 8. September 2014 06:17:37(UTC)
MartinRJ Fayray

Rang: Ehrenmitglied

Ansehen:

Mitglied seit: 05.09.2014(UTC)
Beiträge: 90
Germany
Wohnort: Tulln und Rostock

Dankte: 6 mal(e)
Interface

Ganz kurz zum Interface (auch für diejenigen die überhaupt noch nie ein Skript gesehen haben):

Ich habe die wichtigsten Schritte auf dem folgenden Bild unten rot markiert - mit dem oben abgebildeten Beispielskript:

LSL Interface


  1. Wenn man ein neues geskriptetes Objekt erstellen möchte, klickt man zunächst auf die 'Bauen' Schaltfläche im Viewer (meist ganz unten im Viewerfenster, falls man sie nicht findet, kann man im Bauen-Menü auf 'Bauen' klicken, oder auch die Tastenkombination STRG+4 verwenden).
  2. Es öffnet sich das Bau-Fenster, und es sollte automatisch das 'Zauberstab'-Werkzeug zum Erstellen (rezzen) von Objekten ausgewählt sein. Damit klickt man dann auf den Boden, um ein neues Objekt zu rezzen.
  3. Dann klickt man - das neue Objekt sollte ausgewählt sein - auf 'Neues Skript' im Inhalts (Content)- Bereich des Baumenüs, um ein neues, leeres Skript zu erstellen.
  4. Mit einem Doppelklick öffnet man das Skript, und sieht das Skriptfenster.
  5. Im Skriptfenster wird der Text vom Skript eingetragen (es ist bei einem neuen, leeren Skript zuerst ein Beispielskript im Skripteditor-Fenster zu sehen, das 'Hello World'-Skript).
  6. Wenn man fertig programmiert hat, klickt man auf 'Speichern' (Save), und wenn keine Fehlermeldungen unten im Skripteditor-Fenster angezeigt werden, hat man alles richtig gemacht.

Die Running-Schaltfläche ganz unten im Skripteditor ist dazu da, um die Ausführung von Skripten anzuhalten. Wenn man den Haken abwählt, dann bleibt das Skript so lange inaktiv (ohne das Skript neu abspeichern zu müssen), bis der Haken wieder gesetzt wird.



Prozedural
Prozedural bedeutet, dass sämtlicher Programmcode stur von oben nach unten abgearbeitet wird, und jede Aktion genau in der Reihenfolge wie sie im Skript-Code steht ausgeführt wird.

LSL ist demnach eine Mischung aus prozeduralem, ereignisorientiertem und zustandsgesteuertem Programmierparadigma.




Bitte besucht die offizielle LSL-Wiki, wo man sämtliche Informationen zur Progammierung mit LSL findet:
https://wiki.secondlife.com/wiki/LSL_Portal/de


Man kann dort alle Grundlagen, Funktionen, Events usw. nachschlagen, und es gibt eine Suchfunktion.

Bearbeitet vom Benutzer Montag, 29. September 2014 13:45:01(UTC)  | Grund: Nicht angegeben

It is the mark of an educated mind to be able to entertain a thought without accepting it.
Offline MartinRJ Fayray  
#3 Geschrieben : Montag, 29. September 2014 13:44:44(UTC)
MartinRJ Fayray

Rang: Ehrenmitglied

Ansehen:

Mitglied seit: 05.09.2014(UTC)
Beiträge: 90
Germany
Wohnort: Tulln und Rostock

Dankte: 6 mal(e)
Programmierung - Schnelleinführung

Dieses Kapitel ist für Leute die noch nie programmiert haben. Jeder der zumindest grundlegende Kenntnisse hat, kann diesen Abschnitt getrost überspringen.


Ein Skript (oder "Programm") ist zuallererst eine für Menschen gut lesbare codierte Textdatei. Die Befehle, Schlüsselwörter und Funktionen die ich hier zeigen werde, werden nach dem Abspeichern von einem Computer in einen maschinenlesbaren Code umgewandelt (kompiliert), der am Ende nur aus einer sehr geringen Anzahl an Befehlen für den Prozessor besteht, zum Einlesen von Daten, der Kalkulation von Berechnungen, und der anschließenden Ausgabe (dann wird das vorige Ergebnis wieder eingelesen, damit weiter gerechnet, und daraufhin wieder auf ein Speichermedium ausgegeben, usw).

Für den Menschen interessant ist lediglich die Syntax sowie die Semantik der Programmiersprache die er verwendet, um Code zu entwickeln.

(Anmerkung: manchmal werden die Elemente einer Programmiersprache noch stärker aufgeschlüsselt in Lexikalik - gültige Zeichen und Worte, Syntax - gültige Zusammensetzung der Befehle aus Worten, Semantik - die Bedeutung der Kombinationen aus Worten und Zeichen, und Pragmatik - Einsatzbereich der Programmiersprache, siehe auch hier)



Gültige Worte und Zeichen von LSL

Operatoren:
LSL beinhaltet die meisten Operatoren der gängigen Programmiersprache "C". Operatoren sind größtenteils arithmetische und logische Befehlszeichen, wie * (Multiplikations-Operator), + (Additions-Operator), Klammern (), usw.

Die häufigsten Operatoren sind:
= (Zuweisung, z.B. Name = "Peter"),
+ (Addition, z.B. Ergebnis = 3+6),
- (Subtraktion, z.B. Ergebnis = 5-2),
* (Multiplikation, z.B. Produkt = 2*9),
/ (Division, z.B. Quotient = 4/2),
und Klammern () und [].

Ich habe eine ausführliche Liste der LSL-Operatoren aus der Englischen SL-Wiki übersetzt und hier zur Verfügung gestellt: https://wiki.secondlife.com/wiki/LSL_Operators/de


Typenbezeichnungen:
Jede Information die in einer sogenannten Variablen in einem Skript gespeichert wird, muss von einem der folgenden Typen sein:
integer (Ganzzahl)
float (Fließkommazahl)
string (Text)
key (UUID oder Text)
vector (3D-Vektor, die einzelnen Komponenten sind Fließkommazahlen)
rotation (Quaternion, die vier Komponenten sind jeweils Fließkommazahlen)
list (Liste aus einer oder mehreren Variablen beliebigen Typs)

Siehe auch: LSL Datentypen

Um eine Variable zu verwenden, muss man sie zunächst deklarieren.
Das darf man entweder innerhalb eines Event-Codeblocks, oder im globalen Gültigkeitsbereich (oberhalb von 'default'):

integer c;

Bei einer Variablendeklaration drückt man zuerst den Typ aus, und vergibt dann einen Namen. Danach schließt man die Deklaration mit einem Semikolon ab.
Man kann das noch erweitern, indem man der Variablen gleich einen Startwert zuweist (mit dem Gleichheitszeichen, gefolgt vom eigentlichen Wert):

integer c = 3;

Man beachte, dass die Namen von Variablen nicht mit einer Zahl beginnen dürfen, und nur Groß- und Kleinbuchstaben sowie Zahlen im Namen vorkommen dürfen, sowie ein paar ausgewählte Sonderzeichen, z.B. "_#\" (ASCII-Zeichen die ansonsten nicht in LSL verwendet werden).
Gültiger Variablenname: integer meine3te_Variable = 3;
Ungültiger Variablenname: float 3teVariable = 2.0;

Den Variablen von unterschiedlichen Typen dürfen ausschließlich entsprechende Werte zugewiesen werden.
Man kann einer Ganzzahl-Variablen (Integer-Variable) keinen Text zuweisen, und umgekehrt.

Dafür gibt es implizite und explizite Typkonvertierung.

float f = 3;
Es ist möglich, einer Variable vom Typ Float (Fließkommazahl) eine Ganzzahl zuzuweisen, da diese automatisch konvertiert wird (implizite Typkonvertierung).

Umgekehrt ist das nicht möglich:
Der Compiler meldet einen Fehler

Im Skriptfenster wird eine Fehlermeldung angezeigt, wenn man versucht das Skript zu speichern: "Type mismatch" (Deutsch: Unverträglichkeit der Typen).


Bei expliziter Typkonvertierung weist man den zu konvertierenden Wert einer Variablen zu, indem man davor in Klammern den gewünschten neuen Datentyp schreibt:

integer zaehler = (integer)4.2;

Bei dieser Form der Typkonvertierung (von Fließkommazahl zu Ganzzahl) wird einfach der Teil nach dem Dezimalpunkt verworfen.
Das funktioniert auch zum Beispiel für die Konvertierung von einem Text (Datentyp "string"):

integer zaehler = (integer)"5";


Funktionen:
Es gibt eine große Anzahl an LSL-Funktionen, die fast das gesamte Spektrum an Interaktions-Möglichkeiten mit der Welt in Second Life abdecken.
Eine komplette Liste findet man hier: LSL Funktionen, SL Wiki

Diese Funktionen, z.B. llSay(), haben immer einen Funktionsnamen der mit 'll' beginnt, danach die (oft leere) Parameterliste in Klammern, und nach dem Funktionsaufruf steht meistens ein Semikolon, um den aktuellen Befehl abzuschließen.

Es gibt auch User-Definierte Funktionen, die der Programmierer selbst definieren kann, doch dazu später.


Kontrollstrukturen
Die Bedingte Anweisung (Konditional), Schleifen und die Sprunganweisung sind die wesentlichen Konstrukte moderner Programmiersprachen.
Ohne sie kann man nur sehr bedingt oder überhaupt keine Programme schreiben.


Liste von Kontrollstrukturen

if {} else if {} else {}
for {;;}
do {} while ()
while() {}
default {}
state BEZEICHNUNG {}
state BEZEICHNUNG;
@BEZEICHNUNG;
jump BEZEICHNUNG;
return;

If-Abfrage (auch Konditional oder Bedingte Anweisung)
Die If-Abfrage dient dazu, anhand von Bedingungen eine Verzweigung im Programmcode umzusetzen.
So kann man als Beispiel den Text "morgen" ausgeben, wenn es noch vor 12 Uhr ist, und "abend" wenn es schon nach 17 Uhr ist:
Zitat:
integer stunde = 3;
if (stunde <= 12)
{
llSay(0, "morgen");
}
else if (stunde >= 17)
{
llSay(0, "abend");
}
else
{
llSay(0, "uhrzeit unbekannt");
}

Die Verzweigungen sind in entsprechende Codeblöcke aufgegliedert.

Mit if (stunde <= 12) wird der Wert der Variablen 'stunde', der zuvor auf 3 festgelegt wurde, mit dem literalen Wert 17 verglichen. (Anmerkung: 'literale' Werte sind direkt als Zahl oder Text in eine Berechnung oder Operation hineinprogrammiert, anstatt zuvor in einer Variablen gespeichert worden zu sein)
Wenn der Wert kleiner (oder gleich) ist, wird der direkt dahinter liegende Codeblock ausgeführt, andernfalls wird dieser Block übersprungen, und die nächste Bedingungs-Überprüfung ausgewertet:
else if (stunde >= 17).
Das kann man beliebig wiederholen, und falls alle Bedingungsprüfungen ergebnislos geblieben sind, kann optional noch ein 'else'-Block an die Bedingte Anweisung angehängt werden wie im Beispiel, deren Codeblock immer dann ausgeführt wird, wenn keine der vorigen Bedingungen zu WAHR (true) ausgewertet wurde.


Zu der genauen Funktionsweise von Bedingten Anweisungen siehe auch https://de.wikipedia.org/wiki/Be...nweisung_und_Verzweigung.
So viel sei gesagt: die Ausdrücke in Klammern sind immer Vergleiche von Texten, Zahlen, oder Boole'sche Algebra.


Syntax von LSL

Mit "Syntax" wird bei Programmiersprachen im Allgemeinen gemeint, wie man im Detail die Sprache benutzt, viele Programmiersprachen haben eine sehr ähnliche Semantik, und unterscheiden sich dennoch sehr deutlich in ihrer Syntax.

Das lässt sich an einem Beispiel verdeutlichen:
Zitat:

function add(a,b) return a+b end
add = function(a,b) return a+b end

Diese beiden Zeilen führen exakt den gleichen Vorgang aus, sie beschreiben eine Funktion, um zwei Zahlen miteinander zu addieren.
Dennoch unterscheidet sich die Syntax der beiden Zeilen deutlich, obwohl sie semantisch ident sind (sie haben die gleiche Bedeutung).


Ein LSL-Skript setzt sich aus einem oder mehreren States, Events, Funktionen, User-definierten Funktionen ('UDF'), Bedingten Anweisungen, Schleifen, Operatoren und Variablen bestimmter Typen zusammen, und wird immer in unterschiedliche Gültigkeitsbereiche aufgeteilt - markiert durch geschweifte Klammern { }.
All diese Begriffe werde ich jetzt kurz und knapp vorstellen:

States (Deutsch: 'Zustand') definieren das Grundgerüst eines jeden Skripts, sie sind sozusagen ein eigenständiges Skript, das sich mit anderen States innerhalb derselben Skriptdatei globale Ressourcen teilen kann. Wobei es aber zu jedem gegebenen Zeitpunkt nur genau einen aktiven State geben kann.
Diese States werden erzeugt durch das Schlüsselwort 'state' und einem darauffolgenden Namen. Der default-State, den jedes Skript enthalten muss, ist eine Ausnahme. Hier wird das Schlüsselwort 'state' einfach weggelassen.

Nach dem Schlüsselwort und der Bezeichnung folgen geschweifte Klammern, die den Gültigkeitsbereich definieren, in dem sich Events erstellen lassen: "state test { }".
Auf dieselbe Weise wie man einen State definiert wird er auch aufgerufen: "state test;"


Events sind Einstiegsstellen in das Skript, deren Code vollautomatisch angestoßen - also ausgeführt - wird, wenn ein bestimmtes Ereignis eintritt, das kann das Verstreichen von einer vorgegebenen Zeit sein, oder ein Avatar der etwas im Chat sagt. Tritt diese Bedingung ein, dann wird das Event ausgeführt.

An dieser Stelle ist es wichtig anzumerken, dass LSL-Skripts immer nur eine Aktion zur gleichen Zeit ausführen können. Während der Code, der durch ein Event angestoßen wurde aktiv ist und läuft (etwa sehr lange Berechnungen), kann kein weiteres Event gestartet werden. Wenn ein weiteres Event ansteht, muss es in einem 'Queue' (Warteschlange) warten, bis die vorigen Events fertig gerechnet haben. Wenn der Queue bereits mehr als 64-Event-Aufrufe enthält, dann werden weitere Aufrufe still verworfen, bis wieder ein Platz im Event-Queue frei ist.

Das state_entry()- Event
Es wird gebildet durch das Schlüsselwort state_entry, runden Klammern und danach dem Gültigkeitsbereich (geschweifte Klamern), in dem sich der Code für das Event befindet.
Das State-Entry- Event eines States wird immer sofort aufgerufen wenn dieser State beginnt, und da jedes Skript als Einstiegspunkt das default-Event hat,
wird das State-Entry-Event des "State Default" immer beim Abspeichern eines Skripts sofort ausgeführt
(vorausgesetzt das Skript läuft in-world, und die Ausführung von Skripts ist im Simulator nicht global deaktiviert).

Zitat:
default
{
state_entry()
{
float Sekunden = 10.0;
llSetTimerEvent(Sekunden);
}

timer()
{
llSay(PUBLIC_CHANNEL, "Timer abgelaufen und getriggert!");
}
}


Dieser Beispielcode erzeugt im State-Entry- Event des Default-States einen 'Timer'. Dieser Timer ist eine Art Stoppuhr, und sorgt dafür dass nach einer vorgegebenen Zeit (10 Sekunden in diesem Fall) ein Timer-Event vollautomatisch aufgerufen wird.
Im Timer-Event (gebildet durch das Schlüsselwort 'timer', darauffolgenden Klammern, und dem Gültigkeitsbereich - dargestellt durch geschweifte Klammern) wird schließlich mithilfe der llSay-Funktion eine Nachricht im Chat ausgegeben.

Ohne Events gibt es keine LSL-Skripts, da man innerhalb der Gültigkeitsbereiche von States ausschließlich Events definieren darf.



(tbc)
Schlüsselwörter: Aufbau eines LSL-Skripts, Einstiegspunkt, Syntax, Schlüsselwörter, Befehle, Variablen, Bedingungen, Zuweisungen, Scope, Funktionen, Datentypen key/list/rotation/vector/string, User-Definierte Funktionen, Kontrollstrukturen
It is the mark of an educated mind to be able to entertain a thought without accepting it.
Rss Feed  Atom Feed
Benutzer, die gerade dieses Thema lesen
OceanSpiders 2.0
Das Forum wechseln  
Du kannst keine neue Themen in diesem Forum eröffnen.
Du kannst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge nicht löschen.
Du darfst deine Beiträge nicht editieren.
Du kannst keine Umfragen in diesem Forum erstellen.
Du kannst nicht an Umfragen teilnehmen.

Powered by YAF.NET | YAF.NET © 2003-2017, Yet Another Forum.NET
Diese Seite wurde in 0.980 Sekunden generiert.

Datenschutzrichtlinie
Haftungsausschluss
Impressum
Datenschutzerklärung
AGB, ToS
Kontakt