Skip to content

jganser/3DAdventureIn2D

Repository files navigation

A Flatlands Adventure

Algorithmic Thinking - Non Straight Lines

screenshot1

Als ich von dem Thema Non Straight Lines erfuhr, gingen meine ersten Gedanken um gerade Linien und ihre Eigenschaften. Wie, dass sich zwei Parallele Linien in der Unendlichkeit schneiden. Was sie in meiner Vorstellung um einen runden Körper krümmt. Als ich allerdings anfing mich in die Mathematik hinter dieser Aussage einzulesen musste ich jedoch schnell feststellen, dass ich keine mich zufriedenstellende Idee bekam. Keine Inspiration, wie dieser mathematische Kontext sich mit einem Algorithmus vermitteln ließe.

Also grub ich tiefer und dachte weiter nach, was mir sonst noch zu dem Thema einfiel. Und da war es dann.

Die kürzeste Verbindung zwischen zwei Punkten ist eine gerade Linie

Aber was wenn der Pfad geblockt wird? Was wenn eine Non Straight Line ein gekrümmte gebraucht wird? Oder noch interessanter ein Pfad mit mehreren Stationen?

Wenn der Pfad zum Ziel geblockt ist, wird für gewöhnlich nach einer Umgehung gesucht. Zu Fuß lassen sich auch viele Hindernisse über klettern. Dies ist offensichtlich. Doch was wäre, wenn dies abwegig ist. Beispielsweise Rollstuhlfahrer würden ein Hindernis wohl nicht als erstes Überklettern wollen.

Da kam mir die mathematische Fabel über die Flatlands wieder in den Sinn. In der Fabel geht es primär um eine zwei dimensionale Gesellschaft aus geometrischen Formen und deren Beziehungen zu einander. Was für mich jedoch noch viel wichtiger ist, in der Fabel geht es auch um Dimensionsreisen. Wie ein Flatlander in die Strichwelt kommt und wie eine Sphäre den Flatlander auf eine Reise in höhere Dimensionen mit nimmt.

An diesem Punkt fand ich meine Inspiration und wusste wie ich meine Umsetzung des Themas Non Straight Lines machen wollte.

Die Idee

Ich fasste den Plan ein Abenteuer in den Flatlands zu gestalten, bei dem ein offensichtliches Hindernis, es unmöglich macht mit einer Bewegung in gerader Linie das Spiel zu beenden. Stattdessen sollte sich der Spieler auf der dritten Dimension, also einer Höhenachse, bewegen. Und durch einen Umweg ans Ziel kommen.

screenshot2

Da kein Abenteuer ohne Konflikt auskommt, beschloss ich, dass das Dorf des Protagonisten von einem dreidimensionalen Monster heimgesucht wird.

Diesem Monster wird die geliebte Person des Protagonisten geopfert und Protagonist muss die dritte Dimension nutzen um das Monster zu vertreiben und die geliebte Person zu retten.

Flachdenken

There is more than you can see.

Um die dimensionale Problematik weiter zu zuspitzen, habe ich beschlossen, dass der Protagonist nur eine Ebene zur Zeit wahrnehmen kann. Also nichts erkennt was unter oder über ihm liegt. Somit soll auch beim Spieler nicht ein Eindruck einer Draufsicht auf ein dreidimensionales Konstrukt entstehen. Stattdessen kann der Spieler nur wie ein Arzt der auf Schichtbilder schaut, versuchen, dass dreidimensionale Konstrukt in seinem Kopf zu bauen.

Schnitt

Wenn nun, aber der Protagonist nicht selbstverständlich durch die dritte Dimension reisen kann, dann braucht er Hilfe. An dieser Stelle beschloss ich, dass er von dreidimensionalen Wesen abhängig sein soll um auf und ab zu reisen.

Da alle Wesen jedoch einfach Geometrien sind und er ja nur einen zweidimensionalen Schnitt durch das Wesen wahrnehmen kann, fand ich eine mystische Komponente in meinem Konzept.

Anderswelten

Angenommen was wir sehen ist nur ein dreidimensionaler Schnitt durch eine vierdimensionale Welt, dann würde wir wenn wir uns in der vierten Dimension bewegen unter Umständen, etwas völlig anderes mit jedem Schritt sehen. Einiges was wir jedoch dreidimensional wahrnehmen bliebe. Da es eine konstante Form auf der vierten Dimension hat.

Wäre das nicht wie eine Anderswelt auf einer Schamanenreise wahrzunehmen?

