3D Gamestudio und MySQL
3D Gamestudio und MySQL
3D Gamestudio und MySQL
Erfolgreiche ePaper selbst erstellen
Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │1
<strong>3D</strong> <strong>Gamestudio</strong> <strong>und</strong> <strong>MySQL</strong><br />
von Wicht<br />
Hallo <strong>und</strong> herzlich willkommen zu meinem ersten Tutorial. In diesem werdet Ihr lernen, wie man<br />
mit einer 3dgs-Anwendung Daten an einen <strong>MySQL</strong>-Server senden kann. Und auch empfangen.<br />
Und wozu? Nun, überall da, wo jeder, der Euer Spiel benutzt, auf zentral gelagerte Daten (auch von<br />
anderen Benutzern) zugreifen kann. Eine Möglichkeit wäre z.B. ein Online-Highscore-System. Ein<br />
Nutzer sendet seine erreichte Punktezahl an eine <strong>MySQL</strong>-Datenbank <strong>und</strong> sieht sofort, welche<br />
Punkte die anderen Spieler erreicht haben. Oder wie wäre es mit einem r<strong>und</strong>enbasierten Spiel?<br />
Oder einem Chat? Oder oder oder ... Möglichkeiten gibt's genug.<br />
Was brauchen wir?<br />
Zunächst einmal das <strong>3D</strong> <strong>Gamestudio</strong>. Soweit ich weiß, können alle <strong>3D</strong>GS-Editionen DLLs<br />
ansprechen. Ist doch prima, oder? Und dann natürlich die gshttp.dll von Peacekeeper (zu finden<br />
unter http://www.peacekeeper.com/3dgs). Und die ist auch noch kostenlos. Was will man mehr.<br />
Ach ja, ein funktionierender <strong>MySQL</strong>-Server wäre auch nicht schlecht ;-)<br />
Achtung: Ich hatte Probleme, die Anweisung HTTP_POST zu verwenden. Stattdessen verwendete<br />
ich die HTTP_GET Anweisung. Außerdem müssen Sonderzeichen wie Leerzeichen, Ü,Ä,Ö usw. noch<br />
umgewandelt werden. Aus diesem Gr<strong>und</strong> habe ich die DLL um eine weitere Funktion ergänzt, die<br />
genau das macht.<br />
Die modifizierte DLL (gshttp.dll) kann unter http://www.darkware.de/3dgsmysql_tut/gshttp.dll<br />
runtergeladen werden.<br />
Wer sich zunächst einmal die ganze Materie anschauen will, ohne gleich ein Webhosting-Paket zu<br />
ordern, kann sich auch die Kombination Apache->PHP-><strong>MySQL</strong> lokal installieren. Damit kann man<br />
alles offline testen. Wie diese Programme/Module installiert werden, steht in zahlreichen<br />
Anleitungen im Internet.<br />
Wer jetzt genau aufgepasst hat, dürfte sich folgendes fragen: Nanu? Wozu auch noch den Apache-<br />
Webserver <strong>und</strong> PHP? Ich dachte immer, man kann einen <strong>MySQL</strong>-Server auch direkt ansprechen. Ihr<br />
habt recht. Natürlich geht das. Nur die meisten Webhoster wollen das aus sicherheitsrelevanten<br />
Gründen nicht <strong>und</strong> sperren den direkten externen Zugriff auf den <strong>MySQL</strong>-Server. Um aber dennoch<br />
unser Ziel zu erreichen, müssen wir PHP verwenden.<br />
Ein erster Test<br />
Jetzt wollen wir aber endlich mal was auf dem Bildschirm sehen.<br />
Erstellt eine neue 3dgs-Anwendung (nach Möglichkeit ohne die Templates zu benutzen) <strong>und</strong> kopiert<br />
die gshttp.dll in Euer Projektverzeichnis.<br />
Jetzt brauchen wir noch eine php-Datei. Die könnte etwa so aussehen:<br />
Die Datei mit dem Namen "textausgabe.php" ( den Namen könnt Ihr natürlich selbst wählen ) liegt<br />
jetzt auf meinem Webserver <strong>und</strong> kann bereits über einen Browser abgerufen werden.<br />
Bei mir sieht die URL so aus: "http://www.darkware.de/3dgsmysql_tut/textausgabe.php". Und was<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │2
macht die php-Datei? Nun, sie gibt nur einen einfachen Text aus. Mehr nicht.<br />
Im Hauptskript unserer 3dgs-Anwendung erstellen wir zunächst unser Gr<strong>und</strong>gerüst.<br />
Die Zeilen 13-24 sollten eigentlich klar sein. Interessant sind allerdings die Zeilen 4-9. Über die<br />
"dllfunction"-Anweisung wird der A6-Engine mitgeteilt, welche weiteren Funktionen ihr durch eine<br />
DLL zusätzlich zur Verfügung gestellt werden. In unserem Beispiel sind es ein Teil der Funktionen,<br />
die in der Datei gshttp.dll stehen.<br />
Und nun erweitern wir unsere main-Funktion um diese neuen Befehle.<br />
Und das kommt dabei heraus:<br />
Jetzt haben wir's schon geschafft. Unsere Anwendung greift auf eine php-Datei zu, die irgendwo im<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │3
Internet erreichbar ist <strong>und</strong> liefert deren Ergebnis zurück.<br />
Die neuen Anweisungen im Überblick:<br />
HTTP_CREATE erstellt einen neuen HTTP-Client mit einer ID-Nummer. Es können also entsprechend<br />
mehrere Clients gleichzeitig erstellt werden. Sicherheitshalber sollte man sich aber mit nur einem<br />
begnügen.<br />
HTTP_GET ruft schließlich unter der gleichen ID wie HTTP_CREATE eine Datei auf dem Webserver<br />
auf. In unserem Beispiel "http://www.darkware.de/3dgsmysql_tut/textausgabe.php".<br />
HTTP_IsWorking ist ganz wichtig. Diese Funktion überprüft, ob der Webserver mittlerweile mit<br />
seiner Arbeit fertig ist. Sollte dem nicht so sein, müssen wir eben noch etwas warten. Wer will<br />
schon mit Daten arbeiten, die noch nicht da sind ;-)<br />
HTTP_RESULTS beinhaltet schließlich das Ergebnis unserer Webserver-Anfrage. In diesem Beispiel<br />
den String "Der Gargamel mag keinen einzigen Schlumpf !!!".<br />
HTTP_FREE beendet wieder den HTTP-Client.<br />
Wichtig ist, dass bei all diesen Anweisungen immer die gleiche ID-Nummer vergeben wird. In<br />
diesem Fall ist das immer 0. Gr<strong>und</strong>legend war's das schon. Spielt etwas damit, um ein Gefühl für<br />
die neuen Befehle zu bekommen.<br />
Und der <strong>MySQL</strong>-Zugriff?<br />
Nun, diejenigen die sich mit php auskennen, dürften an dieser Stelle schon jubeln. Allen anderen<br />
sei gesagt, dass der reine <strong>MySQL</strong>-Zugriff über php realisiert wird.<br />
Und das schauen wir uns jetzt mal an.<br />
Wir legen uns erstmal eine Tabelle via phpMyAdmin an.<br />
Ein Datenbank-Tutorial liegt mir zwar fern, dennoch möchte ich auf einige wenige, aber wichtige,<br />
Dinge eingehen. Das erste Feld sollte immer eine laufende Nummer UND ein Primärschlüssel sein.<br />
Dadurch hat man die Möglichkeit, auch inhaltlich gleiche Datensätze zu unterscheiden. In diesem<br />
Screenshot könnt Ihr sehen, das das erste Feld vom Typ "int" (Ganzzahl) in der Spalte "Extra" ein<br />
"auto-increment" besitzt. Das heißt nichts weiter, als das bei jedem neuen Datensatz die Nummer<br />
des Feldes um den Wert 1 erhöht wird. Der untere Screenshot verdeutlicht das.<br />
Das Feld "3dgsmysql_tut_nr" ist genau dieses Feld mit dem Primärschlüssel <strong>und</strong> dem Extra "autoincrement".<br />
Hinweis: phpMyAdmin ist eine in der Skriptsprache PHP geschriebene Webseite, mit deren Hilfe<br />
<strong>MySQL</strong>-Datenbanken recht komfortabel verwaltet werden können.<br />
Kostenloser Download unter http://www.phpmyadmin.net.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │4
OK, wir haben also unsere Tabelle, mit mehr oder weniger sinnvollem Inhalt, angelegt. Als<br />
nächstes erstellen wir eine neue php-Datei, welche den gesamten Inhalt der Tabelle ausliest.<br />
Zunächst brauchen wir aber eine php-Datei, welche die Zugangsdaten enthält. Sie heißt<br />
"global.php".<br />
Und dann noch die php-Datei, die den Datenbankinhalt ausliest.<br />
Das obige Bild zeigt den Inhalt der Datei "textausgabe_db.php".<br />
Die Datei "textausgabe_db.php" bindet die Datei "global.php" mit Hilfe des include-Befehls ein.<br />
Also ganz analog dem include-Befehl in C-Script. Man könnte also auch die Datei "global.php"<br />
weglassen <strong>und</strong> die Zugangsdaten direkt in die Datei "textausgabe_db.php" eintragen. Mit ständig<br />
ansteigender Anzahl an php-Dateien wird man jedoch die Auslagerung der Zugangsdaten in eine<br />
separate Datei zu schätzen wissen.<br />
In den Zeilen 7-10 wird eine Datenbankverbindung aufgebaut <strong>und</strong> eine SQL-Anweisung gesendet.<br />
Die Zeile 12 hätten wir sogar weglassen können.<br />
In der Zeile 13 wird ermittelt, wieviele Datensätze als Ergebnis der Abfrage zurückgeliefert wurden.<br />
Dieser Wert wird benötigt, damit wir eine Schleife ausführen können (Zeile 15-21), um jeden<br />
einzelnen Datensatz mithilfe der echo-Anweisung auszugeben (Zeile19). Die Zeile 20 ist nur dazu<br />
da, einen Zeilenvorschub zu integrieren.<br />
Die php-Anweisung mysql_result in den Zeilen 16 <strong>und</strong> 17 liest die einzelnen Werte des aktuellen<br />
Datensatzes aus. Der erste Parameter ($res) beinhaltet das gesamte Abfrageergebnis. $i definiert<br />
den aktuellen Datensatz in der for-Schleife. Der dritte <strong>und</strong> letzte Parameter definiert des Feld.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │5
Schaut Euch dazu nochmal den unteren Screenshot an. Wenn der dritte Parameter 0 ist, dann<br />
meinen wir damit das erste Feld. Also "3dgsmysql_tut_nr". Bei einer 1 entsprechend das Feld<br />
"dw_3dgsmysql_tut_text", usw. ...<br />
In unserer C-Skipt-Datei ändert sich allerdings nicht viel. Wir haben ein weiteres Textelement,<br />
welches den Inhalt unserer "textausgabe_db.php" darstellt.<br />
HTTP_CREATE, HTTP_GET usw. sollten an dieser Stelle auch keine weiteren Fragen aufwerfen.<br />
Und hier ist das Ergebnis ...<br />
Mehr gibt's eigentlich zum empfangen von <strong>MySQL</strong>-Daten nicht zu sagen.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │6
Senden von Daten an einen <strong>MySQL</strong>-Server<br />
Auch an dieser Stelle dürften Anwender, die mit php Erfahrung haben, jubeln. Um Daten an einen<br />
<strong>MySQL</strong>-Server über eine php-Datei zu senden, werden diese einfach an das Ende der URL<br />
angehängt. Das sieht dann z.B. so aus:<br />
"http://www.darkware.de/3dgsmysql_tut/neuerdatensatz.php?user=Wicht&text=lustig".<br />
Der php-Datei "neuerdatensatz.php" werden die Variable "user" mit dem Inhalt "Wicht" <strong>und</strong> die<br />
Variable "text" mit dem Inhalt "lustig" übergeben. Und mit diesen Variablen ( <strong>und</strong> deren Werten )<br />
kann man in PHP weiterarbeiten.<br />
Wir werden unsere kleine 3dgs-Anwendung so erweitern, dass gleich 2 Werte an einen <strong>MySQL</strong>-<br />
Server übertragen werden. Dazu habe ich zunächst die Tabelle um ein weiteres Feld erweitert.<br />
Wie Ihr sehen könnt, wurde mit phpMyAdmin ein neues Feld "username" zwischen den beiden<br />
schon vorhandenen Feldern eingefügt ( Typ: varchar; Länge 60 ).<br />
Die Datei "neuerdatensatz.php, welche Daten an den <strong>MySQL</strong>-Server sendet, sieht so aus:<br />
Zeile 3: Den include-Befehl kennen wir bereits.<br />
Zeile 5: Hier wird die Variable "user" abgefangen, die wir in unserer URL angegeben haben<br />
Zeile 6: Wie Zeile 5, nur mit der Variablen "text".<br />
Hinweis: Einige von Euch werden jetzt bestimmt anmerken, dass man die Variablen <strong>und</strong> deren<br />
Werte auch mit der globalen Variable $QUERY_STRING abfragen kann. Das ist auch soweit richtig.<br />
Nur haben auch da einige Webhoster ihre eigenen Vorstellungen. Der Webhoster Strato, bei dem<br />
ich bin, "mag" diese Variable nicht. Stattdessen soll man $_GET verwenden.<br />
Die Zeilen 10-13 sollten soweit klar sein. Es wird eine Verbindung aufgebaut <strong>und</strong> die Daten werden<br />
über eine SQL-Anweisung abgeschickt. Da wir jetzt aber ein weiteres Feld in der Datenbanktabelle<br />
haben, müssen wir auch unsere "textausgabe_db.php" etwas modifizieren.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │7
Viel geändert haben wir da nicht. Interessant sind aber die Zeilen 21,23 <strong>und</strong> 24. Die Angabe "\n"<br />
steht hier für einen Zeilenvorschub. Was der genau bewirkt, seht Ihr dann, wenn Eure 3dgs-<br />
Anwendung gestartet wurde.<br />
Logischerweise müssen wir auch in der C-Skript-Datei etwas ändern.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │8
OK, gehen wir die wdl-Datei Schritt-für-Schritt durch.<br />
Zeile 04: Eine weitere Funktion wurde eingefügt. Was diese bewirkt, werden wir gleich noch<br />
sehen.<br />
Zeile 15: Ein String zum temporären abspeichern eines neuen Users.<br />
Zeile 16: Ein String zum temporären abspeichern eines neuen Textes.<br />
Zeile 17: In dieser Variable steht dann die komplette URL inkl. Datenanhang<br />
Zeile 40: Wir müssen den String in eine url-konforme Zeichenkette umwandeln ( z.B. wird aus<br />
einem Leerzeichen ein %20; aus einem ü wird ein %FC usw. )<br />
Zeile 41: Gleiches gilt auch für diese Variable.<br />
Die komplette URL sieht ohne die entsprechende Umwandlung ab Zeile 48 so aus:<br />
http://www.darkware.de/3dgsmysql_tut/neuerdatensatz.php?user=Wicht&text=Schlümpfe<br />
anschauen macht Spaß<br />
Mit Umwandlung so:<br />
http://www.darkware.de/3dgsmysql_tut/neuerdatensatz.php?user=Wicht&text=Schl%FCmpfe%20<br />
anschauen%20macht%20Spa%DF<br />
Ihr könnt das auch gerne überprüfen, indem Ihr die nicht umgewandelte URL in Euren Browser<br />
eintippt. Der Browser wandelt diese Zeile ebenfalls um. Der Rest der wdl-Datei dürfte mittlerweile<br />
verständlich sein. Mit HTTP_CREATE wird ein neuer Http-Client erzeugt. HTTP_GET ruft die URL auf.<br />
Dann warten wir, bis der Webserver alles erledigt hat (HTTP_IsWorking). Zum Schluss wird noch<br />
der HTTP-Client freigegeben. Die C-Skript-Zeilen zum abrufen von Daten haben sich derweil nicht<br />
verändert. Nach dem Start unserer 3dgs-Anwendung sehen wir dieses Bild ...<br />
Ein kontrollierender Blick via phpMyAdmin zeigt uns, dass die neuen Daten tatsächlich vorliegen ...<br />
Das war's dann auch erstmal. Ich hoffe, Euch mit diesem Tutorial halbwegs geholfen zu haben.<br />
Fehler, Anregungen, Kritiken usw. könnt Ihr gerne an info@darkware.de.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │9
Terrainerstellung mit Earthsculptor<br />
Dieses Tutorial beschäftigt sich mit der Terrainerstellung mittels dem kostenlosen Tool<br />
Earthsculptor [1] <strong>und</strong> dem Import in <strong>3D</strong> <strong>Gamestudio</strong>.<br />
Wichtig ist hierbei allerdings noch, dass dieses Verfahren nur ab der Commercial Version<br />
funktioniert, da nur ab der Com Shader möglich sind.<br />
Nachdem man Earthsculptor heruntergeladen, installiert <strong>und</strong> gestartet hat, klickt man auf File -><br />
New. Wir belassen es für den Moment bei den Standardeinstellungen. Nun sehen wir also folgendes<br />
Bild (ich habe das kleine Fenster maximiert):<br />
Wen der Nebel stört, der klickt im rechten Fenster auf „Fog" <strong>und</strong> schiebt dann den Regler „Far"<br />
nach ganz rechts. Nun haben wir also ein sehr klares Bild.<br />
In der Toolbox klicken wir nun auf den Button „Detail" (Das Karomuster).<br />
Das Fenster auf der rechten Seite sieht nun so aus:<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │10
In der oberen Reihe sehen wir 4 Buttons, die wir jeweils mit einer Textur belegen können. D.h.<br />
also, dass wir für unser Terrain bis zu 4 unterschiedliche Texturen verwenden können. Dabei gilt<br />
folgende Regel: Eine Textur überlagert immer alle Texturen auf den Buttons links von ihr. D.h. Nr. 4<br />
überlagert alles, Nr. 1 Nichts.<br />
Klicken wir nun auf „Set Detail Texture" <strong>und</strong> wählen beispielsweise „longGrass.png" als Textur aus.<br />
Das Terrain verändert sich sofort zu folgendem Bild:<br />
Nun machen wir am besten damit weiter das Terrain ein wenig zu verformen. Dazu klicken wir in<br />
der Toolbox auf das Symbol oben rechts „Terraform". Das Fenster auf der rechten Seite sieht nun<br />
so aus:<br />
Einfaches experimentieren mit den verschiedenen Tools ergibt meist schon recht schöne<br />
Ergebnisse. Hierzu gebe ich keine genauere Anleitung, da sich die meisten Dinge beim<br />
experimentieren erschließen. Die 3 Regler unter den Buttons geben den Radius des Tools, die<br />
Stärke der Veränderung <strong>und</strong> die Stärke des Randes an.<br />
Hier mal mein Beispiel Terrain nachdem ich einfach ein wenig mit den Tools herumgespielt habe:<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │11
Nun klicken wir in der Toolbox wieder auf „Detail". Wählen bei den 4 Buttons die Nr. 2 aus <strong>und</strong><br />
klicken auf „Set Detail Texture". Hier habe ich nun „cliff.png" gewählt, da ich nun die Berge<br />
bemalen wollte. Nachdem die Textur ausgewählt ist können wir nun mit dem Bemalen des Terrains<br />
beginnen. Die Regler sind ähnlich aufgebaut wie beim Verformen des Terrains.<br />
Ein kurzes Zwischenergebnis:<br />
Nun habe ich weitergemacht <strong>und</strong> auf die selbe Art <strong>und</strong> Weise die Detail-Textur 3 <strong>und</strong> 4 belegt <strong>und</strong><br />
auf das Terrain gemalt:<br />
Klicken wir nun einmal auf den Pinsel „Paint" in der Toolbox.<br />
Nun können wir im Farbauswahlfenster links eine Farbe wählen <strong>und</strong> auf das Terrain mahlen. Ich<br />
habe grün gewählt <strong>und</strong> auf das Gras gemalt. Dadurch wirkt es saftiger <strong>und</strong> frischer:<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │12
Dies stellt nun auch das Endergebnis dar. Das Wasser ist hier nur ein Gimmick <strong>und</strong> kann nicht mit<br />
exportiert werden. Klicken wir also nun auf File -> Save <strong>und</strong> speichern unser Terrain in einen<br />
beliebigen (am besten leeren) Ordner ab. In diesem Ordner haben wir nun 5 Dateien:<br />
„tutterrain.map" ist die Earthsculptor-Datei<br />
„tutterrain.png" ist die Heightmap aus der MED<br />
gleich das Terrain generieren wird<br />
„tutterrain_c0.png" ist die Colormap. Hier ist das<br />
saftige Grün unseres Grases gespeichert<br />
„tutterrrain_d0.png" ist eine RGB-Blendmap. Diese Information dient dem Shader dazu die 4<br />
Texturen richtig zu mischen.<br />
„tutterrain_I0.png" ist die Shadowmap. Hier ist also die Beleuchtung gespeichert.<br />
Nun müssen wir zuerst die Dateien umwandeln in andere Formate, damit MED damit etwas<br />
anfangen kann. Das könnte etwas kompliziert werden, da man hier einige Umwege gehen muss.<br />
Fangen wir mit der Datei „tutterrain.png" an. Diese wandeln wir am besten in eine .tga oder eine<br />
.pcx Datei um .bmp würde zwar auch gehen, aber MED interpretiert diese bei mir nicht. Daher<br />
wählen wir am besten TGS oder PCX. Das geht am einfachsten mit einem Tool wie dem<br />
EasyGraphicsConverter [2].<br />
Nun kommen wir zur Colormap, also die mit der Endung „_c0.png". Diese öffnen wir zuerst mit<br />
Windows Paint <strong>und</strong> speichern sie als BMP Datei ab. Wie bereits erwähnt hat MED Probleme mit den<br />
BMP Dateien <strong>und</strong> deswegen wandeln wir sie gleich mit dem EasyGraphicsConverter [2] in eine PCX<br />
Datei um.<br />
Mit der Blendmap „_d0.png" verfahren wir genauso. Also zuerst Paint -> Speichern als BMP -><br />
Umwandeln in eine PCX Datei.<br />
Die Shadowmap „_I0.png" öffnen wir zuerst mit Photoshop oder Paint <strong>und</strong> stellen den Bildmodus<br />
von Graustufe auf RGB um, sonst haben wir später Kanten bei den Schatten. Die Shadowmap<br />
speichern wir diesmal gleich als PCX Datei.<br />
WICHTIG! Die Blendmap <strong>und</strong> die Colormap nicht mit einem Programm wie Photoshop öffnen. Dann<br />
Photoshop <strong>und</strong> Co. Interpretieren die Transparenz in den beiden Dateien falsch <strong>und</strong> beim Speichern<br />
erhält man schlichtweg leere Dateien. Deswegen diese immer über Paint speichern, dann dieses<br />
stellt keine Transparenzen dar.<br />
So, nun haben wir also alle Dateien im PCX Format. Öffnen wir nun den MED. In MED klicken wir<br />
nun auf File -> Import -> Import Terrain from Pic Dort wählen dann als Dateiformat PCX aus <strong>und</strong><br />
öffnen die „tutterrain.pcx" (also die Datei ohne Endung).<br />
Im sich nun öffnenden Fenster stellen wir 100 x 100 Vertices ein.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │13
Bei mir ließen sich über die Regler nur 99 x 99 einstellen, was aber nicht weiter schlimm ist. Nach<br />
einem Klick auf „OK" sehen wir also nun unser in Earthsculptor erstelltes Terrain. Allerdings ist es<br />
noch ein wenig zu flach. Wir klicken also auf das Skalierungstool <strong>und</strong> skalieren das Terrain ein<br />
wenig in die Höhe, bis in etwa an das in Earthsculptor herankommt.<br />
Nun öffnen wir das Skins-Menü (Edit -> Manage Skins)<br />
Nun wählen wir den „Skin0" an <strong>und</strong> klicken auf „Skin Settings"<br />
Wir machen einen Haken bei „Texture" <strong>und</strong> klicken auf „Texture File" <strong>und</strong> dann auf „...". Hier<br />
wählen wir die Colormap aus. Also als Dateiformat PCX <strong>und</strong> dann die Datei mit der Endung<br />
„_c0.pcx".<br />
Dann klicken wir auf „New Skin" machen wieder einen Haken bei „Texture" <strong>und</strong> wählen diesmal die<br />
RGBBlendmap aus („_d0.pcx").<br />
Und das ganze wiederholen wir noch ein drittes Mal <strong>und</strong> wählen als letztes die Shadowmap<br />
(„_I0.pcx") als Textur aus.<br />
Das war's um Großen <strong>und</strong> Ganzen im MED schon. Wir speichern nun nur noch das Terrain als HMP<br />
ab.<br />
Wechseln wir nun zum WED. Nach einem Klick auf „New" wählen wir über Object -> Load Entity als<br />
Dateiformat HMP aus <strong>und</strong> öffnen unser Terrain. Dann speichern wir den Level ab <strong>und</strong> klicken dann<br />
auf File -> Map Properties. Hier klicken wir bei Script auf das Blatt Papier <strong>und</strong> wählen dann<br />
„template" aus.<br />
Jetzt können wir WED erstmal wieder schließen <strong>und</strong> öffnen die .WDL Datei, die nun in unserem<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │14
Ordner liegt. Wir bearbeiten sie so, dass sie wie folgt aussieht:<br />
Bei „path" solltet ihr den Pfad zu eurem Projektordner angeben. Die Datei „terrain_multitex.wdl"<br />
[3] kopiert ihr in euren Projektordner.<br />
Nun müssen wir noch einmal ein bisschen mit Dateiformaten <strong>und</strong> Bildern jonglieren. Dazu müssen<br />
wir zuerst einmal in Earthsculptor bei „Detail" mit der Maus über die Buttons gehen um die<br />
Dateinamen der Texturen herauszufinden.<br />
Nun müsst ihr diese Dateien (zu finden im Earthsculptor Ordner unter Textures) mit einem<br />
Konvertierungsprogramm in das PCX oder BMP Format konvertieren. Desweiteren müsst ihr darauf<br />
achten, ob die Texturen eine Größe von 256x256, 512x512 oder 1024x1024 haben.<br />
Wenn nicht, müsst ihr sie noch skalieren, ansonsten gibt es nachher unschöne schwarze Ränder<br />
auf dem Terrain. Die konvertieren Dateien legen wir ebenfalls in unseren Projektordner. Nun öffnen<br />
wir die Datei „terrain_multitex.wdl" <strong>und</strong> gehen in die Zeilen 32 – 35.<br />
Hier sind die Texturen angegeben, die nachher auf dem Terrain verwendet werden. Wir müssem<br />
hier die Texturnamen von den eben konvertierten Texturen angeben. Dabei ist Button 1 in<br />
Earthsculptor „tex3" <strong>und</strong> Button 4 „tex6".<br />
Nun haben wir es fast geschafft. Nachdem wir die Datei abgespeichert haben, öffnen wir in WED<br />
wieder unseren Level mit dem Terrain. Wir wählen es an <strong>und</strong> wählen mit einem Rechtsklick<br />
„Properties" klicken auf das Behaviour Reiter <strong>und</strong> klicken dann auf das Ordner-Symbol. Hier wählen<br />
wir dann Aktion „multi_rgb". Nun kompilieren wir den Level <strong>und</strong> bew<strong>und</strong>ern unser Endergebnis:<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │15
Ich hoffe, dass ich hiermit einen Einblick sowohl in Earthsculptor als auch in das Importieren in <strong>3D</strong><br />
<strong>Gamestudio</strong> geben konnte.<br />
Sollte ihr Fragen haben, könnt ihr die gerne im Forum oder im Gästebuch meiner Webseite<br />
loswerden.<br />
Ein Dank geht an Loopix, der den Shader für das Terrain zur Verfügung gestellt hat als auch an<br />
Nagashi, der den Shader für die Colormap modifiziert hat. DANKE!<br />
die Downloadlinks:<br />
[1] Earthsculptor<br />
[2] EasyGraphicsConverter<br />
[3] Terrain_multitex Shader<br />
[4] Beispielprojekt<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │16
Die Sache mit der Motivation<br />
Wenn ein Mann etwas ganz blödsinniges tut, so tut er es immer aus den edelsten Motiven(Oskar Wilde)<br />
Es wurde schon viel über Projektmanagement, Teamarbeit <strong>und</strong> Planung geschrieben. All dies bringt<br />
nicht viel, wenn keine oder kaum Motivation vorhanden ist, das geplante Projekt umzusetzen. In<br />
diesem Artikel soll es nun um die Mannigfaltigkeit der Motivation gehen.<br />
Hierbei muß klar sein: Nicht alles wirkt bei jedem. Aber es wird jeder in der Lage sein, aus diesem<br />
Artikel etwas nützliches für sich herauszulesen.<br />
Ich werde diesen Artikel ausnahmsweise <strong>und</strong> entgegen unserer Konventionen in der „Du" Form<br />
schreiben, da es ein recht persönliches Thema ist. Ich denke, so kommen wir am ehesten weiter.<br />
Vielleicht sollten wir erstmal beleuchten, was genau überhaupt Motivation ist. Wie entsteht der<br />
starke Drang von innen heraus, Energie in eine bestimmte Sache zu stecken, die nicht extentiell<br />
wichtig ist? Du mußt hier zwischen der inneren <strong>und</strong> der äußeren Motivation entscheiden.<br />
Innere Motivation ist schwieriger zu erzeugen, aber nachhaltiger. Äußere Motivation ist schnell<br />
„erheischt", aber verpufft auch ebenso schnell wieder. Ganz so einfach ist es natürlich nicht -<br />
jedem Psychologen würden die Haare zu Berge stehen. Beide sind eng miteinander verknüpft <strong>und</strong><br />
beeinflussen sich. Du wirst sehen, nur die Mischung macht´s.<br />
Motivation kommt von „Motiv" - ohne ein solches keine Motivation. Du kannst also nichts<br />
erzwingen. Die gute Nachricht: Das brauchst <strong>und</strong> sollst Du auch gar nicht!<br />
Die von uns allen gewünschte, innere Motivation braucht also einen Auslöser. Es können auch<br />
mehrere sein, wichtig ist nur, daß dieser Auslöser eine Perspektive gibt, an die Du glauben kannst.<br />
Hier entscheidet wiederum die eigene Skepsis <strong>und</strong> Begeisterungsfähigkeit.<br />
Motivation ist aber gleichzeitig keine auf ein Projekt bezogene Gefühlsregung. Vielmehr ist<br />
Motivation etwas allgemeines. Wenn Du in der Schule motiviert bist, trifft das auch auf viele andere<br />
Bereiche des Lebens zu. Es gilt also, sich ein entsprechendes, „motivierendes" Umfeld zu schaffen.<br />
Hier kann hoffentlich jeder auf einen gewissen Erfahrungsschatz zurückblicken. Gleichzeitig, bei<br />
ersten Erfolgserlebnissen, fährt die Skepsis zurück - neue Horizonte tun sich auf.<br />
Es gibt einige Patentrezepte, um die Motivation zu erhöhen. Du solltest Dir diejenigen raussuchen,<br />
die den größten Erfolg versprechen.<br />
Termin setzen<br />
Wenn eine Sache drängt <strong>und</strong> sie Dir wichtig ist, solltest Du Dir einen festen Termin dafür setzen.<br />
Dieser Artikel ist so entstanden. Wenn Du diesen Termin öffentlich machst, erhöht sich der Druck.<br />
Termine dürfen nicht utopisch früh gewählt sein. Langes Überziehen des Termins bis zur Erfüllung<br />
bewirken nämlich genau das Gegenteil - Demotivation. Darum solltest Du vorsichtig mit dieser<br />
Methode umgehen.<br />
Belohnungen<br />
Belohnungen müssen gar nicht mal vorgesehen sein. Oftmals entstehen sie von alleine. Die vielen<br />
Leser des Magazins sind mir z.B. Lohn genug. Allerdings kann es helfen, sich nach getaner Arbeit<br />
etwas zu gönnen.<br />
Kleine Ziele setzen<br />
Auch dies ist eine Gratwanderung. Kleine Ziele dürfen nicht unbedeutend sein, sonst verkehrt sich<br />
der Motivationseffekt ins Gegenteil. Kleine, aber ambitionierte Ziele helfen, eine große Sache<br />
überschaubar zu machen.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │17
Bei Projektarbeit: Spielen!<br />
Wenn Du mal wieder gar keine Lust hast, an einem Spiel weiterzumachen, so spiele es eine Weile.<br />
Meist wird Dir dann bewußt, wie viel Arbeit schon drin steckt. Und es gehört schon eine ordentliche<br />
Portion Melancholie dazu, dann nicht weiterzumachen. Auch hier gibt es zwei Seiten der Medaille:<br />
Vielleicht fallen Dir lauter Baustellen auf, die Dich in diesem Moment überfordern. Du sagst Dir:<br />
Wie soll ich das alles nur schaffen? Nun, bevor Du mit falschem Stolz <strong>und</strong> überzogenen<br />
Erwartungen nicht weitermachst, schmeiße lieber einige Features raus. Du wirst sehen, wie der<br />
Druck von Dir weicht. Das ist kein Gr<strong>und</strong>, wieder unmotiviert zu werden. Im Gegenteil: Du beweißt<br />
ges<strong>und</strong>en Menschenverstand, indem Du alte Meinungen <strong>und</strong> Vorurteile revidierst! Vor drei Jahren<br />
warst Du vielleicht der Meinung, es muß ein MMORPG werden. Es ist nicht schlimm, wenn es doch<br />
nur ein normales RPG wird.<br />
Kommunikation<br />
Viele User im Forum reden gerne - sei es über Chat, Mails oder PM. Tausche Dich mit ihnen aus.<br />
Nimm das Zusammengehörigkeitsgefühl auf, sauge es ein! Sich gegenseitig zu motivieren ist zwar<br />
nicht so nachhaltig wie die Eigenmotivation - aber es hängt zusammen. Durch konstruktive<br />
Gespräche steigt Deine Laune ebenso wie Deine innere Motivation. Und zwar unterbewußt.<br />
Motiviere Dich bewußt<br />
Das ist vielleicht etwas hölzern ausgedrückt, darum gebe ich Dir ein Beispiel: Wenn Dir jemand ein<br />
Kompliment macht - nimm es an. Sag´"Danke! Das ist nett von Dir!". Das hat viele positive<br />
Effekte. Dein Selbstbewußtsein wird aufgebaut <strong>und</strong> Dein Gegenüber freut sich. Viel mehr, als wenn<br />
Du in falscher Bescheidenheit sagst: „Na ja, so toll ist es auch nicht..."<br />
Setz´ Dich nicht unter Druck<br />
Wenn Du gar keine Lust hast, solltest Du keinen Termin setzen oder mit dem Kopf durch die Wand<br />
wollen. Das ist okay <strong>und</strong> kein Gr<strong>und</strong> zu verzweifeln. Motivation kann man nicht erzwingen. Man<br />
kann sie sich nur „erfühlen". Umgebe Dich nicht mit Schwarzsehern. Sei Dir immer sicher, das alles<br />
klappt - dann gibt es keine Gründe mehr verzweifelt zu sein. Du kannst es, Du machst es <strong>und</strong> Du<br />
weißt es. Wo ist das Problem? Leg´ die Beine hoch, Du schaffst es doch sowieso!<br />
Lass Dich nicht runterziehen<br />
Wenn Du im Team arbeitest, dann steht <strong>und</strong> fällt die Motivation. Das ist ganz natürlich <strong>und</strong> kein<br />
Prozess, den man so einfach aufhalten kann. Stattdessen solltest Du mit gutem Beispiel voran<br />
gehen <strong>und</strong> signalisieren, daß Du an den Erfolg des Teams glaubst. In guten wie in schlechten<br />
Zeiten. Wenn Du als Konstante fungierst, werden andere Teammitglieder davon mitgerissen.<br />
Drohungen, Beschwerden <strong>und</strong> ähnliches helfen nicht. Das mußte ich selbst auch schon feststellen.<br />
Häng´ das Projekt nicht am Team auf. Wenn Peter das getan hätten, wäre Mausgame nicht so weit,<br />
wie es ist.<br />
Einfach anfangen!<br />
Den inneren Schweineh<strong>und</strong> zu überwinden ist nicht einfach. Ich mußte das auch tun, um diesen<br />
Artikel zu schreiben. Aber siehe da: Es macht Spaß! Ich bin völlig überrascht von mir selbst! Das<br />
kannst Du auch. Überrasche Dich immer mal wieder selbst, es ist fast so schön als wenn das<br />
andere tun.<br />
Nimm´ Dich nicht so ernst<br />
Das kannst Du Dir nicht oft genug sagen. Wenn irgendwelche Steine im Weg liegen <strong>und</strong> Du<br />
stolperst, lach drüber! Du kannst nur draus lernen <strong>und</strong> gestärkt daraus hervorgehen. Die<br />
wenigsten Stolpersteine sollte man persönlich nehmen. Betrachte sie als Herausforderung,<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │18
vielleicht sogar als leicht tragischen Gag. Das nimmt ihnen die Härte <strong>und</strong> sorgt dafür, daß Du ihnen<br />
nicht „ohnmächtig" gegenüberstehst.<br />
Ich bin mir sicher, daß dieser Artikel einiges in Dir bewirken wird. Lass es raus!<br />
Ich hätte auch schreiben können, daß ich HOFFE, daß dieser Artikel weiterhilft. Dem ist nicht so.<br />
Stattdessen bin mir einfach sicher, daß er hilft. Basta. Ein schönes Gefühl. ;-)<br />
Viel Spaß beim ausprobieren wünscht,<br />
Torsten Fock<br />
www.vulkanware.de<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │19
Einfache Physik durch Event Funktionen ohne<br />
Newton <strong>und</strong> dergleichen<br />
Ich möchte in diesem Tutorial mit Ihnen ein paar einfache Physik Bewegungen programmieren um<br />
Objekte durch Berührung oder Beschuss zu bewegen.<br />
Mann möge mir verzeihen wenn ich nicht die Befehle my.poligon = on <strong>und</strong> c_trace für<br />
poligongenaue Abtastung verwende, aber da ich nur eine Sybex Version besitze sind diese Befehle<br />
bei mir nicht möglich <strong>und</strong> ich möchte hier keine Skripte bzw. Befehle abdrucken die ich nicht<br />
getestet habe.<br />
Inhalt:<br />
1. Vorstellung des Skriptes<br />
2. Vorstellung der Aktion<br />
2.1 Die Aktion "entity_1"<br />
3. Vorstellung der Funktionen<br />
3.1 Die Funktion "function ent_col_event1();" // Event Funktion der Entity<br />
3.2 Die Funktion "function physik_1();" // Hauptfunktion der Entity<br />
3.3 Die Funktion "function Max_Min_Berechnung();" // Grenzen der Bo<strong>und</strong>ing Box<br />
3.4 Die Funktion "function Abstand_zum_Boden();" // Abstandsberechnung zum Boden<br />
3.5 Die Funktion "function Abstand_Ecken();" // Abstandsberechnung der Ecken<br />
3.6 Die Funktion "function Schieflage();" // Schieflage der Entity über Abgr<strong>und</strong><br />
3.7 Die Funktion "function Anziehungskraft();" // Anziehungskraftberechnung der Entity<br />
3.8 Die Funktion "function Drift();" // Drift der Entity bei Schieflage<br />
3.9 Die Funktion "function Kraftfaktor();" // Kraftfaktorberechnung bei Berührung<br />
3.10 Die Funktion "function Bewegung();" // Bewegung der Entity<br />
Bestimmte Variablen <strong>und</strong> die Handle der Entities werden im Skript in Arrays abgespeichert. Sollte<br />
Ihnen die Verwendungsweise von Arrays nicht geläufig sein, können Sie in diversen Publikationen<br />
<strong>und</strong> Tutorials mehr über diese Art der Speicherung erfahren. Im 3dgsMagazin No.2 finden Sie auch<br />
ein Tutorial über die Benutzung von Arrays. Ich werde hier nicht im Einzelnen auf die<br />
Funktionsweise von Arrays eingehen da dies den Rahmen hier sprengen würde.<br />
Sämtliche Funktionen funktionieren auch mit dem Player der Template Skripte. Sie müssen nicht<br />
erst einen eigenen Player-Skript schreiben.<br />
1. Vorstellung des Skriptes<br />
Zuerst einmal möchte ich Ihnen das Skript vorstellen. Danach werde ich im Einzelnen auf die<br />
verschiedenen Aktionen <strong>und</strong> Funktionen eingehen um Ihnen die Funktionsweise näher zu bringen.<br />
//////////////////////////////////////////<br />
//// Definitionen für Bewegungskörper ////<br />
//////////////////////////////////////////<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │20
define _gewicht,skill1;<br />
define _entity_x,skill2;<br />
define _entity_y,skill3;<br />
define _entity_z,skill4;<br />
define _MaxMin_x,skill8;<br />
define _MaxMin_y,skill9;<br />
define _MaxMin_z,skill10;<br />
//define _speed,skill11; // Noch nicht in Verwendung<br />
//define _speed_x,skill11; // Noch nicht in Verwendung<br />
//define _speed_y,skill12; // Noch nicht in Verwendung<br />
//define _speed_z,skill13; // Noch nicht in Verwendung<br />
define _dist_floorR,skill14;<br />
define _dist_floorL,skill15;<br />
define _dist_floorF,skill16;<br />
define _dist_floorB,skill17;<br />
define _dist_floorM,skill18;<br />
define _ABSOLDIS,skill34;<br />
define _ABSOLDIS_X,skill34;<br />
define _ABSOLDIS_Y,skill35;<br />
define _ABSOLDIS_Z,skill36;<br />
define _floornormal1,skill37;<br />
define _floornormal1_X,skill37;<br />
define _floornormal1_Y,skill38;<br />
define _floornormal1_Z,skill39;<br />
define _f_drift,skill40;<br />
define _move_x,skill41;<br />
define _move_y,skill42;<br />
define _force,skill43;<br />
define _move_force,skill44;<br />
define _Bewegung_Vert,skill45;<br />
define _Bodenhöhe,skill46;<br />
define ent_id,skill47;<br />
define entity_id,skill48;<br />
//////////////////////////////////////////////////////////<br />
//// Variablen in Verbindung mit Templates ausblenden ////<br />
//////////////////////////////////////////////////////////<br />
var force[3] =0,0,0;<br />
var friction;<br />
var slopefac;<br />
var gravity;<br />
///////////////////<br />
//// Variablen ////<br />
///////////////////<br />
var temp_1;<br />
var temp_2;<br />
var t;<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │21
}<br />
var ent_nr;<br />
/////////////////////////////<br />
//// String <strong>und</strong> Entities ////<br />
/////////////////////////////<br />
entity* Koerper;<br />
////////////////<br />
//// Arrays ////<br />
////////////////<br />
var ent_array1[8000];<br />
////////////////////<br />
//// Funktionen ////<br />
////////////////////<br />
function ent_col_event1(); // Event Funktion der Entity<br />
function Max_Min_Berechnung(); // Grenzen der Bo<strong>und</strong>ing Box<br />
function Abstand_zum_Boden(); // Abstandsberechnung zum Boden<br />
function Abstand_Ecken(); // Abstandsberechnung der Ecken der Entity zum Boden<br />
function Schieflage(); // Schieflage der Entity über Abgr<strong>und</strong><br />
function Anziehungskraft(); // Anziehungskraftberechnung der Entity<br />
function Drift(); // Drift der Entity bei Schieflage<br />
function Kraftfaktor(); // Kraftfaktorberechnung bei Berührung der Entity<br />
function Bewegung(); // Bewegung der Entity<br />
//uses _Gewicht,_entity_x,_entity_y,_entity_z,<br />
action entity_1<br />
{<br />
Koerper = my;<br />
t += 10;<br />
ent_nr = t;<br />
my.ent_id = ent_nr;<br />
my.fat = off;<br />
my.narrow = on;<br />
//my.passable = on;<br />
my.push = 0;<br />
if (my._gewicht == 0)<br />
{my._gewicht = 10;}<br />
my.event = ent_col_event1;<br />
my.enable_sonar = on;<br />
my.enable_shoot = on;<br />
my.enable_block = on;<br />
my.enable_entity = on;<br />
my.enable_impact = on;<br />
my.enable_push = on;<br />
my.enable_click = on;<br />
physik_1();<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │22
function ent_col_event1()<br />
{<br />
if(event_type == event_impact)<br />
{<br />
}<br />
if(my == null){return;}<br />
if(you == null){return;}<br />
ent_nr = my.ent_id;<br />
//// Koordinaten Trefferpunkt ////<br />
ent_array1[ent_nr*10+0] = target[0];<br />
ent_array1[ent_nr*10+1] = target[1];<br />
ent_array1[ent_nr*10+2] = target[2];<br />
//// Koordinaten auslösende Entity ////<br />
ent_array1[ent_nr*10+3] = you.x;<br />
ent_array1[ent_nr*10+4] = you.y;<br />
ent_array1[ent_nr*10+5] = you.z;<br />
//// Gewicht der Entity ////<br />
if(you.skill1 == 0){temp = 10;}<br />
if(player == you){temp = 10;}<br />
ent_array1[ent_nr*10+6] = temp;<br />
//// Geschwindigkeit der Entity ////<br />
if(you.skill11 == 0){you.skill11 = 10;}<br />
ent_array1[ent_nr*10+7] = you.skill11;<br />
//// Winkel Aufprallrichtung ////<br />
vec_diff(temp_1,target,you.x);<br />
//// Abprallwinkel ////<br />
vec_to_angle (temp,normal);<br />
ent_array1[ent_nr*10+8] = temp.pan;<br />
ent_array1[ent_nr*10+9] = temp.tilt;<br />
//// Schiebende Kraft ////<br />
my._force = ent_array1[ent_nr*10+6] * ent_array1[ent_nr*10+7];<br />
if(event_type == event_shoot)<br />
{<br />
if(my == null){return;}<br />
if(you == null){return;}<br />
ent_nr = my.ent_id;<br />
//// Koordinaten Trefferpunkt ////<br />
ent_array1[ent_nr*10+0] = target[0];<br />
ent_array1[ent_nr*10+1] = target[1];<br />
ent_array1[ent_nr*10+2] = target[2];<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │23
}<br />
}<br />
//// Koordinaten auslösende Entity ////<br />
ent_array1[ent_nr*10+3] = you.x;<br />
ent_array1[ent_nr*10+4] = you.y;<br />
ent_array1[ent_nr*10+5] = you.z;<br />
//// Gewicht der Entity ////<br />
temp = you.skill4;<br />
if(player == you){temp = 10;}<br />
ent_array1[ent_nr*10+6] = temp;<br />
//// Geschwindigkeit der Entity ////<br />
ent_array1[ent_nr*10+7] = you.skill5/2;<br />
//// Winkel Aufprallrichtung ////<br />
vec_diff(temp_1,target,you.x);<br />
//// Abprallwinkel ////<br />
vec_to_angle (temp,normal);<br />
ent_array1[ent_nr*10+8] = temp.pan;<br />
ent_array1[ent_nr*10+9] = temp.tilt;<br />
//// Schiebende Kraft ////<br />
my._force = ent_array1[ent_nr*10+6] * ent_array1[ent_nr*10+7];<br />
if (event_type == event_click) // Noch nicht in Verwendung<br />
{<br />
}<br />
koerper = me;<br />
function physik_1()<br />
{<br />
Max_Min_Berechnung();<br />
if(my._entity_x == 0)<br />
{<br />
}<br />
my._entity_x = my._MaxMin_x;<br />
if(my._entity_y == 0)<br />
{<br />
}<br />
my._entity_y = my._MaxMin_y;<br />
if(my._entity_z == 0)<br />
{<br />
}<br />
while(1)<br />
{<br />
my._entity_z = my._MaxMin_z;<br />
Abstand_zum_Boden();<br />
Abstand_Ecken();<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │24
}<br />
}<br />
Anziehungskraft();<br />
Schieflage();<br />
Drift();<br />
Kraftfaktor();<br />
Bewegung();<br />
wait(1);<br />
function Max_Min_Berechnung()<br />
{<br />
}<br />
my._MaxMin_x = (my.max_x - my.min_x);<br />
my._MaxMin_y = (my.max_y - my.min_y);<br />
my._MaxMin_z = (my.max_z - my.min_z);<br />
function Abstand_zum_Boden()<br />
{<br />
richten<br />
richten<br />
}<br />
vec_set (temp,nullvector);<br />
vec_set(temp,my.x);<br />
temp.z -=4000;<br />
vec_set(temp_1,my.x);<br />
temp_1.z = my.z - ((my._entity_z)/2);<br />
trace_mode = ignore_me + ignore_sprites + ignore_models + scan_texture;<br />
my._BODENHÖHE = trace(temp_1,temp);<br />
// my._BODENHÖHE beinhaltet die Entfernung zum Boden<br />
my._floornormal1_X = NORMAL.X;// my._floornormal auf die Normale des Bodens<br />
my._floornormal1_Y = NORMAL.Y;// my._floornormal auf die Normale des Bodens<br />
my._floornormal1_Z = NORMAL.Z;<br />
function Abstand_Ecken()<br />
{<br />
//// Trace von Mitte nach unten ////<br />
vec_set(temp.x,my.x);<br />
temp.z = my.z - (my._entity_z)/2;<br />
trace_mode = ignore_me + ignore_passable + ignore_passents;<br />
my._dist_floorM = trace(temp.x,vector(temp.x,temp.y,temp.z-500));<br />
//// Trace von links nach unten ////<br />
vec_set(temp.x,vector(0,(my._entity_y/2),0));<br />
vec_rotate(temp.x,vector(my.pan,0,0));<br />
vec_add(temp.x,my.x);<br />
temp.z = my.z - (my.max_z - my.min_z)/2;<br />
trace_mode = ignore_me + ignore_passable + ignore_passents;<br />
my._dist_floorL = trace(temp.x,vector(temp.x,temp.y,temp.z-500));<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │25
}<br />
//// Trace von rechts nach unten ////<br />
vec_set(temp.x,vector(0,-(my._entity_y/2),0));<br />
vec_rotate(temp.x,vector(my.pan,0,0));<br />
vec_add(temp.x,my.x);<br />
temp.z = my.z - (my._entity_z)/2;<br />
trace_mode = ignore_me + ignore_passable + ignore_passents;<br />
my._dist_floorR = trace(temp.x,vector(temp.x,temp.y,temp.z-500));<br />
//// Trace von vorne nach unten ////<br />
vec_set(temp.x,vector((my._entity_x/2),0,0));<br />
vec_rotate(temp.x,vector(my.pan,0,0));<br />
vec_add(temp.x,my.x);<br />
temp.z = my.z - (my._entity_z)/2;<br />
trace_mode = ignore_me + ignore_passable + ignore_passents;<br />
my._dist_floorF = trace(temp.x,vector(temp.x,temp.y,temp.z-500));<br />
//// Trace von hinten nach unten ////<br />
vec_set(temp.x,vector(-(my._entity_x/2),0,0));<br />
vec_rotate(temp.x,vector(my.pan,0,0));<br />
vec_add(temp.x,my.x);<br />
temp.z = my.z - (my._entity_z)/2;<br />
trace_mode = ignore_me + ignore_passable + ignore_passents;<br />
my._dist_floorB = trace(temp.x,vector(temp.x,temp.y,temp.z-500));<br />
function Schieflage()<br />
{<br />
temp = abs(my._dist_floorF - my._dist_floorB);<br />
if(temp 5 &&<br />
my._dist_floorF > 5 && my._dist_floorB > 5)<br />
{<br />
}<br />
return;<br />
if (my._dist_floorL >= 5)<br />
{<br />
temp = atan(my._dist_floorL/(my._entity_y/2));<br />
if(temp > abs(my.roll)) // Absolutberechnung da Roll negativ ist<br />
{<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │26
}<br />
}<br />
}<br />
my.roll -= 1 * time;<br />
if (my._dist_floorR >= 5)<br />
{<br />
}<br />
temp = atan(my._dist_floorR/(my._entity_y/2));<br />
if(temp > my.roll)<br />
{<br />
}<br />
my.roll += 1 * time;<br />
if (my._dist_floorF >= 5)<br />
{<br />
}<br />
temp = atan(my._dist_floorF/(my._entity_x/2));<br />
if(temp > abs(my.tilt)) // Absolutberechnung da Tilt negativ ist<br />
{<br />
}<br />
my.tilt -= 1 * time;<br />
if (my._dist_floorB >= 5)<br />
{<br />
}<br />
temp = atan(my._dist_floorB/(my._entity_x/2));<br />
if(temp > my.tilt)<br />
{<br />
}<br />
my.tilt += 1 * time;<br />
function Anziehungskraft()<br />
{<br />
if (my._dist_floorM>5&&my._dist_floorL>5&& my._dist_floorR>5&&my._dist_floorF>5&&<br />
my._dist_floorB > 5) // in der Luft?<br />
{<br />
}<br />
force.z = -5; // Schwerkraft<br />
friction = 0.1; // Luftwiederstand<br />
// Geschwindigkeit vertikal<br />
my._Bewegung_Vert = time*force.z + max(1-time*friction,0)*my._Bewegung_Vert;<br />
my._absoldis_Z = time * my._Bewegung_Vert;<br />
if (my._BODENHÖHE < 5 && my._BODENHÖHE > 0)<br />
{<br />
my._Bewegung_Vert = 0;<br />
my._absoldis_Z = 0;<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │27
}<br />
}<br />
if (my._BODENHÖHE < 0 )<br />
{<br />
}<br />
function Drift()<br />
{<br />
}<br />
force.z = -0.5 * my._BODENHÖHE; // Boden-Elastizität<br />
friction = 0.5; // Bodenreibung<br />
// Geschwindigkeit vertikal<br />
my._Bewegung_Vert = time*force.z + max(1-time*friction,0)*my._Bewegung_Vert;<br />
my._absoldis_Z = time * my._Bewegung_Vert;<br />
//// Kippbereich der Objekte ////<br />
if (my._dist_floorM 0 || my._move_force > 0)<br />
{<br />
}<br />
my._move_force = my._force * time + max(1-time*0.5,0)*my._move_force;<br />
my._force = 0;<br />
function Bewegung()<br />
{<br />
ent_nr = my.ent_id;<br />
if(my._move_force > 0)<br />
{<br />
my._absoldis_X =<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │28
(cos(ent_array1[ent_nr*10+8])*(my._move_force/ent_array1[ent_nr*10+6]))*time;<br />
my._absoldis_Y =<br />
(sin(ent_array1[ent_nr*10+8])*(my._move_force/ent_array1[ent_nr*10+6]))*time;<br />
}<br />
if(my._move_force
Diese Zuweisung brauchen wir allerdings erst in einem späteren Tutorial, wenn es darum geht<br />
diverse Kisten <strong>und</strong> dergleichen zu stapeln. Dann haben wir die Erhöhung der Array Variable. Ich<br />
werde verschiedene Parameter, wie Kollisionspunkt, Kollisionsgeschwindigkeit <strong>und</strong> diverse andere<br />
Angaben in einem Array speichern um Entity Skills zu sparen.<br />
In den nächsten zwei Zeilen, ent_nr = t <strong>und</strong> my.ent_id = ent_nr speichere ich den Anfangsarray<br />
jeder Entity in einem Entity Skill ab um später jeder Zeit wieder darauf zugreifen zu können. Dann<br />
schalte ich die dicke Hülle der Entity ab <strong>und</strong> die dünne ein. Gefolgt von der vorher Besprochenen<br />
Gewichtszuweisung von 10 kg wenn keine Eingabe im WED statt gef<strong>und</strong>en hat. Die Zuweisung der<br />
Event Funktion, die Sensibilisierung für gewisse Event Aktionen <strong>und</strong> der darauffolgende Sprung zur<br />
Hauptfunktion physik_1 beendet dann unsere Aktion entity_1.<br />
3. Vorstellung der Funktionen<br />
3.1 Die Funktion "ent_col_event1()"<br />
function ent_col_event1()<br />
{<br />
if(event_type == event_impact)<br />
{<br />
if(my == null){return;}<br />
if(you == null){return;}<br />
ent_nr = my.ent_id;<br />
//// Koordinaten Trefferpunkt ////<br />
ent_array1[ent_nr*10+0] = target[0];<br />
ent_array1[ent_nr*10+1] = target[1];<br />
ent_array1[ent_nr*10+2] = target[2];<br />
//// Koordinaten auslösende Entity ////<br />
ent_array1[ent_nr*10+3] = you.x;<br />
ent_array1[ent_nr*10+4] = you.y;<br />
ent_array1[ent_nr*10+5] = you.z;<br />
//// Gewicht der Entity ////<br />
if(you.skill1 == 0){temp = 10;}<br />
if(player == you){temp = 70;}<br />
ent_array1[ent_nr*10+6] = temp;<br />
//// Geschwindigkeit der Entity ////<br />
if(you.skill11 == 0){you.skill11 = 10;}<br />
ent_array1[ent_nr*10+7] = you.skill11;<br />
//// Winkel Aufprallrichtung //// // Wird noch nicht benötigt<br />
vec_diff(temp_1,target,you.x);<br />
//// Abprallwinkel ////<br />
vec_to_angle (temp,normal);<br />
ent_array1[ent_nr*10+8] = temp.pan;<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │30
}<br />
}<br />
ent_array1[ent_nr*10+9] = temp.tilt;<br />
//// Schiebende Kraft ////<br />
my._force = ent_array1[ent_nr*10+6] * ent_array1[ent_nr*10+7];<br />
if(event_type == event_shoot)<br />
{<br />
}<br />
if(my == null){return;}<br />
if(you == null){return;}<br />
ent_nr = my.ent_id;<br />
//// Koordinaten Trefferpunkt ////<br />
ent_array1[ent_nr*10+0] = target[0];<br />
ent_array1[ent_nr*10+1] = target[1];<br />
ent_array1[ent_nr*10+2] = target[2];<br />
//// Koordinaten auslösende Entity ////<br />
ent_array1[ent_nr*10+3] = you.x;<br />
ent_array1[ent_nr*10+4] = you.y;<br />
ent_array1[ent_nr*10+5] = you.z;<br />
//// Gewicht der Entity ////<br />
temp = you.skill4;<br />
ent_array1[ent_nr*10+6] = temp;<br />
//// Geschwindigkeit der Entity ////<br />
ent_array1[ent_nr*10+7] = you.skill5/2;<br />
//// Winkel Aufprallrichtung ////<br />
vec_diff(temp_1,target,you.x);<br />
//// Abprallwinkel ////<br />
vec_to_angle (temp,normal);<br />
ent_array1[ent_nr*10+8] = temp.pan;<br />
ent_array1[ent_nr*10+9] = temp.tilt;<br />
//// Schiebende Kraft ////<br />
my._force = ent_array1[ent_nr*10+6] * ent_array1[ent_nr*10+7];<br />
if (event_type == event_click) // Noch nicht in Verwendung<br />
{<br />
}<br />
koerper = me;<br />
Die erste If-Anweisung bezieht sich auf die Kollision mit einer anderen Entity. Gefolgt von zwei<br />
Anweisungen die sich auf die my- <strong>und</strong> you-Entity beziehen, dort wird bei nicht vorhanden sein<br />
einer der beiden Entities die Funktion sofort verlassen um etwaige Empty Pointer Fehlermeldungen<br />
aus dem Weg zu gehen. Danach kommt der Aufruf der Array Nummer aus dem Entity Skill um die<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │31
ganzen speicherbaren Werte auch in den richtigen Array Bereich zu speichern <strong>und</strong> nicht etwa in<br />
den Array Bereich einer anderen Entity die mit dieser Kollision garnichts zu tun hatte.<br />
In den folgenden Array Variablen wird gespeichert, der Kollisionspunkt an der Entity, die X-, Y- <strong>und</strong><br />
Z-Werte der kollidierenden Entity, das Gewicht <strong>und</strong> die Geschwindigkeit der Entity.<br />
Desweiteren die Winkelrichtung, die sich hier auf die Normale der Oberfläche beziehen. Und dann<br />
noch die Berechnung der Kraft die auf die Entity wirkt. Die Kraft berechnet man ja bekanntlich, wie<br />
jeder weiss der schon einmal Physik in der Schule gehabt hat, aus dem Produkt von Masse <strong>und</strong><br />
Beschleunigung.<br />
my._force = ent_array1[ent_nr*10+6]*ent_array1[ent_nr*10+7]<br />
Was bedeutet, meine Geschwindigkeit ist dein Gewicht mal deine Beschleunigung. In der If-<br />
Anweisung der shoot-Abfrage befinden sich die selben Berechnungen <strong>und</strong> Abfragen die wir vorher<br />
schon besprochen haben. Nur die Gewichts- <strong>und</strong> Geschwindigkeitsangaben der Entity beziehen sich<br />
hier auf andere Skill Werte. Für die Gewichtsberechnung ist hier der Skill4 <strong>und</strong> für die<br />
Geschwindigkeitsberechnung der Skill5 der kollidierenden Entity zuständig.<br />
Diese Skills finden auch in den Templates Verwendung. Deshalb habe ich sie auch hier verwendet<br />
um Template Benutzer auch die Möglichkeit zu geben dieses Skript hier zu verwenden. Die letzte<br />
If-Abfrage bezieht sich auf das Anklicken der Entity mit der linken Maustaste. Diese Abfrage findet<br />
erst in einem späteren Tutorial Verwendung, wenn wir versuchen diverse Kisten oder Tonnen <strong>und</strong><br />
dergleichen zu stapeln.<br />
3.2 Die Funktion "physik_1()"<br />
function physik_1()<br />
{<br />
Max_Min_Berechnung();<br />
if(my._entity_x == 0)<br />
{<br />
}<br />
my._entity_x = my._MaxMin_x;<br />
if(my._entity_y == 0)<br />
{<br />
}<br />
my._entity_y = my._MaxMin_y;<br />
if(my._entity_z == 0)<br />
{<br />
}<br />
while(1)<br />
{<br />
my._entity_z = my._MaxMin_z;<br />
Abstand_zum_Boden();<br />
Abstand_Ecken();<br />
Anziehungskraft();<br />
Schieflage();<br />
Drift();<br />
Kraftfaktor();<br />
Bewegung();<br />
wait(1);<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │32
}<br />
}<br />
Die Hauptfunktion unserer Entity beinhaltet den Sprung in sämtliche andere Funktionen der Entity.<br />
Ich wähle immer diesen Weg der Hauptfunktion <strong>und</strong> den Sprung in die Unterfunktionen da es mir<br />
auf diesem Wege möglich ist eventuell bei bestimmten Aktionen verschiedene Funktionen der<br />
Entity zu überspringen. Ich gehe hier nicht im einzelnen auf die verschiedenen Funktionssprünge<br />
ein da wir die Funktionen noch genau besprechen werden.<br />
Hier nur eine grobe Auflistung der Funktionen <strong>und</strong> für welche Berechnungen sie zuständig sind.<br />
function Max_Min_Berechnung(); // Grenzen der Bo<strong>und</strong>ing Box<br />
function Abstand_zum_Boden(); // Abstandsberechnung zum Boden<br />
function Abstand_Ecken(); // Abstandsberechnung der Ecken der Entity zum Boden<br />
function Anziehungskraft(); // Anziehungskraftberechnung der Entity<br />
function Schieflage(); // Schieflage der Entity über Abgr<strong>und</strong><br />
function Drift(); // Drift der Entity bei Schieflage<br />
function Kraftfaktor(); // Kraftfaktorberechnung bei Berührung der Entity<br />
function Bewegung(); // Bewegung der Entity<br />
Unterhalb des Funktionssprungs zur Max-Min Berechnung finden Sie die Zuweisung der Max-Min<br />
Parameter in die Entity_X Skills, diese Zuweisung findet statt wenn im WED keine Angaben der<br />
Ausdehnung der Entity gemacht werden.<br />
3.3 Die Funktion "Max_Min_Berechnung()"<br />
function Max_Min_Berechnung()<br />
{<br />
my._MaxMin_x = (my.max_x - my.min_x);<br />
my._MaxMin_y = (my.max_y - my.min_y);<br />
my._MaxMin_z = (my.max_z - my.min_z);<br />
}<br />
Hier berechnen wir die Grenzen der Bo<strong>und</strong>ing Box der Entity. Diese Berechnung könnte man sich<br />
sparen, sie ist nicht unbedingt nötig. Aber dann müsste man jedesmal wenn man die Grösse<br />
feststellen will immer wieder die Berechnung my.max-my.min durchführen. So spare ich mir das<br />
<strong>und</strong> schreibe es in einen Entity Skill.<br />
3.4 Die Funktion "Abstand_zum_Boden()"<br />
function Abstand_zum_Boden()<br />
{<br />
vec_set (temp,nullvector);<br />
vec_set(temp,my.x);<br />
temp.z -=4000;<br />
vec_set(temp_1,my.x);<br />
temp_1.z = my.z - ((my._entity_z)/2);<br />
trace_mode = ignore_me + ignore_sprites + ignore_models + scan_texture;<br />
// my._BODENHÖHE beinhaltet die Entfernung zum Boden<br />
my._BODENHÖHE = trace(temp_1,temp);<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │33
my._floornormal auf die Normale des Bodens richten<br />
my._floornormal1_X = NORMAL.X;<br />
my._floornormal1_Y = NORMAL.Y;<br />
my._floornormal1_Z = NORMAL.Z;<br />
}<br />
Zuerst Überschreiben wir den temp Vektor mit Null, danach weisen wir dem Vektor die X-, Y- <strong>und</strong><br />
Z-Werte der Entity zu <strong>und</strong> verändern den Z-Wert auf 4000 Quants unter der Entity.<br />
Als nächstes schreiben wir die Koordinaten der Entity in den temp_1 Vektor <strong>und</strong> verändern den Z-<br />
Wert so das sich der Punkt genau an den Füßen der Entity befindet. Nun die Angabe des<br />
trace_mode. Hier ignorieren wir die my Entity, Sprites, Modelle <strong>und</strong> scannen die Textur unterhalb<br />
der Entity. Ich verwende hier bewusst nicht use_box da es beim scannen durch kleinere oder<br />
größere Entities als die Bo<strong>und</strong>ing Box bzw. die Hülle zu ungewünschten <strong>und</strong> fehlerhaften Effekten<br />
kommen kann. Das Ergebnis des Trace wird dann in den Skill my._Bodenhöhe geschrieben. Die<br />
letzten drei Zeilen beziehen sich noch auf Winkel des Bodens unterhalb der Entity, also die Normale<br />
des Bodens.<br />
3.5 Die Funktion "Abstand_Ecken()"<br />
function Abstand_Ecken()<br />
{<br />
//// Trace von Mitte nach unten ////<br />
vec_set(temp.x,my.x);<br />
temp.z = my.z - (my._entity_z)/2;<br />
trace_mode = ignore_me + ignore_passable + ignore_passents;<br />
my._dist_floorM = trace(temp.x,vector(temp.x,temp.y,temp.z-500));<br />
//// Trace von links nach unten ////<br />
vec_set(temp.x,vector(0,(my._entity_y/2),0));<br />
vec_rotate(temp.x,vector(my.pan,0,0));<br />
vec_add(temp.x,my.x);<br />
temp.z = my.z - (my.max_z - my.min_z)/2;<br />
trace_mode = ignore_me + ignore_passable + ignore_passents;<br />
my._dist_floorL = trace(temp.x,vector(temp.x,temp.y,temp.z-500));<br />
//// Trace von rechts nach unten ////<br />
vec_set(temp.x,vector(0,-(my._entity_y/2),0));<br />
vec_rotate(temp.x,vector(my.pan,0,0));<br />
vec_add(temp.x,my.x);<br />
temp.z = my.z - (my._entity_z)/2;<br />
trace_mode = ignore_me + ignore_passable + ignore_passents;<br />
my._dist_floorR = trace(temp.x,vector(temp.x,temp.y,temp.z-500));<br />
//// Trace von vorne nach unten ////<br />
vec_set(temp.x,vector((my._entity_x/2),0,0));<br />
vec_rotate(temp.x,vector(my.pan,0,0));<br />
vec_add(temp.x,my.x);<br />
temp.z = my.z - (my._entity_z)/2;<br />
trace_mode = ignore_me + ignore_passable + ignore_passents;<br />
my._dist_floorF = trace(temp.x,vector(temp.x,temp.y,temp.z-500));<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │34
}<br />
//// Trace von hinten nach unten ////<br />
vec_set(temp.x,vector(-(my._entity_x/2),0,0));<br />
vec_rotate(temp.x,vector(my.pan,0,0));<br />
vec_add(temp.x,my.x);<br />
temp.z = my.z - (my._entity_z)/2;<br />
trace_mode = ignore_me + ignore_passable + ignore_passents;<br />
my._dist_floorB = trace(temp.x,vector(temp.x,temp.y,temp.z-500));<br />
In dieser Funktion wird der Abstand von jeder Ecke der Entity zum Boden gemessen. Ich werde das<br />
ganze an Hand des Trace von links nach unten erklären. Die anderen Anweisungen basieren auf<br />
dem gleichen Prinzip. in der ersten Zeile speichern wir in die temp-Variable einen Vektor dessen X-<br />
<strong>und</strong> Z-Wert null sind <strong>und</strong> nur sein Y-Wert die Größe der halben Entity-Breite aufweist. Diesen<br />
Vektor drehen wir nun durch vec_rotate in Bezug auf den Pan-Wert der Entity. Nach der Drehung<br />
haben wir einen Vektor der 90 Grad nach Links steht mit der Länge der halben Entity. So, jetzt<br />
haben wir die Richtung des Vektors festgelegt. Was jetzt noch fehlt ist die genaue Lage, denn bis<br />
jetzt sitzt der Vektor noch auf dem Nullpunkt des WED. Um den Vektor in die richtige Endlage zu<br />
verschieben verwenden wir den Befehl vec_add. Wir addieren nun zu unserem Vektor den Vektor<br />
der Entity <strong>und</strong> schon sitzt der Punkt den wir haben wollten 90 Grad links neben unsere Entity. Nun<br />
noch den Z-Wert an den unteren Punkt der Entity verschieben <strong>und</strong> schon haben wir unseren ersten<br />
Tracepunkt festgelegt. Im trace_mode ignorieren wir diesmal wieder die my-Entity, Blocks die das<br />
passable-Flag gesetzt haben <strong>und</strong> Modelle <strong>und</strong> Sprites die auf passable gesetzt sind. Dann wird der<br />
Trace von unserem linken Punkt in eine Tiefe von 500 Quants ausgeführt <strong>und</strong> in den Skill<br />
my._dist_floorL übertragen. Das ganze führen wir von allen vier seitlichen Punkten <strong>und</strong> von der<br />
Mitte der Entity aus.<br />
3.6 Die Funktion "Schieflage()"<br />
function Schieflage()<br />
{<br />
temp = abs(my._dist_floorF - my._dist_floorB);<br />
if(temp 5<br />
&& my._dist_floorF > 5 && my._dist_floorB > 5)<br />
{<br />
return;<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │35
}<br />
}<br />
if (my._dist_floorL >= 5)<br />
{<br />
}<br />
temp = atan(my._dist_floorL/(my._entity_y/2));<br />
if(temp > abs(my.roll)) // Absolutberechnung da Roll negativ ist<br />
{<br />
}<br />
my.roll -= 1 * time;<br />
if (my._dist_floorR >= 5)<br />
{<br />
}<br />
temp = atan(my._dist_floorR/(my._entity_y/2));<br />
if(temp > my.roll)<br />
{<br />
}<br />
my.roll += 1 * time;<br />
if (my._dist_floorF >= 5)<br />
{<br />
}<br />
temp = atan(my._dist_floorF/(my._entity_x/2));<br />
if(temp > abs(my.tilt)) // Absolutberechnung da Tilt negativ ist<br />
{<br />
}<br />
my.tilt -= 1 * time;<br />
if (my._dist_floorB >= 5)<br />
{<br />
}<br />
temp = atan(my._dist_floorB/(my._entity_x/2));<br />
if(temp > my.tilt)<br />
{<br />
}<br />
my.tilt += 1 * time;<br />
Die Funktion Schieflage ist dafür da um Objekte, wenn sie über einen Abgr<strong>und</strong> geschoben werden<br />
<strong>und</strong> sich ihr Schwerpunkt verlagert, abrutschen zu lassen <strong>und</strong> sie nicht erst mit der<br />
Anziehungskraft in Berührung kommen wenn sie komplett darüber hinweg geschoben wurden.<br />
Als erstes die Berechnung der Deaktivierung der Schieflage <strong>und</strong> der Drift. Wenn der Bodenabstand<br />
zwischen den zwei Punkten der Entity, z.b. der Absolutwert der Differenz des äusseren linken <strong>und</strong><br />
rechten Punktes der Entity, kleiner als 1 Quant ist werden der Tilt-Winkel der Entity <strong>und</strong> der<br />
Driftfaktor auf Null gesetzt. Die gleiche Berechnung findet für den vorderen <strong>und</strong> den hinteren Punkt<br />
statt. Danach kommen zwei Einträge, die die Funktion beenden. Einmal die Abfrage vom mittleren<br />
Punkt zum Boden. Wenn der Abstand kleiner 2 Quants ist wird die Funktion beendet.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │36
Das ist klar denn in diesem Fall wäre der Schwerpunkt nicht über dem Abgr<strong>und</strong> <strong>und</strong> im zweiten Fall<br />
die Abfrage alles Punkte der Entity nach unten, denn da würde ja der freie Fall nach unten<br />
vorliegen was eine seitliche Drift auch beenden würde. Als nächste folgt wieder die Abfrage der<br />
einzelnen Aussenpunkte der Entity ob diese mehr als 5 Quants vom Boden entfernt sind <strong>und</strong> die<br />
darauffolgende Berechnung des Neigungswinkels mit Hilfe des Arcustangens.<br />
Mit temp = atan(my._dist_floorL/(my._entity_y/2)) berechnen wir den Neigungswinkel der Entity.<br />
Neigungswinkel = Arcustangens(Abstand zum Boden Links / Halbe Entity Breite). Dies ist also der<br />
Neigungswinkel, den die Entity erreichen muss wenn sie über einen Abgr<strong>und</strong> geschoben wird. Es<br />
folgt nun die Abfrage ob der Neigungswinkel grösser als der momentane Winkel der Entity ist.<br />
Sollte das der Fall sein wird zyklisch der Wert 1 zum Winkel der Entity dazu addiert. Die<br />
Berechnung der Neigungswinkel der anderen 4 Eckpunkte findet auf die selbe Art statt.<br />
3.7 Die Funktion "Anziehungskraft()"<br />
function Anziehungskraft()<br />
{<br />
}<br />
// in der Luft?<br />
if (my._dist_floorM > 5 && my._dist_floorL > 5 && my._dist_floorR > 5 &&<br />
my._dist_floorF > 5 && my._dist_floorB > 5)<br />
{<br />
}<br />
force.z = -5; // Schwerkraft<br />
friction = 0.1; // Luftreibung<br />
// Geschwindigkeit vertikal<br />
my._Bewegung_Vert = time*force.z + max(1-time*friction,0)*my._Bewegung_Vert;<br />
my._absoldis_Z = time * my._Bewegung_Vert;<br />
// Bis zu 5 Quant über dem Boden<br />
if (my._BODENHÖHE < 5 && my._BODENHÖHE > 0)<br />
{<br />
}<br />
my._Bewegung_Vert = 0;<br />
my._absoldis_Z = 0;<br />
// Eintauchen im Boden<br />
if (my._BODENHÖHE < 0 )<br />
{<br />
}<br />
force.z = -0.5 * my._BODENHÖHE; // Boden-Elastizität<br />
friction = 0.5; // Bodenreibung<br />
// Geschwindigkeit vertikal<br />
my._Bewegung_Vert = time*force.z + max(1-time*friction,0)*my._Bewegung_Vert;<br />
my._absoldis_Z = time * my._Bewegung_Vert;<br />
Kümmern wir uns nun um die Anziehungskraft, die ja bekanntlich auf jeden Körper wirkt. Als<br />
erstes Testen wir ob sich die Entity in der Luft befindet. Das überprüfen wir indem wir feststellen ob<br />
sich jeder Aussenpunkt mindestens 5 Quants über dem Boden befindet. Ist dies der Fall übergeben<br />
wir die Parameter der Schwerkraft <strong>und</strong> der Luftreibung <strong>und</strong> berechnen damit eine negative, da die<br />
Schwerkraft den Wert -5 hat, vertikale Bewegung.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │37
Die Berechnung, Strecke = Zeit * Beschleunigung, ergibt nun die absolute Z-Distanz der Entity. Im<br />
nachfolgenden Schritt, 5 Quant über dem Boden, gebe ich der Entity die Freiheit nicht genau auf<br />
dem Boden aufzusitzen sondern bis zu 5 Quant darüber zu bleiben. Der nächste Funktionsschritt<br />
bezieht sich auf das Eintauchen im Boden. Hier wird die Entity wieder aus dem Boden<br />
herausgezogen. Der Gr<strong>und</strong>wert der Geschwindigkeit ist hier wieder negativ (force.z = -0.5), was<br />
bedeuten würde das wir bei der späteren Berechnung nocheinmal eine negative vertikale<br />
Bewegung hätten. Das ganze bekommt jedoch einen positiven Wert da der force.z-Wert mit der<br />
Bodenhöhe multipliziert wird <strong>und</strong> die ist sobald wir im Boden eintauchen negativ. Da bekanntlich<br />
Minus * Minus = Plus ist werden wir im Laufe der nachfolgenden Berechnungen durch den jetzt<br />
positiven force.z-Wert wieder aus dem Boden herausgedrückt.<br />
3.8 Die Funktion "Drift()"<br />
function Drift()<br />
{<br />
//// Kippbereich der Objekte ////<br />
if (my._dist_floorM 0 || my._move_force > 0)<br />
{<br />
my._move_force = my._force * time + max(1-time*0.5,0)*my._move_force;<br />
my._force = 0;<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │38
}<br />
}<br />
Wenn Sie sich noch erinnern haben wir unseren Kraftfaktor my._force schon am Anfang des<br />
Tutorials kennen gelernt <strong>und</strong> zwar in der Berechnung:<br />
//// Schiebende Kraft ////<br />
my._force = ent_array1[ent_nr*10+6] * ent_array1[ent_nr*10+7];<br />
Dies ist die Kollisionskraft die uns von den Objekten die mit der Entity zusammen gestossen sind<br />
mitgegeben wurde. In der ersten If-Anweisung wird überprüft ob im Moment eine Driftbewegung<br />
ausgeführt wird. Sollte dies der Fall sein werden der Kraftfaktor <strong>und</strong> die daraus resultierende<br />
Geschwindigkeit auf 0 gesetzt. Die nächste If-Abfrage überprüft ob noch eine Kraft auf die Entity<br />
wirkt <strong>und</strong> führt bei einem positivem Ergebnis die Berechnung der schiebenden Kraft fort <strong>und</strong> setzt<br />
den Kraftfaktor auf 0. Das Rücksetzen des Kraftfaktors bewirkt, dass nach dem Erreichen der<br />
maximalen Geschwindigkeit die Entity wieder bis auf 0 abgebremst wird. Was in der Realität für<br />
Kraftbewegungen genauso zutrifft.<br />
3.10 Die Funktion "Bewegung()"<br />
function Bewegung()<br />
{<br />
{<br />
}<br />
ent_nr = my.ent_id;<br />
if(my._move_force > 0)<br />
my._absoldis_X = (cos(ent_array1[ent_nr*10+8])*(my._move_force/my._gewicht))*time;<br />
my._absoldis_Y = (sin(ent_array1[ent_nr*10+8])*(my._move_force/my._gewicht))*time;<br />
if(my._move_force
Bewegungsweg. Genau dieselbe Berechnung führen wir bei der Y-Verschiebung aus. In der<br />
nächsten If-Anweisung überprüfen wir ob noch eine Verschiebung der Entity durch die Drift oder<br />
die Kraftbewegung ausgeführt wird uns setzen bei keiner ausübenden Bewegung die X- <strong>und</strong> Y-<br />
Verschiebung auf 0. Gefolgt wird das Ganze von der Angabe des move_mode <strong>und</strong> der<br />
anschliessenden Bewegung der Entity mit den Absolutwerten.<br />
Ich hoffe ich konnte Ihnen einen kleinen Einblick in die Welt der einfachen Physik vermitteln. In<br />
einem der nächsten Tutorials werden ich noch die Bewegung auf schiefen Ebenen, Rotation, das<br />
Hochheben <strong>und</strong> Stapeln von Fässern oder Kisten basierend auf diesem Physik-Skript besprechen.<br />
Für Fragen <strong>und</strong> Anregungen stehe ich Ihnen gerne unter meiner E-Mail Adr.<br />
aras_game@chefmail.de<br />
MFG<br />
ARAS14<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │40
Zum Kugeln<br />
oder: Der einfache weg zum nahtlosen UV-Gitter<br />
Willkommen zu meinem ersten Tutorial über Mapping <strong>und</strong> 3d-Modelle. Auf zwei Seiten werden Sie<br />
lernen, wie einfach es ist, eines der schwersten Objekte im Raum auf eine Fläche abzuwickeln <strong>und</strong><br />
mit einer Textur zu versehen.<br />
Vorher sollte Ihnen aber klar sein, dass diese, wie jede andere Methode auch, ihre Probleme hat<br />
<strong>und</strong> keineswegs der ultimative Weg zum Glück ist. So eignet sich die Methode gut für Nebel-<br />
Spheres oder Asteroiden, weniger aber für Himmelskörper wie Globen oder Planeten, bei denen es<br />
auf die möglichst verzerrungsfreie Darstellung der Textur ankommt. Hier bleibt Ihnen wohl<br />
vorläufig nichts Anderes übrig, als Ihre Texturen von Hand einzupassen.<br />
Wir beginnen zunächst mit einem Ausgangsbild.<br />
Es ist weder kachelbar, noch für Kugeln angepasst. Für die Umwandlung des Bildes benötigen wir<br />
zwei kostenlose Plugins für Grafikprogramme wie beispielsweise Photoshop oder Paint Shop Pro,<br />
aber auch kostenlose Programme werden unterstützt.<br />
Besuchen Sie http://www.richardrosenman.com/software/downloads/, hier finden Sie auch die<br />
volle Liste der unterstützen Programme. Die benötigten Plugins heißen „Spherical Mapping<br />
Corrector" <strong>und</strong> „Tiler", laden Sie sie herunter <strong>und</strong> entpacken Sie die Zip-Archive in den Plugin-<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │41
Ordner Ihres Malprogrammes.<br />
1) Laden Sie das Bild in Ihr Grafikprogramm.<br />
2) Führen Sie das Plugin „Spherical Mapping Corrector" aus.<br />
3) Nutzen Sie das Plugin „Tiler", um die rechten <strong>und</strong> linken Kanten nahtlos ineinander über gehen<br />
zu lassen, Sie können die Werte des Screenshots als Referenz nehmen:<br />
4) Wickeln Sie Ihre Kugel mit einem Sphere-Mapping- Algorithmus in Ihrem 3d-Programm aus, so<br />
dass das Gitter wie im folgenden Bild aussieht:<br />
Sowohl Cinema4d <strong>und</strong> 3ds Max, als auch kostenlose bzw. kostengünstige Tools wie Wings3d,<br />
UltimateUnwrap/LithUnwrap oder Blender werden mit einem Knopfdruck damit fertig. Texturieren<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │42
Sie Ihre Kugel mit der soeben erstellten Map et voilà. Keine Pole, keine Nähte.<br />
Ein Wermutstropfen bleibt jedoch, streckenweise ist die Textur leicht verzerrt, somit sollte Ihre Map<br />
eine vernünftige Auflösung besitzen <strong>und</strong> keine Beschriftungen oder Ähnliches beinhalten.<br />
Felix Caffier<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │43
Jetzt gibt's auf die Ohren! So<strong>und</strong>effekte Teil 3<br />
Herzlich willkommen zum dritten Teil des So<strong>und</strong>effekt Tutorials.<br />
Heute werden wir einen verwendbaren So<strong>und</strong> designen, einen Schuss, um genau zu sein. Dieser<br />
hier passt am ehesten zu einer Maschinenpistole oder ähnlichem. Sie werden erfahren wie Sie den<br />
So<strong>und</strong> erstellen, ihn bearbeiten <strong>und</strong> in die Engine einfügen. Und Sie werden vielleicht überrascht<br />
sein, wie simpel die Gr<strong>und</strong>sätze mal wieder sind.<br />
Zusätzlich gibt es einige Tipps <strong>und</strong> Tricks zur Einbindung von So<strong>und</strong>s in <strong>Gamestudio</strong>.<br />
Um dieses Tutorial durcharbeiten zu können benötigen Sie den „So<strong>und</strong>forum Synth V 1.0", den Sie<br />
hier erhalten:<br />
http://www1.keyboards.de/so<strong>und</strong>forum.htm#dersynthesizer<br />
WARNUNG: Softwaresynthesizer können jeden möglichen <strong>und</strong> unmöglichen Ton<br />
erzeugen. Auch solche, die jenseits der Leistungsfähigkeit Ihrer Lautsprecher liegen!<br />
Seien Sie vorsichtig, beginnen Sie mit niedrigen Lautstärken <strong>und</strong> verwenden Sie bitte<br />
keine Kopfhörer. Der Schalldruck kann ungeahnte Ausmaße annehmen <strong>und</strong> zu<br />
Hörschäden führen! Ich übernehme keine Verantwortung für materielle <strong>und</strong> / oder<br />
körperliche Schäden die aus der Benutzung dieses Tutorials resultieren.<br />
Starten Sie den So<strong>und</strong>forum Synth <strong>und</strong> wählen Sie die Voreinstellung „Basic Noise".<br />
Wenn Sie einige Tasten drücken, können Sie in der Tat ein Rauschen hören. Nun wollen wir daraus<br />
einen Schuss generieren.<br />
Um Sie nicht zu sehr zu verwirren, stellen wir erstmal alle Hüllkurvenregler auf null, ausgenommen<br />
die „Decay" Regler, die kommen auf 20.<br />
Schauen Sie sich das Bild dazu an:<br />
In der Filter Sektion stellen Sie bitte „Cutoff" auf 70 ein <strong>und</strong> „Env" auf 40. Es werden also nur<br />
tiefere Frequenzen durchgelassen, wobei die Hüllkurve des Filters auch etwas Einfluss hat.<br />
„K-Track" stellen Sie bitte auf Null, um unerwünschte Tonhöheneinflüsse durch das Keyboard<br />
auszuschließen.<br />
Nun müssen Sie etwas lauter machen, entweder am „Level" Regler des Synth oder an Ihren Boxen.<br />
Der Gr<strong>und</strong> hierfür: Der Filter lässt nur noch tiefe Frequenzen durch. Da diese im hellen Rauschen<br />
nur sehr leise vorhanden sind, müssen<br />
Sie sie verstärken.<br />
Was da so ein wenig nach klopfen auf Holz klingt, ist Ihr Ausgangsmaterial für den Schuss!<br />
Nun wird es Zeit für eine bittere Pille: Der So<strong>und</strong>forum Synth kann keine So<strong>und</strong>s exportieren.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │44
Wenn sie über die So<strong>und</strong>karte abgenommen werden, klingen sie sehr verrauscht.<br />
Um Ihnen dennoch die Möglichkeit zu geben, den So<strong>und</strong> fertig zu machen, habe ich mit Reaktor4<br />
den gleichen So<strong>und</strong> erstellt <strong>und</strong> hochgeladen. Sie finden sämtliche Dateien hier:<br />
http://home.arcor.de/braindamaged/so<strong>und</strong>tut3.zip<br />
Zusätzlich brauchen Sie noch das folgende Programm: http://www.audacity.de<br />
Dieses Programm dient zur Bearbeitung von Audiodaten. Genau daß, was Sie brauchen. Und<br />
obendrein kostet es keinen Cent!<br />
Stellen Sie sicher, daß ein Ogg-Codec auf ihrem System installiert ist.<br />
Nach dem starten von Audacity <strong>und</strong> öffnen der Datei „shot1.ogg" bietet sich Ihnen folgendes Bild:<br />
Der So<strong>und</strong> ist immer noch recht leise <strong>und</strong> liegt in Stereo vor. Das ist nicht unbedingt gut. Für einen<br />
Schuß lohnt es sich nicht, auf Stereo zu pochen. Mono reicht hier völlig aus.<br />
Klicken Sie hierzu links neben der oberen „Tonspur" auf den Pfeil bei „shot1". Nun öffnet sich ein<br />
kleines Kontextmenü, in dem Sie „Stereotonspur aufteilen" wählen.<br />
Mit einem Klick auf das Kreuz der zweiten Tonspur löschen Sie diese. Nun ist nur noch eine übrig,<br />
die Sie über das Kontextmenü auf „Mono" setzen können.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │45
Wählen Sie „Bearbeiten" --> „Auswählen" --> „Alles". Dies ist nötig, um den So<strong>und</strong> lauter zu<br />
machen.<br />
Wählen Sie nun „Effekt" --> „Verstärken":<br />
Klicken Sie auf „Ok". Nun ist der So<strong>und</strong> wesentlich lauter. Wählen Sie mit der Maus den stillen<br />
Bereich vor dem So<strong>und</strong> aus <strong>und</strong> löschen Sie ihn mit „Bearbeiten" --> „Auswahl löschen". Mit der<br />
stillen Stelle nach dem So<strong>und</strong> verfahren Sie genauso. Nun ist der So<strong>und</strong> auch schön handlich:<br />
Leider klingt er noch nicht überzeugend. Um ihm etwas mehr punch zu geben, schauen Sie mal<br />
unter „Effekt" --> „Tonhöhe (Pitch) ändern":<br />
Wählen Sie einen Wert von 40%. Wenn Sie damit schon zufrieden sind, können Sie den So<strong>und</strong> als<br />
Ogg oder Wav exportieren. Ich rate Ihnen zu Ogg - sie sind wesentlich kleiner <strong>und</strong> kosten keine<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │46
Lizenzgebühren wie mp3. Das dazu ein extra Codec nötig ist, kann man verschmerzen.<br />
Spielen wir ein wenig mit dem Kompressor herum:<br />
Markieren Sie alles wenn dies nicht schon der Fall ist. Gehen Sie auf "Effekte" --> "Kompressor".<br />
Es ist wichtig daß Sie die Ansprechzeit auf 0,1 Sek<strong>und</strong>en stellen. Ansonsten spricht der Effekt zu<br />
spät an.<br />
Lassen Sie sich nicht täuschen, sollten Sie kaum einen Unterschied hören beim experimentieren<br />
mit diesem Effekt.<br />
In der Wiederholung als MG-So<strong>und</strong> wirken sich auch kleine Änderungen aus.<br />
Starten Sie „shot.exe" <strong>und</strong> schauen Sie sich die wdl Datei an, um einen Eindruck davon zu<br />
bekommen, wie man den So<strong>und</strong> einsetzen könnte. Vor allem mit der „snd_tune" Anweisung kann<br />
man einiges anstellen.<br />
Ich hoffe, es hat Ihnen Spass gemacht. Natürlich kann es dieser So<strong>und</strong> nicht mit aktuellen So<strong>und</strong>s<br />
aus der Spielebranche aufnehmen. Hierfür ist der So<strong>und</strong>forum Synth nicht flexibel genug. Aber<br />
lassen Sie sich gesagt sein: Auch die Profis kochen nur mit Wasser. ;-)<br />
Letztlich wird nahezu jede Explosion <strong>und</strong> jeder Schuss aus Rauschen generiert. Ob es von einem<br />
Oszillator produziert wurde oder ursprünglich ein ganz anderes Geräusch (im wahrsten Sinne) war,<br />
ist nur eine Möglichkeit der Variation.<br />
Das nächste Mal werden wir uns mit der Verfremdung <strong>und</strong> Veränderung von bereits vorhandenen<br />
So<strong>und</strong>s mit Audacity beschäftigen. Außerdem lernen Sie, wie Sie mit vertretbarem Aufwand gute<br />
Aufnahmen erstellen können.<br />
Ich wünsche Ihnen viel Spass bis dahin, Torsten Fock<br />
www.vulkanware.de<br />
Tipps <strong>und</strong> Tricks zur Einbindung<br />
snd_tune(handle, Volume, Freq, balance);<br />
Diese Anweisung hilft Ihnen, etwas Zufall in die Sache zu bringen oder Motorenso<strong>und</strong>s zu steuern.<br />
Schauen Sie sich das folgende, kurze Script an:<br />
function play_crossfire<br />
{<br />
var sndhandle;<br />
sndhandle = snd_play(crossfire_snd, 100, 0);<br />
temp = random(20)+90;<br />
snd_tune(sndhandle, temp, temp, 0);<br />
}<br />
Hier wird direkt nachdem der So<strong>und</strong> angestossen wurde seine Frequenz (<strong>und</strong> die<br />
Abspielgeschwindigkeit!) sowie die Lautstärke zufällig geändert. Dies eignet sich sehr gut für<br />
Kreuzfeuer, Querschläger, Explosionen u.s.w.<br />
Gehso<strong>und</strong>s zur Animation synchronisieren:<br />
-skill1 muß auf 1 gesetzt werden, wenn die Entity läuft.<br />
-skill2 ist in diesem Beispiel der animationszähler der Figur 0...100%.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │47
function char_so<strong>und</strong>s<br />
{<br />
while(me)<br />
{<br />
}<br />
if(my.skill1 == 1) // ich laufe<br />
{<br />
}<br />
snd_play(walk_1_snd, 100, 0);<br />
while(my.skill2 < 50){wait(1);}<br />
snd_play(walk_1_snd, 100, 0);<br />
while(my.skill2 > 0){wait(1);}<br />
wait(1);<br />
}<br />
Motorengeräusche:<br />
freq ist eine Variable, die von der Geschwindigkeit des Wagens beeinflußt wird.<br />
Wenn Sie es realer haben wollen, müssen Sie in ein aufwändigeres Script anfertigen, daß sich mit<br />
der "Drehzahl" der Reifen <strong>und</strong> dem Zustand der Gangschaltung beschäftigt.<br />
function tune_so<strong>und</strong><br />
{<br />
var so<strong>und</strong>handle;<br />
so<strong>und</strong>handle = snd_loop(engine_snd, 100, 0) // oder ent_playloop benutzen, je nach Bedarf<br />
while(me)<br />
{<br />
}<br />
snd_tune(so<strong>und</strong>handle, 0, freq, 0);<br />
wait(1 ;<br />
}<br />
var doppler_factor<br />
Kennen Sie die Variable "doppler_factor"?<br />
Sie dient dazu den bekannten Doppler-Effekt zu steuern. Je nach Wert (0-10) ist der Effekt weniger<br />
oder mehr ausgeprägt.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │48
Versionskontrolle mit Subversion<br />
mit Beispielen anhand einer <strong>3D</strong> <strong>Gamestudio</strong> Demo-Applikation von Christian Behrenberg<br />
Vorwort<br />
Dieser Artikel sollte eigentlich kürzer werden als er tatsächlich wurde. Aber ich habe schnell<br />
gesehen, dass eine Auflistung aller basics r<strong>und</strong> um Subversion <strong>und</strong> eine knappe Erklärung, was<br />
man da macht, einfach nicht genug ist. Ich habe eine Einführung in die Revisionskontrolle<br />
eingefügt <strong>und</strong> anhand eines trivialen Beispiels mit dem <strong>3D</strong>GS das ganze versucht, anschaulich zu<br />
machen. Literaturangaben <strong>und</strong> Quellen stehen am Ende des Artikels. Ich setze meine Hoffnungen<br />
darin, das wenigstens ein paar Leute von diesem Artikel profitieren. Viele Menschen, die sich mal<br />
kurz mit der Revisionskontrolle auseinandersetzen, sagen, dass es zuviel Aufwand sei. Vor allem<br />
bei kleineren Projekten <strong>und</strong> wenn man alleine arbeiten würde. Ich sehe das nicht so, weil mir das<br />
SVN eine Menge Sicherheit <strong>und</strong> Möglichkeiten bietet <strong>und</strong> mich durchdachter meine Projekte planen<br />
lässt. In der professionellen Softwareentwicklung ist eine RC (= Revision Control) unabdingbar, weil<br />
dadurch die Entwicklungszeit dramatisch verkürzt wird <strong>und</strong> dem Projekt eine nötige Stabilität <strong>und</strong><br />
Flexibilität verliehen wird. Viele kleine bis große Projekte, die unglaubliches Potential haben,<br />
scheitern genau an diesem Punkt. Wissen <strong>und</strong> Erfahrung auf dem Gebiet des Projektmanagements<br />
<strong>und</strong> den entsprechenden Tools dafür ist für die meisten ein gigantischer Schritt auf dem Weg vom<br />
eher „dreckigen" oder „schluderigen" Weg der Projektführung (oder von Softwareentwicklung<br />
allgemein) zu einem erfolgreicheren Weg - der zum gewünschten Ziel führt. Zwar gehört dazu eine<br />
Menge eigener Einsatz (<strong>und</strong> vor allem der Wille!), aber wenn man weiß, was man machen kann,<br />
dann ist einem auch schon geholfen - vorrausgesetzt, man wendet es auch an ;) RC ist ein<br />
Standard in der Industrie <strong>und</strong> je früher man damit anfängt, desto besser ist das für sich selbst, für<br />
das Team, aber am meisten für das Projekt. Deshalb hoffe ich, dass der Leser das Potenzial sieht<br />
<strong>und</strong> nicht vor dem Artikel kapituliert - die investierte Zeit wird sich rentieren, ganz sicher.<br />
Einführung<br />
Typische Fehler in der Softwareentwicklung<br />
Wer mit Spieleprojekten vertraut ist, bei denen sehr viel Quelltext <strong>und</strong> sehr viel Content produziert<br />
wird, kennt so einige Situationen, in denen man fast verzweifelt, weil durch einen unglücklichen<br />
Umstand das komplette Projekt auf der Kippe steht. Vor allem aber passieren solche Vorfälle auch<br />
dann, wenn mehrere Leute an einem Projekt arbeiten. Hier nun einige Fälle, die Sie sicherlich<br />
schon einmal durchlebt haben:<br />
✗ Irgendwas im code funktioniert nicht, man sucht den Fehler, man baut zahlreiche Fixes ein <strong>und</strong><br />
am Ende bricht das ganze Programm ein. Nach etlichen St<strong>und</strong>en oder Tagen Arbeitszeit hat man<br />
dann mühsam durch teilweise lückenhafte Backups den code wiederhergestellt <strong>und</strong> vielleicht<br />
funktioniert das Programm dann wieder - oder eben nicht. Das Projekt ist zum Scheitern verurteilt.<br />
✗ Mehrere Programmierer haben an verschiedenen Spielmodulen gearbeitet <strong>und</strong> wollen nun alles<br />
zusammenfügen - ein heilloses Chaos. Denn wie es aussieht, hat jeder Programmierer irgendwo<br />
anders Modifikationen vorgenommen <strong>und</strong> man kann die neuen Sachen nicht einfach so<br />
zusammenfügen. Es geht viel Zeit verloren, nur um die Sachen lauffähig ins Spiel zu integrieren -<br />
sofern jemand dazu in der Lage ist, das überhaupt zu bewerkstelligen.<br />
✗ Es arbeiten mehrere Leute an einem Projekt <strong>und</strong> alle sind über das Internet verstreut. Jeder will<br />
die aktuelle Version haben, aber es gibt nur den Teamleiter, der immer den aktuellen Stand hat <strong>und</strong><br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │49
mal alle paar Wochen eine Version rausgibt, weil das immer so kompliziert ist mit dem<br />
Zusammenpacken aller Daten. Ist er verhindert oder krank, kann das Projekt nicht fortgeführt<br />
werden - alle müssen warten.<br />
✗ Man kann nicht verfolgen, wer was wann gemacht hat. Wenn man dann beim Debuggen nach<br />
Fehlern sucht <strong>und</strong> genau wissen muss, wann wo welche Änderungen weshalb von wem gemacht<br />
worden sind - dann ist man meistens aufgeschmissen - weil es eben niemand weiß!<br />
✗ Etc.pp. - typische Softwarefallen halt.<br />
Solche Fälle passieren zu Hauf während einer Softwareentwicklung. In solchen Fällen leidet das<br />
Team - <strong>und</strong> die Organisation bzw. die Projektverwaltung nimmt immer mehr Zeit in Anspruch als<br />
notwendig. Mit einer sogenannten Versionskontrolle sind aber alle diese Probleme gelöst.<br />
Was ist eine „Versionsverwaltung" <strong>und</strong> was hat das mit<br />
Spieleentwicklung zutun?<br />
Versionsverwaltung<br />
Unter einer Versionsverwaltung versteht man ein System, welches typischerweise in der<br />
Softwareentwicklung zur Versionierung <strong>und</strong> um den gemeinsamen Zugriff auf Quelltexte zu<br />
kontrollieren, eingesetzt wird. Das System hält dabei immer die Änderung der Datei(en) fest, wer<br />
sie bearbeitet hat <strong>und</strong> wann er das getan hat. Wogegen binäre Dateien (Bilder, Musik, etc.) immer<br />
komplett gespeichert werden, werden bei Textdateien (code, Dokumentation, etc.) immer nur die<br />
Unterschiede gespeichert, sodass man sich auch die Unterschiede anschauen kann - insbesondere<br />
dann nützlich wenn man schauen will, was man selbst oder jemand anderes im code eigentlich so<br />
verändert hat. Das ist sehr nützlich bei der Entwicklung von Programmen, Dokumentationen <strong>und</strong><br />
Veröffentlichungen, insbesondere auch dann, wenn mehrere Entwickler daran beteiligt sind.<br />
Dabei wird sichergestellt, dass jeder Benutzer mit dem aktuellen Stand arbeitet oder auf Wunsch<br />
auf die archivierten Stände zugreifen kann. Dadurch ist eine Versionsverwaltung nicht nur für<br />
professionelle Entwickler in großen Teams, sondern auch für einzelne Entwickler interessant. Es<br />
kann jederzeit eine ältere Version aufgerufen werden, falls eine Änderung nicht funktioniert <strong>und</strong><br />
man sich nicht mehr sicher ist, was nun alles geändert wurde - somit sind solche GAUs irrelevant,<br />
weil man jederzeit auf die letzte funktionierende Fassung zurückgreifen kann. Dadurch, dass man<br />
immer funktionierende Versionen in das System einfügt <strong>und</strong> anderen zugänglich macht, ist damit<br />
schlussfolglich auch immer sichergestellt, dass jeder Benutzer Zugriff auf die aktuell voll funktions-<br />
<strong>und</strong> lauffähige Version der Software hat.<br />
Anwendung bei Spieleprojekten<br />
Spieleentwicklungen sind technisch gesehen die anspruchsvollsten Softwareproduktionen<br />
überhaupt: man realisiert mehr oder weniger anspruchsvolle Softwarelösungen für die<br />
verschiedensten Anforderungen, die es in der modernen Softwareentwicklung gibt. Dazu kommt,<br />
dass heutezutage der Anteil des Grafik-contents immer beträchtlicher wird. Kein W<strong>und</strong>er, dass an<br />
kommerziellen Spielen Dutzende Leute arbeiten, zum Teil in verschiedene Teams unterteilt <strong>und</strong> in<br />
diesen Teams Untergruppen mit verschiedenen Aufgabenbereichen. Auch kleine, unabhängige<br />
Produktionen beschäftigen mittlerweile ein Gruppe von Entwicklern, die zusammen an einem Spiel<br />
arbeiten. Solche Probleme, wie sie oben geschildert sind, wären wie ein halber Todesstoß für das<br />
Projekt. Viele Amateur-Entwickler schließen sich nun auch über das Internet zusammen, um<br />
gemeinsam an kleinen Spielen zu basteln.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │50
Die meisten Projekte scheitern allerdings, was statistisch gesehen durchaus plausibel ist: fehlende<br />
Erfahrung, keine Geldmittel für Tools <strong>und</strong> eine <strong>und</strong>urchdachte, fast chaotische Organisation<br />
kristalliert sich schon nach kurzer Zeit heraus. Man kann davon ausgehen, dass über 75% dieser<br />
„Projekte" den Bach runtergehen. Das liegt aber auch daran, das meistens nur eine, maximal zwei<br />
Personen Zugang zum source-code des Spiels haben. Das ist dann auch schon meistens der Haken,<br />
weil diese Person selber entwickelt <strong>und</strong> meistens keine Ahnung davon hat, was sie eigentlich zutun<br />
hat. Es entsteht kein echter Workflow, weil jeder nur über diese eine Person Zugang hat.<br />
Ein Revision Control System, z.B. „Subversion", löst aber alle diese Probleme (s.o.). Nun können<br />
alle Leute gleichzeitig an dem Spiel arbeiten, jederzeit eine aktuelle Version herunterladen, Zugriff<br />
auf alle Änderungen haben, zu unterschiedlichen Zeiten daran arbeiten <strong>und</strong> live neue<br />
Dateiversionen einspielen, wenn man zeitgleich zeitkritisch an einem bugfix arbeitet, etc. Grafiker<br />
können dann auch ihre Dateien unter Revision Control setzen, Änderungen durchführen <strong>und</strong> wenn<br />
Sie später feststellen, dass die aktuellen Änderung im Spiel schlecht aussehen, das ändern.<br />
Komplizierte Backupsysteme sind somit nicht mehr nötig <strong>und</strong> die Entwicklung kann viel<br />
dynamischer <strong>und</strong> viel sicherer stattfinden.<br />
Subversion <strong>und</strong> andere Tools<br />
Es gibt eine Reihe von Revision Control Software auf dem Markt, sowohl kommerzielle als auch<br />
kostenlose. Subversion ist ein Open Source Projekt <strong>und</strong> der inoffizielle Nachfolger von CVS. Es gibt<br />
auch einige Tools, wie z.B AlienBrain, die speziell auf content-reiche Projekte, wie eben<br />
Spieleproduktionen, ausgelegt sind. Allerdings kosten diese auch z.T. viel Geld. Es gibt eine<br />
Windows shell-extension für Subversion, „Tortoise SVN" genannt, welches in diesem Artikel<br />
vorgestellt <strong>und</strong> benutzt wird. Im Folgenden wird Subversion mit SVN abgekürzt.<br />
Download <strong>und</strong> Installation von Subversion auf einem Einzelplatz PC<br />
✔ Besuchen Sie die Internetseite http://tortoisesvn.tigris.org/<br />
✔ Klicken Sie auf den Bereich „Download" (http://tortoisesvn.net/downloads)<br />
✔ Es werden 32-bit <strong>und</strong> 64-bit Versionen vom SVN angeboten. Klicken Sie auf die entsprechende<br />
Installerfile. Sie werden automatisch auf die entsprechende Source Forge Seite re-directed, wo Sie<br />
automatisch die Installationsdatei herunterladen.<br />
✔ Wenn Sie die Datei herunterladen haben, starten Sie sie <strong>und</strong> folgen Sie den<br />
Bildschirmanweisungen. Am Ende haben Sie das SVN <strong>und</strong> die Tortoise shell erfolgreich installiert.<br />
Eventuell müssen Sie den PC neustarten.<br />
Wie funktioniert das SVN?<br />
Eine kleine Geschichte<br />
Das SVN benutzt ein sogenanntes Repository. Diese Repository logged alle geänderten Dateien,<br />
Modifikationen im SVN, wer was wann gemacht hat. Wenn Sie einen neuen Ordner erstellen <strong>und</strong><br />
dort die aktuellste Version der unter RC gestellten Dateien haben wollen, so ziehen Sie eine<br />
sogenannte Working Copy („WC") - dies impliziert, dass jede WC lauffähig <strong>und</strong> funktionabel ist.<br />
Stellen Sie sich nun vor, Sie sind Programmierer <strong>und</strong> wollen eine Änderung vornehmen, z.B. die<br />
Gegner in Ihrem Spiel intelligenter machen. Sie ändern die Dateien in der WC <strong>und</strong> wollen diese<br />
geänderten Dateien nun in das Repository hochladen (damit die anderen Entwickler des Spiels<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │51
auch Zugriff auf den geändert Code haben). Den Upload ins Repository nennt man „Commit". Das<br />
heißt, dass Sie ihre Änderungen dem System mitteilen. Es wird nicht nur ihre User-ID gespeichert,<br />
sondern auch wann sie commited haben <strong>und</strong> welche Dateien sie modifiziert haben (<strong>und</strong> wie). Sie<br />
können optional auch noch eine change-log Message einbauen, die einen Kurzüberblick gibt.<br />
Nehmen wir an, ihr Programmierkollege im Büro nebenan hat diesselbe Version der WC vm<br />
Firmenserver gezogen <strong>und</strong> hat nun auch im Gegnerskript was an der Animation geändert. Sie<br />
haben also die beiden gleichen Dateien bearbeitet, sie haben aber schon comitted. Was passiert<br />
nun, wenn ihr Kollege comitten will? Das SVN bemerkt diesen Conflict <strong>und</strong> teilt diese ihrem<br />
Kollegen mit. Er kann sich nun die Unterschiede von seiner zur neuen Version der Datei anschauen<br />
<strong>und</strong> entscheiden, welche Codeteile von ihm übernommen werden, welche von Ihnen entfernt<br />
werden oder welche Teile gemergedt (zusammengefügt) werden. Nach dem Commit von ihrem<br />
Kollegen (er teilt es Ihnen über einen Messenger mit), sind sie neugierig auf die neuen<br />
Animationen im Zusammespiel mit ihrer KI. Sie machen also ein Update <strong>und</strong> dabei werden die<br />
Änderungen (Changes) direkt in ihrer WC geändert. Sie freuen sich: es sieht gut aus <strong>und</strong> die<br />
Zusammenarbeit fand gleichzeitig ohne Probleme statt.<br />
Anmerkungen zum Multi-User System<br />
Im Folgenden wird Ihnen nun erklärt, wie sie selbst eine SVN RC auf ihrem Einzelplatz PC<br />
einrichten <strong>und</strong> bedienen.<br />
Wichtig: wenn Sie Subversion auf einem Server benutzen wollen, den Sie von überall aus<br />
erreichen wollen, so brauchen Sie einen Root-Server Account bei Ihrem Hoster oder einen eigene<br />
Server, weil Sie den Server entsprechend konfigurieren müssen. Daher wird in diesem Artikel nur<br />
auf die Einzelplatzbenutzung eingegangen. Weitere Details zur Benutzung des SVNs als Server<br />
finden Sie im OpenBook „Versioncontrol with Subversion" (http://svnbook.red-bean.com/).<br />
Wenn Sie im Netzwerk arbeiten, so können Sie Subversion auf einem Rechner einrichten <strong>und</strong> das<br />
Repository als Netzlaufwerk verbinden. Im Folgenden werden auch Situationen aus einem Multi-<br />
User Betrieb geschildert, allerdings trifft dies auch zu, wenn Sie alleine mit dem SVN arbeiten - es<br />
dient nur der Veranschaulichung. Damit Sie gleich die Benutzung im Zusammenhang mit dem<br />
<strong>3D</strong>GS lernen, wird dies an einem Miniprojekt erläutert.<br />
Der normale Arbeitsablauf mit dem SVN - Features <strong>und</strong> Erklärungen<br />
Subversion hat viele Features, Optionen <strong>und</strong> viele Kleinigkeiten <strong>und</strong> Extras - aber im täglichen<br />
Betrieb werden Sie nur ein paar benutzen. Der typische Arbeitsablauf (oder -zyklus) mit dem SVN<br />
sieht so aus:<br />
• man updatet seine eigene Working Copy<br />
• SVN update<br />
• man macht seine Änderungen (neuer code, bugfixes, neue Grafiken, etc.)<br />
• SVN add (neue Dateien hinzufügen)<br />
• SVN delete (Dateien löschen)<br />
• man schaut sich seine Änderungen an<br />
• SVN status (Dateistatus (s.o.) abfragen<br />
• SVN diff (Unterschiede zur letzten oder einer anderen Revision angucken)<br />
• SVN revert (die geänderte Datei auf den letzten WC Stand bringen oder auf den Stand einer<br />
anderen Revision)<br />
• man merged seine Änderungen mit den Änderungen der anderen Entwickler<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │52
• SVN update (s.o.)<br />
• SVN resolved (bei Konflikten)<br />
• man commited seine Änderungen ins SVN Repository<br />
• SVN commit<br />
Das Repository<br />
Bevor wir nun das Spieleprojekt überhaupt starten, erzeugen wir uns ein leeres Repository,<br />
welches gleich die ersten Daten von der ersten unter RC gestellten Version unserer Demo enthalten<br />
wird.<br />
1. Erstellen Sie in Ihrem Projekte-Verzeichnis (wenn Sie denn eins haben) einen Ordner für unsere<br />
SVN Demo. Ich habe ihn „SVNDemo" genannt. Erstellen Sie dort ein Verzeichnis, welches das SVN<br />
Repository beherbergt. In meinem Beispiel lautet der Ordner „SVNDEMO_REPO".<br />
2. Klicken Sie mit der rechten Maustaste auf diesen Ordner. Sie sehen 2 neue Icons im<br />
Kontextmenü: „SVN Checkout" <strong>und</strong> „TortoiseSVN". Zeigen Sie auf „TortoiseSVN" <strong>und</strong> klicken Sie auf<br />
„Create repository here...".<br />
3. Im folgenden Dialog werden Sie gefragt, welches Dateisystem Sie wählen wollen. Da uns das<br />
egal ist, bleiben wir beim „Native filesystem (FSFS)". Das Erstellen eines SVN Repository in diesem<br />
Ordner wird dann bestätigt.<br />
Glückwunsch! Ihr Repository ist nun eingerichtet. Bitte ändern Sie NICHTS in diesem Ordner, das<br />
wird später das SVN für Sie übernehmen. Bevor wir die erste Spielversion comitten, müssen wir<br />
erst eine erste Version überhaupt erstellen:<br />
1. Erstellen Sie im Ordner „SVNDemo" einen temporären Ordner „temp"<br />
2. Starten Sie den WED <strong>und</strong> erzeugen Sie einen hollow-cube <strong>und</strong> weisen Sie ihm die Standard-<br />
Textur zu. Speichern Sie die Szene als room.wmp in diesem temp-Ordner <strong>und</strong> kompilieren Sie die<br />
WMB Datei.<br />
3. Erzeugen Sie eine .wdl Datei in diesem Ordner <strong>und</strong> nennen diese „main.wdl". Weisen Sie diese<br />
WDL Datei dem Level zu. Schreiben Sie folgenden code in die WDL Datei:<br />
function main ()<br />
{<br />
level_load("room.wmb");<br />
wait(3);<br />
while (1)<br />
{<br />
}<br />
camera.pan += 5 * time_step;<br />
wait(1);<br />
}<br />
Wenn Sie das Level über den WED starten, dreht sich die Kamera andauernd im Kreis.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │53
Die soll unsere erste Version des Spiels sein. Ihnen werden alle Features vom SVN anhand dieses<br />
Beispiels erklärt. Nun wollen wir aber diese Version in das Repository als erste Version importieren:<br />
1. Klicken Sie mit der rechten Maustaste auf den Ordner „temp".<br />
2. Gehen Sie auf „TortoiseSVN \ Import...". Im folgenden Import-Fenster werden Sie zunächst dazu<br />
aufgefordert die URL des Repositories anzugeben. Da es sich bei Ihnen auf der Festplatte befindet,<br />
klicken Sie auf „..." <strong>und</strong> klicken Sich durch ihr System bis zu diesem Ordner. Markieren Sie ihn <strong>und</strong><br />
klicken Sie auf OK. Im Textfeld müsste dann z.B. sowas wie<br />
„file:///I:/Projects/SVNDemo/SVNDEMO_REPO" stehen.<br />
3. Bei jedem Import können Sie eine Import-Message anlegen. Geben Sie beispielhaft „SVN-Demo<br />
Repository eröffnet!" an.<br />
4. Klicken Sie OK. Sie sehen dann, wie das SVN die Dateien in das Repository addet.<br />
5. Nun löschen Sie den Ordner „temp". Er wird nicht mehr benötigt.<br />
6. Erzeugen Sie nun den Ordner, unter dem Sie das unter RC stehende Spiel finden. Nennen Sie<br />
ihn z.B. „work".<br />
7. Klicken Sie mit rechter Maustaste auf diesen Ordner <strong>und</strong> dann auf „SVN Checkout...". Sie<br />
müssen unter „URL of repository" ihr Repository angeben - i.d.R. wird das eben erstellte angezeigt.<br />
Klicken Sie auf HEAD Revision um den aktuellsten Status zu ziehen. Klicken Sie auf OK <strong>und</strong> sie<br />
sehen, welche Daten das SVN aus dem Repository holt.<br />
8. Der „work" Ordner hat jetzt ein kleines grünes Häkchen, genauso wie jede Datei. Ein grünes<br />
Häkchen bedeutet immer, dass diese Datei seit dem letzten Abgleich mit dem Repository nicht<br />
verändert wurde.<br />
Glückwunsch! Sie haben gelernt, wie Sie ein Repository erstellen, eine erste Dateiversion unter<br />
Revisionskontrolle stellen <strong>und</strong> in ein Repository importieren. Außerdem haben Sie gelernt, wie Sie<br />
eine Working Copy beziehen.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │54
Dateien verändern <strong>und</strong> committen<br />
Wollen wir unseren Sourcecode ein wenig verändern. Sie stellen fest, dass der Kameracode lieber<br />
in eine eigene Kamerafunction gehört, die von der main function aufgerufen werden soll. Sie<br />
schreiben nun stattdessen:<br />
function cam();<br />
function main ()<br />
{<br />
}<br />
level_load("room.wmb");<br />
wait(3);<br />
while (1)<br />
{<br />
}<br />
cam();<br />
wait(1);<br />
function cam ()<br />
{<br />
camera.pan += 5 * time_step;<br />
}<br />
Nachdem Sie auf „Speichern" geklickt haben, hat sich das Icon der Datei verändert:<br />
Das rote Ausrufezeichen signalisiert, dass die Datei verändert ist. Nun wollen Sie die Datei<br />
commiten, damit die Datei gesichert ist. Dazu klicken Sie mit der rechten Maustaste auf den „work"<br />
Ordner <strong>und</strong> dann auf „SVN commit ...". Im folgenden Fenster sehen Sie ein Feld für die Changelog,<br />
wo sie etwas eingeben können <strong>und</strong> ein Fenster, indem alle Änderungen angezeigt werden. Klicken<br />
Sie auf OK. Nun ist die Änderung im SVN verzeichnet. Ändern Sie nun wieder was im Code:<br />
schreiben Sie irgendwas rein, einen Kommentar zum Beispiel, <strong>und</strong> bauen Sie einen Fehler ein:<br />
//meine kleine Kamerafunktion<br />
function cam ()<br />
{<br />
camera.pan += 0 * time_step;<br />
}<br />
Die Datei ist wieder mit einem roten Ausrufezeichen versehen. Nun, das Programm läuft nicht.<br />
Nehmen wir mal an, sie wissen nicht mehr was Sie verändert haben <strong>und</strong> wollen das jetzt wissen -<br />
<strong>und</strong> nehmen wir mal an, sie wissen auch nicht mehr, welche Dateien Sie verändert haben. Klicken<br />
Sie einmal mit der rechten Maustaste auf den „work"-Ordner <strong>und</strong> dann auf „TortoiseSVN\\Check for<br />
modifications". Sie sehen dann einmal alle Änderungen auf einen Blick. Aha, Sie haben die Datei<br />
„main.wdl" geändert. Klicken Sie mit der rechten Maustaste auf die Datei <strong>und</strong> dann auf „Compare<br />
with base" - nun wird die Datei mit der letzten Version aus dem Repository verglichen. Dann sehen<br />
Sie folgendes:<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │55
Sie sehen links die letzte Fassung aus dem letzten Update / WC <strong>und</strong> rechts die Änderungen. Zeilen<br />
mit einem + Zeichen weisen auf eine Änderung oder einer neuen Zeile hin <strong>und</strong> - (Minus-) Zeichen<br />
auf veränderte, bzw. gelöschte Zeilen. Sie sehen, das der Kommentar neu ist <strong>und</strong> das sie die<br />
camera.pan - Zeile geändert haben. Sie sehen, dass da eine 0 steht. Die Kamera dreht also nicht -<br />
das ist der Fehler! - Ändern Sie ihn aber committen Sie ihn (vorerst) nicht.<br />
Neue Dateien, updates <strong>und</strong> merging<br />
Bevor jetzt weitere Features besprechen, ziehen Sie eine weitere Working Copy in den Ordner<br />
„work2". Dort müsste nun der fehlerhafte Code drin sein. In „work" haben Sie den ja schon<br />
korrigiert, aber noch nicht commited. „Work" hat also ein rotes Ausrufzeichen, während „work2" ein<br />
grünes Häkchen hat.<br />
Fügen Sie nun ein Sprite in „work" ein <strong>und</strong> stellen Sie diesen in ihr Level <strong>und</strong> kompilieren Sie die<br />
Levelfile erneut. Nun müssten ein paar level-Dateien ein rotes Ausrufezeichen haben. Der Sprite<br />
hingegen hat kein Symbol - die Datei steht nicht unter Versionskontrolle. Um diesen Sprite zu<br />
erfassen, klicken Sie mit einem Rechtsklick drauf <strong>und</strong> dann auf „TortoiseSVN\\add..". Die Datei hat<br />
ein blaues + Zeichen <strong>und</strong> wird beim nächsten Commit dem Repository hinzugefügt. Committen Sie<br />
diesen Stand des „work" Ordners.<br />
Stellen Sie sich vor, die WC im Ornder „work2" wäre auf dem PC eines anderen Programmierers.<br />
Der hat den Kamerafehler entdeckt <strong>und</strong> baut noch eine laufende Tilt-Veränderung ein:<br />
function cam ()<br />
{<br />
camera.pan += 2 * time_step;<br />
camera.tilt += 1 * time_step;<br />
}<br />
Er hat weder den Kommentar eingebaut, noch diesen Sprite. Er denkt sich, bevor er committed:<br />
„vielleicht hat ja schon jemand weiter gearbeitet".. er macht also ein update, indem er mit rechter<br />
Maustaste auf seine WC klickt <strong>und</strong> dann auf Update klickt. Er sieht, wie die Sprite-Datei geaddet<br />
wird, die Levelfiles geupdated wird bei der Script-Datei - die er gerade bearbeitet hat, steht<br />
„merged" - was heißt das? Er guckt in die Datei <strong>und</strong> stellt fest, dass dort z.B. der Kommentar neu<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │56
ist. Das SVN ist in der Lage, neue Änderungen von außen (durch ein Update) zu erkennen <strong>und</strong> die<br />
geänderten Dateien anzupassen, sodass beide Versionen zusammengefügt werden. Der<br />
Programmierer von „work2" startet sein Programm <strong>und</strong> sieht seine neue Kamerarotation <strong>und</strong> den<br />
geupdateten Sprite. Er ist zufrieden <strong>und</strong> committet die neue Version.<br />
Dateien verändern<br />
Gr<strong>und</strong>sätzlich gilt: alle Sachen, die man an einer Datei ändert, muss das SVN mitkriegen. Wenn Sie<br />
innerhalb vorhandener Dateien was ändern - die unter RC stehen - dann ist das ok. Wenn Sie aber<br />
- mit der Hand, also im Windows Explorer - Dateien löschen, umbenennen, verschieben o.ä., dann<br />
meckert das SVN.<br />
Dateien umbenennen<br />
Wir haben jetzt eine Date „sprite.bmp" in unseren Ordner getan, der im Level angezeigt wird. Wir<br />
wollen aber, das er anders heißt. Sie müssen jetzt über das SVN diese Datei umbenennen, sonst<br />
zeigt das SVN an, dass die Datei „sprite.bmp" fehlt <strong>und</strong> die umbenannte Datei wird als nicht RC<br />
stehend anerkannt - obwohl es ja prinzipiell die gleiche Datei ist. Klicken Sie mit der rechten<br />
Maustaste auf die Datei <strong>und</strong> dann auf „TortoiseSVN\\Rename..". Geben Sie im Dialogfeld<br />
„testSprite.bmp" ein. Durch ein blaues + Zeichen wird die Änderung signalisiert. Vergessen Sie<br />
nicht in der WMP Datei den Sprite abzugleichen <strong>und</strong> neu zu kompilieren.<br />
Dateien löschen<br />
Sie stellen fest, dass es in dem Ordner Dateien gibt, die Sie für das editieren des Levels nicht<br />
benötigen, weil sie sowieso immer automatisch erzeugt werden, wenn sie nicht vorhanden wären.<br />
Dazu gehören „*.bak" Dateien, als auch die Dateien „*.$$M", „*.$$w", „*.raw" <strong>und</strong> „*.wed".<br />
Markieren Sie alle diese Dateien <strong>und</strong> klicken Sie mit rechter Maustaste auf diese <strong>und</strong> dann auf<br />
„TortoiseSVN\\Delete". Die Dateien werden sowohl physikalisch aus dem work Verzeichnis entfernt<br />
als auch aus der Revisionskontrolle herausgenommen. Wenn Sie jetzt committen, wird das an das<br />
SVN Repository weitergegeben. Wenn ein anderer user jetzt ein update machen würde, würde das<br />
SVN bei ihm diese Dateien auch löschen.<br />
Dateien ignorieren<br />
Wenn Sie jetzt wieder an der WMP arbeiten, werden diese Dateien wieder erzeugt. Nun, es kommt<br />
darauf an, was unter RC steht - Ihnen ist es aber egal, ob diese Dateien bei Ihnen in der WC<br />
herumliegen. Sie können im SVN auch ignore-tags setzen, sodass das SVN diese Dateien „nicht<br />
sieht".. also ignoriert. Editieren Sie also die WMP (machen Sie den hollow cube größer oder so),<br />
speichern Sie die wmp ab <strong>und</strong> kompilieren Sie. Sie sehen dann, dass die neuen Dateien kein SVN<br />
Symbol haben:<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │57
Logs<br />
Bei jedem Commit können Sie eine Log-Message eingeben, die gespeichert wird. Das ist dann<br />
besonders interessant, wenn Sie wissen wollen, was bei jeder Revision geändert wurde. Das<br />
können Sie auf das gesamte unter RC stehende Projekt tun, aber auch nur für Ordner <strong>und</strong> auch für<br />
einzelne oder mehrere Dateien. Klicken Sie z.B. mit der rechten Maustaste auf den Sprite <strong>und</strong> dann<br />
auf „TortoiseSVN\\Show log". Sie sehen dann z.B. Folgendes:<br />
Sie können einen Zeitraum der Log (für diese Datei in diesem Fall) angeben, von dem Sie<br />
auswählen wollen. Dann steht in einem Fenster jede Revision, in der die Datei geändert wurde, wer<br />
die Datei geändert hat, welche Actions auf die Datei ausgeübt wurde(n), wann dies getan wurde<br />
<strong>und</strong> eine Kurzform der log message. Wenn Sie einen Eintrag auswählen, wird die Log dann<br />
angezeigt.<br />
Repository Browser<br />
Man kann sich auch die aktuelle „Head" (= Kopf) Revisionstruktur im Repository anschauen, oder<br />
eben eine spezielle. Dort wird dann die Verzeichnisstruktur des Repositories angezeigt <strong>und</strong> alle<br />
dazugehörigen Daten wann was von wem wie verändert wurde. Hier nun ein Beispiel eines<br />
größeren Repositories von mir:<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │58
Wann soll man immer commiten?<br />
Im Prinzip könnte man sagen, das dies egal ist. Wenn man viele Änderungen oder ein großes<br />
neues Feature oder sowas einbaut, so sollte man immer in kleinen Häppchen commiten - damit bei<br />
evtl. Fehlern schnell wieder reverted werden kann. Wenn man eher immer große commits macht,<br />
dann kann man beim späteren Rekonstruieren eventuell die Übersicht verlieren, weil zuviel auf<br />
einmal gemacht worden ist.<br />
Reverten<br />
Das reverten ist eigentlich ganz einfach. Wir wollen nun einen einfaches Beispiel machen: nehmen<br />
Sie den Testsprite, laden Sie ihn in ein Grafikprogramm <strong>und</strong> malen Sie was darauf, sodass er<br />
verändert wird. Committen Sie die neue Version. Malen Sie nochmal was drüber, <strong>und</strong> committen<br />
Sie nochmals. Die neue Revision hat nun eine Nummer, z.B. 10. Der Sprite in Revision 8 war also<br />
der ursprüngliche Stand. Nehmen Sie einmal an, dass ist eine Textur oder so <strong>und</strong> Sie als Grafiker<br />
haben neue Versionen hochgeladen.<br />
Änderungen tätigen, nicht commiten, aber reverten<br />
Nehmen Sie an, sie zeihen nun ein update <strong>und</strong> wollen den Sprite verändern (tun Sie dies!). Sie<br />
stellen fest, dass die Änderung schlecht aussieht <strong>und</strong> wollen zum Stand der WC. Klicken Sie mit der<br />
rechten Maustaste darauf <strong>und</strong> dann auf „TortoiseSVN\\Revert...". Sie sehen dann alle geänderten<br />
Dateien (in diesem Fall der Sprite). Klicken Sie auf OK <strong>und</strong> die Datei ist auf dem alten Stand - sie<br />
ist reverted worden.<br />
Auf eine ältere Revision reverten <strong>und</strong> als neue Revision commiten<br />
Wenn Sie nun feststellen, dass die allererste Version, z.B. aus Revision 8, viel besser aussieht als<br />
alle nachfolgenden Revisionen (oder das ein code damals funktionierte <strong>und</strong> alle Neuerungen<br />
danach nur schlechte bugfixes waren) <strong>und</strong> sie wollen diese jetzt wieder - so geht das auch! Stellen<br />
Sie sicher, dass die Datei auf dem Stand der WC ist (bei einer Änderung also erst reverten). Gehen<br />
Sie dann im SVN Menü auf „Update to Revision" <strong>und</strong> geben Sie die gewünschte Revision an.<br />
Wichtig: die Datei ist dann nicht auf dem Stand der aktuellen Revision! Sie müssen dann den<br />
Dateiinhalt kopieren, die Datei wieder auf die Head-Revision bringen (auch mit „Update to<br />
revision") <strong>und</strong> die aktuelle Dateiversion mit dem Duplikat der „zurückgeholten" Datei<br />
überschreiben. Wenn Sie jetzt commiten, ist dann der Inhalt der „alten" Revision wieder „neu".<br />
Alte Dateien, die früher mal gelöscht wurden, wiederherstellen<br />
Sie können wie oben gezeigt, im Repository-Browser alte Revisionen anschauen. Wenn Sie nun<br />
eine alte Datei, die früher einmal gelöscht wurde, wiederherstellen wollen, dann suchen Sie sich<br />
zunächst die letzte bekannte Revision der Datei heraus. Dann können Sie im Repo-Browser - wenn<br />
sie diese Datei gef<strong>und</strong>en haben - die Datei irgendwo auf ihrem Computer speichern. Dann haben<br />
Sie die Datei wiederhergestellt!<br />
Ein Blick über den Tellerrand<br />
Dies sind nur die Basisoperationen, die Sie kennen müssen. Es gibt viele Ausnahmesituationen,<br />
denen Sie begegnen (z.B. conflicts, filelocks, etc.) werden, aber weitere Details dazu finden Sie im<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │59
oben genannten OpenBook. Wie Sie das SVN als server einrichten, steht dort auch - eine Erklärung<br />
wie man das macht <strong>und</strong> das SVN für diesen Betrieb einstellt, würde den Rahmen dieses Artikel bei<br />
weitem sprengen. Dazu gehört nämlich unter anderem der uneingeschränkte Zugang zu einem<br />
Server. Ich bezweifle das der durchschnittliche Leser einen solchen Besitzt oder Geld für einen<br />
Root-Server ausgibt. Wer aber die notwendigen Ressourcen hat, sollte sie aber auch anwenden:<br />
erst durch serverbasierte RC kann man ein echtes Projekt durchziehen, bei denen die Mitglieder<br />
einer Gruppe weit verstreut sind. Gerade bei internationalen Projekten mit Zeitzonen usw. ist das<br />
überaus hilfreich.<br />
Eine weitere Software, die ich in diesem Zusammenhang erwähnen will, ist das sogenannte TRAC,<br />
welches man mit dem SVN nahtlos kombinieren kann. Es ist eine Art Projektmanagement<br />
Software, die Aufgaben über Tickets verteilt, die bestimmten Personen zuteilen kann. Man kann<br />
auch bugreports einreichen, in den Tickets Diskussionen führen (z.B. wenn es um neue Features<br />
oder reporduzierbare bugs geht). Über sogenannten GANTT charts kann man Zeitpläne zur<br />
Projektrealisierung durchführen <strong>und</strong> anzeigen - <strong>und</strong> vieles mehr!<br />
Ich bedanke mich für Ihre Aufmerksamkeit,<br />
mit spielerischen Grüßen,<br />
Christian Behrenberg<br />
Literaturangaben<br />
Version Control with Subversion; open book. URL:<br />
http://svnbook.red-bean.com/<br />
Subversion Website; URL:<br />
http://subversion.tigris.org/<br />
TortoiseSVN Website; URL:<br />
http://tortoisesvn.tigris.org/<br />
Wikipedia Artikel<br />
http://en.wikipedia.org/wiki/Revision_control<br />
http://de.wikipedia.org/wiki/Versionsverwaltung<br />
http://de.wikipedia.org/wiki/Subversion (Software)<br />
http://en.wikipedia.org/wiki/Comparison_of_revision_control_software<br />
Autorenwebsite:<br />
http://www.christian-behrenberg.de<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │60
Wings3d Tutorial Teil1<br />
Start!<br />
Hallo mein Name ist Ronny Leonhard <strong>und</strong> vielleicht kennt mich der ein oder andere aus dem <strong>3D</strong>GS<br />
Forum. Ich möchte heute in meinem ersten Tutorial erklären wie man Wings3d so einrichtet das<br />
man damit vernünftig arbeiten kann. Wie gesagt das ist mein erstes <strong>und</strong> ich werde in weiteren<br />
erklären wie man damit modelliert <strong>und</strong> Texturen auf dem Modell auflegt, bis hin zum exportieren<br />
<strong>und</strong> importieren im WED.<br />
Kurz was zur Software selbst, Wings3d ist ein kostenfreies <strong>3D</strong> Programm mit dem man 3d Modelle<br />
erstellen kann <strong>und</strong> auch für alles verwenden kann (darf). Downloaden könnt Ihr die Software bei<br />
www.wings3d.com.<br />
Startet euer Wings3d, für denjenigen der mit 3ds Max <strong>und</strong> G-Max gearbeitet haben sollte, ist die<br />
Bedienoberfläche was neues, denn in Wings3d gibt's keine gleichzeitigen Ansichten von „Top, Front,<br />
Left, Perspektive" hier wird immer in einer Ansicht gearbeitet. Man kann die Ansichten aber<br />
umstellen, aber später mehr dazu.<br />
Jetzt seht Ihr ein Rastermuster <strong>und</strong> die Richtungsanzeigen „X, Y, Z", Ihr könnt das Rastermuster<br />
<strong>und</strong> die Achsen rechts oben aus <strong>und</strong> einblenden. Was beim Arbeiten manchmal sehr hilfreich sein<br />
kann.<br />
Damit man besser versteht was ich erklären möchte, erstelle ich einen „Cube" ( rechte maustaste<br />
-> Cube ). Der Cube ist erstellt <strong>und</strong> nun möchten wir auch gern die hinteren Seiten bearbeiten<br />
oder zumindest sehen können, also müssen wir den Cube drehen. Das funktioniert in Wing3d mit<br />
dem Scrollrad, einfach klicken <strong>und</strong> schon kann man den Cube drehen. Soweit so gut, nun ist aber<br />
unser Modell etwas länger <strong>und</strong> ragt über die Bildschirmlänge hinaus, also muss man das Modell<br />
etwas verschieben um den Rest sehen zu können. Das geht so ohne weiteres nicht, dazu muss<br />
man die Standardeinstellungen verändern damit dies auch geht.<br />
Preferences -> Camera <strong>und</strong> stell bei Camera Mode auf „ 3ds Max". -> „OK".<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │61
Jetzt können wir das Modell verschieben <strong>und</strong> das geht mit dem Scrollrad. Das Wenden <strong>und</strong> Drehen<br />
funktioniert fast immer noch genauso nur das Ihr zum Drehen jetzt die Taste „Alt" dazu mit<br />
benutzen müsst, also „Alt + Scrollrad" <strong>und</strong> schon könnt Ihr das Modell wieder drehen.<br />
Wer es mag kann auch die Hintergr<strong>und</strong>farbe ändern, ich habe es bei mir gemacht weil ich es<br />
besser finde so zuarbeiten. Leider gibt's die Software nicht in deutsch aber wer polnisch oder<br />
schwedisch kann kann die Sprache umstellen. Es gibt auch noch andere Sprachen...<br />
So jetzt habt Ihr die optimalen Einstellungen um gute Ergebnisse zu produzieren. Im nächsten<br />
Tutorial erkläre ich wie man ein einfaches Modell erstellt.<br />
Viel Spaß beim modellieren! Ronny<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │62
Interview mit Ulf Ackermann, Gewinner des Conitec<br />
Spring Contests 2007<br />
3dgs Magazin<br />
Dein Spiel hat den letzten Conitec Contest gewonnen. Es sprüht vor lustigen Ideen <strong>und</strong> Features.<br />
Was hat Dich zum Prinzip Utz Wollewutz inspiriert?<br />
Ulf Ackermann<br />
Ich habe einige Marble Madness Clones gespielt zu der Zeit. Da gab es zum Beispiel eins mit einem<br />
Hamster in einer Kugel. Allerdings fand ich das recht trist, da die Umgebung nur aus farbigen<br />
Quadraten bestand. Ich bin ein grosser Fan von Sonic. Da dachte ich mir, ich probiere einfach mal,<br />
das Marble Madness Spielprinzip mit Jump and Run Einlagen zu würzen!<br />
3dgs Magazin<br />
Woher nimmst Du all die lustigen Ideen?<br />
Ulf Ackermann<br />
Nunja, die kommen mit der Zeit... Ausserdem ist einiges natürlich bewährt aus anderen<br />
Spielprinzipien, zum Beispiel die Powerups. Ich mag Schafe, das sind einfach lustige Tiere. Ich<br />
kann auch den Ton eines Schafes fast naturgetreu nachahmen, willst Du mal hören? ;-)<br />
3dgs Magazin<br />
Vielen Dank für das Angebot. ;-)<br />
Du hast die Newton Physik Engine sehr kreativ eingesetzt. Kannst Du uns einige Tipps in Bezug auf<br />
die Verwendung von Newton mitteilen?<br />
Ulf Ackermann<br />
Anfangs, als ich noch eine überschauliche Anzahl an Physikobjekten hatte, machte Newton<br />
keinerlei Probleme. Hat man hingegen zuviele Objekte, kann es unter ungünstigen Bedingungen<br />
abstürzen. Man sollte auch keine zu komplexen Modelle als Newtonentities nutzen! Am besten<br />
verstreut man die Objekte, so dass maximal 4-5 auf einmal miteinander kollidieren können. Das ist<br />
gut für die Performance! Für Kollision mit anderen Objekten, welche keine Newtonentities sind, hat<br />
es sich bewährt ein "normales" <strong>Gamestudio</strong>entity auf der selben Postion mitzuführen <strong>und</strong> die<br />
Kollisionen bequem mit Events zu organisieren.<br />
3dgs Magazin<br />
Das Spiel wirkt sehr sauber konstruiert <strong>und</strong> alles passt zusammen. Hattest Du einen Plan oder hast<br />
Du einfach losgelegt?<br />
Ulf Ackermann<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │63
Um ehrlich zu sein habe ich einfach angefangen. Ich hab mit Newton ein wenig herumgespielt <strong>und</strong><br />
das machte mir einen Mordsspass. Ich wollte diese Sandkastenidee aufgreifen. Das man quasi viel<br />
umwerfen kann, Kettenreaktionen in Gang setzt <strong>und</strong> so weiter. Anfangs war Utz noch ein Igel. Mit<br />
der Zeit ist das Ganze gewachsen <strong>und</strong> das Resultat ist ein Schaf gefangen in einer Kugel was sich<br />
durch 30+ Level rollen muss. Gibt es eigentlich schon den Begriff Jump & Roll?<br />
3dgs Magazin<br />
War dies Dein erstes Projekt?<br />
Ulf Ackermann<br />
Nicht wirklich. Ich habe schon eine Menge gemacht. Über manches bin ich im nachhinein nicht so<br />
stolz. Zum Beispiel gab es mal "Killerhuhn <strong>3D</strong>", das erste Moorhuhn in <strong>3D</strong>. Wenn ich mir das heute<br />
anschaue, ist es mir ein wenig peinlich. Zu meiner Verteidigung: Ich war damals erst 17 <strong>und</strong> es<br />
war mein erstes Projekt. Ansonsten hatte ich neben allerlei Experimenten einen<br />
Westernshooter/adventure angefangen. Screenshots davon gibt es noch in AUM 7.<br />
(http://www.coniserver.net/coni_users/web_users/pirvu/aum/aum7/english/images/danrecent_scr<br />
eenshots.jpg)<br />
3dgs Magazin<br />
Hast Du schon Pläne für die Zukunft?<br />
Ulf Ackermann<br />
Allerdings. Ich werde auf jeden Fall bei <strong>Gamestudio</strong> bleiben. Weil ich glaube, daß ich als quasi<br />
Einzelkämpfer mit der Hilfe von ein paar guten Modellern nur als Casual-Game Entwickler eine<br />
Chance habe. Grosse Projekte werden es nicht - ich habe allerdings einige spassige Ideen für<br />
kleinere Spiele. Mehr möchte ich noch nicht verraten.<br />
3dgs Magazin<br />
Was gefällt Dir an <strong>Gamestudio</strong> besonders gut?<br />
Ulf Ackermann<br />
Es ist "einfach", <strong>und</strong> läuft auf sehr unterschiedlicher Hardware nahezu absturzfrei. Das ist wohl das<br />
grösste Plus <strong>und</strong> sehr wichtig wenn man Spiele für eine breite Zielgruppe mit "älteren" Rechnern<br />
entwickeln möchte. Die Community ist wohl auch eine der besten, die mir über den Weg gelaufen<br />
ist bisher.<br />
3dgs Magazin<br />
Und was findest Du eher nicht so toll?<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │64
Ulf Ackermann<br />
Der Multiplayerteil ist momentan noch sehr unkomfortabel. Es ist zwar gr<strong>und</strong>sätzlich möglich ein<br />
Mehrspielerspiel zu entwickeln, allerdings ist der Aufwand extrem hoch. Der 2D Part gefällt mir<br />
auch noch nicht so (mein Menü hat ca. 5000+ Zeilen Code), ein Drag & Drop Gui Editor würde der<br />
Engine gut tun. Ausserdem sollte der Renderer etwas schneller werden. Die Map/Modelleditoren<br />
sind zwar okay, aber auch hier gibt es innovativere, nutzerfre<strong>und</strong>lichere Entwicklungen.<br />
3dgs Magazin<br />
Was würdest Du Anfängern raten?<br />
Ulf Ackermann<br />
Lest meinen Blog (http://www.ackbytes.de)! ;-)<br />
Nein, quatsch. Ich rate ganz klassisch dazu, als erstes die Gr<strong>und</strong>lagentutorials durchzuarbeiten.<br />
Danach sollte man sich ein total einfaches Spielprinzip hernehmen (z.b. Pacman, Asteroids,<br />
Snake...) <strong>und</strong> das probieren mit <strong>Gamestudio</strong> nachzubauen. Natürlich mit eigenen<br />
Änderungen/Ergänzungen. Man sollte es zuendebringen! Also selbst wenn es nur ein Level hat, ein<br />
komplettes Spiel daraus machen mit Installationsprogramm, Hilfedatei usw. Daraus lernt man<br />
enorm. Spieleentwicklung ist nicht nur Spass <strong>und</strong> dabei lernt man auch unangenehme Aufgaben zu<br />
erledigen.<br />
Vielen Dank an Ulf, daß er sich die Zeit genommen hat unsere Fragen zu beantworten!<br />
Das Interview wurde von Torsten Fock im Auftrag des 3dgs Magazins durchführt.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │65
Interview mit Sven Paroth, dem Zweitplatzierten im<br />
Conitec Spring Contest 2007<br />
3dgs Magazin<br />
Du hast mit "Angelas World" ein sehr reizvolles Spiel entwickelt, dass unter anderem von seiner<br />
Einfachheit <strong>und</strong> Deinem besonderen Style lebt. Welches Programm hast Du benutzt um die<br />
stilvollen Grafiken zu erstellen?<br />
Sven Paroth<br />
Alle Grafiken wurden mit Adobe Photoshop CS erstellt, welches ich leider nur auf meiner Arbeit<br />
nutzen kann. An ungeduldigen Tagen hab ich dann Zuhause mit dem kostenlosen Programm<br />
"GIMP" gearbeitet.<br />
3dgs Magazin<br />
Arbeitest Du mit einem Grafiktablett?<br />
Sven Paroth<br />
Nein. Da meine Grafiken alle nur einfarbig sind <strong>und</strong> ich jede Art von r<strong>und</strong>en Formen vermeiden<br />
wollte, reicht da eine Maus aus. Ich finde es auch persönlich angenehmer mit dem "Pen-Tool" von<br />
Photoshop (erstellen von Pfaden) mit der Maus zu arbeiten, als mit einem Grafiktablett, da das<br />
Nachbearbeiten der Pfade präziser mit einer Maus ist (meiner Meinung nach).<br />
3dgs Magazin<br />
Wie inspirierst Du Dich?<br />
Sven Paroth<br />
Wenn ich das wüsste... Ich kann das nicht erzwingen <strong>und</strong> mir sagen "so, jetzt denk dir mal was<br />
neues aus". Das muss einfach von selbst kommen. Inspirieren tun mich sicherlich so einige Sachen<br />
wie Menschen, Kunststile, Musik, etc...<br />
3dgs Magazin<br />
Der Lohn dafür war der zweite Platz im letzten GS-Contest. Hast Du damit gerechnet?<br />
Sven Paroth<br />
Mit dem zweiten Platz hab ich auf keinen Fall gerechnet. Ich war mir zwar mittlerweile bewusst,<br />
dass das Spiel bei einigen Leuten gut ankam, aber als ich die Liste der teilnehmenden Projekte<br />
gesehen habe, hab ich nicht geglaubt unter die besten 5 zu kommen. Projekte wie Utz Wollewutz,<br />
Memowar oder ähnliches sind einfach umfangreicher als mein Projekt. Mir war´s besonders wichtig<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │66
zu sehen was man von meinem Projekt hält, egal ob positiv oder schlecht. Von daher bin ich sehr<br />
dankbar für den 2. Platz.<br />
3dgs Magazin<br />
Du hast im Forum schon des öfteren davon geschrieben, dass Du manchmal ein kleines<br />
Motivationstief hast. Das geht uns allen so. Wie gehst Du damit um <strong>und</strong> wodurch steigerst Du<br />
Deine Motivation?<br />
Sven Paroth<br />
Ohja das Motivationstief... Ich denke das ist das Hauptproblem Nr. 1 bei mir <strong>und</strong> vielen anderen,<br />
was das scheitern an Projekten betrifft. Da sich meine Stimmung sehr häufig ändert <strong>und</strong> leicht von<br />
vielen Dingen beeinflusst wird, gabs bei mir wirklich Wochen bis gar Monaten wo ich absolut keine<br />
Motivation für irgendwelche Projekte hatte. Um das bei "Angelas World" zu ändern, hab ich<br />
eigentlich recht wenig getan. Neue Motivation hab ich aber aus den ganz vielen positiven<br />
Kommentaren zu meinem Projekt gewonnen. Sowas baut schon sehr auf. Im neuen Projekt,<br />
"Angelas World 2", hab ich allein die Motivation vom Vorgängertitel mit eingebracht. Zur Zeit läuft<br />
alles super <strong>und</strong> meine Motivation bleibt dauerhaft oben, was vor allem daran liegt, dass ich viel<br />
mehr plane als vorher, mir Milestones setze, <strong>und</strong> die richtige Musik beim arbeiten auswähle.<br />
3dgs Magazin<br />
Standen alle Features des Spiels von vornherein fest oder hast Du "ins Blaue hinein" entwickelt?<br />
Sven Paroth<br />
Um ehrlich zu sein, nein. Das ganze Projekt basierte nur auf den Gr<strong>und</strong>gedanken "Ich will ein Spiel<br />
FERTIGSTELLEN". Die Gr<strong>und</strong>idee für das Spiel hat mir meine Fre<strong>und</strong>in verschafft. Bei der Grafik<br />
habe ich vorher immer auf die "Masse" geschaut, was denen eventuell gefallen kann. Dadurch hab<br />
ich oft Probleme beim Umsetzen bekommen. Aus dem Gr<strong>und</strong> wollte ich diesesmal einfach meinen<br />
persönlichen Stil nutzen <strong>und</strong> hatte bedenken das er bei niemanden gefallen finden würde. Mehr<br />
Planung gabs eigentlich nicht. Der Rest kam durch meine Laune <strong>und</strong> wurde einfach "ins Blaue<br />
hinein" entwickelt, um´s mal mit deinen Worten zu sagen.<br />
3dgs Magazin<br />
Was gefällt Dir an <strong>Gamestudio</strong> besonders gut?<br />
Sven Paroth<br />
Besonders gefällt mir einfach die Möglichkeit, mit einfachen Mitteln in kurzer Zeit wirklich<br />
"brauchbare" Ergebnisse zu erzielen. Am Anfang kann man sich als Beginner mit Templates,<br />
fertigen Modellen <strong>und</strong> Scripten bereits kleinere Spiele zusammenbauen. Wenn man dann<br />
konkretere Projekte angehen möchte (egal welches Genre), schreibt man sich eben alles selbst,<br />
gerade mit der A7 Engine <strong>und</strong> Lite-C. Zudem gibt es eine super Community, die bei Fragen oft gute<br />
Antworten liefern, <strong>und</strong> durch Plugins das <strong>3D</strong>GS immer weiter ausbauen.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │67
3dgs Magazin<br />
Und was findest Du eher nicht so toll?<br />
Sven Paroth<br />
Schlecht finde ich eigentlich nichts an <strong>3D</strong>GameStudio. Leute, die dauernd die A6 Engine mit der<br />
Unreal 3 Engine oder ähnlichem vergleichen, haben einfach den Sinn für die Realität verloren. Es<br />
hat schon seine Gründe wieso Engines wie die Unreal 3 Engine mehrere tausende Dollar kosten. Es<br />
war auch mit Sicherheit nie das Ziel von Conitec, eine ähnliche Engine zu entwickeln. Meiner<br />
Meinung nach gibt es keine bessere Engine für Neulinge <strong>und</strong> Fortgeschrittene in der Games<br />
Industry als die A6 Engine. Man bekommt extrem viel für sein Geld <strong>und</strong> muss nur lernen wie man<br />
selbst an seine Ziele kommt. Die Engine allein macht das Spiel nicht qualitativ. Wer dann<br />
irgendwann mal reich ist <strong>und</strong> eine große Firma gründet, kann dann gerne zu den Königen der<br />
Engines greifen<br />
3dgs Magazin<br />
Was würdest Du Anfängern raten?<br />
Sven Paroth<br />
Ich rate Leuten sich erstmal die Gr<strong>und</strong>lagen mit der A6 Engine beizubringen. Dabei hilft es, das<br />
Manual, Tutorials oder einfach Scripte von existierenden Projekten anzuschauen. Dann kann man<br />
irgendwann anfangen, mit den Templates oder eigenen Scripten, kleine Spiele zu programmieren.<br />
Geht auf Freewareseiten, schaut euch kleine Spiele an <strong>und</strong> versucht das ganze mit der A6 Engine<br />
umzusetzen. Besonders wichtig ist hier bei die Planung! Um so früher man damit anfängt, desto<br />
schneller wird man für spätere, größere Projekte Design Dokus <strong>und</strong> Konzepte schreiben können.<br />
Ich hab ebenfalls viel zu oft gesagt das ich sowas nicht brauche, wie z.B. bei Angelas World. Das<br />
war der Hauptgr<strong>und</strong> für meine Motivationstiefs. Im zweiten Teil ist alles schriftlich festgehalten <strong>und</strong><br />
man sieht direkt was realisierbar ist, was zu tun ist, wie Umfangreich das Projekt ist <strong>und</strong> kann so<br />
viel gezielter <strong>und</strong> Motivierter arbeiten! Und bitte, fangt garnicht erst mit MMORPG's oder des<br />
gleichen an. Sowas erfordert Jahre lange Erfahrung <strong>und</strong> ein professionelles Team.<br />
Im Namen des 3dgs Magazins bedanke ich mich ganz herzlich bei Sven "Kihaku" Paroth für die<br />
Beantwortung der Fragen.<br />
Das Interview wurde von Torsten Fock im Auftrag des 3dgs Magazins durchführt.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │68
Interview mit Johann Christian Lotter, dem "Vater"<br />
des <strong>3D</strong> <strong>Gamestudio</strong>s<br />
JCL gibt Antworten<br />
3dgs Magazin<br />
Mit Lite-C schließen Sie eine Produktlücke <strong>und</strong> machen zugleich <strong>Gamestudio</strong> wesentlich flexibler.<br />
Wie kamen Sie auf diesen kleinen Geniestreich? Was hat Sie inspiriert?<br />
JCL<br />
Lite-C ist kein Geniestreich, sondern nur die logische Fortentwicklung einer reinen Skriptsprache zu<br />
einer Programmiersprache. C-Skript erlaubte nur Zugriff auf die Engine-Funktionen, lite-C dagegen<br />
Zugriff auf alle Softwarebibliotheken des PC, insbesondere die DirectX-Funktionen. Dies ist ein<br />
konsequenter Schritt für <strong>Gamestudio</strong> von einem reinen Spieleentwicklungssystem hin zu einem<br />
universellen Entwicklungssystem für alle möglichen Programme.<br />
3dgs Magazin<br />
Vielen Usern mißfällt etwas die die Art, in der neue Features angekündigt werden. Einige hätten<br />
gerne einen "Fahrplan", nach dem sie die Entwicklung größerer Projekte hinreichend planen<br />
können. Auch wenn Sie verständlicherweise keine genauen Angaben machen können - wäre nicht<br />
eventuell eine grobe "Timetable" denkbar?<br />
JCL<br />
Diesen Wunsch kann ich verstehen. Wir haben im Büro ein grosses Whiteboard, auf dem Features<br />
mit Hilfe von Klebezetteln auf Termine verteilt sind. Diese Klebezettel lassen sich leicht abnehmen<br />
<strong>und</strong> neu gruppieren, <strong>und</strong> das passiert auch ab <strong>und</strong> zu. Eine feste Timetable hingegen hat die<br />
Eigenschaft, sich zu verselbständigen <strong>und</strong> das Kommando zu übernehmen. Entweder müsste ich<br />
mich strikt daran halten (schlecht für mich) oder sie immer wieder abändern (schlecht für User, die<br />
sich darauf verlassen). Deshalb lasse ich das lieber bleiben. Wir werden aber den Forecast<br />
umgestalten, so dass User besser erkennen können, in welchem Entwicklungsstand sich die<br />
verschiedenen Features befinden.<br />
3dgs Magazin<br />
Was hat Sie dazu bewogen Lite-C <strong>und</strong> MED als Freeware anzubieten? (anm.: nicht für kommerzielle<br />
Zwecke)<br />
3dgs Magazin<br />
Ich kann es mir natürlich nicht verkneifen <strong>und</strong> es muß ja auch sein... Können Sie uns irgend etwas<br />
über die Verbindung zu Atari mitteilen? Wir wollen uns doch nur für Sie freuen.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │69
JCL<br />
Es freut mich, wenn ich mit einer Antwort gleich zwei Fragen erledigen kann: Atari haben Sie es zu<br />
verdanken, dass lite-C <strong>und</strong> MED Freeware sind. Leider kann ich erst in ein paar Wochen mehr dazu<br />
sagen.<br />
3dgs Magazin<br />
Sie haben eine besondere Art von Humor, die oftmals auf Logik begründet ist. Eigentlich schon ein<br />
Markenzeichen. Waren Sie - mit Verlaub - schon immer so?<br />
JCL<br />
Wer mich kennt, weiss, dass ich nicht besonders witzig bin. Der Spassvogel in unserem Team ist<br />
Doug.<br />
3dgs Magazin<br />
Gibt es für Sie ein "Lieblingfeature" an der Acknex Engine?<br />
JCL<br />
Ja, ein eher unauffälliges Feature: das Template-System mit dem sich selbst editierenden<br />
Sourcecode per Kommentarmarken.<br />
3dgs Magazin<br />
Wo sehen Sie <strong>Gamestudio</strong> in fünf Jahren? Haben Sie eine Vision?<br />
JCL<br />
Mit dieser Frage werden oft Kandidaten in Bewerbungsgesprächen genervt: Wo sehen Sie sich in<br />
fünf Jahren? Für <strong>Gamestudio</strong> hängt es davon ab, wie sich die PC-Hardware weiterentwickelt. In fünf<br />
Jahren haben wir die A8 Engine, die keinen Map-Compiler mehr benötigt <strong>und</strong> nicht nur das<br />
Rendern, sondern vermutlich auch Physik, Kollisionserkennung <strong>und</strong> Pathfinding per Hardware<br />
erledigt. Und wir haben ein Template-System, das automatisch viele Gr<strong>und</strong>typen von Spielen <strong>und</strong><br />
Simulationen mit "Wizard"-Funktionen erzeugt.<br />
3dgs Magazin<br />
Warum Hilbert´s Hotel? Warum die Unendlichkeit? Können Sie uns etwas über Ihre zweite Passion<br />
erzählen?<br />
JCL<br />
Warum die Unendlichkeit? Ich kann mir schlecht vorstellen, dass es jemanden gibt, den die<br />
Unendlichkeit gar nicht interessiert. Wer aber mehr wissen will, kann sich den Einleitungs-Sermon<br />
auf www.unendliches.net durchlesen.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │70
3dgs Magazin<br />
Mal anders gefragt: Gibt es einen Rat, den Sie ambitionierten <strong>und</strong> erfahrenen Entwicklern mit auf<br />
den Weg geben möchten?<br />
JCL<br />
Ambitionierte <strong>und</strong> erfahrene Entwickler brauchen keinen Rat von mir. Für weniger erfahrene<br />
Entwickler hätte ich den Rat, ihre Ambitionen solange zu zügeln, bis ihre Erfahrungen aufgeholt<br />
haben.<br />
Mit fre<strong>und</strong>lichem Gruss jcl / Conitec<br />
Vielen Dank Herr Lotter, daß Sie sich die Zeit genommen haben auf unsere Fragen zu antworten.<br />
Das Interview wurde von Torsten Fock im Auftrag des 3dgs-Magazins durchgeführt.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │71
SEED_IT for <strong>3D</strong>GS<br />
SEED_IT ist das hilfreiche Werkzeug für <strong>3D</strong>GS, welches die Verteilung <strong>und</strong> Platzierung von Objekten<br />
(Modelle/Sprites/Entities) bei der Levelgestaltung einfach <strong>und</strong> komfortabel macht.<br />
Mit nur wenigen Mausklicks ist es möglich einen gesamten Level, eine Landschaft <strong>und</strong> vieles andere<br />
zu erstellen <strong>und</strong> zu verändern. Mit SEED_IT hat das langwierige Platzieren einzelner Objekte ein<br />
Ende.<br />
Aber SEED_IT kann noch mehr...<br />
Mit den zahlreichen Optionen kann die Sichtbarkeit, zusätzliche (benutzerdefinierte)<br />
Aktionen/Funktionen, die Positionierung, die Größe, das Aussehen, das Material, Bewegung <strong>und</strong><br />
Animation, ..., der einzelnen Objekttypen schnell eingestellt <strong>und</strong> jederzeit verändert werden.<br />
SEED_IT generiert aus den Einstellungen performantes c-script welcher für spezielle Wünsche<br />
auch einfach erweiterbar ist.<br />
Wie funktioniert SEED_IT?<br />
SEED_IT verwendet je Objektplatzierung eine sogenannte SEEDMAP. Diese SEEDMAP ist ein<br />
einfaches Abbild der Objektverteilung anhand der drei Gr<strong>und</strong>farben:<br />
Jede der drei Gr<strong>und</strong>farben (R/G/B) repräsentiert dabei einen Objekttyp welcher wiederum aus bis<br />
zu zehn verschiedenen Modelle, Sprites, Entities bestehen kann.<br />
Der Farbwert (0..255) der einzelnen Gr<strong>und</strong>farben kann dabei auch noch die Dichte der<br />
Objektverteilung bestimmen.<br />
Die Verteilung der Objekte, welche sehr schnell in Echtzeit im Spiel durchgeführt wird, ist somit<br />
eine Projektion der Objekte nach der SEEDMAP auf das Terrain oder Modell (SEEDGROUND).<br />
Ein SEEDGROUND muss nicht zwingend sichtbar sein (z.B. bei Asteroiden).<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │72
Das Erstellen eines Levels in drei Schritten<br />
Zum Erstellen eines Levels mit SEED_IT sind nur drei Schritte notwendig:<br />
1. Vorbereiten des Levels, auswählen der Modelle <strong>und</strong> erstellen der SEEDMAP.<br />
2. Definieren der Objekttypen <strong>und</strong> deren Eigenschaften mit SEED_IT sowie das generieren des<br />
Scriptes mit einem Mausklick.<br />
3. Einmalig das Einbinden des erzeugten Scriptes in das Projekt <strong>und</strong> auswählen der Seed-Action für<br />
das Terrain.<br />
Nachträgliche Änderungen am Leveldesign durch Neuplatzierung, Umsortierung, ändern der<br />
Modelle oder deren Eigenschaften ist dann nur noch eine Sache von Sek<strong>und</strong>en.<br />
Die Einstellungen in SEED_IT mit wenigen Mausklicks verändern, das Script neu generieren, <strong>und</strong><br />
im Nu ist das Aussehen des Levels verändert.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │73
SEED_IT bietet aber noch viel mehr!<br />
- Aus-/einblenden der Objekte mit weichen Übergängen mit frei definierbarem Abstand<br />
- automatisches entfernen/erzeugen der Objekte zur Reduzierung des Speicherverbrauchs<br />
- Objektanimation oder -bewegung (Wind, Rotation, ...)<br />
- Einstellen der physikalischen Eigenschaften der Objekte (<strong>3D</strong>GS pro erforderlich)<br />
- Wettersimulation mit nur einem Schalter - einfache LOD-System Konfiguration<br />
- einfaches Einstellen des fog-Systems<br />
- Objektskills <strong>und</strong> -flags vordefinieren, Skins (fix/random Skin), Material (Material-LOD (einstufig))<br />
- pixelgenaue Platzierung von einzelnen Modelle bis zur freien Verstreuung von vielen Modellen<br />
- <strong>und</strong>, <strong>und</strong>, <strong>und</strong>...<br />
Laden Sie sich die Demo herunter unter http://www.gameus.de <strong>und</strong> lassen Sie von nun an<br />
SEED_IT for <strong>3D</strong>GS die Arbeit der Objektplatzierung übernehmen.<br />
SEED_IT for <strong>3D</strong>GS Version 1.0 kostet nur € 25,- /~$33.-<br />
Also nichts im Vergleich zu der Zeit für mühevolle manuelle Levelgestaltung.<br />
Vielen Dank an Ulrich "mercuryus" Seiffert für die Erklärung des Tools <strong>und</strong> die Bereitstellung einer<br />
Version für´s Autorengewinnspiel.<br />
<strong>3D</strong> GAMESTUDIO-Magazin ■ Ausgabe 05 | Juni 2007 │74