Die Gemäuer von Kalawaum (90s Classic, Rework)

Spiele, Demos, Grafikzeug und anderes unterhaltendes.
Benutzeravatar
DrShrek
Beiträge: 1970
Registriert: 08.09.2004 00:59

Re: Die Gemäuer von Kalawaum (90s Classic, Rework)

Beitrag von DrShrek »

@diceman
Dein wievieltes RPG ist das nun? Du schreibst jedesmal so als wenn Du alles immer wieder neu erfindest.
Warum verwendest Du nicht bereits "gelerntes" und schreibst Dir Routinen die Du jedesmal bei Deiner "RPG Challenge" wiederverwenden kannst?
Siehste! Geht doch....?!
PB*, *4PB, PetriDish, Movie2Image, PictureManager, TrainYourBrain, ...
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Die Gemäuer von Kalawaum (90s Classic, Rework)

Beitrag von diceman »

Das ist der 5te Versuch ... /:->
Und rate mal, warum ich jetzt bereits nach knapp 12 Tagen den Fortschritt von mindestens einem Monat habe. :wink: Ich habe einen Haufen Routinen, einiges copy/paste ich und passe es an die neue Struktur an! Und man lernt jedesmal dazu ... viele vorherige Versuche sind gescheitert, weil ich mich an overengineering verklüngelt habe; mit teilweise wirklich überladenen Funktionen, die im Endeffekt nur den Code vermüllt haben und zunehmend schlechter zu warten waren.
Habe gemerkt, ich bin häufig schneller und effizienter, wenn ich einiges neu schreibe, als alten Code an neue Gegebenheiten anzupassen. Und die Erfahrung aus vergangenen Jahren hilft ja auch. :)
Würde sagen, mit dem "Kalawaum"-Projekt hier bin ich zu ca. 60-70% fertig - was natürlich auch daran liegt, daß ich diesmal ein klares Ziel vor Augen habe, ich weiß zu 100% was da am Ende rauskommen soll, und wie es sich anfühlen muß. Das konnte ich vorher nie behaupten.
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
DrShrek
Beiträge: 1970
Registriert: 08.09.2004 00:59

Re: Die Gemäuer von Kalawaum (90s Classic, Rework)

Beitrag von DrShrek »

diceman hat geschrieben: Würde sagen, mit dem "Kalawaum"-Projekt hier bin ich zu ca. 60-70% fertig - was natürlich auch daran liegt, daß ich diesmal ein klares Ziel vor Augen habe, ich weiß zu 100% was da am Ende rauskommen soll, und wie es sich anfühlen muß. Das konnte ich vorher nie behaupten.
Das Problem sind die letzten 5 -15% nicht die ersten 60 -70 % ;-)
Siehste! Geht doch....?!
PB*, *4PB, PetriDish, Movie2Image, PictureManager, TrainYourBrain, ...
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Die Gemäuer von Kalawaum (90s Classic, Rework)

Beitrag von diceman »

Oder, wie es so schön heißt: 80% Code entstehen in 20% der Zeit. :mrgreen:
Drück mir mal die Daumen, bin momentan ganz guter Dinge. Bislang bin ich nie über (gefühlte) 30% rausgekommen. :allright:
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Die Gemäuer von Kalawaum (90s Classic, Rework)

Beitrag von diceman »

Bild


"Ladies and Gentleman, the first Monster has just entered the dungeon ..."
Das war eine Aufgabe für die ganze Nacht ... habe bis morgens früh um 5:00 durchprogrammiert, bis das alles so funktionierte wie gedacht (NullPointer-Exceptions, Array Index out of Bounds-Meldungen, etc.), aber jetzt habe ich die komplette Monster-Navigation fertig.
:coderselixir: :coderselixir:
Monster haben verschiedene states: wenn sie "geboren" werden, schlafen sie, bis der Spieler sie aufweckt (wenn er ein Feld neben ihnen betritt). Dann bekommt das Monster den Zustand "aufgewacht", der Spieler hat also die Wahl ob er direkt draufhauen, oder weglaufen will. Im nächsten Schritt wechseln Monster in den Verfolger-Modus ... die KI und Wegfindung ist rudimentär, leistet aber ihren Zweck, und viel mehr hatte das Original auch nicht zu bieten - Ich habe das so gelöst:

Monster suchen die 8 umliegenden Felder ab, und geben jedem Feld einen Wichtungsfaktor, abhängig von der Distanz jedes Feldes zum Spieler im kartesischen Koordinatensystem (Satz des Pythagors, anyone?). Die Formel hierfür lautet:

Code: Alles auswählen

Sqr(Pow(x-targetX, 2) + Pow(y-targetY, 2))
Für jedes Feld wird ein dummy()-Element angelegt, welches die Koordinaten enthält, sowie den Wichtungsfaktor. Dann werden alle Elemente herausgeschmissen, für welche Distanz > Minimum. Von den verbleibenden Feldern (in der Regel 1-2) sucht das Monster eines zufällig heraus und bewegt sich dorthin. Das reicht, um dem Spieler auf den Fersen zu bleiben, aber hat man es einmal abgeschüttelt, ist es in der Regel in seiner Ecke gefangen, solange bis man im großen Bogen zurückkommt.