Ob dies nun so ist, der Gedanke brachte mich nicht nur darauf, dass ich eines Tages gerne ein vierdimensionales Abenteuer designen würde, sondern vor allem auch auf Schamanen.

Ich beschloss, dass mein Abenteuer einen schamanistischen Ritualplatz, eine Art Stonehenge haben sollte. Und von der Mitte dieses Ritualplatzes sollte der Protagonist, das erste mal durch die dritte Dimension reisen.

Der Ritualplatz

henge

Die Mystik hat es mir angetan und so bekam ich die Idee, dass wenn eine Sphere regelmäßig durch den Ritualplatz gehen würde. Dann hätten das schon viele gesehen und der Pfad durch die Dimensionen wäre zumindest den Schamanen aufgefallen. Dies wäre allerdings nicht der Fall, wenn das dreidimensionale Wesen ein Zylinder wäre.

An dieser Stelle wurde mir klar, dass ich nicht nur eine sondern mehrere Plattformen in mein Abenteuer aufnehmen würde, die den Protagonisten das Reisen auf der dritten Dimension erlauben.

Das Monster besiegen - Falling with Style

Um das Monster nun zu verscheuchen, dachte ich mir, dass der Protagonist von oben in das Monster hinein gehen sollte. Anfangs dachte ich über einen diagonalen Pfad durch die Flatlands nach, doch dann kam mir eine interessantere Idee.

In Comic fallen Charaktere oft erst, wenn sie nach unten blicken. Was wenn ein Flatlander erst lernen müsste zu fallen?

Wenn etwas völlig neues gelernt werden muss, dann dauert dies entweder sehr lange oder ein Lehrmeister ist von Nöten.

Meine Geschichte bekam somit einen Lehrmeister, einen verschollenen Flatlander, der die dritte Dimension erforschte. Dieses sollte der Protagonist in den Anderswelten treffen und von ihm das Fallen lernen.

Lehrmeister - Ebner des Pfades

Als Lehrmeister bot sich ein alter Schamane an, der schon seit langer Zeit verschwunden war.

Da kam mir der Gedanke, dass das Monster schon vorher einmal besiegt worden sein könnte. Und zwar von eben jenem Schamanen. Der nun nach dem er die dritte Dimension kannte, diese weiter erforschte um aufzusteigen zu einem höher dimensionalen Wesen.

Der Gedanke gefiel mir gut, auch bot mir der alte Schamane eine Figur mit der ich die Flatlander-Problematik, sich keine dritte Dimension vorstellen zu können, noch einmal verdeutlichen zu können.

Das ist aber ja nur ein Spiel mit Aufzug

Während ich daran arbeitete viel mir auf, dass meine Spielidee im Endeffekt nichts weiter zu sein schien, als ein zweidimensionales Spiel mit Aufzug. Das die ganze mehr Dimensionsidee den Spieler völlig kalt lassen würde... Doch da wurde mir klar, dass ich dies dem Spieler überlassen sollte.

Solange mein Spiel den einen oder anderen zum grübeln über mehr und weniger dimensionale Welten bringt.

Mich jedenfalls hat es wieder an das Thema heran geführt und so wie ich finde auch weiter gebracht.

Umsetzung - Algorithmus

Zur Umsetzung der Idee habe ich mich des Processing Moduls für Haskell (processing for haskell alias Graphics.Proc) bedient. Haskell ist eine rein funktionale Programiersprache die sich für mich sehr ästhetisch anfühlt.

Da ich etwas ästhetisches oder wenigstens irgendwie künstlerischen Vorhatte machte ich mich also daran in meiner liebsten Programmiersprache meine Idee umzusetzen.

Mein Vorgehen um die Idee Algorithmisch umzusetzen habe ich sehr dynamisch angefangen. Zu Anfang hatte ich noch kein konkretes Aussehen für die Ebenen im Sinn, sodass ich erst einmal entschied, dass ich wie in Game Engines vorgehen würde.

Ich kreierte dementsprechend Datentypen, die eine wie Spielobjekte fungieren. Also Datentypen die ich an beliebige Stellen platzieren könnte und die dann einen Level ergeben.

Meine Ansprüche hierbei waren, dass wie oben genannt, jedes Objekt das eine Instanz der Datentypen sein würde, sich malen lässt und eine Fläche definiert, die Begehbar oder Unbegehbar ist.

Die Flächen mussten Schnitt durch die Geometry des Objektes sein, sodass dreidimensionale Objekte auf ein zweidimensionales Abbild reduziert werden.

Genaueres dazu gibt es nun im folgenden Kapitel.

Engine

