Bresenham-Algorithmus

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Bresenham-Algorithmus

Beitrag von diceman »

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: Alles auswählen

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
Zuletzt geändert von diceman am 06.02.2018 23:57, insgesamt 5-mal geändert.
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Bresenham-Algorithmus

Beitrag von RSBasic »

:allright:
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Bresenham-Algorithmus

Beitrag von diceman »

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: Alles auswählen

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

Code: Alles auswählen

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.
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Bresenham-Algorithmus

Beitrag von RSBasic »

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
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Bresenham-Algorithmus

Beitrag von diceman »

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!
Zuletzt geändert von diceman am 07.02.2018 14:03, 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
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Bresenham-Algorithmus

Beitrag von NicTheQuick »

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: Alles auswählen

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
Bild
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Bresenham-Algorithmus

Beitrag von diceman »

@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!
Zuletzt geändert von diceman am 07.02.2018 15:41, 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
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Bresenham-Algorithmus

Beitrag von NicTheQuick »

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: Alles auswählen

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]
Bild
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Bresenham-Algorithmus

Beitrag von diceman »

@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.
Zuletzt geändert von diceman am 07.02.2018 16:13, 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
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Bresenham-Algorithmus

Beitrag von diceman »

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: Alles auswählen

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
Zuletzt geändert von diceman am 08.02.2018 19:08, insgesamt 5-mal geändert.
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Antworten