Und da kommt der nächste monster()\state ins Spiel, der "Such"-Modus: Sobald nämlich das Monster mindestens 2 Felder weit entfernt vom Spieler ist, werden bei der Umgebungssuche die letzten 4 besuchten Felder mit einem abnehmenden Penalty-Wert belegt. Mit dem feinen Trick habe ich natürlich keine Skynet-KI geschaffen, aber die Monster sind jetzt mitunter in der Lage weiträumiger nach Umgehungen zu suchen, anstatt nur mit dem Kopf vor die Wand zu laufen. Der "dumme" Verfolger-Modus bei unmittelbarer Distanz hat aber auch seinen taktischen Zweck - würde man hier die KI "einschalten" würde das Monster, wenn man um ein Hinternis herumläuft, immer nur stupide in einer Richtung hinterherlaufen, ohne die Richtung abzuwechseln.

Puh, weitere Tweaks:

Es gibt eine Variable maxActiveMonsters, welche vorgibt, wieviele Monster gleichzeitig aktiv sein dürfen. Zu Beginn des Spiels ist dies immer 1. Also wenn man vor einem Monster wegläuft, und man weckt ein weiteres auf, wird das erste Monster in den Zustand "Lauern" versetzt (Lauern ist effektiv wie schlafen, aber die Monster wissen bereits vom Spieler), und das neu aufgeweckte Monster "übernimmt". Und jetzt das Aha: wenn ein Monster stirbt, wird automatisch gecheckt, ob sich auf der Map Monster im "Lauern"-Modus befinden, und wenn ja, werden von denen soviele aufgeweckt wie die maxActiveMonsters-Variable erlaubt! Zu Beginn ist das nur ein weiteres.
Mit maxActiveMonsters (etwas ähnliches gab es auch im Originalspiel, aber mein System ist deutlich elaborierter) lässt sich prima die Gefährlichkeit des Dungeons an den gegenwärtigen Power-Level des Spielers anpassen: jede Map hat eine min/max-Range wie stark die Monster mindestens sind, und sein können. Und da der Spieler effektiv auch nur ein Monster ist, und somit irgendwo auf dieser Skala zu finden ist, kann man den maxActiveMonster-Wert dynamisch anpassen. maxActiveMonsters wird einmal gecheckt, wenn man eine Map neu betritt, und dann jedesmal aktualisiert, wenn ein Monster stirbt.

Verlässt man eine Map, werden alle Monster, deren\state >= #monsterStateLurking ist, in den Zustand "Lauern" versetzt. Also man kann die Monster so vorübergehend "abschalten", und hat beim Neu-Betreten der Map auch erstmal seine Ruhe, bis man ein Monster erfolgreich besiegt - dann wachen unter Umständen eines oder mehrere (abhängig von maxActiveMonsters) lauernde Monster auf, um ihren Kameraden zu rächen.

Monster haben eine Animation beim Laufen (also keine wirkliche Animation im Sinne von Gliedmaßen bewegen, duh), aber das Sprite bewegt sich halt kontinuierlich aufs nächste Feld. Animationen werden nur ausgeführt, wenn auf entsprechenden Feldern der Fog of War aufgedeckt ist; also wenn man kein Monster sieht, werden für diese auch keine Animations-Berechnungen ausgeführt. Für den Spieler habe ich die Bewegungsanimation ohnehin deaktiviert - der bewegt sich statisch von Tile zu Tile, das fühlt sich besser, flotter und in jeder Hinsicht "knuspriger" an.

Bislang ist es nur möglich, Monster in Fallen zu locken (dies funktioniert hervorragend, inklusive Animation) - Monster teleportieren sich auch munter durch die Gegend, wenn sie auf eine Teleport-Falle treten - also meine Vorarbeit in dieser Richtung hat sich voll ausgezahlt.
Im nächsten Schritt werde ich das Kampf-System entwickeln.
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Die Gemäuer von Kalawaum (90s Classic, Rework)

Beitrag von diceman »

Bild


UPDATE:

- Das wichtigste zuerst (warum hat mich eigentlich keiner darauf angesprochen?), DER DUNKELDÜRRE HAT NUR EINEN FLÜGEL!!1!
Ist jetzt zum Glück gefixt!

- Das "Bump"-System ist voll entwickelt! Das heißt, das Spiel registriert, wenn der Spieler in ein Monster rennt (und vice versa). Damit zusammenhängend hatte ich ein schönes Erlebnis bezüglich emergent behavior: ich hatte die Kollisions-Abfrage für das monsterMap()-Array herausgenommen, damit Kollisionen mit Monstern überhaupt als solche erkannt werden; hatte aber nicht bedacht, daß das Array nicht zwischen Monstern und Spielern unterscheidet, also begannen die Monster munter sich gegenseitig anzugreifen im Versuch, auf die entsprechenden Felder zu gelangen. Komplett mit allem was dazugehört: Schaden austeilen, Blut-Animation, Sterben, XP für den Spieler. Das sind solche raren Momente, da fühlt man sich so:
Bild
auch wenn es nicht beabsichtig war, und ich es wieder deaktiviert habe.

- Blutgrafik zugefügt, wenn ein Charakter Schaden nimmt.

