Aktuelle Zeit: 18.06.2018 13:13

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 11 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
 Betreff des Beitrags: Bresenham-Algorithmus
BeitragVerfasst: 06.02.2018 23:17 
Offline
Benutzeravatar

Registriert: 06.07.2017 12:24
So, ich traue mich dann mal, meinen ersten konstruktiven Beitrag reinzustellen ... :)
Hier isser, der berühmt-berüchtigte Bresenham-Algorithmus, mit dem man Line-of-Sight in einer Tile-based Umgebung berechnen kann (nützlich für Roguelikes, RPGs und Adventures) ...
Der eigentliche Code ist vom entsprechenden Wikipedia-Eintrag, ich habe ihn in PureBasic übersetzt und in eine funktionierende Umgebung eingebettet (das Original-Snippet hat nur eine einzige Linie von einem Startpunkt zu einem Endpunkt berechnet):

Bild

Funktionsweise:
Die World-Daten (Freie Felder/Mauern/Bäume, etc.) werden in eine binäre Map übersetzt, welche nur aus 0en und 1en besteht, also nur Informationen enthält ob ein Feld frei ist oder theoretisch in der Lage ist, Sichtlinie zu blocken. Diese binäre Map wird mittels der LOS-Variable (maximale Sichtweite vom Spieler = Rechteck um Spieler-Charakter herum) in der eigentlichen Bresenham-Prozedur verarbeit; Output ist eine sogenannte "bresenMap()", welche ebenfalls nur aus 0en und 1en besteht, und somit alle notwendigen Informationen liefert, welche Tiles vom Spieler aus sichtbar sind, und welche durch Hinternisse verdeckt werden.
Anschließend wird die Welt mit diesen neuen Ergebnissen gezeichnet:

Code:
Global xMax = 30
Global yMax = 30

Global Dim worldMap.s(xMax,yMax)
Global Dim line$(yMax)
Global Dim binaryMap(xMax,yMax)
Global Dim bresenMap(xMax,yMax)
Global startX = 17
Global startY = 18
Global lineOfSight = 10

Restore world_data
For y = 1 To yMax
   For x = 1 To xMax
      Read.s worldMap(x,y)
   Next
Next





Procedure buildWorld()
   Define tile$
   
   For y = 1 To yMax
      line$(y) = ""
      For x = 1 To xMax
         tile$ = worldMap(x,y)
         If x = startX And y = startY
            tile$ = "@"
         EndIf
         line$(y) = line$(y) + tile$
      Next
   Next   
EndProcedure


Procedure drawWorld()
   ClearConsole()
   For y = 1 To yMax
      PrintN(line$(y))
   Next
EndProcedure


Procedure translateWorld()
   Dim binaryMap(xMax,yMax)
   For y = 1 To yMax
      For x = 1 To xMax
         Select worldMap(x,y)
            Case "." : binaryMap(x,y) = 1 ;Freies Feld
            Case "#" : binaryMap(x,y) = 0 ;Mauer
         EndSelect
      Next
   Next
EndProcedure


Procedure getBresenmap(x,y,xT,yT)
   Define dX,dY      ;Pixel
   Define dXabs,dYabs    ;Absolut-Distanzen
   Define dXsgn,dYsgn    ;Signum-Distanzen
   Define pdX,pdY       ;Parallel-Schritt
   Define ddX,ddY       ;Diagonal-Schritt
   Define eFast,eSlow  ;Fehlerschritte, schnell, langsam
   Define error

   dX = xT - x ;Target-Koordinaten
   dY = yT - y
   dXabs = Abs(dX)
   dYabs = Abs(dY)
   dXsgn = Sign(dX)
   dYsgn = Sign(dY)
            
   If dXabs > dYabs ; x = schnelle Richtung
      pdX = dXsgn
      pdY = 0
      ddX = dXsgn
      ddY = dYsgn
      eFast = dYabs
      eSlow = dXabs
   Else
      pdX = 0
      pdY = dYsgn
      ddX = dXsgn
      ddY = dYsgn
      eFast = dXabs
      eSlow = dYabs
   EndIf
         
   error = eSlow/2

   For i = 1 To eSlow
      error = error - eFast
      If error < 0
         error = error + eSlow
         x = x + ddX
         y = y + ddY
      Else
         x = x + pdX
         y = y + pdY
      EndIf
      
      bresenMap(x,y) = 1   ;Letztes Feld vor Abbruch der Funktion noch auf 1 setzen,
                     ;da sonst blockende Mauern nicht angezeigt werden
      If binaryMap(x,y) = 0
         ProcedureReturn
      EndIf
   Next