Bis jetzt hatte ich Spieler immer in irgendwelchen GameEngines umgesetzt, was meine Art zu denken stark geprägt hat. Dementsprechend habe ich mir ein Konstrukt aus Datentypen, Typklassen und Funktionen geschrieben, die an vielen stellen durch Unity und die Unreal Engine inspiriert wurden.

So sind die Unterteilung in mal-bare Geometrien, Aktoren die zusätzlich noch ticken können, also ihren Zustand und ihr Verhalten ändern, und einen Spielstand entstanden.

Eine Geometrie ist hierbei auch gleichzeitig dafür Gedacht die Pfade zu definieren, die Spieler nehmen können soll.

Eine Geometrie ist mal-bar, was in meiner Umsetzung bedeutet, dass sie die Typklasse Drawable implementiert. Damit muss sie mal-bar sein, einen Pfad definieren, eine BoundingBox für schnellere Kollisionsabfragen und ihre interne Mal-Funktion muss austauschbar sein.

An dieser Stelle habe ich mir die Ästhetik Haskells zu Nutze gemacht und den Datentyp Geometry so definiert, dass er intern eine Funktion speichert, die seine Mal-Funktion und seine Pfadberechnung speichert. Somit kann eine Geometrie zweidimensional oder dreidimensional sein und beliebige Formen annehmen.

Der Einfachheit halber, habe ich mir dann jedoch, inspiriert von den Shapes in dem gewöhnlichen Processing, vorgefertigte Objects erstellt. Bei denen nur noch Größe, Position, Höhenebene und Farbe(n) definiert werden mussten.

Mit diesem Baukastensystem konnte ich, dann meine Vorstellung deutlich einfacher, kreiieren und anpassen. Als Nebenprodukt ist dabei meine erste kleine Game Engine entstanden.

![Baukasten](screenshots/Objects\ code.PNG)

Missing Rotation

Als Grundlage für die Orientierung im Raum einer Geometry liegt ihr Transform. Bestehend aus einer Position, einer Rotation und einer Skalierung.

Geplant war die Geometrien beliebig drehbar zu machen und immer der zweidimensionalen Schnitt durch diese anzuzeigen. Nach einigen versuchen musste ich diese Idee jedoch verwerfen, da die dafür notwendigen Algorithmen leider zu kompliziert für mich waren. Und mir bewusste wurde, dass meine Idee den Zeitaufwandsrahmen wahrscheinlich auch ohne Rotationen schon sprengen würde.

Zufall

Nach dem meine Geschichte und der Levelaufbau, dem Spiel einen festen Rahmen verliehen. Habe ich gemerkt, dass es noch einige Bereiche gibt in denen, das Spiel durch Zufall, jedes mal zu einem leicht anderen Erlebnis führen kann.

Diese Punkte sind, erstens die unwichtigen Dorfbewohner, also diejenigen die keine Plot relevanten Informationen bereithalten und den Spielstand nicht beeinflussen. Und zweitens die Objekte auf den ungenutzten, aber Zeitweilig sichtbaren Höhenebenen.

townpeople

Auch was die allgemeinen Farbgebungen angeht, wäre es möglich gewesen noch mehr Zufall rein zubringen. Doch habe ich an dieser Stelle merken müssen, dass es mir zu viel Zufall wurde und mein Spielerlebnis beim Testen nicht weiter gefördert sonder eher verschlechtert hat.

Warum nicht alles Zufall ist

Ursprünglich hatte ich auch die Idee gehabt die ganze Karte zufällig generieren zu lassen und mit Regeln sicher zu stellen, dass das Spiel lösbar ist.

Dieser Gedanke führte mich zu Prozedural erstellten Spielen und Spielsolvern, die Erreichbarkeit und Lösbarkeit von Spielen prüfen. Meine Untersuchung ergab allerdings, dass der Programmieraufwand hier in keinem sinnvollen Verhältnis zu stand, was ich Vermitteln will.

Projektverwaltung

Für die Projektverwaltung habe ich mir mit Haskell Tool Stack das Leben leichter gemacht. Eine Anleitung zur Nutzung in meinen Projekt findet sich in meinem Github Repository.

Playthrough - Taking that straight line

Das Video liegt unter video/game_loss.mp4. Und kann auf Youtube unter https://youtu.be/ilRwnTGOHqg angeschaut werden.

Playthrough - Non Straight Line

Das Video liegt unter video/playthrough.mp4. Und kann auf Youtube unter https://youtu.be/E6wh-FTxBtg angeschaut werden.

About

A Flatlanders Adventure

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published