- Monster haben kleine Healthpoint-Bars! Der Spieler benötigt Feedback, wieviel Schaden er anrichtet, und das antiquierte Text-Message-System des Originals ("Du hast so und soviel Schaden gemacht, das Monster hat jetzt noch so und soviel Kraftpunkte") ist, nun ja, antiquiert. Die Frage war, wie ich das umsetze, also ob jedes Monster sein eigenes HUD-Element hat, wie ich die Prozentanzeige aktualisiere, etc. Habe mich letztendlich für die bequemste und schnellste Möglichkeit entschieden: 20 Healthbar-Sprites werden vorgerendert, mit Anzeige in 5%-Abständen, und in der drawScreen()-Routine, wenn durch die Monster iteriert wird, kann mit (hp*100)/hpMax/5 bequem und schnell der Index des korrekten Sprites herausgesucht und angezeigt werden. Bei so kleinen Grafiken die korrekte Prozentanzeige jedesmal "in Echtzeit" nachzujustieren, wäre Design-Overkill - die festen 5% Stufen sind absolut ausreichend um anschaulich zu vermitteln, wie effektiv der eigene Angriff war. Später, in der Polish-Phase, kommen noch Floating Numbers hinzu. :allright:

- Die Healthbar-Anzeige wird dynamisch angezeigt, das heißt, nur bei aktiven Monstern ist sie zu sehen, und nachdem ein Monster 5 Schritte gelaufen ist, wird sie ausgeblendet. Sobald ein Monster angreift, oder der Spieler ein Monster, oder ein Monster geweckt wird, wird die jeweilige Anzeigen-Abfrage wieder auf #True gesetzt, und der Schritt-Counter resettet.

- Außerdem habe ich das Kampf-System grob entwickelt. Man kann zwar noch keine Waffen und Schilde aufsammeln, die entsprechende Funktionalität ist aber implementiert und ich kann Monster und Spieler virtuell via hardcoding ausrüsten. An den Zahlen werde ich noch schrauben müssen, da gibt es einige Rädchen an denen man drehen kann, aber fürs erste fühlt es sich ganz gut an (wie gesagt, ich habe keinen Quellcode des Originals, muß mich also auf Beobachtungs-Gabe und Einfallsreichtum verlassen, um ein ähnliches Erlebnis zu re-kreieren).

- Das Kampfsystem in "Kalawaum" ist so simpel wie genial: Die Hitpoints sind zugleich das Maximum an Schaden, die man theoretisch anrichten kann. Wieviel Schaden man macht, hängt von der ausgerüsteten Waffe ab (dahinter verbirgt sich eine prozentuale min/max-Range) - also je mehr Hitpoints ein Charakter verliert, umso näher ist er dem Tode, und umso weniger potentiellen Schaden kann er anrichten, da nützt die beste Waffe nichts. Wenn man herumläuft, regenerieren ALLE Charaktere (Monster wie Spieler) pro Spieler-Schritt einen Lebenspunkt. Das heißt, im Idealfall zwackt man einem Monster via Erstschlag soviele Hitpoints ab, daß es einem im Gegenschlag nicht mehr töten kann. Ansonsten ist taktisches Rumlaufen um Hindernisse angesagt, Monster abhängen indem man durch magische Türen geht, etc. nur um die Hitpoints wieder aufzufüllen. Alternativ kann man Monster auch in Fallen locken, dafür kriegt man jeweils nur 1 Erfahrungspunkt. So richtig XP regnet es nur, wenn man stärkere Monster (= mehr Hitpoints als man selbst) besiegt.

- Die XP-Anzeige gibt das Maximum an Hitpoints an, die man durch Rumlaufen erreichen kann - also es gibt kein Level-Up-System im herkömmlichen Sinne, dennoch wird man mit der Zeit kontinuierlich stärker.
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Die Gemäuer von Kalawaum (90s Classic, Rework)

Beitrag von diceman »

Bild


UPDATE:

Die Item-Grafiken sind fertig!
Es gibt, wie im originalen Kalawaum, 6 verschiedene Waffen mit ansteigendem Power-Level. Die Start-Waffe ist die Dämonenpeitsche (so heißt sie auch bei mir). Später kommt noch eine siebte Waffe hinzu, die Fackel, welche die Funktionalität des Zauberstabs im Original übernimmt.

Bild

Von links nach rechts:
- Die Dämonenpeitsche (Demon Whip)
- Der geschwungene Ritualdolch (Curved Ritual Dagger)
- Das scharf geschliffene Beil (sharp-edged Hatchet)
- Die stattliche Sense (trusty Scythe)
- Der prächtige Krummsäbel (splendid Scimitar)
- Der mächtige Vorlader (mighty Blunderbuss)
- Die fremdartige Strahlenwaffe (alien Energy Coil)

Bild

Schilde reduzieren Schaden. In "Kalawaum" gab es 4, bei mir gibt es 5. Von links nach rechts:
- schartiger Lederschild (worn Leather Shield)
- solider Holzschild (sturdy Buckler)
- wehrhafter Knochenschild (jagged Bone Shield)
- imposanter Metallschild (imposing Tower Shield)
- glühender Kometenschild (glowing Comet Shield)

