1. Define a function sprout
that moves the
turtle forward
and back by a small amount. In CoffeeScript, the ->
notation defines a function, and lining up the indent is important.
sprout = (size) -> # define sprout: a function with one parameter fd size # move forward by that amount bk size # backward by the same amount, end the function pen green # use green sprout 30 # run sprout with size 30
2. The function sprout
can be used anywhere,
including inside other functions. Try this:
sprout = (size) -> fd size bk size tree = (size) -> # tree is another function with one parameter fd size # go forward by the size lt 30 # left turn by 30 degrees sprout size * 0.7 # draw a sprout with 70% of the size rt 60 # right turn by 60 degrees sprout size * 0.7 # draw another sprout at 70% lt 30 # left turn by 30 degrees bk size # backward by size, and end the function pen green tree 30 # call tree instead of sprout
Notice how the parameter size
has a different meaning
inside each function call. Inside the call to tree
,
size
is 30, but inside sprout
,
size
is 30 * 0.7 = 21.
3. Use an if
so that a small tree is just a
sprout, and draw a couple trees.
Each time tree
is called,
size
has another value: first 9 (which triggers the
if size < 10
, and then 30 (which does not).
sprout = (size) -> fd size bk size tree = (size) -> if size < 10 # do the following only if size is less than 10 sprout size # draw a sprout return # finish and return out of the function fd size lt 30 sprout size * 0.7 rt 60 sprout size * 0.7 lt 30 bk size pen green tree 9 # draw a little tree jump 50, 0 # jump 50 to the right tree 30 # draw a bigger tree
4. How can we add branches to our branches? Make a tree out of smaller trees instead of sprouts:
sprout = (size) -> fd size bk size tree = (size) -> if size < 10 # this "if" defines the important "base case" sprout size # drawing a sprout instead of a tree when size < 10 return # it prevents tree from calling itself forever fd size lt 30 tree size * 0.7 # a function can call itself! rt 60 tree size * 0.7 # experient by removing one of these. lt 30 bk size pen green tree 9 jump 50, 0 tree 30
When a function calls itself, it is
called recursion. Again, the parameter size
has a different meaning each time tree
is called.
tree
is called for the tiny tree,
size
is 9, and it draws a sprout.
tree
is called for the bigger tree,
size
is 30, and it draws a trunk and calls itself.
tree
calls itself again for the big branches,
size
is 30 * 0.7 = 21.
tree
is called yet again for the smaller branches,
size
is 21 * 0.7 = 14.7
size
is 9.87, which is the
base case because size < 10, and it draws a sprout.
Notice that the 14.7 size tree draws two sprouts, and the 21 size tree draws two 14.7 size trees (making four sprouts on its branches). How many sprouts are there in total on a 30 size tree? The base case with size < 10 is important: without it, this program would never stop.
5. Add some randomness to make the tree seem more natural.
The function random()
returns a different
random decimal number betwen 0 and 1 each time it is called.
sprout = (size) -> fd size bk size tree = (size) -> if size < 10 sprout size return fd size lt 30 tree size * (0.6 + 0.2 * random()) # random between 0.6 and 0.8 rt 60 tree size * (0.6 + 0.2 * random()) # different each time lt 30 bk size pen green tree 50