/
Update.elm
163 lines (131 loc) · 4.48 KB
/
Update.elm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
module Sutcliffe.Update exposing (Modifier(..), modify, tick)
import Color exposing (hsl)
import Direction2d as Direction
import LineSegment2d as LineSegment
import List.Extra as List
import Perlin exposing (noise)
import Point2d as Point
import Random
import Sutcliffe.Model as Model exposing (Line, Model, Phase(..), StrutGroup)
import Time exposing (Posix)
type Modifier
= StrutMod
| OffsetMod
| ZoomSpeed
tick : Posix -> Model -> Model
tick time model =
let
newModel =
{ model
| scale = model.scale / (model.zoomSpeed / 1000 + 1)
, rotation = model.rotation + 0.11
}
growing =
model.growing
growingStruts =
List.map .strut growing.groups
growingSides =
List.map .sides growing.groups
in
case model.phase of
Struts ->
if List.all (\line -> line.growth >= 1) growingStruts then
{ newModel
| phase = Sides
, strutLength = model.strutLength * 3 * model.strutMod
}
else
{ newModel
| growing = { growing | groups = List.map growStruts growing.groups }
}
Sides ->
if List.all (\( sideA, sideB ) -> sideA.growth >= 1 && sideB.growth >= 1) growingSides then
let
seed0 =
Random.initialSeed (Time.posixToMillis time)
colorGen =
Random.map3 hsl
(Random.float 0 1)
(Random.float 0.5 1)
(Random.float 0.4 0.6)
( newColor, seed1 ) =
Random.step colorGen seed0
in
{ newModel
| finished =
[ growing ]
++ model.finished
, growing =
{ groups = newGroups seed1 model.strutLength model.offsetMod growing.groups
, color = newColor
, pentNum = model.pentCount + 1
}
, phase = Struts
, pentCount = model.pentCount + 1
}
else
{ newModel
| growing = { growing | groups = List.map growSides growing.groups }
}
modify : Model -> Modifier -> Float -> Model
modify model mod val =
case mod of
StrutMod ->
{ model | strutMod = val }
OffsetMod ->
{ model | offsetMod = val }
ZoomSpeed ->
{ model | zoomSpeed = val }
growStruts : StrutGroup -> StrutGroup
growStruts group =
{ group | strut = grow group.strut }
growSides : StrutGroup -> StrutGroup
growSides group =
let
( sideA, sideB ) =
group.sides
( embA, embB ) =
group.embellishments
in
{ group
| sides = ( grow sideA, grow sideB )
, embellishments = ( grow embA, grow embB )
}
grow : { a | growth : Float } -> { a | growth : Float }
grow growable =
if growable.growth < 1 then
{ growable | growth = growable.growth + 0.0075 }
else
growable
newGroups : Random.Seed -> Float -> Float -> List StrutGroup -> List StrutGroup
newGroups seed length offsetMod groups =
let
( probs, _ ) =
Random.step (Random.list 5 <| Random.float 0 1) seed
in
Model.spawnGroups <|
List.map
(\( prob, group ) ->
let
offset =
(prob - 0.5) / 3 * length * 2 * offsetMod
side =
Model.lineSegment (Tuple.first group.sides)
startPoint =
LineSegment.endPoint side
direction =
LineSegment.direction side
|> Maybe.withDefault Direction.x
perpDirection =
Direction.perpendicularTo direction
endPoint =
startPoint
|> Point.translateIn perpDirection length
|> Point.translateIn direction offset
in
{ origin = startPoint
, endpoint = endPoint
, growth = 0
}
)
(List.zip probs groups)