Roguelike-Diary (WIP ...)

Spiele, Demos, Grafikzeug und anderes unterhaltendes.
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Roguelike-Diary (WIP ...)

Beitrag von diceman »

Wer Lust hat, darf's nochmal testen, ich glaube es steuert sich jetzt besser ...
- Der Camera-Center ist jetzt absolut, und wenn man sich bewegt, bewegt sich die Kamera in Relation zum Spieler mit.
- Mit den Taste W,A,S,D kann man die Kamera in die entsprechende Richtung "schwenken". Und zwar nicht mehr sprunghaft, sondern fließend.
- Leertaste zentriert den Viewport wieder zurück auf den Spieler.
- Irgendwann, wenn mal ein Menü existiert, könnte man den Spieler noch ein Häkchen setzen lassen zum optionalen Invertieren der Kamera-Steuerung. 8)

Außerdem:

- Wenn man der Mauszeiger das Fenster verlässt, wird automatisch die Windows-Maus aktiviert.
- Ein Klick (rechte oder linke Maustaste) irgendwo aufs Fenster re-aktiviert die Spieloberfläche.

DOWNLOAD

Vielen Dank! :)
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: Roguelike-Diary (WIP ...)

Beitrag von diceman »

Mir ist übrigens grad aufgefallen, daß die Kamerabewegung nach rechts und links Blödsinn ist. ;-)
Die maximal mögliche Sichtweite ist ohnehin anhand der x-Achse gebalanced; eigentlich muß man nur nach oben und unten sehen können.
Das Mausrad würde sich hier anbieten ... das sind jetzt aber tatsächlich kleine QoL-Tweaks, an denen ich mich nicht lange aufhalten möchte. :-)
Bin euch jedenfalls zu Dank verpflichtet - so ganz ohne Feedback kann man schnell Tunnelblick bekommen und sich mit dem kleinsten Übel zufrieden geben.
Eine gute, intuitive Steuerung ist mir nicht ganz unwichtig.
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Roguelike-Diary (WIP ...)

Beitrag von ccode_new »

So ist es definitiv schon mal besser.

Weiter verbessern kann man im laufe des Projektes immer noch.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Roguelike-Diary (WIP ...)

Beitrag von diceman »

***** VIDEO *****
Roguelike Diary 05: Basic Monster Intelligence

Ein paar graue Haare später ... /:-> :coderselixir:
Monster haben jetzt Verhaltensmuster und einen ersten (simplen) KI-Baum:

Code: Alles auswählen

If canSee(actor()\x,actor()\y,*player\x,*player\y)
	actor()\tactic = 1 ;Engage
	If actor()\hp = 1
		actor()\tactic = 0 ;Flee
	EndIf
Else
	actor()\tactic = 2 ;Idle (move randomly)
EndIf
Die Pfadsuche habe ich mit einer Dijkstra-Map umgesetzt. Dijkstra-Maps sind toll, weil man die nur einmal pro Zug updaten muß und trotzdem für alle Monster gültig sind. Und wenn man alle Werte einer fertig berechnete Dijkstra-Map mit -1.2 multipliziert, und das Ergebnis erneut scannt, erhält man eine gewichtete Safety-Map: effektiv wird die Pfadsuche geflippt und weiter entlegene Felder bekommen einen "Safety-Bonus", was die Monster zum Rückzug bewegt.
Das funktioniert in 70% aller Fälle recht ordentlich; manchmal aber waren die Monster in einer "kognitiven" Dissonanz gefangen, so daß sie immer abwechselnd einen Fluchtschritt und wieder einen Schritt zum Spieler hin machten.
Der entscheidene Durchbruch kam dann mit der Idee, daß sich jeder Actor seine 4 zuletzt beschrittenen Felder merkt, und für solche Felder einen "Penalty-Bonus" zu der Dijkstra-Flucht-Map addiert! Das jeweils zuletzt betretene Feld bekommt dabei den größten "Strafwert", und nach jedem Schritt findet ein sogennanter "Penalty-Decay" statt, d.h. die Strafwerte nehmen ab, je länger ein Feld nicht betreten wurde:

Code: Alles auswählen

