1
2 REBOL [
3 Title: "Simple Spirograph"
4 Author: "Gregg Irwin"
5 EMail: greggirwin@acm.org
6
7 Comment: {
8 Set max number of lines
9 Generate random start point and velocity
10 at each iteration
11 for each set
12 calculate next set of end-points from previous end-points
13 append line command to draw effect, wrap if at max-lines
14
15 TBD
16 Allow for multiple line "sets".
17 Figure out why it's so slow for large canvases.
18 Use color-shifting lines, rather than restarting with a new color.
19 }
20 ]
21
22 num-lines: 30 ; change this for longer, or shorter, line sets.
23 end-points: make block! 128
24 pt-1: pt-2: 0x0
25 delta-1: delta-2: 0x0
26 direction-1: direction-2: 'SE
27 color: 0.0.0
28
29 directions: [
30 SE 1x1
31 NW -1x-1
32 NE 1x-1
33 SW -1x1
34 ]
35
36 initialize: func [
37 "Initialize starting coordinates, directions, and colors."
38 face
39 i [integer!]
40 ][
41 random/seed now
42 ; Starting locations for line end points
43 pt-1: random face/size
44 pt-2: random face/size
45 change/only at end-points i [pt-1 pt-2]
46 ; Direction of travel
47 direction-1: pick [SE NW NE SW] random 4
48 direction-2: pick [SE NW NE SW] random 4
49 ; Angle of travel. Bigger numbers move things faster.
50 ;delta-1: 2 + (random 3x3)
51 ;delta-2: 2 + (random 3x3)
52 delta-1: random 3x3
53 delta-2: random 3x3
54 ; Colors. The + 32 keeps it from being too dark.
55 color: (random 200.200.200) + 32
56 ]
57
58 move-points: func [face] [
59 ; direction-1 = Direction of Travel for Point 1
60 ; direction-2 = Direction of Travel for Point 2
61
62 ;TBD Should be able to map these so the code isn't duped for each point.
63 pt-1: pt-1 + (delta-1 * (select directions direction-1))
64 switch direction-1 [
65 NE [if pt-1/x > face/size/x [direction-1: 'NW]
66 if pt-1/y < 1 [direction-1: 'SE]]
67 SE [if pt-1/x > face/size/x [direction-1: 'SW]
68 if pt-1/y > face/size/y [direction-1: 'NE]]
69 SW [if pt-1/x < 1 [direction-1: 'SE]
70 if pt-1/y > face/size/y [direction-1: 'NW]]
71 NW [if pt-1/x < 1 [direction-1: 'NE]
72 if pt-1/y < 1 [direction-1: 'SW]]
73 ]
74
75 pt-2: pt-2 + (delta-2 * (select directions direction-2))
76 switch direction-2 [
77 NE [if pt-2/x > face/size/x [direction-2: 'NW]
78 if pt-2/y < 1 [direction-2: 'SE]]
79 SE [if pt-2/x > face/size/x [direction-2: 'SW]
80 if pt-2/y > face/size/y [direction-2: 'NE]]
81 SW [if pt-2/x < 1 [direction-2: 'SE]
82 if pt-2/y > face/size/y [direction-2: 'NW]]
83 NW [if pt-2/x < 1 [direction-2: 'NE]
84 if pt-2/y < 1 [direction-2: 'SW]]
85 ]
86
87 ]
88
89 do-spiro: func [
90 face
91 max-interval [time!]
92 /local i t interval
93 ][
94 i: j: 0
95 t: now/time/precise
96 interval: 0:0:3 + random max-interval
97 initialize face i
98 forever [
99 if now/time/precise > (t + interval) [
100 clear draw-cmds
101 interval: 0:0:3 + random max-interval
102 t: now/time/precise
103 initialize face i
104 wait .05
105 ]
106
107 append draw-cmds compose [pen (color) line (pt-1) (pt-2)]
108 ; Erase oldest line
109 if (length? draw-cmds) > (num-lines * 5) [
110 remove/part head draw-cmds 5
111 ]
112
113 ;print mold draw-cmds
114 move-points face
115 i: either i < 127 [i + 1][0]
116 j: either j < 127 [j + 1][0]
117
118 show face
119 ; wait 0 isn't as system friendly as wait .001, but it's faster.
120 wait 0 ;.001
121 ]
122 ]
123
124 lay: layout [
125 origin 0x0
126 backdrop black
127 ; Using a larger canvas really slows things down
128 ;canvas: image black 640x480
129 canvas: image black 320x240
130 across
131 button "go" [do-spiro canvas 0:0:10]
132 button "quit" [quit]
133 ]
134 canvas/effect: reduce ['draw draw-cmds: make block! (num-lines * 5)]
135
136 view lay
137 ;view/offset lay 0x0