Type TLightning
	Const MIN_SEG_LENGTH:Int = 20			'Minimum segment length
	Const MIN_SEG_BRANCH_LENGTH:Int = 5		'Minimum segment length on branches
	Const BRANCH_ANGLE_MOD:Int = 40			'Max angle difference between mainlightning and branches
	Const GLOWCOLOR_R:Int = 100
	Const GLOWCOLOR_G:Int = 100
	Const GLOWCOLOR_B:Int = 255
	Field segments:TList = CreateList()		'List of segments of the mainlightning
	Field branches:TList = CreateList()		'List of branches
	Field branches2:TList = CreateList()	'Branches of the segmentized branches
	Field generations:Int = 4				'Iterations of seperation of the mainlightning
	Field offset:Int = 10					'Segments offset
	
	
	Rem
	bbdoc:Creates a new lightning from x1, y1 to x2, y2.
	Public Function
	End Rem
	Function getInstance:TLightning(x1:Int, y1:Int, x2:Int, y2:Int)
		Local instance:TLightning = New TLightning
		instance.setStartEndPoint(x1, y1, x2, y2)
		
		Return instance
	End Function
	
	
	Rem
	bbdoc:Sets new start- and endpoint coordinates.
	Public Method
	End Rem
	Method setStartEndPoint(x1:Int, y1:Int, x2:Int, y2:Int)
		'Create segment from x1,y1 to x2,y2
		Local startpoint:TPoint = TPoint.getInstance(x1, y1)
		Local endpoint:TPoint = TPoint.getInstance(x2, y2)
		Local firstSeg:TSegment = TSegment.getInstance(startpoint, endpoint)
		
		'Remove old lightning
		Self.segments.Clear()
		Self.branches.Clear()
		Self.branches2.Clear()
		
		'Create the lightning out of the first segment
		Self.segments.AddFirst(firstSeg)
		Self.segmentize(Self.segments, Self.generations, Self.offset)
		Self.branches = Self.createBranches(Self.segments)
		Self.segmentize(Self.branches, Self.generations - 1, Self.offset - 7, True)
		Self.branches2 = Self.createBranches(Self.branches)
		Self.segmentize(Self.branches2, Self.generations - 3, Self.offset - 7, True)
	End Method
	
	
	Rem
	bbdoc:Draws the lightning (Scale must be set to 1.0/1.0)
	Public Method
	End Rem
	Method draw()
		SetBlend(ALPHABLEND)
	
		'Branch2 Glow
		Self.setDrawings(0.4, 3, True)
		Self.drawSegments(Self.branches2)
		'Branches2
		Self.setDrawings(0.5, 1)
		Self.drawSegments(Self.branches2)
		
		'Branch Glow
		Self.setDrawings(0.5, 5, True)
		Self.drawSegments(Self.branches)
		'Branches
		Self.setDrawings(0.6, 1)
		Self.drawSegments(Self.branches)
		
		'Glow Paths
		Self.setDrawings(0.09, 20, True)
		Self.drawSegments(Self.segments)
		Self.setDrawings(0.25, 11, True)
		Self.drawSegments(Self.segments)
		Self.setDrawings(0.55, 6, True)
		Self.drawSegments(Self.segments)
		'Original Paths
		SetColor(255, 255, 255)
		SetAlpha(1.0)
		Local counter:Int = 0
		For Local seg:TSegment = EachIn Self.segments
			counter:+1
			Local thickness:Float = 0.3 * Float(Self.segments.Count() - counter)
			If thickness < 2.0 Then thickness = 2.0
			SetLineWidth(thickness)
			DrawLine(seg.startpoint.x, seg.startpoint.y, seg.endpoint.x, seg.endpoint.y)
		Next
	End Method
	
	
	Rem
	bbdoc:Private Method (don't use).
	Draws a list of segments.
	End Rem
	Method drawSegments(givenList:TList)
		For Local seg:TSegment = EachIn givenList
			DrawLine(seg.startpoint.x, seg.startpoint.y, seg.endpoint.x, seg.endpoint.y)
		Next
	End Method
	
	
	Rem
	bbdoc:Private Method (don't use).
	Sets the color to "Glow-Color"
	End Rem
	Method setDrawings(alpha:Float, lineThickness:Float, isGlowing:Byte = False)
		SetColor(255, 255, 255)
		If isGlowing Then SetColor(TLightning.GLOWCOLOR_R, TLightning.GLOWCOLOR_G, TLightning.GLOWCOLOR_B)
		SetAlpha(alpha)
		SetLineWidth(lineThickness)
	End Method
	
	
	Rem
	bbdoc:Private Method (don't use).
	Splits a line (segment) into two lines, which are moved by maxOffset at one point (start or endpoint of the line).
	End Rem
	Method segmentize(givenList:TList, generations:Int, offset:Int, isBranch:Byte = False)
		'Preconditions
		If givenList.IsEmpty() Then Return
		Local minLength:Int = TLightning.MIN_SEG_LENGTH
		If isBranch Then minLength = TLightning.MIN_SEG_BRANCH_LENGTH
		
		'Start segmentation
		For Local i:Int = 1 To generations
			Local workList:TList = givenList.Copy()
			For Local seg:TSegment = EachIn workList
			
					'Check if the segments length allows a split into 2 segments
					If TDistance.pointToPoint(seg.startpoint.x, seg.startpoint.y, seg.endpoint.x, seg.endpoint.y) >= minLength Then
						'The original segment is obsolete, as we replace it with 2 new ones
		    			givenList.Remove(seg)
			
			    		Local midpoint:TPoint = seg.getMidPoint()
						Local randomAngle:Int = 90
						If Rand(1, 2) = 1 Then randomAngle = -90
						'Move the midpoint
						midpoint.x:+(Cos(seg.angle + randomAngle) * offset)
						midpoint.y:+(Sin(seg.angle + randomAngle) * offset)
			
						'Add the new segments
						givenList.AddLast(TSegment.getInstance(seg.startpoint, midpoint))
						givenList.AddLast(TSegment.getInstance(midpoint, seg.endpoint))
					End If
				Next
			Next
	End Method
	
	
	Rem
	bbdoc:Private Method (don't use).
	Creates a branch at every segments startpoint.
	End Rem
	Method createBranches:TList(givenList:TList)
		'Preconditions
		If givenList.IsEmpty() Then Return Null
	
		Local returnList:TList = New TList
		Local i:Int = 0
	
		For Local seg:TSegment = EachIn givenList
			i:+1
			Local branchAngle:Int = seg.angle + Rand(-TLightning.BRANCH_ANGLE_MOD, TLightning.BRANCH_ANGLE_MOD)
			Local branchLength:Int = Float((Rnd(1.0, 3.0) * TDistance.pointToPoint(seg.startpoint.x, seg.startpoint.y, seg.endpoint.x, seg.endpoint.y))) * Float((Float(i) / Float(givenList.Count())))
			Local branchX:Int = seg.endpoint.x + Cos(branchAngle) * branchLength
			Local branchY:Int = seg.endpoint.y + Sin(branchAngle) * branchLength
			Local branchpoint:Tpoint = TPoint.getInstance(branchX, branchY)
			returnList.AddLast(TSegment.getInstance(seg.endpoint, branchpoint))
		Next
		Return returnList
	End Method
	
End Type



Rem
bbdoc:Defines a linesegment between two points in 2D space.
End Rem
Type TSegment
	Field startpoint:TPoint
	Field endpoint:TPoint
	Field angle:Int
	
	
	Rem
	bbdoc:Constructor.
	End Rem
	Function getInstance:TSegment(startpoint:TPoint, endpoint:TPoint)
		Local instance:TSegment = New TSegment
		instance.startpoint = startpoint
		instance.endpoint = endpoint
		instance.angle = ATan2((endpoint.y - startpoint.y), (endpoint.x - startpoint.x))
		Return instance
	End Function
	
	
	Rem
	bbdoc:Returns a point on the mid of the segment.
	End Rem
	Method getMidPoint:TPoint()
		Local midpoint:Tpoint = New TPoint
		midpoint.x = (startpoint.x + endpoint.x)/2
		midpoint.y = (startpoint.y + endpoint.y)/2
		Return midpoint
	End Method
End Type



Rem
bbdoc:2D Point helper class.
End Rem
Type TPoint
	Field x:Int
	Field y:Int
	
	
	Rem
	bbdoc:Constructor.
	End Rem
	Function getInstance:TPoint(x:Int, y:Int)
		Local instance:TPoint = New TPoint
		instance.x = x
		instance.y = y
		Return instance
	End Function
End Type



Rem
bbdoc:Helper tool to calculate the distance between 2 points in a 2D environment.
End Rem
Type TDistance Abstract
	
	Rem
	bbdoc:Berechnet die Distanz zwischen 2 Punkten.
	End Rem
	Function pointToPoint:Double(x1:Double, y1:Double, x2:Double, y2:Double)
		Return Sqr(TDistance.quad(x2 - x1) + TDistance.quad(y2 - y1))
	End Function
	
	
	Rem
	bbdoc:Quadriert einen Integer.
	End Rem
	Function quad:Double(v:Double)
		Return (v * v)
	End Function
	
End Type