For r = 0 To #recentMovesMax
	If actor()\x+xMod(dir) = actor()\xRecent[r] And actor()\y+yMod(dir) = actor()\yRecent[r] 
		chooseDirection()\value[1] + (((#recentMovesMax+1)-r)*2)
	EndIf
Next	
Das Ergebnis seht ihr oben. :)



Und wer mehr über Dijkstra-Maps und deren Anwendung erfahren möchte, dem empfehle ich diese beiden Artikel auf roguebasin.com:

• The Incredible Power of Dijkstra Maps
• Dijkstra Maps Visualized
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: Roguelike-Diary (WIP ...)

Beitrag von diceman »

Von sowas habe ich in Blitzbasic immer geträumt ... On the fly Alpha mapping!
:bounce:

Roguelike Diary 06: More Alpha Map Testing

Den Sichtradius für den Bresenham-Algorithmus halte ich jetzt immer maximal, und regele die effektive Sichtweite (abhängig von Leuchtquellen, die der Spieler bei sich trägt) ausschließlich über Alpha Mapping (für jedes Tile überprüfe ich mit dem Satz des Pythagoras, in welchem Abstand es sich zum Spieler befindet, und regele so die Leuchtstärke). Spielerisch habe ich einige Ideen, z.B. kann man so Schüsse ins "Blaue" abgeben, oder externe Leuchtquellen im Dungeon können ihren eigenen Leuchtradius haben (muß man nur einmal beim Betreten des Dungeons mit dem Bresenham-Algorithmus initialisieren, ergo keine Geschwindigkeitseinbußen), und man kann deren Alpha Mapping-values zum Leuchtradius des Spielers aufaddieren.
Aber damit will ich mich jetzt (noch) nicht aufhalten - der nächste Milestone sind aggressive Monster (bis jetzt liefen die Kämpfe recht einseitig ab).
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: Roguelike-Diary (WIP ...)

Beitrag von diceman »

Eine Monster-KI muß gut geplant werden, damit es hinterher keine bösen Überraschungen gibt. Die Abfragen und Konsequenzen sind fertig programmiert, jetzt muß alles auf logische Art und Weise verknüpft werden ... und ich wollte nur einen einzigen KI-Baum, der für alle Monster gleich gültig ist, nur die variablen Parameter werden "hinzugeladen".
Habe daher einen "trockenen" Konzept-Code aufgestellt, mit dem ich verschiedene Bedingungen und deren Konsequenzen überprüfen kann:

Code: Alles auswählen

;Neue, noch zu erstellende Actor-Attribute:
Define moraleLowerLimit		;wenn Lebensenergie moraleLowerLimit (prozentualer Wert) unterschreitet, FLEE-Modus einleiten
Define moraleUpperLimit		;wenn Lebensenerge > moraleUpperLimit (prozentualer Wert), FLEE-Modus beenden

Define fleeCounter			;Fluchtschritte im FLEE-Modus werden gezählt
Define fleeLimit			;Wenn Fluchtschritte = fleeLimit, FLEE-Modus beenden

Define minSafeDistance		;Mindest-Abstand zum Gegner (für Fernkampf-Gegner). Wenn unterschritten, temporär in Fluchtmodus wechseln

Define hasMeleeAbility		;kann Nahkampfangriffe ausführen
Define hasRangedAbility		;kann Fernkampfangriffe ausführen

Define meleeKiteChance		;Chance auf Flucht Spieler im Nahkampf anzugreifen
Define rangedKiteChance		;Chance auf Flucht Spieler aus der Distanz anzugreifen
Define repositionChance		;Chance, statt Angriff auszuführen, neue Position zu finden
Define approachChance		;Chance, beim Annähern zufälligen Move zu machen
Define standStillChance		;Chance im IDLE-Modus stehenzubleiben
Define searchChance			;Chance, wenn Spieler aus den Augen verloren, in den SEARCH-Modus zu wechseln
Define randomFleeChance		;Chance, wenn canSeePlayer = #False, im FLEE-Mode zufälligen Move zu machen

Define FLEE					;Monster ist im permanenten Flucht-Modus
Define TARGET_AQUIRED		;speichert den zuletzt bekannten Spieler-Standort
Define SEARCH				;Monster im SEARCH-Mode versuchen (mittels aStar) den zuletzt bekannten Spieler-Standort zu lokalisieren
							;kann extern getriggert werden, wenn Monster z.B. ein verdächtiges Geräusch gehört (braucht TARGET_AQUIRED)
Define IDLE					;Monster im IDLE-Mode machen entweder eine zufällige Bewegung oder bleiben stehen




selectMove = 0
selectAttack = 0

If FLEE
	If hp > moraleUpperLimit Or fleeCounter = fleeLimit
		FLEE = #False
		IDLE = #True
		TARGET_AQUIRED = 0
		SEARCH = #False
	EndIf
Else
	If hp < moraleLowerLimit
		FLEE = #True
		fleeCounter = 0
		TARGET_AQUIRED = 0
		SEARCH = #False
		IDLE = #False
	EndIf
EndIf

If canSeePlayer
	IDLE = #False
	SEARCH = #False
	TARGET_AQUIRED = playerLocation
	If hasRangedAbility
		If distance < minimumSafeDistance Or FLEE
			If inMeleeRange
				If hasMeleeAbility And Random(100) <= meleeKiteChance
					selectAttack = 1
				Else
					fleeCounter +1
					selectMove = 2
				EndIf
			Else
				If isNotBlocked And Random(100) <= rangedKiteChance
					selectAttack = 2
				Else
					fleeCounter +1
					selectMove = 2
				EndIf
			EndIf
		Else
			If targetInRange
				If isNotBlocked
					If Random(100)<= repositionChance
						selectMove = 3
					Else
						selectAttack = 2
					EndIf
				Else
					selectMove = 3
				EndIf
			Else
				If Random(100) <= approachChance
					selectMove = -1
				Else
					selectMove = 1
				EndIf
			EndIf
		EndIf
	Else
		If Not FLEE
			If hasMeleeAbility
				If Not inMeleeRange
					If Random(100) <= approachChance
						selectMove = -1
					Else
						selectMove = 1
					EndIf
				Else
					If Random(100) <= repositionChance
						selectMove = 1
					Else
						selectAttack = 1
					EndIf
				EndIf
			Else
				selectMove = -1
			EndIf
		Else
			If inMeleeRange and hasMeleeAbility And Random(100) <= meleeKiteChance
				selectAttack = 1
			Else
				fleeCounter +1
				selectMove = 2
			EndIf			
		EndIf
	EndIf
Else
	If Not FLEE
		If SEARCH = #False
			If TARGET_AQUIRED
				If Random(100) <= searchChance
					SEARCH = #True
				Else
					IDLE = #True
				EndIf
			Else
				IDLE = #True
			EndIf
		EndIf
		If SEARCH = #True
			If standingOnLastKnownLocation
				IDLE = #True
			Else
				selectMove = 4
			EndIf
		EndIf
	Else
		fleeCounter +1
		If Random(100) < randomFleeChance
			selectMove = -1
		Else
			selectMove = 2
		EndIf
	EndIf
EndIf


If IDLE = #True
	TARGET_AQUIRED = 0
	SEARCH = #False
	FLEE = #False
	If Random(100) > standStillChance
		selectMove = -1
	EndIf
EndIf


If selectMove
	Select selectMove
		Case -1	:	Debug "Random Move"
		Case 1	:	Debug "Approach"
		Case 2	:	Debug "Move Away"
		Case 3	:	Debug "Reposition"
		Case 4	:	Debug "aStar to LastKnownLocation"
	EndSelect
Else
	If selectAttack
		Select selectAttack
			Case 1	:	Debug "Perform Melee"
			Case 2	:	Debug "Perform Ranged"
		EndSelect
	EndIf
EndIf
Zuletzt geändert von diceman am 19.03.2018 23:07, insgesamt 1-mal geändert.
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
mk-soft
Beiträge: 3691
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Roguelike-Diary (WIP ...)

Beitrag von mk-soft »

Hi,

es macht vielleicht sinn mal mit Konstanten anzufangen. Dann ist das Programm besser lesbar als nur mit Zahlen.

Code: Alles auswählen

; Meine Konstante
 
Enumeration -1
  #Move_Random
  #Move_Null
  #Move_Approach
  #Move_Away
  #Move_Reposition
  #Move_LastKnownLocation
EndEnumeration

Enumeration
  #Attack_Null
  #Attack_PerformMelee
  #Attack_PerformRanged
EndEnumeration

Debug "Move Const"
Debug #Move_Random
Debug #Move_Null
Debug #Move_Approach
Debug #Move_Away
Debug #Move_Reposition
Debug #Move_LastKnownLocation

Debug "Attack Const"
Debug #Attack_Null
Debug #Attack_PerformMelee
Debug #Attack_PerformRanged

Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Roguelike-Diary (WIP ...)

Beitrag von diceman »

Ja, das ergibt Sinn. :)
Muß dazu sagen, daß ich das im Hauptprogramm schon stellenweise nutze; aber noch nicht konsequent genug, da geht noch mehr.
Das mit der automatischen Enumeration kannte ich aber noch nicht, bzw. habe ich mich bislang nicht beschäftigt.
Sieht nützlich aus, ich gucks mir gleich mal an! 8)

