November 28, 2020, 10:23:39 AM

### Author Topic: [bb] XKCD Time Castle Generator by Mr Snidesmin [ 1+ years ago ]  (Read 513 times)

#### BlitzBot

• Jr. Member
• Posts: 1
##### [bb] XKCD Time Castle Generator by Mr Snidesmin [ 1+ years ago ]
« on: June 29, 2017, 12:28:41 AM »
Title : XKCD Time Castle Generator
Author : Mr Snidesmin
Posted : 1+ years ago

Description : Much debate was had about this XKCD comic which updated every 30 minutes.  This is just a demo to show how it could possibly have been scripted.

Demo and image files here: <a href="http://kieryn.com/xkcd-time/" target="_blank">http://kieryn.com/xkcd-time/[/url]

Code :
Code: BlitzBasic
2. Global sizeX = ImageWidth(baseImage)
3. Global sizeY = ImageHeight(baseImage)
4. Graphics sizeX, sizeY
6. Global imgClumps = LoadAnimImage("C:clumps.png", 30,30,0,4)
7. Global imgSquareClumps = LoadAnimImage("C:squareclumps.png", 30,30,0,4)
10.
11.
12. Const stateWandering = 0
13. Const statePlanning = 1
14. Const stateBuildingClumps = 2
15. Const stateBuildingSquareClumps = 3
16. Const stateBuildingSmooth = 4
17. Const stateBuildingBattlements = 5
18. Const stateBuildingFinished = 6
19.
20.
21. Type Person
22.         Field dir
23.         Field x, y
24.         Field cx, cy, cw, ch
25.         Field state
26.         Field bTimer
27. End Type
28.
29.
30. Function Render()
31.         SetBuffer BackBuffer()
32.         DrawImage baseImage, 0,0
33.         For p.Person = Each Person
34.                 RenderPerson p
35.         Next
36.         VWait
37.         Flip
38. End Function
39.
40.
41. Function RenderPerson(p.Person)
42.         Color 0,0,0
43.         waveA# = Rnd(0.5, 1.2)
44.         waveB# = Rnd(2, 3.5)
45.         offSetA# = Rnd(360)
46.         offSetB# = Rnd(360)
47.
48.         For a# = 0 To 360.0     Step 0.2
49.                 r = 8 + 0.5 * Sin(waveA*a+offSetA) + 0.3 * Sin(waveB*a+offSetB)
50.
51.                 For r2# = r To r+0.6 Step 0.3
52.                         x = px + r2 * Cos(a)
53.                         y = py + r2 * Sin(a)
54.                         Plot x, y
55.                 Next
56.         Next
57.
58.         x0 = px
59.         y0 = py + 10
60.         x1 = px + Rnd(-5,5)
61.         y1 = py + 30 + Rnd(-2,2)
62.         WLine x0,y0,x1,y1
63.
64.         x2 = x1 + Rnd(5,8)
65.         x3 = x1 - Rnd(5,8)
66.         y2 = y1 + 30 + Rnd(-2,2)
67.
68.         WLine x0,y0,x2,y1
69.         WLine x0,y0,x3,y1
70.
71.         WLine x2,y2,x1,y1
72.
73.         WLine x3,y2,x1,y1
74. End Function
75.
76.
77.
78. Function WLine(x0,y0,x1,y1)
79.         waveA# = Rnd(0.5, 2) * 360
80.         offsetA = Rnd(360)
81.         waveB# = Rnd(0.5, 2) * 360
82.         offsetB = Rnd(360)
83.
84.         For n# = 0 To 1.0 Step 0.01
85.                 wobble1# = Sin(n*180) * (0.5+ Sin(n*waveA+offsetA))
86.                 wobble2# = Sin(n*180) * (0.5+ Sin(n*waveB+offsetB))
87.
88.                 dX# = x1 - x0
89.                 dY# = y1 - y0
90.
91.                 x# = x0 + (n+0.05*wobble1) * dX
92.                 y# = y0 + (n+0.05*wobble2) * dY
93.
94.                 For x2# = x To x+0.6 Step 0.3
95.                 For y2# = y To y+0.6 Step 0.3
96.                         Plot x2, y2
97.                 Next
98.                 Next
99.         Next
100. End Function
101.
102.
103. Function UpdatePeople()
104.         SetBuffer ImageBuffer(baseImage)
105.
106.         For p.Person = Each Person
107.
108.                 If pstate >= stateBuildingClumps Then
109.                         px = pcx + pcw*0.5
110.                         py = pcy - 50
111.                         pTimer = pTimer + pstate -1
112.                         If pTimer > 6 Then
113.                                 pstate = pstate + 1
114.                                 pTimer = 0
115.                         End If
116.                 End If
117.
118.                 If pstate = stateBuildingSquareClumps Or pstate = stateBuildingSmooth Or pstate = stateBuildingBattlements Then
119.                         x = Rnd(pcx, pcx+pcw-30)
120.                         y = pcy-pch
121.                         f = Floor(Rnd(4))
122.                         DrawImage imgSquareClumps, x, y+2, f
123.                         Color 2,2,2
124.                         Rect x, y+30, 30, sizeY
125.                 End If
126.
127.                 If pstate = stateWandering Then
128.
129.                         px = sizeX * Rnd(0.1, 0.7)
130.                         py = sizeY * 0.52 + 0.11 * px
131.
132.                         If Rnd(10) > 8 Then
133.                                 pstate = statePlanning
134.                         End If
135.
136.                 ElseIf pstate = statePlanning Then
137.                         If Rnd(10) > 8 Then
138.                                 pstate = stateWandering
139.                         End If
140.
141.                         For i = 1 To 100
142.                                 If (pstate = statePlanning)
143.                                         FindGoodSandCastlePlace(p)
144.                                 End If
145.                         Next
146.
147.
148.                 ElseIf pstate = stateBuildingClumps Then
149.                         x = Rnd(pcx, pcx+pcw-30)
150.                         y = pcy-pch
151.                         f = Floor(Rnd(4))
152.                         DrawImage imgClumps, x, y, f
153.                         Color 2,2,2
154.                         Rect x, y+30, 30, sizeY
155.
156.                 ElseIf pstate = stateBuildingSmooth Then
157.                         Color 1,1,1
158.                         bwL = Rnd(1, 3)
159.                         bwR = Rnd(1, 3)
160.                         bh = -Rnd(5, 15)
161.                         Rect pcx-bwL, pcy-bh, pcw+bwL+bwR, sizeY
162.
163.                         th = 7
164.                         x0 = Rnd(pcx-2.5, pcx+pcw)
165.                         x1 = x0 + Rnd(10, 20)
166.                         If x1 > pcx+ pcw+2.5 Then x1 = pcx+ pcw+2.5
167.
168.                         Rect x0, pcy-pch, x1-x0, th
169.
170.                 ElseIf pstate = stateBuildingBattlements Then
171.
172.                         Color 255,255,255
173.                         For x = pcx + 4 To pcx+pcw-2 Step 7
174.                                 If Rnd(10) > 7 And measureBlack(x,pcy-pch-1, x+2, pcy-pch-1) = 0 Then
175.                                         Rect x,pcy-pch, 2, 2
176.                                 End If
177.                         Next
178.
179.                 ElseIf pstate = stateBuildingFinished Then
180.
181.                         Color 1,1,1
182.
183.                         bwL = Rnd(1, 3)
184.                         bwR = Rnd(1, 3)
185.
186.                         bh = -Rnd(5, 15)
187.
188.                         Rect pcx-bwL, pcy-bh, pcw+bwL+bwR, sizeY
189.
190.
191.
192.                         Rect pcx, pcy-pch, pcw, sizeY
193.
194.                         th = Rnd(7,10)
195.                         Rect pcx-2.5, pcy-pch, pcw+5, th
196.                         Rect pcx-1.3, pcy-pch, pcw+2.7, th +2
197.
198.
199.                         Color 255,255,255
200.                         For x = pcx + 4 To pcx+pcw-2 Step 7
201.                                 If measureBlack(x,pcy-pch-1, x+2, pcy-pch-1) = 0 Then
202.                                         Rect x,pcy-pch, 2, 2
203.                                 End If
204.                         Next
205.
206.                         SetBuffer BackBuffer()
207.                         pstate = stateWandering
208.                 End If
209.         Next
210.
211. End Function
212.
213.
214. Function FindGoodSandCastlePlace(p.Person)
215.         x = sizeX * 0.4 + 0.3 * sizeX * Rnd(-1,1) * Rnd(1)
216.
217.         y = sizeY * Rnd(0.5, 0.9)
218.
219.         w = Rnd(1,10)
220.         h = 16 - w*2
221.         w = w * 7 + 10
222.         h = h + 18 + Rnd(10)
223.
224.         x2 = x + Rnd(20)
225.
226.         If measureBlack(x, y, x+w, y) < 40 And measureBlack(x, y+5, x+w, y+5) > 90 Then
227.                 pcx = x
228.                 pcy = y+8
229.                 pcw = w
230.                 pch = h
231.                 pstate = stateBuildingClumps
232.         End If
233. End Function
234.
235.
236. Function measureBlack(x0, y0, x1, y1)
237.         SetBuffer ImageBuffer(baseImage)
238.         black = 0
239.         For n# = 0 To 1.0 Step 0.01
240.                 dX# = x1 - x0
241.                 dY# = y1 - y0
242.
243.                 x = x0 + n * dX
244.                 y = y0 + n * dY
245.
246.                 GetColor x, y
247.                 If ColorRed() < 20 Then
248.                         black = black + 1
249.                 End If
250.         Next
251.         Return black
252. End Function
253.
254.
255. SeedRnd MilliSecs()
256.
257. p.Person = New Person
258.
259. Global iframe = 1
260. Global iSequence = 1
261. While Not KeyHit(1)
262.         UpdatePeople()
263.         Render()
264.         If (KeyHit(57)) Or iframe > 100 Then
265.                 FreeImage baseImage
267.                 pstate = stateWandering
268.                 iSequence = iSequence + 1
269.                 CreateDir "C:out" + iSequence
270.                 iframe = 1
271.         End If
272.
273.         SaveBuffer BackBuffer(), "C:out" + iSequence + "" + iframe  + ".bmp"
274.         iframe  = iframe  + 1
275. Wend
276. End

`Graphics 553,395,32,2Global baseImage= LoadImage("C:start.png")Global sizeX = ImageWidth(baseImage)Global sizeY = ImageHeight(baseImage)Global imgClumps = LoadAnimImage("C:clumps.png", 30,30,0,4)Global imgSquareClumps = LoadAnimImage("C:squareclumps.png", 30,30,0,4)`