Items haben ein generisches Icon in der Welt-Ansicht; erst wenn man auf das Feld läuft, weiß man genau, um was genau für eine Waffe oder ein Schild es sich handelte. Trägt man bereits ein entsprechendes Item, wird es fallengelassen und das neue Item wird ausgerüstet (Items können zerbrechen im Kampf, das ist einer der nächsten Schritte, die ich programmieren werde).


WEITERE UPDATES:
- Monster fliehen, wenn ihre Hp unter 10% des Maximalwertes sinken. Steigt der Wert wieder über 10%, wechseln sie zurück in den Verfolger-Modus (beim Originalspiel sind sie erst geflohen, wenn Hp < 10, absoluter Wert).
- Jegliche Schaden- und Schadensreduktionswürfe im Kampf werden im Spektrum der Gaußschen Normalverteilung ausgewürfelt, will heißen, es gibt einen Min und einen Max-Wert, und die effektive Spanne wird auf 2 Würfel aufgeteilt. So hat man mehr Konsistenz in der Zufallszahlen-Erzeugung, und bekommt ein besseres Gefühl, welches Item wie stark ist.
- Habe weiter an den Zahlen geschraubt, und nähere mich einem Wert an, der sich richtig gut anfühlt. Habe mich an einen GDC-Talk von einem Blizzard-Designer erinnert, über die "Make it overpowered"-Philosophie des Studios - nur mit drastischen Änderungen (in beiden Richtungen) kommt man dem Zahlenteufel beim Balancing auf der Schliche!
- Die XP-Funktion ist fertig. Man bekommt Erfahrungspunkte abhängig von der Stärke des Monsters, welches man besiegt hat: ein doppelt so starkes Monster (+100% Hp) gibt 8 Erfahrungspunkte, danach scaled der ganze Rest. Also wenn *player\hp = 20 und monster()\hp = 50, erhält man 12 Erfahrungspunkte. Das ist ein schönes, selbst regulierendes System, und existierte genauso im Original (if it ain't broke, don't fix it).

- Zufällige Monster-Verteilung wird dynamisch an maximal zulässige freie Felder angepasst. Die genaue Formel, die ich mir dafür ausgedacht habe, lautet:

Code: Alles auswählen

percent = (Rnd(4,5) * countFree) /100
deviation = (Rnd(4,5) * percent) /100
monsterCount = percent + (Random(deviation*2) - deviation)
- Dann habe ich eine erste grobe Scaling-Funktion geschrieben, welche im Laufe des Spiels kontinuierlich die Schwierigkeit erhöht. Der Difficulty-Level richtet sich primär nach den Monster-Stats (Hitpoints), es gibt eine Min-Max-Range, in welcher die Monster (entsprechend ihrem Subtyp) ihre Hitpoints auswürfeln dürfen. Diese Min-Max-Rage wird pro Map erhöht, und zwar als nicht-lineare Kurve:
Der jeweilige Difficulty-Level für eine beliebige Map errechnet sich nach folgender Formel:

Code: Alles auswählen

; Konstanten:
#hitpointsStart = 20 ;Kraftpunkte mit denen der Spieler startet
#dungeonStrengthRange = 100
#dungeonStrengthBaseInc = 10
#dungeonStrengthFactorFloor = 1
#dungeonStrengthFactorCeil = 1.5