EndProcedure


Procedure calculateLOS()
   Dim bresenMap(xMax,yMax)

   ;lineOfSight = maximale Sichtweite in jeder orthogonalen Achse vom Spieler aus
   ;kann (und sollte) optimiert werden mit einem limitCheck, damit es keinen
   ;"Array Index -out of Bounds"-Fehler gibt, falls Distanz > Spielfeld

   For y = startY-lineOfSight To startY+lineOfSight
      For x = startX-lineOfSight To startX+lineOfSight
         getBresenmap(startX,startY,x,y)
      Next
   Next
   
   For y = 1 To yMax
      For x = 1 To xMax
         If bresenMap(x,y) = 0
            worldMap(x,y) = " "
         EndIf
      Next
   Next
EndProcedure





OpenConsole()

buildWorld()
drawWorld()
PrintN("Press ENTER") : Input()

translateWorld()
calculateLOS()

buildWorld()
drawWorld()
PrintN("Press ENTER") : Input()

End





DataSection
world_data:
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".","#","#","#",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#","#","#","#","#","#","#",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".",".",".",".",".",".",".","#",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".",".",".",".",".",".",".","#",".","#","#","#",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".",".",".",".",".",".",".","#",".",".",".","#",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".","#",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".","#",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".","#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".","#",".",".","#",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".","#",".",".","#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".","#",".",".","#","#","#",".",".",".","#","#","#","#","#","#",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".","#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#","#","#","#","#",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
   Data.s ".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","."
EndDataSection

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


Zuletzt geändert von diceman am 06.02.2018 23:57, insgesamt 5-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Bresenham-Algorithmus
BeitragVerfasst: 06.02.2018 23:29 
Offline
Moderator
Benutzeravatar

Registriert: 05.10.2006 18:55
Wohnort: Rupture Farms
:allright:

_________________
BildBildBildBild
Bild | EnableExplicit ist kostenlos und vermeidet Fehler | Gib Goto keine Chance | Schneller als die Telekom erlaubt | Avira? Nein Danke
WinAPI forever | Bei Problemen bitte Beispielcode posten | Mit Adblock werbefrei, schneller und sicherer surfen | brain.exe ist der beste Schutz | Userlibrary ohne Source = NoGo


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Bresenham-Algorithmus
BeitragVerfasst: 07.02.2018 00:09 
Offline
Benutzeravatar

Registriert: 06.07.2017 12:24
Das Einlesen der WorldData könnte natürlich mit Hilfe des Mid()-Befehls noch eleganter gestaltet werden, merke ich gerade.
Das würde insbesondere den Data-Wust am Ende des Programms übersichtlicher gestalten.
Man sehe mir das nach, ich lerne momentan jeden Tag neue Befehle und Eigenarten von PB kennen. :)

Also nicht so:
Code:
Data.s ".",".",".","#","#",".","."
Data.s ".",".",".",".","#",".","."
Data.s ".",".",".",".","#",".","."


Sondern so:
Code:
Data.s "....##.."
Data.s ".....#.."
Data.s ".....#.."

Das Prinzip sollte trotzdem klar sein, und ist auch leicht übersetzbar in eine echte Tile-Map mit Grafikausgabe.

_________________
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: Bresenham-Algorithmus
BeitragVerfasst: 07.02.2018 13:39 
Offline
Moderator
Benutzeravatar

