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

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

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