Ooops
January 16, 2021, 06:21:05 AM

Author Topic: [bmx] 2d lightning by AdamStrange [ 1+ years ago ]  (Read 410 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bmx] 2d lightning by AdamStrange [ 1+ years ago ]
« on: June 29, 2017, 12:28:39 AM »
Title : 2d lightning
Author : AdamStrange
Posted : 1+ years ago

Description : taken from the german blitz site and modified to support color

Code :
Code: BlitzMax
  1. SuperStrict
  2.  
  3.  
  4.  
  5. Type TLightning
  6.         Const MIN_SEG_LENGTH:Int = 20                   'Minimum segment length
  7.         Const MIN_SEG_BRANCH_LENGTH:Int = 5             'Minimum segment length on branches
  8.         Const BRANCH_ANGLE_MOD:Int = 40                 'Max angle difference between mainlightning and branches
  9.        
  10.         Field glowred:Int = 100
  11.         Field glowgreen:Int = 100
  12.         Field glowblue:Int = 255
  13.        
  14.         Field segments:TList = CreateList()             'List of segments of the mainlightning
  15.         Field branches:TList = CreateList()             'List of branches
  16.         Field branches2:TList = CreateList()    'Branches of the segmentized branches
  17.         Field generations:Int = 4                               'Iterations of seperation of the mainlightning
  18.         Field offset:Int = 10                                   'Segments offset
  19.        
  20.        
  21.         Rem
  22.         bbdoc:Creates a new lightning from x1, y1 to x2, y2.
  23.         Public Function
  24.         End Rem
  25.         Function getInstance:TLightning(x1:Int, y1:Int, x2:Int, y2:Int)
  26.                 Local instance:TLightning = New TLightning
  27.                 instance.setStartEndPoint(x1, y1, x2, y2)
  28.                
  29.                 Return instance
  30.         End Function
  31.        
  32.        
  33.         Rem
  34.         bbdoc:Changes the color of the lightning
  35.         Public Function
  36.         End Rem
  37.         Method SetGlowColor(r:Int, g:Int, b:Int)
  38.                 glowred = r
  39.                 glowgreen = g
  40.                 glowblue = b
  41.         End Method
  42.  
  43.  
  44.         Rem
  45.         bbdoc:Sets new start- and endpoint coordinates.
  46.         Public Method
  47.         End Rem
  48.         Method setStartEndPoint(x1:Int, y1:Int, x2:Int, y2:Int)
  49.                 'Create segment from x1,y1 to x2,y2
  50.                 Local startpoint:TPoint = TPoint.getInstance(x1, y1)
  51.                 Local endpoint:TPoint = TPoint.getInstance(x2, y2)
  52.                 Local firstSeg:TSegment = TSegment.getInstance(startpoint, endpoint)
  53.                
  54.                 'Remove old lightning
  55.                 Self.segments.Clear()
  56.                 Self.branches.Clear()
  57.                 Self.branches2.Clear()
  58.                
  59.                 'Create the lightning out of the first segment
  60.                 Self.segments.AddFirst(firstSeg)
  61.                 Self.segmentize(Self.segments, Self.generations, Self.offset)
  62.                 Self.branches = Self.createBranches(Self.segments)
  63.                 Self.segmentize(Self.branches, Self.generations - 1, Self.offset - 7, True)
  64.                 Self.branches2 = Self.createBranches(Self.branches)
  65.                 Self.segmentize(Self.branches2, Self.generations - 3, Self.offset - 7, True)
  66.         End Method
  67.        
  68.        
  69.         Rem
  70.         bbdoc:Draws the lightning (Scale must be set to 1.0/1.0)
  71.         Public Method
  72.         End Rem
  73.         Method draw()
  74.                 SetBlend(ALPHABLEND)
  75.        
  76.                 'Branch2 Glow
  77.                 Self.setDrawings(0.4, 3, True)
  78.                 Self.drawSegments(Self.branches2)
  79.                 'Branches2
  80.                 Self.setDrawings(0.5, 1)
  81.                 Self.drawSegments(Self.branches2)
  82.                
  83.                 'Branch Glow
  84.                 Self.setDrawings(0.5, 5, True)
  85.                 Self.drawSegments(Self.branches)
  86.                 'Branches
  87.                 Self.setDrawings(0.6, 1)
  88.                 Self.drawSegments(Self.branches)
  89.                
  90.                 'Glow Paths
  91.                 Self.setDrawings(0.09, 20, True)
  92.                 Self.drawSegments(Self.segments)
  93.                 Self.setDrawings(0.25, 11, True)
  94.                 Self.drawSegments(Self.segments)
  95.                 Self.setDrawings(0.55, 6, True)
  96.                 Self.drawSegments(Self.segments)
  97.                 'Original Paths
  98.                 SetColor(255, 255, 255)
  99.                 SetAlpha(0.45)
  100.                 Local counter:Int = 0
  101.                 For Local seg:TSegment = EachIn Self.segments
  102.                         counter:+1
  103.                         Local thickness:Float = 0.3 * Float(Self.segments.Count() - counter)
  104.                         If thickness < 2.0 Then thickness = 2.0
  105.                         SetLineWidth(thickness)
  106.                         DrawLine(seg.startpoint.x, seg.startpoint.y, seg.endpoint.x, seg.endpoint.y)
  107.                 Next
  108.         End Method
  109.        
  110.        
  111.         Rem
  112.         bbdoc:Private Method (don__COMMENT18__
  113.         Draws a list of segments.
  114.         End Rem
  115.         Method drawSegments(givenList:TList)
  116.                 Local realLineWidth:Float = GetLineWidth()
  117.                 For Local seg:TSegment = EachIn givenList
  118.                         Local lineWidth:Float = realLineWidth/2
  119.                        
  120.                         Local ps1point:TPoint
  121.                         Local ps2point:TPoint
  122.                         Local pe1point:TPoint
  123.                         Local pe2point:TPoint
  124.                         Local lastSeg:TSegment = seg.lastSegment
  125.                         Local nextSeg:TSegment = seg.nextSegment
  126.                        
  127.                         Local tvec:TPoint = seg.endpoint.sub(seg.startpoint)
  128.                         Local tvecn:TPoint = tvec.normalize()
  129.                         Local tnorm:TPoint = tvec.normalize().normal()
  130.                        
  131.                         If (lastSeg=Null) Then
  132.                                 ps1point = seg.startpoint.add(tnorm.mult(lineWidth))
  133.                                 ps2point = seg.startpoint.add(tnorm.mult(-lineWidth))
  134.                         Else
  135.                                 Local lvec:TPoint = lastSeg.endpoint.sub(lastSeg.startpoint)
  136.                                 Local lnorm:TPoint = lvec.normalize().normal()
  137.                                
  138.                                 ps1point = seg.startpoint.add(lnorm.mult(lineWidth))
  139.                                 ps2point = seg.startpoint.add(lnorm.mult(-lineWidth))
  140.                         EndIf
  141.                        
  142.                         If (nextSeg=Null) Then
  143.                                 lineWidth = lineWidth/2
  144.                         EndIf
  145.                        
  146.                         pe1point = seg.endpoint.add(tnorm.mult(-lineWidth))
  147.                         pe2point = seg.endpoint.add(tnorm.mult(lineWidth))
  148.                        
  149.                        
  150.                         Local corners:Float[] = [ps1point.x,ps1point.y,ps2point.x,ps2point.y,pe1point.x,pe1point.y,pe2point.x,pe2point.y]
  151.                        
  152.                         DrawPoly(corners)
  153.                 Next
  154.         End Method
  155.        
  156.        
  157.         Rem
  158.         bbdoc:Private Method (don__COMMENT19__
  159.         Sets the color to "Glow-Color"
  160.         End Rem
  161.         Method setDrawings(alpha:Float, lineThickness:Float, isGlowing:Byte = False)
  162.                 SetColor(255, 255, 255)
  163.                 If isGlowing Then SetColor(glowred, glowgreen, glowblue)
  164.                 SetAlpha(alpha)
  165.                 SetLineWidth(lineThickness)
  166.         End Method
  167.        
  168.        
  169.         Rem
  170.         bbdoc:Private Method (don__COMMENT20__
  171.         Splits a line (segment) into two lines, which are moved by maxOffset at one point (start or endpoint of the line).
  172.         End Rem
  173.         Method segmentize(givenList:TList, generations:Int, offset:Int, isBranch:Byte = False)
  174.                 'Preconditions
  175.                 If givenList.IsEmpty() Then Return
  176.                 Local minLength:Int = TLightning.MIN_SEG_LENGTH
  177.                 If isBranch Then minLength = TLightning.MIN_SEG_BRANCH_LENGTH
  178.                
  179.                 'Start segmentation
  180.                 For Local i:Int = 1 To generations
  181.                         Local workList:TList = givenList.Copy()
  182.                         For Local seg:TSegment = EachIn workList
  183.                        
  184.                                         'Check if the segments length allows a split into 2 segments
  185.                                         If TDistance.pointToPoint(seg.startpoint.x, seg.startpoint.y, seg.endpoint.x, seg.endpoint.y) >= minLength Then
  186.                                                 'The original segment is obsolete, as we replace it with 2 new ones
  187.                                         Local lastSegment:TSegment = seg.lastSegment
  188.                                         Local nextSegment:TSegment = seg.nextSegment
  189.                                         givenList.Remove(seg)
  190.                        
  191.                                         Local midpoint:TPoint = seg.getMidPoint()
  192.                                                 Local randomAngle:Int = 90
  193.                                                 If Rand(1, 2) = 1 Then randomAngle = -90
  194.                                                 'Move the midpoint
  195.                                                 midpoint.x:+(Cos(seg.angle + randomAngle) * offset)
  196.                                                 midpoint.y:+(Sin(seg.angle + randomAngle) * offset)
  197.                        
  198.                                                 'Add the new segments
  199.                                                 Local seg1:TSegment = TSegment.getInstance(seg.startpoint, midpoint)
  200.                                                 Local seg2:TSegment = TSegment.getInstance(midpoint, seg.endpoint)
  201.                                                 seg1.lastSegment = lastSegment
  202.                                                 seg1.nextSegment = seg2
  203.                                                 seg2.lastSegment = seg1
  204.                                                 seg2.nextSegment = nextSegment
  205.                                                
  206.                                                 If (lastSegment<>Null) Then lastSegment.nextSegment = seg1
  207.                                                 If (nextSegment<>Null) Then nextSegment.lastSegment = seg2
  208.                                                
  209.                                                 givenList.AddLast(seg1)
  210.                                                 givenList.AddLast(seg2)
  211.                                         End If
  212.                                 Next
  213.                         Next
  214.         End Method
  215.        
  216.        
  217.         Rem
  218.         bbdoc:Private Method (don__COMMENT27__
  219.         Creates a branch at every segments startpoint.
  220.         End Rem
  221.         Method createBranches:TList(givenList:TList)
  222.                 'Preconditions
  223.                 If givenList.IsEmpty() Then Return Null
  224.        
  225.                 Local returnList:TList = New TList
  226.                 Local i:Int = 0
  227.        
  228.                 For Local seg:TSegment = EachIn givenList
  229.                         i:+1
  230.                         Local branchAngle:Int = seg.angle + Rand(-TLightning.BRANCH_ANGLE_MOD, TLightning.BRANCH_ANGLE_MOD)
  231.                         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())))
  232.                         Local branchX:Int = seg.endpoint.x + Cos(branchAngle) * branchLength
  233.                         Local branchY:Int = seg.endpoint.y + Sin(branchAngle) * branchLength
  234.                         Local branchpoint:Tpoint = TPoint.getInstance(branchX, branchY)
  235.                        
  236.                         Local branch:TSegment = TSegment.getInstance(seg.endpoint, branchpoint)
  237.                        
  238.                         returnList.AddLast(branch)
  239.                 Next
  240.                 Return returnList
  241.         End Method
  242.        
  243. End Type
  244.  
  245.  
  246.  
  247. Rem
  248. bbdoc:Defines a linesegment between two points in 2D space.
  249. End Rem
  250. Type TSegment
  251.         Field startpoint:TPoint
  252.         Field endpoint:TPoint
  253.         Field angle:Int
  254.         Field lastSegment:TSegment
  255.         Field nextSegment:TSegment
  256.        
  257.        
  258.         Rem
  259.         bbdoc:Constructor.
  260.         End Rem
  261.         Function getInstance:TSegment(startpoint:TPoint, endpoint:TPoint)
  262.                 Local instance:TSegment = New TSegment
  263.                 instance.startpoint = startpoint
  264.                 instance.endpoint = endpoint
  265.                 instance.angle = ATan2((endpoint.y - startpoint.y), (endpoint.x - startpoint.x))
  266.                 Return instance
  267.         End Function
  268.        
  269.        
  270.         Rem
  271.         bbdoc:Returns a point on the mid of the segment.
  272.         End Rem
  273.         Method getMidPoint:TPoint()
  274.                 Local midpoint:Tpoint = New TPoint
  275.                 midpoint.x = (startpoint.x + endpoint.x)/2
  276.                 midpoint.y = (startpoint.y + endpoint.y)/2
  277.                 Return midpoint
  278.         End Method
  279. End Type
  280.  
  281.  
  282.  
  283. Rem
  284. bbdoc:2D Point helper class.
  285. End Rem
  286. Type TPoint
  287.         Field x:Float
  288.         Field y:Float
  289.        
  290.        
  291.         Rem
  292.         bbdoc:Constructor.
  293.         End Rem
  294.         Function getInstance:TPoint(x:Float, y:Float)
  295.                 Local instance:TPoint = New TPoint
  296.                 instance.x = x
  297.                 instance.y = y
  298.                 Return instance
  299.         End Function
  300.        
  301.         Rem
  302.         bbdoc:Addiert zwei TPoints zusammen (Vektorrechnung)
  303.         End Rem
  304.         Method add:TPoint(other:TPoint)
  305.                 Return getInstance(x+other.x,y+other.y)
  306.         End Method
  307.        
  308.         Rem
  309.         bbdoc:Subtrahiert zwei TPoints (Vektorrechnung)
  310.         End Rem
  311.         Method sub:TPoint(other:TPoint)
  312.                 Return getInstance(x-other.x,y-other.y)
  313.         End Method
  314.        
  315.         Rem
  316.         bbdoc:Multipliziert einen TPoint mit einem Skalar (Vektorrechnung)
  317.         End Rem
  318.         Method mult:TPoint(f:Float)
  319.                 Return getInstance(x*f,y*f)
  320.         End Method
  321.        
  322.         Rem
  323.         bbdoc:Liefert die Laenge des Vektors (Vektorrechnung)
  324.         End Rem
  325.         Method length:Float()
  326.                 Return Sqr(x*x+y*y)
  327.         End Method
  328.        
  329.         Rem
  330.         bbdoc:Normalisiert den Vektor (Vektorrechnung)
  331.         End Rem
  332.         Method normalize:TPoint()
  333.                 Return mult(1.0/length())
  334.         End Method
  335.        
  336.         Rem
  337.         bbdoc:Erstellt einen Normalvektor (Vektorrechnung)
  338.         End Rem
  339.         Method normal:TPoint()
  340.                 Return getInstance(y,-x)
  341.         End Method
  342.        
  343.         Rem
  344.         bbdoc:Liefert das Skalarprodukt zweier Vektoren (Vektorrechnung)
  345.         End Rem
  346.         Method dot:Float(other:TPoint)
  347.                 Return (x*other.x+y*other.y)
  348.         End Method
  349. End Type
  350.  
  351.  
  352.  
  353. Rem
  354. bbdoc:Helper tool to calculate the distance between 2 points in a 2D environment.
  355. End Rem
  356. Type TDistance Abstract
  357.        
  358.         Rem
  359.         bbdoc:Berechnet die Distanz zwischen 2 Punkten.
  360.         End Rem
  361.         Function pointToPoint:Double(x1:Double, y1:Double, x2:Double, y2:Double)
  362.                 Return Sqr(TDistance.quad(x2 - x1) + TDistance.quad(y2 - y1))
  363.         End Function
  364.        
  365.        
  366.         Rem
  367.         bbdoc:Quadriert einen Integer.
  368.         End Rem
  369.         Function quad:Double(v:Double)
  370.                 Return (v * v)
  371.         End Function
  372.        
  373. End Type
  374.  
  375.  
  376.  
  377. 'Test
  378. 'Include "Lightning.bmx"
  379.  
  380. Graphics 1024, 768
  381. Global blitz:TLightning = TLightning.getInstance(100, 100, 500, 500)
  382. blitz.setGlowColor(255,0,0)
  383. Global oldMausX:Int
  384. Global oldMausY:Int
  385. SetClsColor(10, 10, 10)
  386.  
  387. Repeat
  388.         Cls
  389.        
  390.         If MouseX() <> oldMausX Or MouseY() <> oldMausY Then
  391.                 oldMausX = MouseX()
  392.                 oldMausY = MouseY()
  393.                 blitz.setStartEndPoint(100, 100, MouseX(), MouseY())
  394.         End If
  395.        
  396.         blitz.draw()
  397.        
  398.         Flip
  399. Until AppTerminate()


Comments :


jankupila(Posted 1+ years ago)

 Cool!


 

SimplePortal 2.3.6 © 2008-2014, SimplePortal