Mit dem Voranschreiten in meinem Spieleprojekt Espionage, stoße ich auch ständig auf neue Herausforderungen, die ich mit Blueprints meistern will. In diesem Zusammenhang hab ich mir kürzlich Gedanken zu einem NPC-Patroulliensystem mit Wegpunkten gemacht. Allerdings sollte das Wegsystem einigermaßen flexibel sein, so dass es für verschieden komplizierte Wegpunktpfade eingesetzt wwerden kann. Wie ich das in Blueprints umgesetzt habe, findet ihr in folgendem Artikel.
Soweit ich über Wegpunktesysteme in Unreal Engine im Internet nachlesen konnte, waren diese alle auf dem Ansatz aufgebaut, dass in den Level ein Wegmarker hinzugefügt wurde, der nicht dargestellt ist, aber für den NPC als Ziel seiner Bewegung dient. Basierend auf diesem Ansatz und einiger Tutorials auf Youtube (unter anderen dieses hier AI Navigation Tutorial) zu dem Thema, hatte ich ein Verständnis davon wie ich grundsätlich einen Wegmarker für einen NPC platziere und über einen Blueprint die Bewegungsabfolge steuere.
Allerdings tendiere ich grundsätzlich dazu meine Lösungen soweit generisch zu halten, dass ich diese später in unterschiedlichtsen Situationen wiederverwenden kann. Deswegen wollte ich das ganze im R
ahmen meines Spiels Universum: Espionage auch so lösen, dass ich nicht bezüglich der Patrouillenmuster eingeschränkt bin. Damit meine ich, dass ich keine EInschränkung der Form, dass der Pfad maximal 5 Wegpunkte haben kann, hinnehmen muss. Aus diesem Grund wollte ich ein Wegpunktesystem für meinen NPC, das prinzipiell beliebig viele Wegpunkte verarbeiten kann.
Der intuitive erste Ansatz war deswegen, dass ich dem NPC über eine Variable in den Blueprint eine Liste aller seiner Wegpunkte mitgeben. Diese Liste würde dann im Blueprint iteriert und der NPC bewegt sich entsprechenden der Sortierung in der Liste von einem Wegpunkt zum anderen. Allerdings stieß ich dabei schnell auf mein erstes Problem, wie ich einem Blueprint in einer Variablen eine Liste von Actor-Objekten mitgeben kann. Denn das sind die Wegpunkte letzten Endes, Actor-Objekte. Im Kontext von Unreal Engine handelt es sich dabei um Actoren, die nicht dargstellt werden. Außerdem war ich dann im Patrouillenweg festgelegt. D.h. ich konnte nicht dynamisch auf Gegebenheiten an einem Wegpunkt reagieren.
Deswegen kam mir ein zweiter Gedanke,den ich letzten Endes umgesetzt habe. Ich realisierte ein System von referenzierenden Wegpunkten. Das bedeutet, dass ein Wegpunkt an sich nur sich selber und einen Verweis auf den nächsten anzulaufenden Wegpunkt kennt. Der NPC bekommt zu Beginn eine Referenz auf seinen ersten anzulaufenden Wegpunkt. Mittels "AI move to Location" lässt sich der NPC im Blueprint an sein Ziel bewegen. Am Wegpunkt angekommen, wird der Blueprint des Wegpunktes durch ein BeginCollisionOverlap-Event ausgelöst. Dieser Blueprint setzt für den NPC mittels "AI move to Location" ein neues Ziel. Damit lassen sich beliebig komplexe Patrouillenwege realisieren. Selbst eine Verwzeigung mittels modifizierten (z.B. Verzweigungswegpunkten) Wegpunkten lassen sich damit umsetzen.
Dieses Verfahren setze ich nun in meinem Spiel zunächst für NPCs mit festen Pfaden ein. Die nächste Aufgabe wird dann NPC-Bewegungen mit zufälligen Patrouillenwegen sein, aber dazu gibts dann einen extra Artikel.
Ein weiteres Jahr ist zu Ende und ich sehe Licht am Ende des Tunnels. Es gelingt mir doch tatsächlich wieder etwas mehr Zeit für meine Spieleentwicklung und die damit verbundenen Aufgaben zu investieren. Dazu gehört, dass ich in diesem Jahr die Introstory zum Spiel Espionage fertiggestellt habe, dessen erstes Kapitel bereits hier auf der Webseite im Storybereich veröffentlicht wurde. Ganz besonders freue ich mich dabei, dass ich dabei bei den Bildern zur Story unterstützung von joeydee erhalten habe. Außerdem habe ich für dieses Spiel nochmals das Gemdesigndokument gereviewed und zu meiner Freude festgestellt, dass es bereits ziemlich vollständig ist und nun eigentlich nur auf die Umsetzung eines ersten Prototypen wartet. Das ist dann das Ziel für das 1. Halbjahr 2018 mit der Unrealengine.
So dann wünsche ich Euch allen einen guten Rutsch und ein gesundes und erfolgreiches neues Jahr 2018.
Als Besucher ist es wahrscheinlich schon längst aufgefallen, dass einige Spiele, die noch auf der alten Webseite gelistet waren, hier auf der neuen Webseite fehlen. Dafür gibt es jetzt neue Spiele bzw. haben manche der alten Spiele Namensergänzungen erhalten. Was hat es damit auf sich?
Universum, die neue, alte Spielewelt
Universum: Domination ist aus dem ehemals auf der Webseite geführten AlphaOmega hervorgegangen. Der alte Name war einfach zu wenige aussagekräftig. Zwischenzeitlich haben sich aber mehrere Spielideen entwickelt, die alle über die gleiche Spielwelt verknüpft sind. Um deutlich zu machen, dass alle Spiele die gleiche Spielwelt teilen, wurde die Universum-Reihe geschaffen, die den dazugehörigen Spielen als Namen vorangestellt wurde.
Die gemeinsame Spielwelt hat sich im Laufe der Zeit entwickelt, angefangen mit dem Spiel Sternenjäger, das sozusagen eine Art Prequel zur ganzen Welt darstellt und die Ereignisse erzählt, als die Menschheit ihre ersten Schritte im Weltall unternahm. Darauf aufbauend entstand die Idee von Domination, einem klassichen Multiplayer-Online-Spiel im Stille von 4X- oder auch Globalstrategiespielen genannt, also Spielen bei denen man erforschen, sein Gebiet erweitern, Rohstoffe abbauen und letzten Endes andere Völker bekämpfen muss, wenn es zum Krieg kommt. Dieses Spiel ist bisher am längsten in Entwicklung und hat leider auch einige Neuentwicklungen hinter sich, was der Hauptgrund dafür ist, dass es immer noch nicht fertiggestellt ist.
Zwischenzeitlich ist die Idee für das Spiel Unversum: Espionage enstanden, was im Prinzip ein Puzzler ist, der auf verschiedenen Planeten des Universum spielt und dabei die Geschichte eines Agenten erzählt dessen Welt zerstört und dessen Volk am Rande der Ausrottung steht. Dazu gibt es dann auch hoffentlich bald die komplette Introgeschichte.
Einige Ideen sind noch in der Schublade, aber vorerst sollten die bereits hier erwähnten genug Arbeit für die nächste Zeit liefern.
In diesem Sinne hoffe ich, bald Neues von der Entwicklung berichten zu können.
Qt 5.8 ist eine sehr umfangreiche Softwarebibliothek, die unter anderem ein großes Widgetset besitzt, aber auch weitere Funktionalitäten, wie Boost-ähnliche Container, Zustandsautomaten und Skriptingsprache. Obendrauf erlaubt diese Bibliothek auch noch die platformübergreifende Entwicklung für PC, Android, iOS, Windows Tablets und noch weitere Zielplatformen. Für mich ist das Grund genug, die Möglichkeit zu prüfen, auf Basis von Qt Teile meiner Spiele zu entwicklen, bzw. einzelne Komponenten davon. Da Qt unter anderem auch eine Datenbank-Abstraktionsebene bietet, möchte ich Qt zusammen mit PostgreSQL einsetzen. Die auf der Qt-Webseite zum Download bereitsgestellten Installationspakete enthalten allerdings keine direkte Unterstützung für PostgreSQL. Damit bleiben nur zwei Möglichkeiten, entweder das Plugin für PostgreSQL wird von mir separat nachträglich kompiliert und ich verwende ein fertiges Paket, oder ich kompiliere Qt komplett aus den Sourcepaketen und binde dabei die PostgreSQL-Funktionalität direkt ein. Ich habe mich für letztere Option entschieden, da ich Qt5.8 eigentlich ursprünglich für Visual Studio 2008 kompilieren wollte. Leider musste ich einsehen, wie der Titel dieses Artikels bereits verät, das VS2008 nun wirklich in die Jahre gekommen ist und Qt damit nicht mehr wirklich gut kompiliert werden kann, zumal es vom Qt-Projekt nicht mehr supported wird. Deshalb und weil ich doch einige Informationen zusammentragen musste um Qt 5.8 zu kompilieren, beschreibe ich im Folgenden, wie ich Qt 5.8 mit Visual Studio 2013 Community Edition kompiliert habe.
Zwischenzeitlich nutze ich aber nun die Visual Studio 2015 Community Edition, weswegen meine aktuellen Arbeiten damit durchgeführt werden. Deshalb habe ich auch den Titel angepasst.
Qt und -static-runtime
Eigentlich ist es ne coole Sache ein statisches Qt mit einer statischen VC-Runtime zu bauen, weil man dann direkt das erzeugte Executable verwenden kann und keine weiteren Abhängigkeiten benötigt. Die Lizenzrechtlichen Angelegenheiten die diesbezüglich die LGPL mitbringt lasse ich hier bewußt außen vor, da es mir nicht um einen Lizenzrechtlichen Aspekt hier geht, sondern um einen technischen. Ich habe einige zeit damit verbracht Qt 5.8 mit statischer Runtime zu kompilieren. Das funktioniert zunächst einmal ganz gut. Bis man an den Punkt kommt, an dem man seine Anwendung linkt. Dann werden nämlich alle statisch kompilierten Bibliotheken erst zur Anwendung zusammen gelinkt. Un da fängt das Problem an. Es müssen wirklich alle Bibliotheken, die in Eurer Anwendung verwendet werden mit der gleichen statischen Runtime gebaut worden sein, mit der ihr auch Qt gebaut habt. Und damit meine ich wirklich alle. Das geht soweit, dass man auch alle Abhängigkeiten die Qt einbindet mit der gleichen statischen Runtime bauen muss. Bei mir hat das dazu geführt, dass ich PostgreSQL mit statischer Runtime hätte bauen müssen, wo es mir dann einfach zu viel wurde. Ich wollte nicht den Großteil meiner Zeit mit Bibliotheken bauen verbringen. Das war den letzten Endes auch der Grund, warum ich mich für eine dynamische Runtime entschieden habe. Das Leben ist jetzt sehr viel einfacher beim Bauen von Bibliotheken.
Damit will ich sagen überlegt es Euch nicht nur zweimal, sondern besser dreimal bevor Ihr anfangt Qt mit statischer Runtime zu bauen. Der dadurch gewonnene Vorteil ist meiner Meinung nach den Aufwand nicht wert.
Vorraussetzungen und Setup
Zur Durchführung benötigt werden:
- Visual Studio 2013 CE - Visual Studio 2015 CE
- Qt 5.8 Windows Source ZIP
- ausreichend Platz auf der Fetsplatte ( ca. ?? GB)
- Python > 2.7
- Perl Strawberry
- (optional) Jom
Zunächst braucht man natürlich eine installierte Version von VS2015 CE. Für das kompilieren von Qt5.8 verwende ich die x64-VS-Commandline. Man findet diese in der Programmgruppe von VS2015 CE. Auf die Installation der VS2015 CE gehe ich hier nicht gesondert ein, da sie selbsterklärend ist.
Mit Hilfe der Kommandozeile legt man sich die Verzeichnisstruktur an, in der später das Kompilat liegen soll. Bei mir sieht das so aus, dass ich zunächst mal einen Entwicklungsordner habe. Dort liegen alle Softwarebibliotheken, die ich in meinen Programmen verwende, wie z.B. Qt. In diesem Verzeichnis lege ich mir ein Unterverzeichnis mit dem Namen "qt" an. Dort werden, dann für jede Version, die ich von Qt kompiliere, Verzeichnisse angelegt. Im Beispiel von Qt5.8.0 lege ich mir also ein Verzeichnis "5.8.0" an. Wenn ich einen reinen Debugbuild kompiliere, ergänze ich den Namen noch um das Suffix "-deb". Das mache ich deshalb weil ich mit dem kompilieren von Qt in Debug und Release im gleichen Buildverzeichnis schlechte Erfahrungen gemacht habe. Damit kann ich später Debug- und Release-Builds auseinanderhalten. Also im konkreten Beispiel sieht dass dan wie folgt aus:
cd d:\devel
mkdir qt
cd qt
mkdir 5.8.0-deb
Ergebnispfad: d:\devel\qt\5.8.0-deb
Sobald dies erledigt ist, kommt der erste Schritt, nämlich das Konfigurieren des Qt-Builds mit dem configure-Skript. Bitte stellt im Vorfeld sicher, dass sowohl perl als auch python im Pfad sind, so dass diese Tools während des späteren Kompiliervorgangs aufrufbar sind. Der Aufruf des configure-Skripts ist der Knackpunkt. Hier muss man genau angeben wass man von Qt alles haben will und von eventuelle 3rd-Partybibliotheken die include- und lib-Verzeichnisse angeben. In meinem Fall ist das z.B. PostgreSQL. Zunächst mal der Aufruf den ich verwende als Beispiel:
configure -debug -prefix %CD% -shared -platform win32-msvc2015 -sql-psql -no-warnings-are-errors -opengl desktop -qt-zlib -nomake examples -nomake tests -I "E:\devel_2017\pgsql\include" -I "E:\devel_2017\qt-ZLib" -L e:\devel_2017\qt-ZLib\x64\Debug -L E:\devel_2017\pgsql\lib
Nun mal die Parameter im einzelnen:
- debug - ist klar, es wird nur die Debug-Version gebaut
- prefix - legt fest wo ich die Kompilate ablege, in meinem Fall im aktuelle Verzeichnis, indem ich configure aufrufe, dazu später mehr.
- shared - Qt wird als DLLs gebaut
- platform gibt proinzipiell den Kompilier an (interessanterweise bleibt das win32-msvc2015 obwoh ich für 64-bit baue
- sql-psql - bedeutet, dass das PostgreSQL-Plugin gebaut wird. Das bedeutet aber auch, dass ich die PostgreSQL libraries und includes verfügbar haben muss.
- no-warning-are-errors - keine Warnings als Errors. Beim ersten Bauen von Qt lass ich diese Einstellung so, später kann man das immer noch ändern. D.h. aber auch, dass der Qt-Build ohne Warnings durchlaufen muss.
- opengl verwende OpenGL im Desktop
- qt-zlib verwende eine externe zLib ( ich verwende hier die gleiche zLib die ich auch in meinen anderen Codeteilen verwende)
- nomake examples baue keine Beispiele ( spart Zeit)
- nomake tests (spart Zeit)
- -I inlucde-Verzeichnisse zu den 3rd-Partybibliotheken
- -L lib-Verzeichnisse zu den 3rd-Partybibliotheken
Dieses Kommando rufe ich immer im Verzeichnis auf in das die Kompilate gebaute werden sollen. Also z.B. liegt mein Qt opensource code in E:\dev-3rd-src\qt-everywhere-opensource-src-5.8.0, aber mein out-of-source build wird dann in E:\devel_2017\qt\5.8-deb liegen. Der Aufruf erfolgt dann in E:\devel_2017\qt\5.8-deb und sieht exakt wie oben angegeben aus. Hier noch mal der Vollständigkeit halber:
Will man Qt statisch bauen, ersetzt man -shared durch -static. Ich würde es grundsätzlich vermeiden, configure mit -static-runtime aufzurufen (siehe seperater Kasten), da man damit in die dependency-Hölle kommt. (Just my 2 cents). Nach dem Ausführen von configure bekommt man am Ende eine Zusammenfassung wie etwa die folgende:
Im Anschluß daran beginnt das Erzeugen der Makefiles. Ich verwende dazu wie vom Qt-Projekt empfohlen anstelle von nmake, jom.
D.h. ich rufe im Verzeichnis e:\devel_2017\qt\5.8.0-static-deb den Befehl jom auf. Jom ist ein Tool, dass paralleles kompilieren erlaubt und von der Qt-Wiki-Webseite heruntergeladen werden kann. Der Aufruf erfolgt dann mit <Pfad-zu-Jom>\jom.exe. Von da an sollte die Kompilierung von Qt laufen. sollte es wieder erwarten während der Kompilierung abbrechen, würde ich es zunächst nochmals neu starten. Wenn dann der Fehler nochmals auftritt, dann sollte man dem Fehler mehr Aufmerksamkeit. Meist befindet sich der einige Zeilen vorher, bevor der eigentlich Kompileabbruch stattgefunden hat.
Kommt man gar nicht mehr weiter, dann kann man sich immer noch an das Qt-Form wenden. ich hatte dort bisher immer hilfsbereite und nette Menschen getroffen.
Soviel erstmal zum Kompilieren von Qt 5.8.0 mit VS 2015 CE.
Fragen und Feedback könnt ihr gerne in den Kommentaren hinterlassen.
Thoran
Nach einigen Tagen, die ich mit Einarbeitung in IIS 8.5 und SSL-Zertifikate zu gebracht habe, sind nun alle Domains auf meinem Server auf gültige HTTPS-Zertifikate umgestellt. Was sich am Anfang als kompliziert dargestellt hat, ließ sich letzen Endes doch recht angenehm realisieren. Da ich bisher keine Ahnung hatte wie SSL insbesondere im Kontext eines Internet Information Servers 8.x funktioniert begann ich damit, selbstsignierte Zertifikate einzusetzen. Das Ziel dabei war zunächst erstmal HTTPS ansich auf meiner hauptdomain www.silvercoin-gamedev.net funktionsfähig zu bekommen. Danach verwendete ich Zertifikate von Let's Encrpt um meine Seiten im Produktionsbetrieb abzusichern.
OpenSSL Self-Signed Zertifikate
Als Voraussetzung für das Installieren selbstsignierter Zertifikate benötigte ich folgendes:
- OpenSSL-Binary-Paket für Windows mit Kommandozeilentools zum Erstellen einer CA und danach damit erzeugter Zertifikate
- Eine Anleitung zum Import der OpenSSL Zertifikate in den Windowszertifikatsstore
Nachdem man über diese Anleitung eine CA sowie benötigte Zertifikate für die Domains erstellt hat, müssen diese noch nach *.pfx konvertiert werden, damit der Windows Zertifikatstore diese verarbeiten kann.
openssl pkcs12 -inkey bob_key.pem -in bob_cert.cert -export -out bob_pfx.pfx
Dabei ersetzt man den Namen "bob_key.pem" durch sein eigenes Domainzertifikat und die Ausgabedatei durch den Dateinamen des eignenen Domainzertifikats mit Dateiendung ".pfx".
Um dieses Zertifkat nun in den Windowsstore zu importieren und damit im IIS 8 zugänglich zu machen, geht man wie folgt vor. Da man mit selbst-signierten Zertifikaten jedoch auch weiterhin den Nachteil hat, dass die eigene Webseite von aktuelle Browser nicht mehr dargestellt wird, musste also ein Zertifikat her welches eine ordentliche Chain-of-Trust (Link leider nur in Englisch) hatte, d.h. letzten Endes von einer vertrauenswürdigen CA signiert ist. Aus diesem Grund bin ich schon vor längerer Zeit auf das Projekt "LetsEncrypt" gestoßen.
Let's Encrypt-Zertifikate
Let's Encrypt ist ein super Ansatz für Privatpersonen, um Ihre Webseiten zukünftig abzusichern. Das ist insbesondere deshalb wichtig, da die gängigen Browser Firefox und Chrome in nahe Zukunft ungesichertes HTTP nicht mehr zulassen wollen. Let's Encrypt bietet für Linux einen Client zum beantragen von Zertifikaten bzw. zu deren Erneuerung. Dabei ist kein Papierkram notwendig. Der Nachweis, dass man eine Domain tatsächlich besitzt, läuft dabei über ein automatisiertes Challenge-System ab.
Zwischenzeitlich gibt es auch unter WIndows mit IIS die Möglichkeit direkt Zertifikate zu beantragen und diese gleich im IIS eintragen zu lassen. Die Basis dafür stellt ACMESharp zur Verfügung, eine .NET-basierte Bibliothek, die die Funktionen für die Let's Encrypt API zur Verfügung stellt. Darauf aufbauend existiert ein OpenSource-Tool namens Certify, welches die Beantragung und Verwaltung der Zertifikate für die eigenen Domains komfortabel ermöglicht.
Das Tool fragt eigenständig den IIS auf konfigurierte Websites und Domains ab und stellt die gefundenen Einträge in einer Combobox zur Auswahl. Sobald man dort einen Eintrag gewählt hat, hat man die Möglichkeit ein Zertifikat zu beantragen. Damit der automatische Ablauf auch funktionert muss der Zugriff auf einen bestimmten Http-Url auf dem Webspace der gewählten Domain verfügbar sein. damit prüft Lets Encrypt, ob man wirklich Besitzer der Domain ist. Dort legt der ACME client in Certify ein mit seinem Private Key signierte Nonce ab, die Let's Encrypt dazu dient, festzustellen, ob der Antragssteller des Zertifikats wirklich der Inhaber der Domain ist. Wichtig dabei zu beachten ist, dass der Aufruf durch Let's Encrypt auf die auf dem IIS liegende signierte Nonce immer per HTTP erfolgt und nicht per HTTPS.
Sobald diese Prüfung erfolgreich war, erhält der Certify-Client das fertige Zertifikat zurück und trägt es daraufhin gleich in den IIS ein. Das war es dann schon im Großen und Ganzen. Eventuell muss man noch im IIS-Manager die Bindungen auf HTTPS pro Webseite erstellen.
Zertifikatserneuerung
Mit der Version 0.9.6 von Certify ist zwischenzeitlich auch die Erneuerung eines Zertifikats recht einfach. Man kann über die Im Certify-Tool enthaltenen Domäneneinträge einfach die Anfrage "Neues Zertifikat" ausführen, wodurch das existierende mit einem neuen Zertifkat ersetzt wird. Grundsätzlich ist die Gültigkeitsdauer eines Zertifikates bei "Lets Encrypt" 90 Tage.
Fazit
Grunsätzlich ist "LetsEncrypt" eine super Sache und hilft auch Privatpersonen ihre Domänen SSL abzusichern. Mit dem Tool Certify ab Version 0.9.6 klappt das auch unter Windows Server wunderbar. Zwischenzeitlich gibt es das Tool Certify in Version 2.0 welches auch Zertifikate für mehrere Subdomains ausstellen kann. In der Version 2.0 ist das Tool für bis 5 Domains ohne Kauf herunterladbar. Für eine größere Domänenzahl kann die freie Version mittels eines Upgradekeys auf die Version mit unbegrenzter Domänenverwaltung umgestellt werden.
Eine kleine persönliche Anmerkung: Ich halte es für eine gute Idee, wenn man den "LetsEncrypt"-Service nutzt, dem Projekt von Zeit zu Zeit eine kleine Spende zukommenzulassen. Damit kann das Projekt hoffentlich noch lange fortgesetzt werden.