Aktuelle Zeit: 29.09.2020 00:41

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 124 Beiträge ]  Gehe zu Seite Vorherige  1, 2, 3, 4, 5 ... 13  Nächste
Autor Nachricht
 Betreff des Beitrags: Re: Roguelike-Diary (WIP ...)
BeitragVerfasst: 09.03.2018 01:00 
Offline
Benutzeravatar

Registriert: 06.07.2017 12:24
Alles klar, danke! :)
Wie gesagt, ich habe den Codeblock kopiert, etwas für meine Programm-Struktur angepasst, und war einfach happy, daß es funktionierte.
Dann war das also nur ein Platzhalter!

//EDIT:
Ich bilde mir ein, daß ich mir über die Jahre einen recht sauberen, deskriptiven Programmier-Stil erarbeitet habe, aber es ist halt auch nur EIN Weg, der nach Rom führt; Programmcode von anderen Leuten zu lesen UND zu verstehen UND konsktruktiv für mich zu nutzen, das war schon immer einer meiner Defizite, bzw. ein Schwachpunkt, an dem ich arbeite; denn wenn ich schon etwas übernehme, will ich auch etwas daraus lernen!

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


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Roguelike-Diary (WIP ...)
BeitragVerfasst: 09.03.2018 09:52 
Offline
Benutzeravatar

Registriert: 08.09.2004 08:53
Macht Spaß hier mitzulesen. Weiter so! :)

_________________
"Papa, mein Wecker funktioniert nicht! Der weckert immer zu früh."


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Roguelike-Diary (WIP ...)
BeitragVerfasst: 09.03.2018 10:01 
Offline
Admin

Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
+1

_________________
BildBildBildBild BildBild


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Roguelike-Diary (WIP ...)
BeitragVerfasst: 09.03.2018 17:54 
Offline
Benutzeravatar

Registriert: 24.11.2004 13:12
Wohnort: Germany
++1

_________________
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul / OPC-Helper DLL
PB v3.30 / v5.7x - OS Mac Mini OSX 10.xx / Window 10 Pro. (X64) /Window 7 Pro. (X64) / Window XP Pro. (X86) / Ubuntu 14.04
Downloads auf My Webspace


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Roguelike-Diary (WIP ...)
BeitragVerfasst: 09.03.2018 18:12 
Offline
Benutzeravatar

Registriert: 25.09.2016 01:42
+1

_________________

Links:
PureBasic Discord
[INCLUDE] GLFW 3.3 Library
[MODULE] Bass Library 2.4 (Win)
[LIBRARY] Hexi Binary2Hex (Win)



Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Roguelike-Diary (WIP ...)
BeitragVerfasst: 09.03.2018 22:45 
Offline
Benutzeravatar

Registriert: 06.07.2017 12:24
Actors, Baby!

*********** VIDEO ***********
Roguelike Diary 02: Actors
*******************************