Registriert: 05.10.2006 18:55
Wohnort: Rupture Farms
Hallo diceman,

ich habe deinen Quellcode genauer angeschaut und möchte dir ein paar Tipps geben:
  1. EnableExplicit :)
  2. Innerhalb einer Prozedur solltest du nicht Define nehmen, sondern Protected.
  3. Wenn du Variablen verwendest, definiere sie immer vorher. Also auch solche Hilfsvariablen: y, x, i
  4. Der Index bei einem Array beginnt nicht bei 1, sondern 0. Und bei Max musst du natürlich eins abziehen. Z.B. For x = 0 To xMax-1

_________________
BildBildBildBild
Bild | EnableExplicit ist kostenlos und vermeidet Fehler | Gib Goto keine Chance | Schneller als die Telekom erlaubt | Avira? Nein Danke
WinAPI forever | Bei Problemen bitte Beispielcode posten | Mit Adblock werbefrei, schneller und sicherer surfen | brain.exe ist der beste Schutz | Userlibrary ohne Source = NoGo


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Bresenham-Algorithmus
BeitragVerfasst: 07.02.2018 13:56 
Offline
Benutzeravatar

Registriert: 06.07.2017 12:24
Heyho, danke! :)
Ja, das mit EnableExplicit und dem Definieren von Hilfsvariablen werde ich versuchen ins Rückenmark zu bekommen. War jetzt auch, ehrlich gesagt, pure Bequemlichkeit, weil self-contained Snippet. Finde ich aber gut, daß ihr das so streng seht und mich darauf hinweist (Blitzbasic hat mich in dieser Hinsicht ganz schön verdorben). :)

RSBasic hat geschrieben:
Innerhalb einer Prozedur solltest du nicht Define nehmen, sondern Protected.

Ist notiert, gucke ich mir nachher mal an.

RSBasic hat geschrieben:
Der Index bei einem Array beginnt nicht bei 1, sondern 0. Und bei Max musst du natürlich eins abziehen. Z.B. For x = 0 To xMax-1.

Oh, ja, das ist eine ganz doofe Gewohnheit von mir, auf die ich wieder besseren Wissens immer wieder zurückfalle. Ist jetzt aber, zum Beginn des Lernens einer neuen Sprache, eine ganz gute Gelegenheit, die loszuwerden. Und statt xMax-1 kann ich dann gleich die Variable mit 29 dimensionieren (OCD, anyone?) ... ;)
Ich gelobe Besserung!

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


Zuletzt geändert von diceman am 07.02.2018 14:03, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Bresenham-Algorithmus
BeitragVerfasst: 07.02.2018 14:02 
Offline
Ein Admin
Benutzeravatar

Registriert: 29.08.2004 20:20
Wohnort: Saarbrücken
Ich habe noch einen schönen Trick für dich um deine Map noch eleganter auszulesen. Dafür nutze ich Strukturen, Pointer und Makros. Vielleicht gefällt dir das ja auch:
Code:
Structure World
   f.c[30 * 30] ;um dich noch mehr zu verwirren, kannst du hier auch einfach eine 0 reinschreiben
EndStructure

Global *world.World = ?world_data

Macro field(x, y)
   Bool(*world\f[y * 30 + x] = '#')
EndMacro

Debug field(13, 8)
Debug field(14, 8)
Debug field(15, 8)
Debug field(16, 8)

DataSection
world_data:
   Data.s ".............................." +
          ".............................." +
          ".............................." +
          ".............................." +
          ".............................." +
          ".............................." +
          ".............................." +
          ".............................." +
          ".............###.............." +
          ".............................." +
          "............#...#######......." +
          "............#.........#......." +
          "............#.........#.###..." +
          "............#.............#..." +
          "............#.............#..." +
          "............#.........#...#..." +
          ".........#............#...#..." +
          ".........#............#...#..." +
          ".........#................#..." +
          ".........#..#.............#..." +
          ".........#..#................." +
          ".........#..###...######......" +
          ".........#...................." +
          ".............................." +
          "................#####........." +
          ".............................." +
          ".............................." +
          ".............................." +
          ".............................." +
          ".............................."