//EDIT:
Ist super! :D
Vielen Dank für den Tip!

Das da oben ist allerdings eher Pseudo-Code, den habe ich zur Planung verwendet.
War trotzdem eine gute Idee, das vorher "trocken" hinzuschreiben, dafür fluppt es mit der praktischen Implementierung jetzt umso besser.
Gehe es aber vorsichtig an, und teste nach jedem neuen Schritt, ob auch wirklich alles ordnungsgemäß funktioniert.
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: Roguelike-Diary (WIP ...)

Beitrag von diceman »

Die KI steht!
Was noch fehlt, ist der "Search-Modus", welcher Monster die zuletzt bekannte Position des Spielers aufsuchen lässt, sobald sie diesen aus den Augen verlieren.
Und wer mag, darf auch nochmal testen: :-)

DOWNLOAD

• Ihr habt 1Mio. Lebenspunkte, das sollte reichen um zu überleben. :?
• Es gibt 3 Monster: 1x recht langsames (bewegt sich primär orthogonal) Nahkampf-Monster, das aber viel einstecken kann, 1x wendiges (mag gerne diagonale Richtungen) Flugmonster, und 1x Fernkampf-Monster.
• Monster werden erst aktiv, sobald sie Sicht zum Spieler haben.
• Fernkampf-Monster suchen sich aktiv Positionen, von denen aus sie den Spieler beharken können, und versuchen gleichzeitig Abstand zu halten.
• Wenn ein Monster zuviel Schaden einstecken mußte, versucht es zu fliehen; Monster haben eine 50% Chance pro Schritt 1 Lebenspunkt zu regenerieren.
• Wenn sich ein Monster erholt hat (oder nach einer gewissen Anzahl von Fluchtschritten) wechselt es wieder in den "Idle"-Modus
• Es gibt noch keine Waffen oder "richtiges" Gameplay: rechter Mausklick initiiert entweder einen Nahkampf- oder einen Fernkampf-Angriff, je nachdem wie ihr steht.
• Linksklick auf den Spieler selbst lässt euch eine Runde aussetzen (man kann auch gedrückt halten).
• Wenn ihr "eingesperrt" startet, dann einfach schließen (mit ESC) und neu starten. Dann gibts einen neuen Dungeon.
• Mit den W,S,A,D-Tasten könnt ihr die Kamera etwas schwenken für weitere Sicht (Fenstergröße ist 1024*768 - könnte ich on the fly anpassen; für manche Laptops ist das evtl. zu groß und der untere Rand vom Fenster verschwindet in der Taskleiste)
• Leertaste zentriert die Sicht
• Mit + und - könnt ihr den Sichtradius verringern, bzw. vergrößern.
• Wenn ihr den Mauszeiger vom Fenster runterbewegt, wird die Maus automatisch freigegeben. Um weiter zu spielen, einfach auf dem Fenster irgendeinen Klick ausführen.



Next milestone: Items!
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Antworten