Es gibt keine xPlayer,yPlayer-Koordinaten mehr, stattdessen ist JEDES Objekt ein Actor, inklusive dem Spieler (Actor vom Typ #monsterActor).
Ich mache keinen Unterschied mehr zwischen Türen, Schatztruhen und Monstern! Das hat den Vorteil, daß ich so recht einfach ein Agent System basteln kann, welches ein stabiles Fundament für Emergent Gameplay legt: jeder Actor kennt seine DisplaySprite()-Parameter (actor()\type, actor()\subtype[0], actor()\subtype[1], usw), x/y-Koordinaten, ob er Kollision hat, ob er Sichtlinie blockt, ob er sich bewegen kann, ob er eine KI hat, usw. Oder anders ausgedrückt: Wenn eine Tür Lebenspunkte hat, kann man sie auch mit Gewalt aufbrechen. :D

Dazu braucht es einen *player-Pointer, mit dem ich gezielt die Parameter des Spieler-Actors abrufen kann.

Ich arbeite mit 4 verschiedenen Arrays:
• worldMap(#xMax,#yMax)
• collisionMap(#xMax,#yMax)
• binaryMap(#xMax,#yMax)
• bresenMap(#xMax,#yMax)
Die worldMap() beinhaltet die Level-Architektur (0 = Mauer, 1 = freies Feld) und wird u.a. in der Zeichenroutine benutzt um den jeweiligen Ausschnitt rund um die gegenwärtige KameraCenter-Position zu zeichnen; Felder außerhalb des Viewports werden erst gar nicht angesteuert.
Die collisionMap() beinhaltet Informationen über Kollisionen: 0 = keine Kollision, 1 = Kollision. Das ist notwendig, da es Actors mit wechselnden States gibts, z.B. offene und geschlossene Türen. Jedesmal wenn sich ein Actor bewegt (Spieler/Monster), wird das aktuelle Feld in der collisionMap() um 1 herabgesetzt, und das Zielfeld kriegt +1. Das ergibt Sinn, wenn ich z.B. fliegende Monster haben möchte, die sich auf ein Feld bewegen dürfen, wo sich bereits ein Actor mit Kollision befindet. Jetzt hat dieses Feld in der collisonMap() +2; und wenn das Monster weiterfliegt, wird das Startfeld um 1 herabgesetzt und verliert dabei seine Kollision nicht (2-1 = 1)! Actors, mit denen man gar nicht interagiert, z.B. Bäume oder Säulen, haben Kollision -1, d.h. ich kann so gezielt das rote Interaktions-Rechteck ausblenden, wenn die Maus auf ein solches Feld bewegt wird.
Die binaryMap() ist von Relevanz, wenn bei LoS-Berechnungen und Pfadsuche der gegenwärtige World State in 0en und 1en übersetzt wird: mit CopyArray() wird zunächst der Inhalt der worldMap() kopiert, und anschließend mit ForEach actor() alle Actor-Informationen von Relevanz (Kollision bzw. Sichtlinie blockend) zur binaryMap() hinzugefügt. Es gibt zwei Prozeduren, die eine binaryMap() auslesen und verarbeiten können: getPath(...) und getBresenham(...).
Die bresenMap() enthält Informationen über Sichtlinie und LoS-blockende Felder, und wird nach jedem Schritt aktualisiert.

Außerdem habe ich eine sogenannte actorFactory() - das ist eine Prozedur, in der Actors erstellt werden. Warum ist notwendig?
Ich muß beim Zeichnen von Actors auf die "Zeichentiefe" achten - z.B. muß ein Monster, welches in einer Tür steht, immer sichtbar bleiben, d.h. die Tür muß immer zuerst gezeichnet werden. Und um dies möglichst elegant und effizient zu lösen, dafür habe ich die actorFactory(): Jeder Actor hat einen Parameter drawPriority. Actors mit drawPriority = 0 werden immer zuerst gezeichnet. Und damit ich nicht in meiner linkedList hin und herspringen muß, was verdammt viel Zeit bräuchte, werden die Actors gleich bei Erstellung nach dem Parameter drawPriority sortiert; ich muß also beim Zeichnen die actorList() nur einmal von vorne nach hinten abklappern, und führe trotzdem alle Zeichenoperationen in korrekter Reihenfolge durch:

Code:
Procedure actorFactory(type,subtype0,drawPriority,visible,collision,blockLoS,x,y)
   Define a
   Dim subtype(#actorSubtypeMax)
   subtype(0) = subtype0
   
   LastElement(actor())
   If ListSize(actor()) <> #Null And actor()\drawPriority > drawPriority
   ;funktioniert, weil <>#Null-Abfrage zuerst abgearbeitet wird (kein "Invalid Memory Access" bei leerer Liste)
      ForEach actor()
         If actor()\drawPriority >= drawPriority
            InsertElement(actor())
            Break
         EndIf
      Next
   Else
      AddElement(actor())
   EndIf
   actor()\type = type
   For a = 0 To #actorSubtypeMax
      actor()\subtype[a] = subtype(a)
   Next
   actor()\drawPriority = drawPriority
   actor()\visible = visible
   actor()\collision = collision
   actor()\blockLoS = blockLoS
   actor()\x = x
   actor()\y = y
   
   locatePlayer()
EndProcedure


Anschließend muß ich den *player-Pointer zurück auf den Spieler-Actor setzen, da nach addElement() die Speicheradresse nicht mehr gültig ist:

Code:
Procedure locatePlayer()
   ForEach actor()
      If actor()\type = #monsterActor And actor()\subtype[0] = 0
         *player = @actor()
         ProcedureReturn
      EndIf
   Next
EndProcedure


Und ich muß in der Lage sein, erstellte Elemente wieder zu löschen, ohne daß meine Actor-Library "kaputt" geht ...
Dazu rufe ich killActor(@actor()) auf - so kann ich gewährleisten, daß im Anschluß der *player-Pointer wieder hergestellt wird:

Code:
Procedure killActor(*deletePointer)
   ChangeCurrentElement(actor(),*deletePointer)
   DeleteElement(actor())
   locatePlayer()
EndProcedure

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


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Roguelike-Diary (WIP ...)
BeitragVerfasst: 10.03.2018 15:32 
Offline

Registriert: 23.06.2013 06:26
Pointer sind schön und elegant, bei meinem ersten PureBasic-Project hatte ich einfach 'nen unstrukturierten, mehrdimensionalen Array für Alles...

Zu locatePlayer():
Weiß jetzt nicht, wie dein Code aufgebaut ist, aber ab einer bestimmten ListSize könnte das etwas dauern, den Spieler zu finden (vor allen Dingen wenn du das ganze via SortList() sortierst).
Wenn du den Pointer vom Spieler als Variable speicherst brauchst du diese Prozedur nicht wirklich, Speicherpositionen bleiben gleich.

EDIT: Siehe Post von Bisonte.

_________________
Wer braucht schon Unicode? PB5.24LTS


Zuletzt geändert von Jan125 am 11.03.2018 13:06, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Roguelike-Diary (WIP ...)
BeitragVerfasst: 10.03.2018 16:51 
Offline
Benutzeravatar

Registriert: 06.07.2017 12:24
Danke für Feedback. :-)
Gib mir mal kurz ein Beispiel, was du mit "pointer als Variable" meinst! Würde sehr gerne auf locatePlayer() verzichten!

Um List-Search mache ich mir derzeit keine Probleme - in meinem Blitzbasic-Projekt hatte ich wesentlich schlechter optimierte Routinen, und ins Gewicht gefallen ist das nicht; und von der Geschwindigkeit her tun sich Blitz und PB nicht viel - wie gesagt, das wird ein turn-based Game. Und wenn ich später mal mehrere Dungeon-Ebenen haben möchte, habe ich eh vor, beim Verlassen und Betreten die Ebenen-Objekte auf Festplatte zwischenzuspeichern, bzw. zu laden, und nur mit "lokalen" Variablen und Objekten zu arbeiten.

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


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Roguelike-Diary (WIP ...)
BeitragVerfasst: 10.03.2018 17:05 
Offline
Benutzeravatar

Registriert: 01.04.2007 20:18
Ich denke er meint, dass Du den Pointer *player, der wohl auf ein ListenElement zeigt, in einer Variable zwischenspeicherst,
damit du nicht den Player in der List suchen musst.

Die Adresse eines ListenElements bleibt immer gleich. egal was du damit anstellst (ausser du löscht das Element).

Also bei der Erstellung des Players einfach : Player = *player und dann brauchst du nur noch, wenn das Element gebraucht wird :
*player = Player .... Ohne suchen in der Liste.

_________________
PureBasic 5.72 LTS (Windows x86/x64) | Windows10 Pro x64 | Z370 Extreme4 | i7 8770k | 64GB RAM | iChill GeForce RTX 2080 Super | HAF XF Evo​​


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Roguelike-Diary (WIP ...)
BeitragVerfasst: 10.03.2018 17:33 
Offline
Benutzeravatar

Registriert: 06.07.2017 12:24
Hmm, ich glaube ich habe da gerade einen Denkfehler, bzw. habe irgendwie Mist in meinem Übungscode gebaut ... :?
Jetzt gerade nochmal alles durchgetestet, und es scheint in der Tat so zu sein, daß der *pointer auf das Element erhalten bleibt, ganz egal ob ich Elemente aus der Liste lösche oder zufüge, oder an welcher Stelle. ChangeCurrentElement(foo(),*pointer) wechselt weiterhin aufs korrekte Element.
Dann wäre also die ganz locatePlayer()-Prozedur Quatsch, bzw. überflüssig. Yay. Und, ja, der *pointer ist Global und sollte, wenn möglich, auch bestehen bleiben - auf den muß ich ja quasi die ganze Zeit zugreifen, weil er den Ausgangspunkt für die drawStuff()-Routine gibt.
Danke für den Hinweis!

//EDIT:
Habe gerade mal testweise eine Map mit 1000x1000 Feldern erstellt und 22k actor()-Elementen ... selbst im Debug-Mode sind keine Lags zu vermerken; Bewegung von Punkt zu Punkt ist weiterhin (almost) instant. Yay. <) Es zahlt sich aus, daß ich die Pfadsuche nicht nach jedem Schritt neu aufrufe, sondern nur einmal beim Linksklick, anschließend die Pfadknoten in einer Linked-List zwischenspeichere, und dann, solange die Maustaste gedrückt bleibt, immer den nächsten Knoten aufrufe.

//EDIT:
Bei einer worldMap mit 2500*2500 Feldern und 135k actor()-Elementen siehts schon etwas anders aus, da gerät das Programm ins Schwitzen. Aber solche Dimensionen wären ja auch schwachsinnig, wollte ich das ernsthaft implementieren. ;-) 100x100 hat sich gut bewährt, und davon wird auch nur maximal ein Fünftel mit begehbaren Feldern gefüllt sein. Später kommen ja noch die KI-Modelle der Monster hinzu, die nach jedem Schritt aktualisiert werden wollen.

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


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 124 Beiträge ]  Gehe zu Seite Vorherige  1, 2, 3, 4, 5 ... 13  Nächste

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 6 Gäste


Sie dürfen keine neuen Themen in diesem Forum erstellen.
Sie dürfen keine Antworten zu Themen in diesem Forum erstellen.
Sie dürfen Ihre Beiträge in diesem Forum nicht ändern.
Sie dürfen Ihre Beiträge in diesem Forum nicht löschen.

Suche nach:
Gehe zu:  

 


Powered by phpBB © 2008 phpBB Group | Deutsche Übersetzung durch phpBB.de
subSilver+ theme by Canver Software, sponsor Sanal Modifiye