EndDataSection

_________________
Freakscorner.de - Der Bastelkeller | Neustes Video: Creality 3D CR-10 Review und erste Druckergebnisse
Ubuntu Gnome 16.04.3 LTS x64, PureBasic 5.60 x64 (außerdem 4.41, 4.50, 4.61, 5.00, 5.10, 5.11, 5.21, 5.22, 5.30, 5.31, 5.40, 5.50)
"Die deutsche Rechtschreibung ist Freeware, du darfst sie kostenlos nutzen – Aber sie ist nicht Open Source, d. h. du darfst sie nicht verändern oder in veränderter Form veröffentlichen."


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Bresenham-Algorithmus
BeitragVerfasst: 07.02.2018 15:27 
Offline
Benutzeravatar

Registriert: 06.07.2017 12:24
@NicTheQuick
Vielen Dank für deinen Trick, das sieht echt super aus. :) Auch wenn's auf mich momentan (noch) wie 'ne Explosion in a Printer-Shop wirkt, no offense. :wink:
Makros habe ich mir noch nicht näher angeschaut, würde es dir aber evtl. trotzdem nichts ausmachen, ein paar Worte dazu zu schreiben, also WAS genau du da machst, und warum das funktioniert? :? Zum Beispiel sehe ich nirgendwo, das du spezifisch Strings einliest - in meinem Bespiel war die IDE regelrecht zickig, weil ich das wirklich überall definieren mußte, also im Array(), in dem Data-Segment, und nochmal beim Read-Befehl.
Vielen Dank!

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


Zuletzt geändert von diceman am 07.02.2018 15:41, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Bresenham-Algorithmus
BeitragVerfasst: 07.02.2018 15:45 
Offline
Ein Admin
Benutzeravatar

Registriert: 29.08.2004 20:20
Wohnort: Saarbrücken
Der Trick ist: Ich nehme eine Struktur, die ein Array aus Characters enthält, und weise sie einem Pointer zu, der auf die DataSection zeigt. Das schöne ist, dass ein Character (.c) immer so groß ist wie ein Zeichen in einem String. Da ich die DataSection mit dem +-Operator zu einem langen String gemacht habe, kann ich also über den Index im Character-Array jeden einzelnen Buchstaben ansteuern. Das Macro ist nur noch dazu da die X- und Y-Koordinaten umzurechnen, damit der richtige Buchstabe herausgepickt wird.

Vielleicht wird es damit klarer:
Code:
Define.s text = "Hallo"

Debug "Unicode-Wert des ersten Buchstaben: "
Debug PeekC(@text)

; Das Array hat eigentlich die Größe 0, da das Character-Array darin 0 Elemente hat,
; aber Purebasic lässt das zu und überpüft in diesem Fall auch nicht, ob man die
; Array-Grenzen überschritten hat.
Structure CharacterArray
   c.c[0]
EndStructure

; Wir definieren den Pointer mit der CharacterArray-Struktur
; und lassen ihn auf den Anfang des Textes zeigen
Define *text.CharacterArray = @text

Debug "Unicode-Werte aller Zeichen in text:"
Debug *text\c[0]
Debug *text\c[1]
Debug *text\c[2]
Debug *text\c[3]
Debug *text\c[4]
Debug "Und abschließendes Nullzeichen."
Debug *text\c[5]

_________________
Freakscorner.de - Der Bastelkeller | Neustes Video: Creality 3D CR-10 Review und erste Druckergebnisse
Ubuntu Gnome 16.04.3 LTS x64, PureBasic 5.60 x64 (außerdem 4.41, 4.50, 4.61, 5.00, 5.10, 5.11, 5.21, 5.22, 5.30, 5.31, 5.40, 5.50)
"Die deutsche Rechtschreibung ist Freeware, du darfst sie kostenlos nutzen – Aber sie ist nicht Open Source, d. h. du darfst sie nicht verändern oder in veränderter Form veröffentlichen."


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Bresenham-Algorithmus
BeitragVerfasst: 07.02.2018 16:00 
Offline
Benutzeravatar

