Seminarausarbeitung Die Halflife-Engine
Transcription
Seminarausarbeitung Die Halflife-Engine
Universität Paderborn Fakultät für Elektrotechnik, Mathematik und Informatik Seminarausarbeitung Die Halflife-Engine Lars Tegeler vorgelegt bei Prof. Dr. Hans Kleine Büning Inhaltsverzeichnis 1 Einleitung 1 2 3D-Spiele-Engines 2.1 Entwicklungsgeschichte . . . . . . . . . . . . . . . . . . . . . . 2.2 Arten von 3D-Engines . . . . . . . . . . . . . . . . . . . . . . 2.3 Modellierung der 3D-Welt . . . . . . . . . . . . . . . . . . . . 2 2 4 5 3 Half-Life 3.1 Besondere Merkmale der Half-Life-Engine 3.2 Die Half-Life Welt . . . . . . . . . . . . . 3.2.1 Objekte . . . . . . . . . . . . . . . 3.2.2 Vektoren . . . . . . . . . . . . . . . 3.2.3 Map . . . . . . . . . . . . . . . . . 3.2.4 Binary Space Partitioning . . . . . 3.2.5 Kollisionserkennung . . . . . . . . . 3.3 Programmstruktur . . . . . . . . . . . . . 3.4 Modifikationen . . . . . . . . . . . . . . . 3.4.1 Entwicklungsumgebung . . . . . . . 3.4.2 Beispiel: Geschwindigkeit der RPG 3.4.3 Beispiel: DropXP . . . . . . . . . . 4 Bot’s 4.1 Bot’s 4.1.1 4.1.2 4.1.3 4.1.4 4.2 Bot’s 4.3 Bot’s erstellen und kontrollieren Generierung . . . . . . . Steuerung . . . . . . . . Wahrnehmung . . . . . . Beschränkung . . . . . . in Modifikationen . . . . . in Proxy-DLL’s . . . . . . ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 7 9 9 10 10 10 13 14 15 16 17 17 . . . . . . . 18 18 18 19 19 21 22 22 INHALTSVERZEICHNIS iii 5 Vergleichende Darstellung 24 5.1 Tabelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5.2 Fazit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 A Klassendiagramme 26 A.1 Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 A.2 Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Abbildungsverzeichnis 2.1 Wolfenstein . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Quake . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 Half-Life . . . . . . . . . . Skeletal Animation System BSP Beispiel(Schritt 1) . . BSP Beispiel(Schritt 2) . . BSP Beispiel(Schritt 3) . . Bounding-Box . . . . . . . Achsen-Ausrichtung . . . . Programmstruktur . . . . Counter-Strike . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 4 6 8 11 12 12 13 13 14 16 4.1 Bot-Wahrnehmung . . . . . . . . . . . . . . . . . . . . . . . . 21 4.2 Bot-Proxy-Dll . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 iv Listings 3.1 3.2 3.3 4.1 4.2 4.3 4.4 Orginal: Rpg.cpp (in FollowThink) . . Änderung: Rpg.cpp (in FollowThink) . Player.cpp (in DropPlayerItem) . . . . Bot-Generieung . . . . . . . . . . . . . Bot-Steuerung . . . . . . . . . . . . . . Bot-Sicht . . . . . . . . . . . . . . . . Engine-Header(common/com model.h) v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 17 17 18 19 20 22 Kapitel 1 Einleitung In der Projektgruppe Multiagentensysteme in 3D-Umgebungen“ wird durch ” den Einsatz von 3D-Engines an einer möglichst realistischen Simulationsumgebung für Agenten gearbeitet. Ziel ist es, die Kommunikation, Kooperation und eine kollektive Zielverfolgung zwischen Agenten zu simulieren. Zu diesem Zweck wurden herkömmliche 3D-Engines der Spiele Quake, Half-Life und Unreal auf ihre Verwendbarkeit hin überprüft. Als nächster Schritt ist die Implementation von Agenten in einer dieser Engines geplant. Weiter Informationen sind auf den Seiten der Projektgruppe zu finden: http://www.uni-paderborn.de/cs/agklbue/de/courses/ss03/kimas/project/index.html Im Folgenden gehe ich genauer auf die Untersuchung der 3D-Engines des Spiels Half-Life ein. Dazu gebe ich zunächst einen kurzen Überblick über die Entwicklung von 3D-Spiele-Engines und deren Kernmerkmalen. Im Hauptteil werden die Details der Half-Life-Engine, die Möglichkeiten, eine Welt für unsere Zwecke anzupassen, und die Integration von Agenten1 erörtert. Abschließend zeigt ein Vergleich mit den Spielen Quake und Unreal die Stärken und Schwächen von Half-Life in kompakter Form. 1 Später auch als Bot bezeichnet, was in Computerspielen ein vom Computer gesteuerter Spieler ist. 1 Kapitel 2 3D-Spiele-Engines Die heutigen 3D-Spiele-Engines bieten eine sehr realistische Simulation einer dreidimensionalen Welt nicht nur im Hinblick auf die grafische Darstellung, sondern hinsichtlich der Simulation einer Welt, die auf realen physikalischen Gesetzen basiert. Gerade in den letzten Jahren haben die so genannten First ” person shooter1“ immer mehr an Realismus dazugewonnen. 2.1 Entwicklungsgeschichte Als erstes dieser Art von First person shooter“ brachte 1993 id Software ” das Spiel Wolfenstein 3D[siehe Abb. 2.1] auf den Markt. Hier konnte der Spieler durch eine Labyrinth laufen und wurde dabei von Gegnern verfolgt. Allerdings wurde der dreidimensionale Effekt nur durch geschickte Verwendung von zweidimensionalen Bildern erweckt, die je nach Entfernung verschieden groß dargestellt wurden. Von einer wirklichen physikalischen Simulation konnte noch nicht die Rede sein. Als erste Weiterentwicklung brachte id Software das Spiel Doom im Jahr 1994 auf den Markt. Hierbei wurden die dreidimensionalen Ansichten erstmals wirklich aus einer vorgegeben Karte zur Laufzeit errechnet; und auch physikalische Effekte, wie zum Beispiel das Rutschen auf glatten Flächen, wurden erstmals simuliert. Jedoch blieb die Beschränkung auf eine horizontale Ebene bestehen, so das sich der Spieler immer noch nicht wirklich frei“ ” bewegen konnte. 1 Spiel aus Sicht der ersten Person. Später auch als Ego-Shooter bezeichnet. 2 KAPITEL 2. 3D-SPIELE-ENGINES 3 Abbildung 2.1: Wolfenstein Die Firma 3D Realms entwickelte dann 1995 das Spiel Duke Nukem 3D. In diesem Spiel ist dann auch die Beschränkung gefallen, dass man sich nur in einer Ebene bewegen kann. So konnte man mit Düsenpacks“ im Level herum ” fliegen und dadurch höher gelegene Ebenen erreichen. Abgesehen von dem fixen horizontalen Blickwinkel konnte man also die Welt von jeder möglichen Position aus betrachten. Zudem wurden die physikalischen Effekte immer mehr erweitert; durch die Möglichkeit zu fliegen oder zu schwimmen brauchte man auch eine Simulation von Auftrieb und Erdanziehung. Auf diese Entwicklung reagierte id Software dann 1996 mit Quake [siehe Abb. 2.2]. Die Quake Engine ermöglichte dem Spieler erstmals, sich wirklich frei zu bewegen und auch in jede Richtung zu schauen. Außerdem wurden die Gegner nicht mehr als 2D-Bilder in die Welt eingeblendet, sondern als 3DModelle berechnet. Damit kam also die erste vollständige 3D-Spiele-Engine auf den Markt. Als 1997 Valve Software mit Half-Life, id Software mit Quake II und Epic mit Unreal weiter Spiele-Engines entwickelten, gab es eigentlich keine bahnbrechenden Neuerungen mehr, nur die Grafische Darstellung wurde etwas verschönert2 . 2 Quake machte man insgesamt bunter, bei Half-Life wurde die Umgebung düsterer und bei Unreal mischte man eine düstere Umgebung mit bunten Anzeigen. KAPITEL 2. 3D-SPIELE-ENGINES 4 Abbildung 2.2: Quake Die heutige Entwicklung der 3D-Spiele-Engines versucht durch bessere Graphikdarstellung3 und der Simulation von immer mehr physikalischen Gesetzen ein noch realeres Modell der wirklichen Welt im Computer nach zu bilden. 2.2 Arten von 3D-Engines Bei den 3D-Engines kann zwischen zwei Arten unterschieden werden, einmal den Indoor-Engines zur Simulation von Räumen und den Outdoor-Engines zur Simulationen von offenen Welten. Outdoor-Engines Bei den Outdoor-Engines soll eine gesamte Welt mit allen Zusammenhängen simuliert werden. Gerade da die zu simulierende Welt nicht geschlossen ist, ergibt sich das Problem der Komplexität einer solchen Welt, wozu die heutigen Outdoor-Engines noch nicht leistungsfähig genug sind. 3 Welche durch immer bessere Grafikkarten ermöglicht wird. KAPITEL 2. 3D-SPIELE-ENGINES 5 Indoor-Engines Eigentlich alle gängigen First person Shooter“ basieren auf Indoor-Engines. ” Jeder Raum wird sozusagen als geschlossenes System betrachtet, das mit anderen Räumen durch Gänge verbunden ist. Mann kann also aus einem Raum nicht jemanden in einem anderen Raum treffen, und deshalb erspart man sich die Berechnung entsprechender Kollision und Abhängigkeiten. Daraus ergibt sich die effiziente Anwendung von Indoor-Engines für First person ” Shooter“. 2.3 Modellierung der 3D-Welt Bei den heutigen 3D-Spiele-Engines wird die Welt aus einem dreidimensionalen Modell berechnet, welches in einer Karte gespeichert ist, sowie aus den einzelnen Objekten, die in dieser Welt existieren, wie z.B. andere Spieler, Waffen, etc. Dazu verwaltet die Engine, an welcher Stelle in der Karte sich die einzelnen Objekte befinden, z.B. durch Vektoren4 . Dieses Modell der Welt wird dann durch verschiedene Computergrafische-Verfahren(Raytracing, Radiositi, Projektion)5 zu einem zweidimensionalen Abbild der dreidimensionalen Welt. So kann jeder mögliche Zustand der Welt zur Laufzeit abgebildet werden. Die Interaktion der Objekte untereinander und die physikalischen Gesetze werden mit Hilfe von geeigneten Algorithmen (z.B. zur Kollisionserkennung) umgesetzt. 4 Ein Vektor repräsentieren die X,Y,Z-Koordinate des Objekts vom Nullpunkt aus. Durch Raytracing und Projektion wird das 3D-Modell nach 2D abgebildet, Radiositi erzeugt einen realeren Beleuchtungs-Effekt. 5 Kapitel 3 Half-Life Das Computerspiel Half-Life war das erste Projekt, das von der Firma Valve Software entwickelt wurde. Dabei handelt es sich um einen Ego-Shooter, bei dem man die Figure des Wissenschaftler Gordon Freeman spielt, der im Inneren einer staatlichen Forschungseinrichtung an einem Projekt für Dimensionsportale arbeitet. Ein Versuch misslingt und öffnet eine Tor in eine Dimension voller Monster. Das Spiel wurde dann 1997 von Sierra On-Line vertrieben und wurde mit seiner düsteren Stimmung, unter Ego-ShooterSpielern beliebt. Abbildung 3.1: Half-Life 6 KAPITEL 3. HALF-LIFE 7 Dabei ist die 3D-Engine, die Valve Software verwendet, keine alleinige Eigenentwicklung, sondern basiert auf den Quake Engines von Id Software. Sie ist eine Modifikation der Quake Engine, mit Teilen von Quake II und einigen eigenen Weiterentwicklungen. Es wird immer wieder vermutet, dass die Verwendung der Direkt-X Schnittstele1 , und die Tatsache dass das Spiel nur unter Windows läuft2 nicht zuletzt damit zusammenhängt, dass bei Betrachtung des Softwareteams von Valve auffällig ist, dass einige der Verantwortlichen (z.B. Gabe Newell) von Microsoft kamen. 3.1 Besondere Merkmale der Half-Life-Engine Skeletal Animation System Ein System zur realistischen und detaillieren Darstellung der Modelle mit Hilfe von Skelett-Strukturen, die von Polygone umgeben sind. Werden die Kochen bewegt, so verformen sich auch die Polygon-Netze [siehe Abb. 3.2]. Die Berechnung der Modelle erfolgt also zur Laufzeit und bringt damit Größere Flexibilität und auch eine wesentlich höhere Anzahl von Polygonen(6000+) als bei den bisherigen Engines(600). Rendering Das Rendering System der Quake Engine wurde auf eine 16bit Farbtiefe erweitert. Außerdem wurden Farbige Lichteffekte hinzugefügt. Monster AI Das Entwickler Team hat versucht, durch verschiedene und komplexere Computer-Intelligenztypen, die miteinander agieren können, die vermeintliche Intelligenz der Gegner zu steigern. Decal System Ein System zur Änderung der Texturen von Oberflächen zur Laufzeit. Damit können zum Beispiel Einschusslöcher in Wänden dargestellt werden. Real-Time DSP 3 Zur digitalen Audioverarbeitung, damit kann in Echtzeit ein Klang in der 3D-Welt berechnet werden. So klingen Schüsse in einem Raum aus Metall ganz anderes als in einem Raum aus Holz, weil Hall und Entfernung usw. mit einberechnet werden. 1 Schnittstelle von Microsoft zur Grafik-Programmierung. Obwohl die zugrunde liegende Quake Engine auch unter Linux läuft. 3 Digital Sound Prozessor. 2 KAPITEL 3. HALF-LIFE 8 Abbildung 3.2: Skeletal Animation System DLL 4 Modularer ausführbarer Code. Dadurch werden Geschwindigkeitsvorteile gegenüber den Quake-Skriptsprachen5 erzielt. Direct X Durch die Microsoft-Schnittstelle können auch Grafikkarten, die kein Open-GL unterstützen für die 3D-Darstellung verwendet werden. Singel/Multiplayer-Sourcen Die Sourcen von Half-Life sind in den Multiplayer- und Singelplayer-Code unterteilt. Beides ist als SDK6 frei verfügbar. Binaries der 3D-Engine Diese sind auf Grund der Microsoft-Erweiterungen nur unter Microsoft Windows lauffähig. 4 DLL (Dynamic Link Library): Ermöglicht einem Prozess eine Funktion zu benutzen die nicht zu seinem Ausführbaren Code gehört. 5 Die Quake-Engines verwenden eine spezielle Skriptsprache die zur Laufzeit interpretiert wird. 6 Software Development Kit KAPITEL 3. HALF-LIFE 3.2 9 Die Half-Life Welt Wie im Kapitel Modellierung der 3D-Welt“ [siehe Kap. 2.3] schon beschrie” ben wurde, erzeugen die 3D-Engines aus einem Modell zur Laufzeit die jeweilige Ansicht des Spielers, um so die Möglichkeit zu schaffen, die Welt aus jeglichem Blickwinkel betrachten zu können. Darüber hinaus verwaltet die 3D-Engine die verschiedenen Objekte, deren Eigenschaften und die Interaktion untereinander. In der Half-Life Welt gibt es verschiedene Arten von Objekten, deren Positionen und Bewegungen durch Vektoren beschrieben werden. Die eigentliche Welt, im Spiel als Level bezeichnet, wird in einer dreidimensionalen Karte in Form eines Binary Space Partitioning Baums gespeichert [siehe Kap. 3.2.4]. Ob zwei Objekte sich berühren, wird durch eine Kollisionserkennung mit Boundingboxen [siehe Kap. 3.2.5] überprüft. 3.2.1 Objekte Die Half-Life Welt besteht aus zwei Arten von Objekten: • Solids (Wände, Decken, ...) • Entities – Point-based (statisch) – Brush-based (dynamisch) Die Solids sind feste Objekte wie Wände oder Decken, alle Objekte, die eine statische Position haben und keinerlei Funktionen erfüllen. Die Level Grundstruktur besteht hauptsächlich aus Solids, also einem Boden, den Wänden und einer Decke. Bei den Entities wird noch einmal in zwei Arten unterschieden. Einmal die Point-based Entities, deren Positionen durch die Karte der Welt fest vorgegebenen sind, z.B. eine Lampe die im Raum unter der Decke hängt und flackert. Und den Brush-based Entities welche keine feste Position haben, wie z.B. Waffen, die im Level herumliegen, aufgenommen, benutzt und an anderer Stelle wieder abgelegt werden können. Durch die Half-Life Engine wird die Maximale Anzahl von Entities7 auf 900 begrenzt [siehe List. 4.4]. 7 Point- und Brush-based Entities zusammen. KAPITEL 3. HALF-LIFE 3.2.2 10 Vektoren Um die Entities zu positionieren und zu bewegen, werden Vektoren verwendet. Der Ursprungsvektor (0.0, 0.0, 0.0) ist auch zugleich der Ursprung des Koordinatensystems der Karte eines Levels. Ein Vektor besteht aus drei Gleitkommazahlen welche die X,Y und Z Werte angeben. Diese können einmal dazu verwendet werden, eine Position (der Punkt, auf den der Vektor vom Ursprung aus zeigt) oder aber eine Bewegung8 (durch Richtung und Länge des Vektors) anzugeben. 3.2.3 Map Die Karte, die das dreidimensionale Model der Welt enthält, wird bei HalfLife Map“ genannt. Dazu werden in der Karte alle festen Positionen(Solids) ” der Umgebung gespeichert. Desweiteren werden auch die Positionen der Pointbased Entities und die Anfangspositionen der Brush-based Entities in diesen Karten angegeben. Da diese Daten zur Laufzeit für die Berechnung benötigt werden, wird das Binary Space Partitioning“ [siehe Kap. 3.2.4] verwendet, ” um einen effizienten Zugriff zu unterstützen. Für die Erstellung und Bearbeitung dieser Karten bietet Valve Software direkt im SDK den Hammer Editor“ an. Dies ist ein grafischer Editor, in dem ” eine dreidimensionale Welt konstruiert und entsprechende Objekte positioniert werden können. Diese so erstellten Karten können direkt mit einem entsprechenden Tool ins benötigte bsp“-Format übersetzt werden. ” 3.2.4 Binary Space Partitioning Das Binary Space Partitioning(BSP) bietet eine effiziente Möglichkeit, die Lage von Objekten in einer 2D/3D Welt zueinander zu bestimmen. Der BSP ist ein so genannter Objektraum-Algorithmus“, der mit der Aufteilung eines ” Raumes durch Trennebenen beliebiger Orientierung arbeitet. Das BSP wird zur Darstellung, Ortsbestimmung und auch Kollisionserkennung verwendet. Dazu wird aus der Umgebung ein BSP Baum generiert. Da das Generieren mit einem worst case von O(n2 ) für eine Berechnung zur Laufzeit zu langsam ist, muss es vorher geschehen und ist somit nur für die statische Szenen anwendbar. 8 bzw. Beschleunigung oder Gravitaion (negative Beschleunigung). KAPITEL 3. HALF-LIFE 11 Im Folgenden wird die Erzeugung eines BSP Baum an einem Beispiel verdeutlicht: Abbildung 3.3: BSP Beispiel(Schritt 1) Die Szene besteht aus fünf Objekten A bis E und einen Referenzpunkt Ref9 . Ziel ist es, die Szene so zu unterteilen, dass jedes Objekt allein in einer Region liegt. Dazu wird als erstes eine Trennebene p1 so gelegt, dass sie die Objekte möglichst gleichmäßig aufteilt. Wie in Abb. 3.3(links) zu sehen ist, liegen die Objekte B,C vom Referenzpunkt aus vor p1 und A,D,E dahinter. Somit erhält man einen Baum mit der Wurzel p1 und den Blättern B,C und A,D,E [siehe Abb. 3.3(rechts)]. Als nächstes unterteilt man nach dem gleichen Muster die Bereiche vor und hinter p1 wieder durch neue Trennebenen p2 und p3. Für den Baum bedeutet das, die Blätter B,C und A,D,E durch neue Knoten p2, p3 zu ersetzen. Als neue Blätter ergeben sich dann wieder die Objekte die vor oder hinter den neuen Trennebenen liegen: 9 Das ist z.B. der Punkt von wo die Szene betrachtet wird. KAPITEL 3. HALF-LIFE 12 Abbildung 3.4: BSP Beispiel(Schritt 2) Im letzten Schritt braucht man dann nur noch die Objekte A und E durch die Ebene p4 trennen. Damit ist der BSP-Baum für die gegebene Szene erstellt: Abbildung 3.5: BSP Beispiel(Schritt 3) Will man jetzt z.B. überprüfen, welche Objekte für eine Kollision beim Referenzpunkt in Frage kommen, muss man nur den Baum entlang gehen. Der Referenzpunkt liegt vor p1, also kommen wir zum Knoten p2. Da der Referenzpunkt auch vor p2 liegt, gelangen wir zum Blatt C. Somit ist das einzige Objekt, mit dem eine Kollision stattfinden könnte, das Objekt C. KAPITEL 3. HALF-LIFE 3.2.5 13 Kollisionserkennung Für die Kollisionserkennung werden bei der Half-Life Engine Bounding-Boxen verwendet. Das bedeutet, dass anstelle der 3D-Objekte nur eine quaderförmige Hülle, welche die Objekte komplett einschließt[siehe Abb.3.6], zur Kollisionserkennung verwendet wird. Dies erleichtert die Berechnungen, da nur noch überprüft werden muss, ob sich die Kanten zweier Bounding-Boxen schneiden, um eine Kollision festzustellen. Der Nachteil ist, dass dabei schon zwei Objekte durch ihre Bonding-Boxen kollidieren können, obwohl die Objekte selbst sich noch gar nicht berühren würden. Abbildung 3.6: Bounding-Box Die Bounding-Boxen sind an den Achsen ausgerichtet und können auch nicht gedreht werden, wodurch die Ebenen aller Boxen immer parallel zu den Achsen sind, was ein Verkeilen der Boxen verhindert und sicherstellt, dass Objekte, die sich z.B. in eine Ecke bewegen, diese auch wieder verlassen können[siehe Abb.3.7]. Abbildung 3.7: Achsen-Ausrichtung KAPITEL 3. HALF-LIFE 3.3 14 Programmstruktur Die Half-Life Programmstruktur kann aufgeteilt werden in drei Hauptbestandteile. Die eigentliche Engine, der Server-Teil und die Client-UI [siehe Abb. 3.8]. Da Valve Software von Anfang an stark auf die Möglichkeit gesetzt hat, Abänderungen, so genannte Mods [siehe Kap. 3.4] zuzulassen, wurden der Server- und Client-Teil als DLL implementiert. So können auf einfache Art Erweiterungen oder Änderungen geschrieben werden, ohne etwas an der Engine ändern zu müssen. Abbildung 3.8: Programmstruktur Beim Spielstart ruft die Engine in der Server DLL eine Funktion GiveFnptrsToDll() auf, der sie die Möglichkeiten, die in der Engine zur Verfügung stehen, übergibt. Dann stellt die Engine eine Anfrage an eine Funktion in der Server DLL, die der Engine, mitteilt welche Funktionen in der Server DLL zur Verfügung stehen. Dies geschieht durch die Funktion GetEntityAPI(). Somit wissen beide Programmteile, wie sie miteinander kommunizieren können, und die einzige Grundlage dafür ist, dass die beiden genannten Funktionen zur Initialisierung bereit stehen. Auf die Art wird auch die Client DLL initialisiert und das Spiel kann mit GameDLLInit() gestartet werden. KAPITEL 3. HALF-LIFE 15 • Engine - hl.exe Die hl.exe“ enthält die 3D-Engine. ” • Server - hl.dll (bzw. mp.dll) Die Server DLL“ steuern die Entities (Monster, Waffen, ...). ” • Client - cl dll.dll Die Client DLL“ beinhaltet das gesamte User-Interface. ” Der Programmcode ist in C++ geschrieben. Und die Objektorientierte Programmierung fördert die Übersichtlichkeit des Quellcodes. Aus dem Quellcode sieht man z.B. das alle Objekte von CBaseEntity 10 abstammen. Für den Server und Client Teil gibt es im Anhang A und auf den Projektgruppenseiten auch noch Klassendiagramme, welche die Vererbung aufzeigen. 3.4 Modifikationen Modifikationen (kurz Mod´s genannt) sind Änderungen, die am Spielablauf vorgenommen werden, z.B. an: • Waffen • Monstern • GUI • Regeln • ... Eine der wohl bekanntesten Modifikationen, welche aus Half-Life hervorgegangen ist, ist Counter-Strike [siehe Abb. 3.9]. Bei diesem Mod wurde der Spielablauf so geändert, dass man in zwei Teams gegeneinander spielt. Das eine Team übernimmt die Rolle der Polizei, und das andere die Rolle der Terroristen. Außerdem ist es rundenbasiert, sobald alle Spieler eines Teams tot sind, gewinnt das andere Team. Aber nicht nur so etwas ist möglich, man kann auch so starke Änderungen vornehmen, dass aus dem First Person ” Shooter“ ein Autorenspiel wird. 10 Zu finden in cbase.cpp KAPITEL 3. HALF-LIFE 16 Abbildung 3.9: Counter-Strike 3.4.1 Entwicklungsumgebung Um nun solche Modifikationen am Quellcode vornehmen zu können, benötigt man als Entwicklungsumgebung: • SDK 2.3 (Standart oder Full) • Half-Life 1.1.0.0 • C++ Compiler (der DLL´s erstellen kann, die mit denen von Microsoft Visual C++ kompatibel sind, z.B. MingW32, MSVC++ 6.0, ...) Dabei enthält das SDK den gesamten Quellcode und einige Tools, die zur Entwicklung benötigt werden. Dieses SDK gibt es von Valve in zwei Versionen, einmal der Standart-Version, in der nur der Quellcode für die MultiplayerVariante des Spiels enthalten ist, und einmal in der Full-Version, in welcher auch die Singelplayersourcen mit enthalten sind. Neben dem SDK, was frei verfügbar ist, wird auch noch eine Version von Half-Life benötigt, damit man die 3D-Engine zur Verfügung hat, und so auch seine Modifikationen testen kann. Um die Änderungen vorzunehmen benötigt man auch noch einen C++ Compiler. Hier empfiehlt sich die Verwendung von Mircosoft Visual C++, da hierfür im SDK alle Projektdateien enthalten sind. KAPITEL 3. HALF-LIFE 3.4.2 17 Beispiel: Geschwindigkeit der RPG Eine einfache Modifikation stellt z.B. das Verändern der Geschwindigkeit einer abgefeuerten Rakete dar. Dazu muss einfach im Quellcode in der Rpg.cpp der entsprechende Geschwindigkeits-Vektor auf einen niedrigeren Wert gesetzt werden. 1 pev−>velocity=pev−>velocity ∗ 1 0 0 0 ; Listing 3.1: Orginal: Rpg.cpp (in FollowThink) Somit wird die Rakete nach dem Abfeuern nicht mehr wie sonst auf das 1000-fache [siehe List. 3.1] sondern nur noch auf das 10-fache [siehe List. 3.2] beschleunigt. 1 pev−>velocity=pev−>velocity ∗ 1 0 ; Listing 3.2: Änderung: Rpg.cpp (in FollowThink) 3.4.3 Beispiel: DropXP Eine weitere einfache Modifikation kann in der Player.cpp vorgenommen werden. Ziel ist es, beim Ablegen eines Objektes, die Position zu beeinflussen, wo das Objekt abgelegt wird. Dies erreicht man, indem man z.B. beim Ablegen von Waffen den Aufruf der Create-Funktion der entsprechenden Entity so abändert, dass sie an bestimmten Koordinaten erzeugt wird. 1 CWeaponBox ∗ pWeaponBox = ( CWeaponBox ∗ ) CBaseEntity : : ←Create ( . . . , Koordinaten , . . . ) ; Listing 3.3: Player.cpp (in DropPlayerItem) Normalerweise wird die Waffenbox beim Ablegen einer Waffe immer direkt vor dem Spieler erzeugt. Diese Koordinaten in der Create-Funktion [siehe List. 3.3] der Waffenbox können aber durch die Angabe von festen Koordinaten ersetzt werden. Die Waffenbox wird dann immer an dieser, durch die festen Koordinaten bestimmten Stelle erzeugt. Kapitel 4 Bot’s Da Half-Life, im Gegensatz z.B. zu Quake oder Unreal, von Haus aus keine Schnittstelle für die Unterstützung von Bot’s bietet, muss die Einbindung eines Bot’s durch einen Trick erfolgen: • Einbettung des Bot’s in ein Mod. • DLL’s ausnutzen, um eine Bot.dll zwischen die Engine und den Server (hl.dll) zu setzen. Welche der beiden Methoden man wählt, sollte ganz vom Einsatzgebiet abhängig sein. So kann ein Bot in einem Mod recht einfach realisiert werden, jedoch ist der Bot dann auch an dieses Mod gebunden. Hingegen kann ein dazwischen gesetzter“ Bot auch in verschiedene Spiele eingebunden wer” den, jedoch ist dann der Aufwand höher. Die Prinzipielle Vorgehensweise zum Erstellen und Steuern eines Bot’s im Spiel ist jedoch gleich. 4.1 4.1.1 Bot’s erstellen und kontrollieren Generierung Um einen Bot in ein laufendes Spiel zu bringen, kann einfach die Funktion CreateFakeClient verwendet werden, welche einen virtuellen Clienten erzeugt. Dieser virtuelle Client wird dann von der Engine wie der Client des menschlicher Spieler behandelt. 18 KAPITEL 4. BOT’S 1 2 3 4 19 BotEnt=g_engfuncs . pfnCreateFakeClient ( ” Bot ” ) ; ... ClientConnect ( BotEnt , ”BotName” , ” 1 2 7 . 0 . 0 . 1 ” , ptr ) ; ClientPutInServer ( BotEnt ) ; Listing 4.1: Bot-Generieung Dazu wird als erstes die Funktion CreateFakeClient [List. 4.1, Zeile 1] der Engine-Funktionen aufgerufen. Dann verbindet man den Virtuellen Clienten mit ClientConnect [Zeile 3] zum Server, was dem Hinzukommen eines Netzwerkspielers entspricht. Und schließlich wird mit ClientPutInServer [Zeile 4]der Bot dann zum Spiel hinzugefügt. 4.1.2 Steuerung Da der Bot wie ein normaler Spieler gehandhabt wird, kann er auch genauso gesteuert werden. Dies geschieht über die Engine-Funktion RunPlayerMove. 1 pfnRunPlayerMove ( BotEntitie , BlickRichtung , ←VorwärtsGeschwindigkeit , RechtsGeschwindigkeit , HochGeschschwindiskeit , Taste , Impuls , Dauer ) ; ←- Listing 4.2: Bot-Steuerung Bei dem Aufruf dieser Funktion wird der Engine vom Server mitgeteilt, in welche Richtung der Spieler schaut, wohin er geht, ob er eine Taste gedrückt hat, einen Impuls1 ausgelöst hat und wie lange diese Anweisung von der Engine für den betreffenden Spieler ausgeführt werden soll [List. 4.2]. 4.1.3 Wahrnehmung Um zu Ermitteln, was der Bot im Spiel sehen kann, gibt es viele mögliche Umsetzungen. Da durch die Änderungen am Code auch die Möglichkeit zur Verfügung steht, einfach alle Positionen der Gegner dem Bot direkt mitzuteilen, egal, ob er sie sehen kann oder nicht, muss man selbst das Sichtfeld des Bot’s bestimmen: 1 Z.B. das Einschalten der Taschenlampe. KAPITEL 4. BOT’S 1 2 3 4 5 6 7 f or ( i = 1 ; i <=gpGlobals−>maxClients ; i++) { edict_t ∗ pPlayer = INDEXENT ( i ) ; vec2LOS = ( pPlayer−>v . origin { pEdict−>v . origin ) . ←Make2D ( ) ; ... flDot = Dotproduct ( vec2LOS , gpGlobals−>v . forward . ←Make2D ( ) ) ; i f ( flDot > 0 . 5 0 ) { //im S i c h t f e l d 9 11 12 13 14 20 UTIL_TraceLine { . . . } } else { ...} // Line zum Z i e l // a u s s e r h a l b d e s S i c h t f e l d s } Listing 4.3: Bot-Sicht In der Schleife[siehe List. 4.3] wird für alle Gegner geprüft, ob sie im Sichtfeld eines Bot’s sind. Dazu wird der Vektor, der sich aus der Differenz der Koordinaten des Bot´s und seines Gegners ergibt, ins Zweidimensionale übertragen [Zeile 4]. Würde man die Szene von oben betrachten, wäre der entstehende Vektor VA die direkte Verbindung zwischen dem Bot und seinem Gegner. Dann wird auch der Richtungsvektor VBot , welcher die Blickrichtung des Bot´s angibt, ins Zweidimensionale übertragen. So hat man jetzt zwei Vektoren [siehe Abb. 4.1] und je nachdem, wie groß der Winkel zwischen ihnen ist, kann man bestimmen, ob der Gegner noch im Gesichtsfeld liegt oder nicht. Dazu wird einfach das Kreuzprodukt der Vektoren gebildet [Zeile 6]. Das Kreuzprodukt beschreibt die Fläche zwischen den beiden Vektoren. Ist diese klein genug, liegen die Vektoren auch nahe beieinander. Ist das Kreuzprodukt kleiner 0.5, entspricht das einem Sichtfeld von 120 Grad. Ist bestimmt, ob der Gegner überhaupt im Sichtfeld liegt, so wird eine Linie vom Bot bis zum Gegner gezogen. Trifft die Linie auf keine Hindernisse, so kann der Bot den Gegner sehen. KAPITEL 4. BOT’S 21 Abbildung 4.1: Bot-Wahrnehmung 4.1.4 Beschränkung Da der Bot mit FakeClient als virtueller Client erzeugt wird, zählt der Bot auch wie ein richtiger Spieler und unterliegt somit auch denselben Beschränkungen. Ein Auszug aus den Engine-Headerdatein [siehe List. 4.4] zeigt, dass sich maximal 32 Spieler an ein Spiel verbinden dürfen, und somit auch nur 32 Bot’s erzeugt werden können. Aber was ist, wenn 32 Agenten nicht genug sind? So wäre für unser Projekt, ein Multiagentensystem zu realisieren, eine wesentlich höhere Anzahl von Bot’s wünschenswert. Da ergeben sich dann zwei Alternativen: KAPITEL 4. BOT’S 22 Bot als eigene Entity Hier hätte man keine Einschränkungen, da man alle Gegebenheiten der Entity selbst bestimmen kann. Jedoch ergibt sich hierbei ein erheblich größer Programmieraufwand, weil man alles, was einem durch die Spielersteuerung beim FakeClient vorgegeben ist, neu implementieren muss. Bot als Monster Es würden sich kleine Einschränkungen durch das Erben von CMonster ergeben, wie z.B. begrenzte Rechenzeiten zum Überlegen. Ein Monster bekommt von der Engine eine geringere Rechenzeit zum Nachdenken“ als ein Client. Dafür könnte man auf viele Funk” tionen der Monster zurückgreifen, und muß nicht alles neu implementieren. 1 2 #define MAX_CLIENTS 3 2 #define MAX_EDICTS 9 0 0 Listing 4.4: Engine-Header(common/com model.h) 4.2 Bot’s in Modifikationen Wie schon erwähnt kann man einen Bot in einer Modifikation implementieren. Ob man alles selbst implementiert, den Bot von CMonster erben lässt, oder den FakeClient verwendet, ist dabei unerheblich. Wichtig ist, dass man bei dieser Methode an seine eigene Modifikation gebunden ist, und deshalb ein entwickeltes Multiagentensystem nicht in einer anderen Umgebung getestet werden kann. Als Beispiel für einen Bot in einer Modifikation kann man die im Kapitel Bot’s erstellen und kontrollieren“ [siehe Kap. 4.1] beschrei” benden Kommandos in den Sourcecode des SDK einfügen. Da diese Methode keine weiteren Kenntnisse erfordert und für die Zwecke der Projektgruppe ungeeignet scheint, werde ich hier nicht weiter darauf eingehen. 4.3 Bot’s in Proxy-DLL’s Verwendet man nun eine Proxy-DLL, so macht man sich zu Nutzen, dass die Programmteile über die DLL-Aufrufe kommunizieren. Das im Kapitel Programmstruktur“ [siehe Kap. 3.3] beschriebenen Verfahren, wird mit einer ” neuen Proxy-DLL erweitert, welche den Bot enthält [siehe Abb. 4.2]. KAPITEL 4. BOT’S 23 Abbildung 4.2: Bot-Proxy-Dll Der Aufruf der Funktion GiveFnptrsToDll() wird jetzt anstelle von der ServerDLL von der neu eingefügten Proxy-DLL entgegengenommen. Diese erhält hierdurch die Engine Funktionen die zur Verfügung stehen, und teilt sie durch einen weiteren Aufruf der GiveFnptrsToDll() Funktion der Server-DLL mit. Als nächstes fragt die Engine durch den Funktionsaufruf von GetEntityAPI() die Proxy-DLL nach den von der Server-DLL zur Verfügung gestellten Funktionen. Da die Proxy-DLL diese noch nicht kennt, stellt sie die GetEntityAPI() Anfrage an die richtige Server-DLL und kann dann der Engine die Rückgabewerte der echten Server-DLL mitteilen. Somit ist die Initialisierung der DLL’s abgeschlossen. Da jetzt alle Kommunikationen zwischen Engine und Server-DLL über die Proxy-DLL ablaufen, kann diese somit alles beeinflussen was zwischen den beiden Programmteilen ausgetauscht wird. So kann dann auch die Initialisierung des Bot’s [siehe Kap. 4.1] geschehen, so wie die Steuerung oder jegliche andere Änderung. Kapitel 5 Vergleichende Darstellung Um nun die Vor- und Nachteile der einzelnen, in unserer Projektgruppe untersuchten 3D-Engines aufzuzeigen, sind die Hauptmerkmale in der folgenden Tabelle zusammengefasst. Auf die Modifizierbarkeit der Engines wird im Fazit näher eingegangen, weil sie die subjektive Bewertung unserer Projektgruppe wiederspiegelt. 5.1 Tabelle 24 KAPITEL 5. VERGLEICHENDE DARSTELLUNG 5.2 25 Fazit Wie schon aus der Tabelle ersichtlich ist, unterscheiden sich die 3D-Engines in ihren Hauptmerkmalen nur unwesentlich. Für Half-Life spricht die Verwendung von DLL’s, was einen Geschwindigkeitsvorteil gegenüber den VirtuellenMaschinen von Unreal und Quake bringt. Außerdem hat man so den Vorteil das man Bot’s über die Proxy-DLL-Methode einfügen kann. Für Quake spricht hingegen die Möglichkeit mehr als 32 Bot’s zu verwenden, was gerade für unsere Projektgruppe von belang ist. Da für die Unreal-Engine kein wesentlicher Grund spricht, und auch die zur Verfügung stehende Literatur/Internetartikel nicht unseren Erwartungen entsprechen, sollten wir von der Verwendug absehen. Gerade weil Half-Life auf den Quake-Engines basiert, ergibt sich kein großer Unterschied. Da jedoch die schon angesprochenden Vorteile der DLL-Architektur von Half-Life, und der Portierung nach C++ eine einfachere und übersichtlichere objektorientiert Programmierung erlauben, sollte für unsere Projektgruppe Half-Life als 3D-Engine die beste Basis liefern. 26 ANHANG A. KLASSENDIAGRAMME Anhang A Klassendiagramme A.1 Server 27 ANHANG A. KLASSENDIAGRAMME 28 ANHANG A. KLASSENDIAGRAMME 29 ANHANG A. KLASSENDIAGRAMME A.2 Client 30 ANHANG A. KLASSENDIAGRAMME 31 ANHANG A. KLASSENDIAGRAMME 32 Literaturverzeichnis [PHS] Half-Life FAQ, Steve Cook, http://www.planethalflife.com/hlsdk2/sdk2 articles.htm [PHP] Half-Life programming, http://www.planethalflife.com/hlprogramming/tutorials.asp [RSC] Gamedesign and programming resources, http://www.resourcecode.de [PHB] Botman´s Homepage, http://www.planethalflife.com/botman/ 33