dungeonStrengthMin = #hitpointsStart - #dungeonStrengthBaseInc +1
dungeonStrengthMax = dungeonStrengthMin + #dungeonStrengthRange
For a = 0 To currentStage
	dungeonStrengthMin + (#dungeonStrengthFactorFloor * a)
	dungeonStrengthMax + (#dungeonStrengthFactorCei l* a)
Next
Also die erste Map (Index 0) hat eine Difficulty-Range von 21-121
Die zweite Map (Index 1) hat eine Difficulty-Range von 32-132
Die dritte Map (Index 2 hat eine Difficulty-Range von 44-145
Die vierte Map (Index 3) hat eine Difficulty-Range von 57-160
... usw.
So mal als grobe Demonstration, wie so etwas funktionieren könnte!
An den finalen Werten werde ich aber sicher noch schrauben müssen. :geek:

- Und als letzten kleinen Tweak habe ich den Monster Social Distancing beigebracht - wenn eine neue Map aufgebaut wird, muß initial um den Spieler herum ein Sicherheitsradius von 2 Tiles in allen Richtungen (effektiv also 5x5 Felder) eingehalten werden - so wird vermieden, daß Monster direkt neben dem Spieler spawnen.
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Die Gemäuer von Kalawaum (90s Classic, Rework)

Beitrag von diceman »

Bild


Ich weiß, sowas sagt man nicht, aber ich komme dem Ende zu. :o /:->
Sicherlich werde ich einige Wochen/Monate hiermit verbringen, aber momentan sieht es gut aus, daß ich bis Ende August etwas Spielbares vorzeigen kann. Die Mechaniken sind fast alle implementiert und funktionieren, die Updates in den letzten Tagen haben dem Projekt endlich den notwendigen Charakter gegeben - es fühlt sich wie ein "Spiel" an!


UPDATE:

-Items (Waffen, Schilde, Schlüssel) können abgelegt werden. Insbesondere das Ablegen von Schlüsseln hatte in "Kalawaum" einen taktischen Nutzen, da man automatisch offene Türen beim Durchschreiten abschließt, sofern man den entsprechenden Schlüssel im Inventar trägt.
Ursprünglich hatte ich streng kontrolliert, welche Felder zulässig für Item-Ablage sind - diese Abfrage-Routinen habe ich nun weitgehend entfernt, weil ich mir gedacht habe: what the heck, lass den Spieler doch Items auf Teleporter ablegen, wenn er mag!
Dazu mußte ich die checkStep()-Logik, welche nach jedem Schritt überprüft, ob ein Event getriggert wurde, umstellen, damit multiple Ereignisse methodisch abgearbeitet werden können, und Fallen weiterhin so tödlich bleiben wie zuvor. Das Ergebnis ist ein super-modales System, bei dem man, wenn man auf einen Teleporter tritt auf dem zugleich ein Item liegt, zunächst das Item aufsammelt, und dann direkt wegteleportiert wird, UND dann kann man noch ein Monster am Zielort aufwecken. Lediglich für das Zielfeld wird kein Check ausgeführt - also wenn dort auch ein Item liegt, muß man sich erst wegbewegen und dann erneut das Feld betreten.
Theoretisch kann einen ein Teleporter mit fixer Zieladresse auf ein Feld mit Monster schicken - das ist aber nicht weiter tragisch, das Programm kommt gut klar damit, und wenn man es einfach "Ambush" nennt, hat man sogar ein Feature anstelle eines Bugs: :mrgreen: - je nachdem, wer am Zug ist (Monster oder Spieler - letzterer, wenn er das Monster gerade aufgeweckt hat), muß das Feld verlassen, und wird dann wahrscheinlich im nächsten Zug direkt angegriffen. Und da dies eine Ausnahmesituation darstellt, da bei Monster-Erstellung Zieladressen von statischen Teleportern ohnehin aus dem Pool an zulässigen Tiles herausgenommen werden, handelt es sich um einen edge case, dessen Konsequenzen gut tragbar sind.

- Waffen und Schilde können zerbrechen! Hier habe ich einiges getweaked und verschiedene Systeme ausprobiert. Im ersten Draft hatte jedes Item einen durability-Stat, und wenn dieser einen festgelegten Breaking Point erreicht hat, ist das Item zerbrochen. Das funktionierte, aber fühlte sich nicht wirklich gut an. Dadurch bekommt der Item-Verschleiß einen unangenehm deterministischen Charakter, also quasi jedes Item, was man aufsammelt, ist letztendlich zum Zerbrechen verurteilt.
Also back to the drawing board ... in der finalen Routine gibt es jetzt einen Threshhold-Wert, welcher für Waffen variiert, wie stark man damit zugeschlagen hat. Dieser Wert wird durch eine Prozentangabe beschrieben, wo genau in der Range der Waffe sich der gewürfelte Schaden befindet (1-100). Gegen diesen Wert wird mit Random(5000, 1) gewürfelt (5000 ist die Breaking-Point-Konstante), und wenn das Ergebnis kleiner/gleich dem ermittelten Threshhold-Value ist, zerbricht das Item. Also effektiv, je nachdem wie stark zugeschlagen wurde, gibt es eine 0.02 - 2.0 % Chance, daß ein Item zerbricht). Für Schilde existiert derselbe Breaking-Point, allerdings werden hier 2 Threshhold-Values aufaddiert, bevor dagegen gewürfelt wird: wie stark der Gegner zugeschlagen hat, und wieviel % Schaden reduziert wurden. Effektiv haben Schilde also einen etwas höheren Verschleiß. Das fühlt sich richtig gut an, und scheint ähnlich im Originalspiel ähnlich abzulaufen - da konnte auch ein Langschwert beim ersten Schlag zerbrechen ( :twisted: ) - ich glaube sogar, daß mein System ETWAS freundlicher ist.

- Türen können mit Gewalt geöffnet werden. Diese Option wird einem angeboten, wenn man versucht, eine Tür zu öffnen und keinen passenden Schlüssel besitzt UND wenn man mindestens eine Waffe und/oder einen Schild ausgerüstet hat (mit der Dämonenpeitsche = Startwaffe kann man keine Türen öffnen). Dazu wird einmal gegen jedes ausgerüstete Item-Wertigkeit gewürfelt (Random(5, 1) für Schilde, und Random(6, 1) für Waffen ), und wenn mindestens einer der beiden Würfe <= der Item-Wertigkeit, wird die Tür erfolgreich aufgebrochen. Anschließend wird für jedes ausgerüstete Item gewürfelt, ob es zerbricht (33%-Chance bei Mißerfolg, 66%-Chance bei Erfolg). Also wenn man Waffe UND Schild ausgerüstet hat, hat man eine höhere Chance auf Erfolg, riskiert aber auch, daß evtl. beide Items kaputt gehen.
Sowieso sollte dies nicht die bevorzugte Art und Weise sein, Türen zu öffnen, aber da im Originalspiel es immer wieder zu unglücklichen Situationen kommen konnte, in denen man sich eingeschlossen hat, habe ich diese Option als letzten Strohhalm eingebaut.

- Bestimmte Events haben atmosphärische Text-Nachrichten bekommen. Je nach ausgewählter Sprache in deutsch oder englisch (kein großer Akt, da ich jeglichen ingame-Text vorab als dimensionierte Strings einlese):


Bild


- Da das Spiel über Lovecraft-Thematik verfügt, und somit geistige Gesundheit des Protagonisten eine Rolle spielt, habe ich mir eine "Sanity"-Mechanik ausgedacht - diese ist recht simpel, gibt aber dem Gameplay-Loop mehr Atmosphäre und taktischen Pfiff:
Man startet mit Sanity = 5. Im endgültigen Spiel wird es 10 verschiedene Monster geben, die Hälfte hat ab sofort die Fähigkeit, dem Spieler Geistige Gesundheit zu rauben (Tiefe Wesen, Dunkeldürre, Shogotten, Phantome und Sternengezüchte) ... und zwar nicht durch Angriffe, sondern passiv, alleine dadurch, daß der Spieler am Ende seines Zuges neben einem Monster steht. Dieser Monster-Skill ist Prozent-basiert, gibt mir somit einen größeren Design Space, da sich Monster nun auch durch andere Werte definieren, als nur Kraftpunkte und Schadenspotential. Also wenn man wegläuft vor Monstern um seine Kraftpunkte wieder aufzuladen, muß man nun zusätzlich seine Sanity-Anzeige im Blick haben
Geistige Gesundheit lädt sich wieder auf, wenn man herumläuft, und kein Monster neben sich stehen hat. Zusätzlich gibt jeglicher physische Schaden, der ausgeteilt wird, egal ob durch Spieler oder Monster, +1 Sanity-Punkt zurück. Dies ist ungemein thematisch, da man nun, bei niedriger Sanity + getriggerter Aggro, sich zwischendurch immer Schmerzen zufügen muß, um nicht wahnsinnig zu werden. :freak:
Der letzte entscheidende taktische Kniff bei dem System: Für jedes im Kampf besiegte Monster (nicht durch Fallen), ganz egal wie stark, erhöht sich die maximale Geistige Gesundheit um +1. Man hat nun ein sinnvolles Entscheidungsgefälle im Umgang mit schwächeren Monstern: cheesed man sie lediglich in eine Falle, kriegt man zwar +1 XP, aber levelt keine Sanity. Andersrum riskiert man natürlich daß Waffe oder Schilde zerbrechen, und man bekommt keine XP, aber man erhöht dauerhaft seine Geistige Gesundheit. Und Sanity ist später, wenn man gefährlicheren Monstern wie Shogotten und Sternengezüchten begegnet, kein zu unterschätzender Stat.

- Items, die im Editor platziert werden, haben ab sofort nur noch eine relative Position. Das Programm liest die Koordinaten aller platzierter Items aus und wendet eine "FloodFill"-Routine auf das entsprechende Tile an, um angrenzende, ebenfalls zulässige Tiles zu erkennen und in einer Liste zu speichern. Ab sofort können Items also in variablen Position gefunden werden - innerhalb der natürlichen Begrenzung ihrer Start-Areale, also kein Item, welches im Editor vor einer Tür platziert wurde (egal ob diese offen oder zu ist), wird sich im Spiel auf einmal dahinter befinden! Das war eine kleine, aber effektive Maßnahme, welche den Adventure- und Exploration-Fokus des Spiels gehörig aufwertet.
In Kombination mit dem neuen, eleganteren event-Handling ist nun Potential für tolle emergent gameplay-Situationen gegeben: da initial platzierte Items nun auch auf Teleport-Feldern und Spawn-Traps (welche ebenfalls zufällig verteilt werden) landen können, muß man nun Konsequenzen abwägen, wenn man das daraufliegende Item aufsammeln möchte (tödliche Fallen bleiben natürlich tabu für Item-Placement - so ein Arschloch bin ich dann doch nicht :doh: ).

- Last but not least habe ich Funktionalität für einen Screen Shake implementiert. Damit lassen sich prima "Event"-Treffer, also wenn man Monster besiegt, Items kaputt gehen, oder eine Tür aufbricht, visuell hervorheben.
Fühlt sich einfach gut an! :allright:
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Die Gemäuer von Kalawaum (90s Classic, Rework)

Beitrag von diceman »

Bild


UPDATE:

Ich habe das Sanity-System weiter getweaked und poliert. Es gibt einen zusätzlichen Item-Typ im Spiel zu finden, die "Consumables". Da ich das Kern-Spielprinzip von "Kalawaum" nicht verwässern möchte, und weiterhin einen flotten Gameplay-Loop anstrebe, den man ohne Number-Crunching aus dem Bauch heraus spielen kann, sind das weitestgehend auch nur Items mit passivem Effekt ... Consumables helfen Geistige Gesundheit zu wahren, und wieder aufzufüllen: trägt man eines bei sich, wird das Sanity-Check-Value des Monsters, welches einen verfolgt, je nach Item-Wertigkeit ein wenig reduziert; desweiteren geben Consumables, wenn man physischen Schaden zufügt oder erleidet, jeweils eine Chance auf +1 Bonus Sanity-Gain (auch abhängig von der Wertigkeit des Items).
Es gibt 5 Consumables:


Bild


- eine Phiole mit Weihwasser
- eine Dose mit Tabakhalmen :freak:
- eine Flasche Whisky
- einige Zauberpilze
- einen Schuss Mohn-Serum

Consumables haben, wie Schilde und Waffen, eine Chance zerstört (sprich: "aufgebraucht") zu werden, jedesmal, wenn ein Monster einem erfolgreich Geistige Gesundheit abzieht. Consumables können auch abgelegt werden - hier öffnet sich zusätzlich ein Dialog, ob man das Item ablegen, oder in Notfällen gar komplett konsumieren möchte, für einen signifikanten einmaligen "Oh Shit"-Prozent-basierten Boost auf Geistige Gesundheit. Danach ist es ganz aus dem Inventar verschwunden.

Ich habe die UI fertiggestellt: für jeweils Hitpoints und Sanity gibt es ein Herz- (anatomisch korrekt, selbstverständlich), bzw. ein Gehirn-Symbol, welche den Wert prozentual visualisiert. Nimmt einer der Werte ab, "leert" sich auch das entsprechende Symbol:


Bild


Das Währungs-System ist fertiggestellt: Monster, sofern man sie im Kampf besiegt, droppen "Kristallscherben" (Crystal Shards). Gesammelte Kristallscherben sind einerseits Punkte für die Highscore-Liste (werden bei Spielende oder Ableben mit dem Erfahrungslevel = hitpointsMax multipliziert), man kann mit ihnen aber auch die Gunst der Götter bezahlen, und an Schreinen (sofern man dem jeweiligen Orden beigetreten ist), ein Bindungsritual ausführen - dahinter verbirgt sich eine "True Save"-Funktion, also eine zweite Chance. Hat man ein solches Ritual abgehalten, und man stirbt, wird der Spielstand an den Moment zurückversetzt, an dem das Ritual abgehalten wurde. Dieses Ritual kann man aber nur einmal pro Schrein ausführen ... Das Spiel verlassen und später an derselben Stelle fortsetzen, ist selbstverständlich immer möglich!

Ab sofort besteht bei erstmaligem Betreten einer Map eine Chance, daß zusätzlich zu den im Editor platzierten ausrüstbaren Items (Waffen/Schilde/Consumables) ein zufälliges Bonus-Item spawnt, bzw. ein vorhandenes Item gelöscht wird (oder eine Kombination aus beidem).

Ich habe gemerkt, daß ich den ganz dunklen Grünton aus meiner 16-Farben-Palette so gut wie gar nicht benutzt habe - der ist jetzt raus, und wurde durch ein sickes, dreckiges Gelb ersetzt, welches mir mehr Design-Space gibt; z.B. haben die Dunkeldürren jetzt Klauen, und das letzte Waffen-Item, welches in diesem Update ebenfalls neu dabei ist, sieht so auch hübscher aus:


Bild


Mit der Fackel kann man keinen Schaden zufügen, aber Monster in die Flucht schlagen. Sie hat eine virtuelle Damage-Range von 1-100, und je nachdem welcher Wert gewürfelt wurde (Gaußsche Bell-Curve), flieht das Monster weiter oder weniger weit, bevor es wieder in den Suchen-und-Verfolgen-Modus wechselt. Weil das ein recht mächtiges Item ist, hat es auch eine höhere Chance beim Schlag zu zerbrechen.

Und weil ich so gut vorankomme, habe ich beschlossen, jedem Monster eine kleine Spezialfähigkeit zu geben, um den jeweiligen Charakter und die zugehörige Fantasy zu betonen. Das werden keine Game-Changer sein (siehe erster Absatz, soviel gibt das gestreamlinete Design nicht her), aber kleine individuelle Tweaks, z.B dürfen die Dunkeldürren im Fluchtmodus zwei Felder weit laufen (macht sie herrlich evasive, und passt zum Design mit den Flügeln).

Außerdem ist das zweite Monster fertig, ein "Rat-Thing", bzw. ein "Rättling".
Das ist von den Stats her das schwächste Monster, es saugt auch keine geistige Gesundheit ab, aber wenn der Rättling nach seinem ersten Zug auf einem "dunklen" Bodenfeld stehenbleibt, darf er eine 50% Chance auf einen zweiten Zug würfeln. Wenn man den Rättling nicht sieht, also solange er sich im Fog of War bewegt, bewegt er sich IMMER zwei Felder. Rättlinge können Geheimgänge nutzen, und sind immun gegen Pfeilfallen.


Bild


Außerdem ganz oben im Bild zu sehen: die Kristallscherben (Währung im Spiel) gibt es jetzt auch als Pick-Ups zum Aufsammeln. Man kann sie im Editor platzieren (der letzendliche Wert pro Item ist zufällig (Gauß'sche Wichtung gen 1), auch die endgültige Location wird - wie bei anderen Items -innerhalb der Schranken des initialen Areals randomisiert), außerdem werden, abhängig von der Anzahl der Maps in einem Modul, eine randomisierte Menge an Kristallscherben in allen Maps verteilt.
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Die Gemäuer von Kalawaum (90s Classic, Rework)

Beitrag von diceman »

Bild


GROßES UPDATE:

Ich habe den deutschen Sprachsatz rausgeschmissen. Es war ursprünglich eine Challenge, wie man Lokalisationen effektiv und elegant einbinden kann, es hat funktioniert, aber ich hatte keine Lust mehr auf Nominativ und Akkusativ-Edge Cases, die man alle seperat als Data-Files einlesen und berücksichtigen muß. Englisch ist in dieser Hinsicht weesentlich pflegeleichter, und sonderlich textlastig ist das Spiel sowieso nicht - Feedback kriegt der Spieler primär über die visuelle Schiene.

Das voraussichtliche letzte Tileset ist fertiggestellt, die Wasserfelder. Im Wasser kommt man schwerer vorwärts, deswegen gibt es einige besondere Interaktionen: per Default haben alle Monster eine 25% Chance auf Wasser einen Bewegungsbefehl zu ignorieren. Angreifen kann man aber immer. Und der Spieler regeneriert auf Wasserfeldern 2 Hitpoints, anstatt nur einem. Einige Monster, zum Beispiel die Nightgaunts, haben Angst vor Wasser, das heißt es gibt eine 75% Chance, wenn sie auf einem Feld <> Wasser stehen, daß bei der Pfadsuche Vorschläge mit Wasserfeldern mit einem Penalty-Wert belegt werden.

Statt spezifische Eigenschaften von Monstern einzeln abzufragen, habe ich ein modales "Ability-System" geschrieben, welches in der Lage ist, jedes Monster mit jeder beliebigen Eigenschaft auszustatten. Dies können positiv konnotierte Fähigkeiten, aber auch negative, thematische Traits sein. Ich kann nun, wie im Baukasten, mir Monster zusammenbasteln - dies öffnet Tür und Tor für die aus ARPGs bekannten Features wie den "einzigartigen Monstern", welche zufällige Eigenschaften zugeteilt bekommen (dergleichen werde ich aber - wenn überhaupt - sehr viel später implementieren):


Bild


Weitere visuelle Tweaks zugefügt: eine Teleport-Animation, eine Idle-Animation für Monster, und semi-permanente Blutflecken, die nach und nach verblassen.


Komfort-Features für den Editor: Wenn man Türen platziert, wird direkt das gegenwärtig aktive Mauer-Tile mitplatziert, respektive beim Löschen durch das primär selektierte Boden-Tile ersetzt. Und im FloodFill-Mode kann man nun auf Türen klicken, um alle anderen Türen auf derselben Map mit dem ausgewählten Mauer-Tile zu ersetzen.

"Spawning" implementiert: wenn Spieler oder Monster auf eine Spawn-Trap treten, wird ein zufälliges Monster irgendwo auf ein freies Tile in die Map teleportiert.Die entsprechende Funktion ist modal designt, sie kommt bei der Summon-Ability der Deep Ones zum Einsatz, und wenn Kultisten mutieren.

Neue Ability für den Nightgaunt: sie können den Spieler "wegtragen", ("tickle into Submission" - um es mit den Worten von H.P. Lovecraft auszudrücken): bei einem erfolgreichen Angriff gibt es eine 50% Chance, daß ein Nightgaunt mit dem Spieler den Platz tauscht. Das hört sich simpel an, war aber programmiertechnisch eine Herausforderung, da an der Aktion eine Kette an Design-Entscheidungen hing - letztendlich habe ich es so gelöst, daß der Switch effektiv als ferngesteuerter Spieler-Move funktioniert - so werden automatisch alle Effekte für das Betreten des neuen Feldes mit ausgeführt, zum Beispiel aufsammeln von Gegenständen, oder Ausführen von Teleports. :uff:

Erstes neues Monster: The Cultist
Der Kultist ist ein recht schwaches Monster, vergleichbar mit dem Rat-Thing; er hat keine besonderen Fähigkeiten - wenn er aber von einem beliebigen Bodenfeld auf ein Wasserfeld tritt, hat er eine 66% Chance zu einem Deep One (einem "Tiefen Wesen") zu mutieren:


Bild


Zweites neues Monster: The Deep One (Tiefes Wesen)
Deep Ones sind für sich gesehen nicht wahnsinnig stark, haben aber ein recht komplexes Set an Fähigkeiten, welches sie unter Umständen sehr gefährlich machen kann: zunächst mal ziehen sie Geistige Gesundheit, wenn sie den Spieler verfolgen. Dann können sie sich ungehindert auf Wasser bewegen; im Wasser sind sie tauchend unterwegs, das heißt, man sieht sie nur als Kringel auf der Wasseroberfläche, und ihren Lebenspunkte-Balken sieht man auch nicht (allerdings wird jedes Monster bei erster Begegnung vorgestellt - man weiß in der Regel, wie stark ein Monster initial ist - und eins der nächsten Updates wird Floating Numbers einführen, für direkteres Feedback, wieviel Schaden man macht).
Last but not least haben Deep Ones eine Summon-Ability: wenn sie sterben, gibt es eine 75% Chance, daß einem zufällig ausgewürfelten Schrein-Objekt auf der Map ein weiteres Monster herbeigerufen wird ... 50% Chance auf einen Subtypen der eigenen Klasse, 50% ein Kultist:

Bild
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Antworten