Registriert: 06.07.2017 12:24
@NicTheQuick
1000 Dank! Ja, damit kann ich schon mehr anfangen! Der Hinweis auf "Character" hätte mir schon gereicht, die entsprechende Deklaration habe ich überlesen ... die F1-Hilfe ist zwar umfangreich, aber teils doch recht abstrakt geschrieben, da ist nicht immer gleich klar, für welche Meta-Kniffe man das alles verwenden kann.

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


Zuletzt geändert von diceman am 07.02.2018 16:13, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Bresenham-Algorithmus
BeitragVerfasst: 08.02.2018 11:50 
Offline
Benutzeravatar

Registriert: 06.07.2017 12:24
Ich habe das Programm nochmal sauber überarbeitet und mich redlich bemüht, alle eingegangene Hinweise, Ratschläge, und was ich mir in der Zwischenzeit selbst erarbeitet habe, umzusetzen (z.B. daß Arrays immer mit Index 0 beginnen, der Code mit "EnableExplicit" läuft, und das Verwenden von #Konstanten wo es Sinn ergibt).
Mir ist es zudem wichtig, nur Code zu verwenden, den ich selbst verstehe, daher sei mir nicht böse, NicTheQuick, aber die World-Data lese ich jetzt Zeile für Zeile als temporären String ein, und suche mir dann mit dem Mid-Befehl die entsprechende x-Koordinate heraus. Trotzdem ist das jetzt eine 100% sauberere Angelegenheit (und auch leichter wartbar, wenn man beispielsweise die Architektur verändern möchte). :) In einer spielbaren Umgebung würde man die WorldData ohnehin aus einem externen File einlesen, oder jedesmal prozedural aufs Neue erstellen.
Auch neu ist eine limit()-Funktion, welche den LineOfSight-Radius auf das sichtbare Spielfeld begrenzt, und so "Array Index out of Bounds"-Fehler vermeidet, sollte man die Spieler-Position nahe am Spielfeldrand positionieren.
Vielen Dank für eure Geduld mit mir.

Code:
EnableExplicit

;{ Declare Procedures
Declare readWorldData()
Declare buildWorld()
Declare drawWorld()
Declare translateWorld()
Declare getBresenham(x,y,xT,yT)
Declare calculateLOS()
Declare limit(val,min,max)
;}

