Autor: | Timo Stark (aka Triple-X, Hawkgames) |
In Zusammenarbeit mit: | Robert Andreas Ternes (Design ©2004 Pharao-Software) |
Datum: | 01.05.2004 |
Letzte Aktualisierung: | 07.05.2004 |
Download: | cscript_tut.zip |
Tipp: Durch Klicken auf einen Kapitelunterpunkt gelangen Sie sofort zur gewünschten Stelle. Über die Pfeilbuttons gelangen Sie wieder an den Anfang dieses Tutorials.
Als aller erstes sollten sie sich einen guten Scripteditor
besorgen. Für Nutzer der A6 empfehle ich SED (im 3D Gamestudio Ordner).
Für Benutzer von A5 gibt es sehr viele verschiedene Script Editoren, wie GST Builder oder Wdledit. Am besten
einmal auf der Downloadseite von 3D Gamestudio (http://www.3dgamestudio.de)
suchen.
TripleX
In diesem Tutorial wollen wir mit
Kommentaren anfangen. Kommentare kommentieren, wie der Name schon sagt, ihr
Script. Wenn Sie ihre ersten schwierigeren Scripte schreiben werden Sie
irgendwann feststellen, dass Sie ihre eigenen Scripte nicht mehr kapieren, wenn
Sie sie nicht ausreichend kommentieren.
Kommentare haben keinerlei Auswirkung auf ihr Script. Sie sind
ausschließlich dazu da, dass Sie und andere Leute in ihrem Team ihr Script
verstehen.
Es gibt 2 Arten von Kommentaren:
//Alles was hinter diesen zwei
Backslashs steht wird ignoriert |
An dieser Stelle empfehle ich, Kommentare wirklich in schwierigeren Scripten zu benutzen.
Variablen sind ein sehr wichtiges
Thema in der Spieleentwicklung und in fast jeder anderen Scriptsprache. Variablen
sind Platzhalter für Zahlen. Das heißt, dass Sie nichts weiter machen als Zahlen
zu ersetzen.
Das hat folgende Vorteile:
Eine Variable kann fast jeden Namen haben den SIE wollen. Dies ergibt eine wesentlich bessere Lesbarkeit und Verständlichkeit des Scriptes.
Nehmen wir an Sie haben ein Waffensystem mit 20 Waffen, bei dem jede Waffe bei jedem Schuss um 1 Grad erhitzt. Nun stellen Sie sich vor Sie wollen 1 Grad durch 1.5 Grad ersetzen. Jetzt müssen Sie, wenn Sie Zahlen statt Variablen genommen haben 20 Zahlen von 1 auf 1.5 verändern. Wenn Sie eine Variable nehmen ändern Sie einfach den Wert bei der Variabelendefinition.
Variablen definiert man folgendermaßen:
var name = wert; |
Eine Variabelendefinition beginnt
immer mit den Stichwort „var“. Danach kommt der Name für die Variable. Über
diesen Namen kann man die Variablen verändern und benutzen. „Name“ kann
irgendein Name deiner Wahl sein. Als letztes wird der Variable noch über den
Zuweisungsoperator = den Wert deiner Wahl zugewiesen.
Sie können übrigens eine Variable auch ohne Zuweisung definieren. In diesem Fall
hat die Variable den Wert 0.
var name; |
Ganz am Ende kommt noch ein
Semikolon. Semikolons müssen an das Ende jeder Anweisung gesetzt werden, damit
die Engine weiß, dass der Befehl zu Ende ist.
Wenn man einen Semikolon vergisst kommt es häufig zu Folgefehlern, was zur Folge
hat, dass die Engine Ihnen 1000 von Fehlern ausspuckt obwohl Sie nur 1 Fehler
gemacht haben.
Nachdem wir im letzten Kapitel gelernt haben Variablen zu initialisieren, müssen wir jetzt auch noch lernen wie man mit ihnen rechnet. In C-Script kann man unter anderem die 4 Grundrechenarten Operatoren + (plus), - (minus), / (geteilt), * (mal), als mathematische Funktionen benutzen. Hier ein paar einfache Code Beispiele:
Var a = 5; |
Die Kommentare sollten das meiste erklären. Wichtig ist noch, dass diese Zeilen...
a+=b; |
...vollkommen das gleiche bedeutet wie folgende Zeilen:
a = a + b; |
Solche Abkürzungen sieht man in Programmiersprachen häufig (Programmierer sind ziemlich faul).
Im oberen Kapitel haben Sie sie ja
schon eine "Main Function" gesehen. Als erstes stellen wir uns die Frage: Was
ist überhaupt eine Funktion?
Eine Funktion ist eine Reihe von Anweisungen die nacheinander ausgeführt werden.
Eine Funktion wird folgendermaßen definiert:
Function Name() |
Alle Anweisungen von der Funktion
stehen zwischen den beiden Klammern ( { und } ). Diese Klammern macht man mit
der Tastenkombination ALT GR+ 7 bzw. ALT GR + 0.
Nun ist die Function Main aber eine besondere Funktion. Dies ist die Funktion
die als erstes ausgeführt wird. Das ist der Grund, warum in der Function Main
häufig z.B. das Level geladen wird.
Funktionen werden nicht automatisch ausgeführt, sondern müssen erst aufgerufen
werden. Sie tun dies mit "Funktionsname();". Die main Funktion bildet hierbei eine
Ausnahme. Diese Funktion wird beim Start der Engine aufgerufen. Nun ein Beispiel wie Sie eine Funktion aufrufen können.
Var function_test; |
In diesem Fall wird beim starten
der main Funktion die Funktion my_function() aufgerufen. Durch diesen Aufruf
springt die Engine zu dieser Funktion und führt alle Anweisung in ihr aus.
Danach fährt sie mit der alten Funktion fort.
Sie müssen my_function VOR der main Funktion schreiben, damit der Compiler die
Funktion bereits kennt wenn sie aufgerufen wird.
Nur was ist, wenn Sie nicht alles über eine Funktion schreiben wollen, oder sich
zwei verschiedene Funktionen gegenseitig aufrufen?
Das kommt in den nächsten Kapiteln!
Um eine Funktion in z.B. der Main Funktion nutzen zu können, wenn Sie die Funktion erst unter der Main Funktion schreiben müssen Sie nur am Beginn ihres Programms die Funktionsdefinition schreiben. Das Funktioniert folgendermaßen:
Function my_function;
//Definierung der Funktion |
Nun kennt der Compiler die Funktion my_function schon bevor er Sie aufruft. Deshalb gibt es keine Probleme.
Ja ich weiß auch, dass Sie jetzt
wahrscheinlich dieses Thema überspringen wollen. Was will man schon mit der
mathematischen Funktion Modulo!? Trotzdem will ich Modulo kurz hier zur
Vollständigkeit erklären.
Modulo ist der Rest einer Division. Hört sich als erstes kompliziert an ist aber
ganz einfach. Das Zeichen für die mathematische Funktion Modulo ist % (wird
genauso angewendet wie plus, minus usw.).
Ein paar Beispiele zum Verständnis:
Var a; //Bei einer
solchen Definierung von Variablen bekommen die |
Dieses Codebeispiel sollte alles erklären.
Bei einem Array handelt es sich um
einen Verbund von mehreren Variablen.
Eine Erklärung an einen konkreten Beispiel:
Sie möchten ein Waffensystem mit 10 unterschiedlichen Waffen schreiben, die alle
einen unterschiedlichen Schaden haben. Hier gibt es nun 2 Möglichkeiten.
Entweder schreiben Sie 10 verschiedene Variablen(
Var schaden_waffe1;
Var schaden_waffe2;
//usw.
)
oder Sie benutzen einen Array, den Sie wie folgt definieren:
var name[n]; |
Name ist wie immer ein Name den Sie sich selber auswählen können. Nun kommt eine rechteckige Klammer mit einer ZAHL drinnen (n soll irgendeine Zahl repräsentatieren). Diese Zahl gibt die Anzahl an Variablen an, die in den Verbund sind. Sie können den einzelnen Variablen in den Array natürlich auch bei der Definierung einen Wert geben. Das funktioniert folgendermaßen:
Var erster_array[4] = 20,24,17,20; |
Jetzt hat die erste Variable in
erster_array den Wert 20, die zweite den Wert 24, die dritte den Wert 17 und die
vierte den Wert 20.
Man kann jetzt folgendermaßen auf die Arraywerte zugreifen:
Erster_array[0]=10; |
Dies verändert den ersten Wert des Arrays auf 10. ACHTUNG: Der erste Wert wird mit [0] aufgerufen, der zweite mit [1] usw. der letzte mit [n(in der Definition geschrieben) – 1]. Wenn Sie die Arraygrenzen überschreiten wird ihnen die Engine sofort einen Fehler ausspucken. Ein typischer Fehler:
Var new_array[3]; |
Nun wollen wir mal einen Array auf das Beispiel oben mit den Waffensystem anwenden (Es sei noch mal erwähnt, dass man auch einfache Zahlen anstatt Arrays nehmen könnte. Warum das nicht zu empfehlen ist sehen Sie bei der Variabelendefinition):
Var waffe_schaden[10]; |
Ein Vektor ist ein Array mit 3 Variablen. Ein Vektor kann für folgende Dinge stehen:
Raumkoordinaten (x,y,z)
Drehwinkel
Farben (Rot, Grün, Blau)
Wenn man mit Vektoren Raumkoordinaten anspricht geht man wie folgt vor:
Var first_vektor[3];
//Vektor wird definiert |
Nun liegt, in diesem Fall, der
First_vektor Vektor auf den Raumkoordinaten {10,20,0}.
Man kann genauso mit einen Vektor die drei Eulerwinkel (Pan,Tilt,Roll) und die 3
Farben red,green,blue mit einen Vektor ansprechen.
Es gibt nun noch eine Reihe von Vektor Anweisungen wobei ich hier nur die
wichtigsten erwähnen möchte:
Vec_set übertrage alle Werte eines
Vektors auf einen anderen Vektor.
Die Syntax von vec_set:
Vec_set(vec1,vec2); |
Vektor1 hat nun den gleichen Inhalt
wie Vektor2. Wenn Vec1 schon in vorhinein Werte beinhaltete werden die
überschrieben.
Ein Beispiel:
Var vektor_1[3] = 5,2,1; |
Vec_add addiert vektor1 und
vektor2. Das Ergebnis wird in Vektor1 geschrieben.
Beispiel:
Var vektor_1[3] = 5,2,1; |
Vec_sub zieht Vektor2 von Vektor1
ab. Das Ergebnis wird in Vektor1 geschrieben.
Wie immer ein Beispiel:
Var vektor_1[3] = 5,2,1; |
Lokale Variablen sind eine
spezielle Form von Variablen. Lokale Variablen werden innerhalb von Funktionen
definiert und sind auch nur in dieser einen Funktion gültig.
Programmbeispiel:
Function main() |
Die Variablen A und B sind jetzt nur in der Funktion main gültig. Folgenden Fehler unbedingt vermeiden:
Function addiere() |
Dies würde eine Fehlermeldung hervorrufen da a und b in der Funktion addiere nicht gültig sind.
Schnell kommt man in Programmen an die Stelle wo man gerne zwei Werte mit einander vergleichen will. Dafür gibt es die If Unterscheidung. Die korrekte Syntax von if ist:
If(Bedingungen) |
In Worten ausgedrückt:
Wenn die Bedingung in der Klammer wahr ist, werden die Anweisungen in den geschweiften
Klammern ausgeführt. Wenn nicht dann springt die Funktion bis zum Ende der
Klammer.
In der Bedingung werden immer 2 Werte mit einander verglichen. Dazu gibt es
jetzt verschiedene Operatoren:
Wert1 == Wert2
//Bedingung ist wahr wenn beide werte gleich sind // Bedingung ist
wahr wenn Wert1 ungleich Wert2 ist |
Um das ganze noch mal an einen ganz konkreten Beispiel zu zeigen:
Function main() |
Es gibt auch noch die Möglichkeit
verschiedene if Bedingungen zu verknüpfen. Und zwar mit dem UND und den ODER
Operator.
Wenn Sie z.B. wollen, dass der If Block ausgeführt wird wenn wert1 > 2 ist aber
wert 1 auch kleiner als 10 ist müssen Sie das wie folgt schreiben:
If(wert1 < 10) && (wert1 > 2) {
//tue das.. |
Auf Deutsch: Wenn Wert1 kleiner als
10 ist UND wert1 größer als 2 ist führe die Anweisung aus.
Die Oder Anweisung sieht so aus:
If(wert1 < 10) || ( wert1 > 2) {
//tue das... |
Wenn Wert1 kleiner als 10 ist ODER
wert1 größer als 2 ist führe die Anweisung aus.
Diese Verknüpfung kann man mit so vielen Werten gleichzeitig machen wie man
will.
Dies sollte die If Bedingungen hinreichend erklären.
Nun kommen wir zu den Else Bedingungen:
Die Else Bedingung wird ausgeführt wenn die If Bedingung falsch ist.
If(wert1 == 6) |
In Worten:
Wenn 5 gleich 6 ist, führe die Anweisungen in den IF Klammern aus, wenn 5 nicht
gleich 6 ist führe die else Bedingung aus.
Eine Schleife ist eigentlich vom
Syntax ähnlich wie der von der If Bedingung. Eine Schleife wiederholt nur die
Anweisungen in den geschweiften Klammern so lange bist die Bedingung wahr ist.
Die If hingegen Anweisung überprüft die Bedingung einmal, führt vielleicht die
Anweisung aus, und fährt dann einfach im Script fort.
Die Syntax einer Schleife:
While(Bedingung) |
In Worten:
Solange die Bedingung wahr ist führe die Anweisungen in den Klammern aus.
Ich will ihnen jetzt einmal ein Skriptbeispiel geben:
Function main() |
Am ende dieses Skripts ist a und b
99!
Bei Schleifen kommt manchmal die Fehlermeldung „possible endless loop“. Das
bedeutet, dass die Schleife öfter als 5000 mal ausgeführt wurde ohne das die
Bedingung wahr wurde.
Der Wait und der Sleep Befehl
halten die Funktion die grade ausgeführt wird um eine bestimmte Zeit auf. Die
Syntax von Sleep bzw. Wait:
Wait(Zahl);
Sleep(Zahl);
Wait(1); hält eine Funktion um eine Frame an.
Sleep(2); hält eine Funktion um genau 2 Sekunden an. Das heißt bei sleep wird
die Zahl nicht in Frames sondern in Sekunden angegeben.
Wait kann man auch perfekt bei Schleifen benutzen.
Stellen Sie sich vor, Sie wollen eine Schleife endlos durchführen. Das ist zum
Beispiel bei der Bewegung des Spielers der Fall. In diesem Fall setzt man an das
Ende der Schleife ein Wait(1);
Hiermit pausiert die Engine diese Funktion einen Frame und führt sie danach
wieder aus. Wenn Sie das Wait(1); weglassen würde die Engine die Funktion immer
und immer wieder ausführen ohne eine Unterbrechung.
Im folgenden Beispiel wollen wir einen kleinen Counter erstellen der jede
Sekunde eine Variable um 1 senkt.
Var counter; |
Hier müssen Sie noch beachten, dass
wenn hinter dem Funktionsaufruf von counter_start(); weiterer Code kommen würde,
der weiterhin ausgeführt worden wäre. Das liegt daran das die Engine mehrere
Funktionen gleichzeitig ausführen kann!
Durch die Kommentare sollten Sie den Code verstanden haben.
Starter sind Funktionen die bei dem
Programmstart aufgerufen werden. Sie müssen nicht durch die main() Funktion
aufgerufen werden.
Ein Beispiel:
Starter starter_beispiel |
Actions sind Funktionen mit der
Besonderheit, dass man eine Action einer Entität in WED zuweisen kann.
Beispiel:
Action player_action |
Manchmal wollen Sie Funktionen beim
Aufruf bestimmte Werte überliefern. Die kann man über Parameter machen. Man kann
bei einer Funktion maximal 4 Parameter überliefern.
Die Syntax:
Function
paramterter_test(paramter1,parameter2,paramter3,paramter4) |
Auf diese Parameter kann man dann in dieser Funktion, genauso wie bei lokalen Variablen, zugreifen. Die Werte der Parameter entsprechen denen bei dem Programmaufruf.
Function addiere(zahl1,zahl2) |
In der oberen Funktion finden Sie
jetzt ein Parameter das Sie noch nicht kennen und zwar return. Return liefert
einen Wert zurück. Nach return wird die Funktion sofort beendet. Wenn Sie also
noch nach der return Anweisung, Codes schreiben ist das der engine egal, weil
Sie die Funktion gar nicht mehr ausführt. Sie müssen übrigens gar keinen Wert
zurückliefern. Wenn Sie einfach nur wollen das die Funktion beendet wird müssen
Sie nur
Return;
schreiben!
Sie können bei
a=addiere(10,15);
jeden beliebigen wert eingeben, auch Variablen. A beinhaltet nach der Berechnung
immer Zahl1+Zahl2.
Jetzt wollen wir lernen wie man
Dateien definiert und welche Dateien 3D Gamestudio nutzen kann.
Dateien die 3D Gamestudio nutzen kann:
Bitmap Dateien ( *.bmp, *.pcx, *.tga)
Sound Dateien (*.wav, *.mid - folgende Dateitypen gehen nur ab der Commercial Edition: *.mp3,*.wma)
Video Dateien (*.avi, *.mpeg, *.jpg, *.png - Videos kann man nur ab der Commercial Edition abspielen)
Scriptdateien (*.wdl)
Levels (*.wmp für die Map editor file, *.wmb die beim Builden erstellte Datei. Die *.wmb Datei wird von Scripten geladen)
Dll Dateien (*.dll)
Die Dateien werden folgendermaßen
definiert:
Typ name = <Dateiname.Dateiart>;
Dies nun an zwei Beispielen:
Bitmap Dateien:
Bmap name <Dateiname.Dateiart>;
Der Dateiname steht in einer spitzen Klammer, dann kommt ein Punkt, dann die
Dateiart (pcx,tga,bmp).
Sound Dateien
Sound name <Dateiname.Dateiart>;
Die restlichen Dateiarten muss man nicht definieren, da man den Dateinamen
direkt beim aufrufen in den Befehl eingibt.
Ein Panel kann viele nützliche Dinge tun. So kann man mit einen Panel Zahlenwerte und Bitmaps auf einem Bildschirm darstellen.
Ein Panel baut sich anders auf als zum Beispiel eine Funktion. Der Grundaufbau ist wie folgt:
Panel name |
Name sollte nun klar sein (wenn nicht nach oben blättern), nur was ist jetzt der Inhalt eines Panels. Nun zum einen kann man natürlich die Position des Panels einstellen. Das geht wir folgt.
Panel name |
Pos_X bzw. Y sind die Positionen
auf den Bildschirm und werden in Pixeln angegeben. Ganz oben links in der Ecke
ist sowohl Pos_x als auch Pos_y 0! Wenn man weiter nach rechts geht erhöht sich
Pos_x, wenn man weiter nach unten geht erhöht sich Pos_Y. Die Grenzwerte sind
jeweils:
Pos_x Grenzwerte: 0......Bildschirmauflösung X (in Pixeln. Also z.B. 1024 bei
einer Auflösung von 1024*768)
Pos_y Grenzwerte: 0.....Bildschirmauflösung Y (natürlich auch in Pixeln).
Nun soll ja das Panel auf irgendetwas darstellen.
Am Anfang wollen wir uns mit einen einfachen schwarzen Bitmap zufrieden Stellen.
Erstellen Sie einen Ordner „Tutorial“.
Öffnen Sie ein Malprogramm und malen Sie ein schwarzes Bild mit der Dateigröße
1024*768. Speichern Sie das Bild in den Ordner Tutorial mit den Namen „Bild“ als
PCX Datei ab.
Nun wollen wir unser erstes Script schreiben, dass man ohne Templates Starten
kann.
Dazu erstellen Sie ein neues Level, erstellen einfach einen Medium Cube in ihm,
builden das Level und speichern es als „tut_level.wmb“ in den oben erstellten
Tutorial ab.
Jetzt öffnen Sie ihren persönlichen Script Editor und schreiben folgendes Script
in ihren Script Editor:
Var video_mode=8;
//Setzte Video_mode auf 8. Erklärung unten |
Hier sind jede Menge neuer Befehle
drinnen. Deshalb will ich einmal den Code Schritt für Schritt durchgehen.
Var video_mode=8;
Video_Mode ist eine Engine Variable. Diese Variable setzt die Auflösung. Hier
alle Auflösungen:
320x240
320x240 (Defaultmodus für Flythrough)
320x400 (wird von einigen Adaptern nicht unterstützt)
400x300 (wird von einigen Adaptern nicht unterstützt)
512x384 (läuft nicht auf einigen Laptops)
640x480
800x600
1024x768 Ab Extra
1280x960 Ab Commerziell
1400x1050 Ab Professionell
1600x1200
Var video_depth=16;
Video_Depth ist genau wie Video_Mode eine vordefinierte Enginevariable.
Video_Depth setzt die Farbtiefe. Diese Variable kann entweder den Wert 16 (16
Bit Farbtiefe) oder 32 (32 Bit Farbtiefe) haben.
Panel bild_pan |
Als erstes wird hier das Panel
bild_pan definiert. Danach wird sowohl die X als auch die Y Position auf 0
gesetzt. Ganz am Ende wird dem Panel noch das Hintergrundsbild schwarz_bmap
gegeben, was wir vorher definiert haben.
bild_pan.visible=on;
Diese Zeile macht das oben definierte Panel sichtbar.
Load_level(“tut_level.wmb“);
Dieser Befehl lädt ein Level. Hier mit den Namen tut_level.wmb! Eine genauere
Beschreibung folgt später noch. Erst mal müssen Sie nur wissen was dieser Befehl
macht.
Jetzt schreiben Sie den Code oben doch mal in ihre Scriptdatei und speichern Sie
die Scriptdatei als „bild.wdl“. Nun öffnen Sie wieder ihr kleines Level und
drücken Sie auf ->file ->map properties ->Load Script › laden Sie ihr Script
Drücken Sie jetzt RUN und siehe da. Das Bild wird auf den Bildschirm ausgegeben.
Nun ein Panel kann noch viel mehr als ein Hintergrundbild darstellen. Es kann
unter anderem:
Variablen darstellen
Buttons darstellen, die eine Funktion ausführen wenn man auf Sie klickt
Slider darstellen (Eine Schiebefläche in der man eine Box von links nach rechts bzw. von oben nach unten bewegt um eine Variable zu verändern.)
Außerdem gibt es noch eine Menge Eigenschaften für Panels
Eine Variable kann man über den
Befehl digits (wörtlich übersetzt „Zahl, Ziffer“) darstellen. Die Syntax von
digits ist relativ lang. Hier der komplette Syntax plus Erklärung:
Digits = pos_x,pos_y,Anzahl der Stellen, Font, Faktor, dargestellte Variable;
Pos_x = Die X Position der Zahl relativ zur X Position des Panels
Pos_y = Die Y Position der Zahl relativ zur Y Position des Panels
Anzahl der Stellen = Anzahl der Stellen die dargestellt werden (wenn dieser Wert
2 ist, aber
Die dargestellte Zahl 999 ist, ist die Dargestellte zahl 99 ( da eben nur 2
Ziffern dargestellt werden))
Font = Font mit dem die Zahl dargestellt wird
Faktor = mit diesen Faktor wird die Zahl bei anzeige multipliziert
(normalerweise 1)
Dargestellte Variable = Die Variable die dargestellt wird.
Nun wollen wir einmal zusätzlich zu den Hintergrundsbild von oben noch den
Counter mit grafischer Darstellung programmieren.
Var video_mode=8;
//Setzte Video_mode auf 8. Erklärung oben |
Die einzigst unbekannte Zeile ist:
Font arial_font = “Arial”,0,20;
Diese Zeile definiert den True Type font Arial mit Schriftgröße 20 Pixel.
Die 0 bedeutet das der Font normal ist. 1 wäre fett, 2 kursiv, 3 ist kursiv und
fett.
Damit diese Zeile funktioniert müssen Sie mindestens A5.52 haben! In Versionen unter A5.52 sind True Type fonts nicht möglich
Hier müssen Sie *.pcx Fonts nehmen.
Nun haben wir einen laufenden Counter.
Nun schauen wir uns auch wie bei
digits erst einmal den Syntax an.
Button = pos_x,pos_y,Button
Grafik1,Grafik2,Grafik3,Funktion1,Funktion2,Funktion3;
Hier sind jetzt jede Menge komische Sachen (wozu braucht man 3 Grafiken und 3
Funktionen?).
Deshalb schauen wir uns jetzt einmal alles an.
Pos_x = Die X Position der Zahl relativ zur X Position des Panels
Pos_y = Die Y Position der Zahl relativ zur Y Position des Panels
Button Grafik1 = Diese Grafik wird dargestellt, wenn die Maus über den Button
ist und
Geklickt wird.
Button Grafik2 = Diese Grafik wird dargestellt wenn die Maus NICHT über dem
Button ist.
Button Grafik3 = Diese Grafik wird dargestellt wenn die Maus ÜBER dem Button
ist.
Funktion1 = Diese Funktion wird aufgerufen wenn auf den Button geklickt wird
Funktion2 = Diese Funktion wird aufgerufen wenn die Maus den Button verlässt.
Funktion3 = Diese Funktion wird aufgerufen wenn die Maus den Button berührt
Ein Beispiel für einen Button:
Bmap button_bmp = <button.pcx>; |
Sie sollte alles verstehen außer
vielleicht die letzten beiden Funktionen. Hier steht: Null,null.
Das bedeutet das der Button keine Funktion ausführt wenn die Maus den Button
berührt oder verlässt.
Ein Slider ist nichts anderes als
ein Schieberegler der zur Eingabe von Variablen mit der Maus bewegt werden kann.
Es gibt zwei Arten von Slider. Den senkrechten und den Wagrechten. Sie haben
aber eigentlich beide den gleichen Syntax:
Hslider = pos_x,pos_y,Breite des Schiebereglers in
Pixeln,Reglerknopfbitmap,min,max,var;
Vslider = pos_x,pos_y,Höhe des Schiebereglers in
Pixeln,Reglerknopfbitmap,min,max,var;
Hslider = horizontaler Slider
Vslider = vertikaler Slider.
Wie immer eine Erklärung aller Punkte:
Pos_x = Die X Position der Zahl relativ zur X Position des Panels
Pos_y = Die Y Position der Zahl relativ zur Y Position des Panels
Breite/Höhe des Reglers = Die Höhe oder Breite des Schiebereglers in Pixeln
Reglerknopfbitmap = Das Bitmap des Knopfes zum ziehen des Sliders mit der Maus.
Min = Minimaler Wert der Variable
Max = maximaler Wert der Variable
Var = benutze Variable
Ein kleines Beispiel:
Bmap slider_bmp = <slider.pcx>;
//Breite des Sliders = 220 Pixel |
Es gibt auch noch eine Reihe von
FLAGS (Schalter). Dies sind bestimmte Einstellungen, mit denen man einstellen
kann ob das Panel z.B. von Anfang an sichtbar ist.
Die Syntax solcher Flags:
Flags=einstellung1,einstellung2;
Es gibt viele solcher Einstellungen, die man einfach per „ , “ aneinander hängt.
Hier alle Einstellungen:
Visible = Nur wenn dieses Flag gesetzt ist, erscheint das Panel von Anfang an
auf dem Bildschirm (man muss es nicht in einer Funktion sichtbar machen.
Overlay = Ist dieses Flag gesetzt, wird die Farbe 0 (schwarz) der Panel-BMAP
nicht gezeichnet.
Transparent= Ist dieses Flag gesetzt, so werden der Hintergrund des Panel und
die Buttons halb durchsichtig über dem Bild angezeigt.
Nun stellen Sie sich einfach mal
vor Sie wollen 2 verschiedene Panels übereinander legen. Nun wollen Sie
natürlich bestimmen welches Panel über den anderen liegt. Das geht mit den layer
befehl. Syntax =
Layer = wert;
Einfach oder? Desto höhere die ebene ist, desto höher ist die ebene eines
Panels.
Z.B. ein Panel mit den Layer Wert 5 liegt über einem Panel mit Layer Wert 2!
Manchmal will man auch Texte darstellen. Dazu müssen Sie als erstes wissen wie man einen String definiert.
Ein String ist eine Reihe von Zeichen. Das heißt, ein String speichert keine Werte sondern Zeichen. Strings definiert man ähnlich wie Variablen:
String new_string = “Hallo! Wie geht es
dir”; |
Zeilenumbrüche in Strings erreicht mit einem „\n“. Ein Beispiel:
String new_string = “Hallo!\nWie geht es
dir?”; //wenn man diesen String ausgibt kommt
folgendes heraus: |
Man kann strings auch noch auf zwei
weitere Arten definieren:
String new_string; //Ein string ohne Inhalt.
String new_string[50]; //Ein string mit 50 Leerzeichen
Noch eine wichtige Sache:
Strings können nicht einfach mit den = Operator gesetzt werden. Darüber aber
später mehr.
Mit Texten ist man nun in der Lage
diese Strings auf den Bildschirm zu bringen.
Die Syntax eines Textes:
Text name |
Texte bauen sich ähnlich auf wie
Panels.
Deshalb sollte auch folgendes Codebeispiel nicht so viel neues bringen:
String first_string = “Hallo”;
//definiere einen String |
Hier sehen Sie jetzt einen
einfachen Text. Das meiste sollte sehr verständlich sein (durch die Kommentare).
Es gibt allerdings ein paar neue flags die ich hier jetzt einmal erläutern
werde:
center_x = Das setzen dieses Flags bewirkt, das der Text horizontal auf pos_x
zentriert wird. Ist das Flag nicht gesetzt, wird der Text linksbündig
ausgerichtet
center_y = Das setzen dieses Flags bewirkt, das der Text vertikal auf pos_y
zentriert wird. Ist das Flag nicht gesetzt, wird der Text nach oben ausgerichtet
condensed = Das Setzen dieses Flag bedingt, dass der Text horizontal um 1 Pixel
pro Zeichen ‘gestaucht’ wird. Insbesondere Kursivfonts sehen so besser aus
narrow = Wie CONDENSED, nur wird der Text noch weiter gestaucht
transparent = Ist dieses Flag gesetzt, so wird der Text halb durchsichtig
angezeigt.
Visible = Der Text ist von Anfang an sichtbar
Shadow = schreibt True-Type Font Text mit schwarzem Schatten
Outline = schreibt True-Type Font Text mit schwarzem Rand um die Zeichen
Die einzelnen Flags werden per „ , “ aneinandergehängt.
Sie können ja mal mit den Text dort oben ein bisschen rumspielen und in unserem
Tutorialscript einsetzten.
Das wichtigste an diesem Tutorial
ist eigentlich das Sie das Handbuch bedienen können. Wenn Sie das können
brauchen Sie keine Tutorials mehr.
Das aktuellste Handbuch bekommen Sie hier:
http://www.3dgs.org/3DGS_Manual.chm
Das Handbuch stammt von Tobias Runde.
Nun öffnen Sie einmal das Handbuch und gehen unter index. Dort haben Sie die
komplette Befehlsliste von 3D Gamestudio.
Als Beispiel gehen Sie mal auf: sys_day
Ganz oben steht jetzt Die Erklärung.
Danach kommt der Werteberreich und meistens noch ein Beispiel oder
Besonderheiten.
Noch ein paar Tipps:
Bei Befehlen mit dem Typ „read-only“ (so z.B. sys_day) können nicht verändert werden! (Man kann ja auch nicht den Systemtag verändern..)
Bei Rückgabewerte sehr ihr was die Funktion zurückliefert. So liefert z.B. bmap_width die Breite eines Bitmaps zurück.
Ein wichtiges aber auch schweres
Thema habe ich noch nicht behandelt. Zeiger.
Ein Zeiger zeigt wie der Name schon sagt auf eine Entität oder auf andere Typen.
Man definiert einen Zeiger folgendermaßen:
TYP* name;
Unter Typ muss einer von ein paar verschiedenen Möglichkeiten angegeben werden:
Entity (Zeiger auf eine Entität)
Bmap (Zeiger auf ein Bitmap)
Es gibt noch einige andere
Möglichkeiten, aber die hier sind erst mal die wichtigsten.
Wenn Sie einen Entity Zeiger definieren müssen Sie diesen Zeiger noch eine
Entität zuweisen.
Zeiger sind eigentlich nur dazu da, dass man in anderen Funktionen Werte einer
Entität ändern kann! Ein Beispiel:
Entity* player; |
Sie müssen noch unbedingt beachten,
dass der Zeiger gesetzt ist bevor Sie auf ihm zugreifen. Wenn Sie sich unsicher
sind ob der Zeiger schon gesetzt ist unbedingt ein :
while(player==0) { wait(1); }
vor den Zugriff auf die Playereigenschaften schreiben (Ein Pointer ist 0 solange
er nicht gesetzt ist). Wenn Sie das nicht machen werden Sie von der Engine eine
Fehlermeldung bekommen weil sie versucht auf einen Zeiger zuzugreifen der nicht
gesetzt ist.
Ich hoffe das dies den Mauszeiger weitestgehend erklärt.
Jede erstelle Entität in WED
besitzt 99 Skills und 8 Flags. Ein Skill ist eigentlich nichts anderes als eine
Variable, nur dass sie sozusagen die Eigenschaften von den Entitäten sind. Die
ersten 20 Skills und alle 8 Flags kann man in Wed setzten. Flags sind in etwa
das gleiche wie Skills außer, dass sie nur zwei Zustände einnehmen können. Und
zwar 1 (on) und 0 (off).
Der Beispiel für Skill1:
Action player_act |
Es ist auch möglich Vektoren in Skills zu speichern. Dabei geht man wie folgt vor:
Action player_act { var local_array[3]=10,5,2; //Vektoren dürfen lokal definiert sein, Arrays nicht! My.skill2=local_array; //my.skill2=10; //my.skill3=5; //my.skill4=2; } |
Weil skill1 oder skill2 nicht besonders aussagekräftig sind kann man die Skillnamen mit Hilfe der define Anweisung verändern.
Mit Define kann man Skills und
Flags andere Namen geben oder aber auch Konstante definieren.
Ein einfaches Beispiel für Define:
Define geschwindigkeit,skill;
//Geschwindigkeit und skill1 ist das selbe!! |
Wie aber bereits angedeutet kann
man mit define auch Konstante definieren.
Dies funktioniert wie folgt:
Define test_define,10; |
In diesem Kapitel wollen wir eine
einfache Maussteuerung realisieren.
Hierbei werden Sie wieder eine Menge neuer Befehle lernen.
Als erstes einmal der Code:
Bmap arrow = <arrow.pcx>;//Mausgrafik |
Nun gehen wir mal jeden Befehl,
Schritt für Schritt durch.
Als erstes wird eine Grafik definiert, die später die Maus wird.
Danach definieren wir die Funktion mouse_fun und starten eine Schleife!
Als erstes bekommt die Maus die Grafik arrow per mouse_map.
Die Syntax von mouse_map ist:
Mouse_map = Bitmap;
Als nächstes wird mouse_mode auf 1 gesetzt. Das hat zur Folge das die Maus
angeschaltet wird.
Danach setzten wir noch die Koordinaten der Maus auf Pointer.x bzw. Pointer.y!
Pointer.X/Y sind die absoluten Maus Koordinaten in Pixeln. Wenn man die
Koordinaten der Maus an Pointer.X/Y setzt, kann man die Maus völlig frei über
den Bildschirm bewegen.
Man muss die Mausfunktion in eine Endlosschleife setzten, damit die Mausposition
immer wieder, je nach Mausbewegung, verändert wird!
Dass eine Funktion auf Tastendrücke
reagiert, ist wirklich denkbar einfach.
Es gibt eine Variable für jede Taste auf der Tastatur. Diese Variable ist
entweder 1 wenn die Taste gedrückt ist, oder null wenn sie nicht gedrückt ist.
Die Namen der Variablen kann man im Handbuch, beim suchen von „Tastenbelegung „
unter „Tasten & Statistik“ sehen.
Hier ist ein Beispiel für eine einfache Funktion die zwei verschiedene Dinge
macht je nachdem welche Taste gedrückt ist.
Function react_to_key |
Ein Event (wörtlich übersetzt
„Ereignis“) kann von Entitäten benutzt werden. Ein Event ist nichts anderes als
eine vom Programmierer geschriebene Funktion,
die ausgeführt wenn etwas bestimmtes mit dem Entity passiert. Zum Beispiel wenn
die Entity von einem anderen Entity gerammt wird. Die grundsätzliche Syntax
eines Events ist wie folgt:
my.event = function;
Function ist eine beliebige Funktion innerhalb ihres Scriptes.
Nun gibt es eine Reihe verschiedener Events. Ich werde hier die wichtigsten
behandeln.
Event block wird ausgelöst wenn das
Entiy einen Levelblock berührt. Damit dieses event ausgelöst werden kann muss
allerdings noch enable_block auf on gesetzt sein.
Ein Beispiel:
Function event_funct |
Wenn das Entity nun einen Block berührt wird die Funktion event_funct aufgerufen.
Event Entity wird genauso aufgebaut
wie Event_block, nur dass event_entity aufgerufen wird wenn z.B. der Spieler
während der Bewegung ein anderes Model rammt.
Ein Codebeispiel:
Function event_funct |
Event_Impact bewirkt genau das gleiche wie Event_entity, nur dass event_block aufgerufen wird, wenn ein Model von einem anderen Model gerammt wird.
Nehmen wir an Sie haben ein sehr
großes Script und wollen dies auf mehrere Wdl Dateien splitten. In diesem Fall
erstellen Sie eine neue Wdl Datei und kopieren den Code in die Datei.
Danach inkludieren Sie die Scriptdatei mit Hilfe des include Befehls. Die Syntax
von include:
Include <dateiname.wdl>;
Normalerweise werden alle Scriptdateien ganz am Anfang des Hauptscriptes
inkludiert.
In diesem Kapitel zeige ich Ihnen ein paar kleine Tricks in WDL.
Wenn Sie wollen, dass eine Bedingung wahr ist, wenn Wert1 gleich 1 ist gibt es 2 Möglichkeiten:
If(wert1 == 1) { //mache
das... //mache das...
|
Wenn Sie das so schreiben ist die Aussage automatisch wahr, wenn Wert1 den Wert 1 hat.
Der gleiche Trick lässt sich auch machen wenn Sie eine Endlosschleife machen wollen.
//entweder so: |
Ist relativ logisch, da die Bedingung while(1) das gleiche Bedeutet wie die Bedingung while(1==1)
Funktionsparameter bei Buttons sind nicht möglich.
Layer können während der Laufzeit NICHT geändert werden. Hier müssen Sie zwei verschiedene Panels machen die Sie dann sichtbar bzw. unsichtbar machen.
Versuche deine Scripts so übersichtlich wie möglich zu gestalten. Das hilft dir bei längern Codes enorm.
Die Funktionsklammern bei
my.event=function;
unbedingt weglassen. Wenn diese Klammern geschrieben
werden, hat das Entity gar kein Event.
Sie haben einen Skill per define
umbenannt und wollen, dass dieser Skill nun auch mit den richtigen Namen in Wed
angezeigt wird? Nichts leichter als das.
Schauen Sie sich einfach das Beispielscript an:
Define leben,skill1; |
Nachdem Sie das //uses
in Ihr Script eingefügt haben müssen Sie WED noch neu starten, damit die
Änderungen übernommen werden.
In diesem Kapitel werden Sie noch einige Grundlegende Funktionen lernen.
Wie ich bei den Strings schon
erwähnt habe kann man strings nicht einfach einen Inhalt durch den
Zuweisungsoperator = zuweisen.
Daher gehe ich im folgenden noch mal auf ein paar String Befehle ein:
Str_cpy kopiert String2 in String1. Wenn String1 schon Zeichen beinhaltet werden diese überschrieben. Ein einfaches Beispiel:
String test_str = “Test the String”; |
Str_trunc schneidet so viele Zeichen vom ENDE des Strings ab, wie in Zahl angegeben wurde. Ein Beispiel:
String test_str = “Test the String”; |
Str_clip funktioniert genauso wie str_trunc nur das Str_clip die Zeichen vom ANFANG des Strings abschneidet.
String test_str = “Test the String”; |
Für weiter Befehle schauen Sie im
Handbuch unter str_
nach.
Eine Entität hat viele verschiedene
Eigenschaften auf die man mithilfe des My Pointers innerhalb der Action oder mit
einem zugewiesenen Pointer außerhalb der Action zugreifen kann.
Ich werde nun auf die wichtigsten und häufigst benutzen Eigenschaften eingehen.
Man kann eine Entität natürlich
rotieren. Dies funktioniert mit den Eigenschaften Pan – Tilt – Roll.
Pan dreht um die Z, Tilt um die Y und Roll um die X Achse. Alle 3 Eigenschaften
haben einen Wertebereich von 360. Die Werte werden in Grad angegeben.
Ein Beispiel zum ständigen rotieren einer Entität:
Action rotate_me |
Mit Passable kann man eine Entität passable machen. Der Wertebereich ist 1 (on) und 0 (off). Ein Beispiel:
Action gegner |
Mit Visible kann man eine Entiät sichtbar bzw. unsichtbar machen. Der Wertebereich ist genau wie bei passable 1(on) oder 0 (off).
Action unsichtbar_act |
Wenn Sie Transparent auf ON schalten wird ein Entity halb durchsichtig.
Action transparent_act |
Sie können den Wert wie viel ein
Entity durchsichtig ist auch noch durch Alpha verändern. Bei Alpha 0 ist das
Entity unsichtbar. Bei Alpha 100 ist das Entity voll sichtbar.
Transparent muss auf ON gesetzt sein wenn Sie Alpha benutzen wollen.
Action alpha_test |
Suchen Sie im Handbuch nach diesen Befehlen. Anhand dieses Tutorials sollten Sie in der Lage sein die Beschreibung zu verstehen:
snd_play,snd_loop (zum abspielen von Musik)
trace (schwer aber notwendig)
str_ Befehle
ent_move bzw. C_move (zum bewegen von Entitäten)
vec_ Anweisungen (zum manipulieren von Vektoren)
inkey (zum direkten eingeben in Strings)
Ich hoffe, dass Sie durch dieses Tutorial einiges gelernt haben und jetzt mit den Handbuch umgehen können. Bei Fragen über dieses Tutorial bitte bei Triple-X@hawkgames.de oder bei mir unter ICQ: 170911701 melden.