#xMax = 22
#yMax = 22
Global Dim worldMap.s(#xMax,#yMax)
Global Dim line$(#yMax)
Global Dim binaryMap(#xMax,#yMax)
Global Dim bresenMap(#xMax,#yMax)
Global playerX = 10
Global playerY = 10
Global lineOfSight = 10



readWorldData()
buildWorld()
If OpenConsole()
   drawWorld()
   PrintN("Press ENTER") : Input()
   
   translateWorld()
   calculateLOS()
   
   buildWorld()
   drawWorld()
   PrintN("Press ENTER") : Input()
EndIf
End





DataSection
world_data:
   Data.s "......................."
   Data.s "......................."
   Data.s "......................."
   Data.s "......######..........."
   Data.s "......######..........."
   Data.s "......................."
   Data.s "..#####..######........"
   Data.s "..#...................."
   Data.s "..#.....##..#.....###.."
   Data.s "..###.......#.....###.."
   Data.s "..###.......#.........."
   Data.s "..#.........######....."
   Data.s "..#..##................"
   Data.s "..#..##................"
   Data.s "...............###....."
   Data.s "......................."
   Data.s "....#####..####........"
   Data.s "......................."
   Data.s "......................."
   Data.s "..#....#####..........."
   Data.s "..#...................."
   Data.s "..##########..........."
   Data.s "......................."
EndDataSection





Procedure readWorldData()
   Define tempLine$
   Define x,y
   
   Restore world_data
   For y = 0 To #yMax
      Read.s tempLine$
      For x = 0 To #xMax
         worldMap(x,y) = Mid(tempLine$,x,1)
      Next
   Next
EndProcedure



Procedure buildWorld()
   Define tile$
   Define x,y
   
   For y = 0 To #yMax
      line$(y) = ""
      For x = 0 To #xMax
         tile$ = worldMap(x,y)
         If x = playerX And y = playerY
            tile$ = "@"
         EndIf
         line$(y) = line$(y) + tile$
      Next
   Next   
EndProcedure



Procedure drawWorld()
   Define y
   
   ClearConsole()
   For y = 0 To #yMax
      PrintN(line$(y))
   Next
EndProcedure



Procedure translateWorld()
   Define x,y
   
   Dim binaryMap(#xMax,#yMax)
   For y = 0 To #yMax
      For x = 0 To #xMax
         Select worldMap(x,y)
            Case "." : binaryMap(x,y) = 1 ;Freies Feld
            Case "#" : binaryMap(x,y) = 0 ;Mauer
         EndSelect
      Next
   Next
EndProcedure



Procedure calculateLOS()
   Define x,y
   
   Dim bresenMap(#xMax,#yMax)
   
   For y = limit(playerY-lineOfSight,0,#yMax) To limit(playerY+lineOfSight,0,#yMax)
      For x = limit(playerX-lineOfSight,0,#xMax) To limit(playerX+lineOfSight,0,#xMax)
         If bresenMap(x,y) = 0
         ;keine unnötigen Aufrufe = Speed!
         ;(wenn ein Feld bereits als sichtbar definiert wurde, keine erneute Berechnung durchführen)
            getBresenham(playerX,playerY,x,y)
         EndIf
      Next
   Next
   
   For y = 0 To #yMax
      For x = 0 To #xMax
         If bresenMap(x,y) = 0
            worldMap(x,y) = " "
         EndIf
      Next
   Next
EndProcedure



Procedure getBresenham(x,y,xT,yT)
   Define dX,dY      ;Pixel
   Define dXabs,dYabs    ;Absolut-Distanzen
   Define dXsgn,dYsgn    ;Signum-Distanzen
   Define pdX,pdY       ;Parallel-Schritt
   Define ddX,ddY       ;Diagonal-Schritt
   Define eFast,eSlow  ;Fehlerschritte, schnell, langsam
   Define error
   Define i

   dX = xT - x ;Target-Koordinaten
   dY = yT - y
   dXabs = Abs(dX)
   dYabs = Abs(dY)
   dXsgn = Sign(dX)
   dYsgn = Sign(dY)
            
   If dXabs > dYabs ; x = schnelle Richtung
      pdX = dXsgn
      pdY = 0
      ddX = dXsgn
      ddY = dYsgn
      eFast = dYabs
      eSlow = dXabs
   Else
      pdX = 0
      pdY = dYsgn
      ddX = dXsgn
      ddY = dYsgn
      eFast = dXabs
      eSlow = dYabs
   EndIf
         
   error = eSlow/2

   For i = 1 To eSlow
      error = error - eFast
      If error < 0
         error = error + eSlow
         x = x + ddX
         y = y + ddY
      Else
         x = x + pdX
         y = y + pdY
      EndIf
      
      bresenMap(x,y) = 1
      If binaryMap(x,y) = 0
         ProcedureReturn
      EndIf
   Next
EndProcedure



Procedure limit(val,min,max)
   If val < min
      ProcedureReturn min
   Else
      If val > max
         ProcedureReturn max
      EndIf
      ProcedureReturn val
   EndIf
EndProcedure

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


Zuletzt geändert von diceman am 08.02.2018 19:08, insgesamt 5-mal geändert.

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

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 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