In the previous chapter we looked at how code art can create emergent patterns through simple (and not so simple) repetitions.
Movement is another feature fundamental to computer graphics. Let’s dive straight into it.
Just like in math, we can replace any number with a longer expression, and wrap it in parenthesis (). The expressions start with a function name, followed by the parameters of that function. Here’s an example:
forward (wave 100..200)
Just like in the last chapter, it’s best to try it out in the editor so you will see the visual as well.
The wave
function becomes a number that oscillates between 100 and 200. We can also change the frequency (cycles per minute):
forward (wave 100..200 frequency=60)
Since many programmers are lazy, there is also a shorthand:
forward (wave 100..200 f=60)
Like said, the functions can be used anywhere:
repeat (wave 10..30)
forward 300
turn-left 129
end-repeat
Or even inside each other:
forward (wave 100..(wave 200..250 f=200))
This becomes more interesting when we combine different functions. Speaking of which...
The wave
function is a soft sine wave, but sometimes we want sharpness.
repeat 20
forward 400
turn-left (linear 162..150 f=9)
forward 300
turn-right 90
end-repeat
The angle in the tips of the star evenly decreases from 162 to 150, then jumps back to 162. And it does that 9 times per minute.
linear
is quite handy for rotations that go on forever:
turn-right (linear 0..360)
forward 1000
Another word for linear
is sawtooth
. They mean the same thing.
Randomness is a way to bring human-like imperfection to the art. It doesn’t move.
repeat 100
forward (random 10..200)
turn-left 90
end-repeat
Let’s draw a series or bars with random lengths:
backward 400
repeat 80
forward 10
turn-left 90
forward (random 100..200)
turn-right 180
forward (random 100..200)
turn-left 90
end-repeat
This looks pretty, but what if we want the bottoms to align? The random value is different every time, so we can’t just come back the same amount.
Luckily, we can wrap part of the code inside a side-track
block, which makes the turtle to return to the same spot after it’s done with the block:
backward 400
repeat 80
forward 10
side-track
turn-left 90
forward (random 100..200)
end-side-track
end-repeat
See, we also got rid of two turn commands!
You can also skew the random distribution to favor one end over the other by using the skew
parameter:
backward 400
repeat 80
forward 10
side-track
turn-left 90
forward (random 0..200 skew=250)
end-side-track
end-repeat
A skew of 0 does nothing. Negative values favor the lower end, and positive values favor the higher end.
To see the effect more clearly, we can animate it:
backward 400
repeat 80
forward 10
side-track
turn-left 90
forward (random 0..200 skew=(wave -250..250 f=10))
end-side-track
end-repeat
Okay, this is the most powerful of them all, once you get the hang of it! Noise is a kind of smooth random that depends on the current location of the turtle. It also changes over time. The noise continues forever and never loops back to the same pattern.
backward 400
repeat 80
forward 10
side-track
turn-left 90
forward (noise 0..200)
end-side-track
end-repeat
You can make it less smooth by changing the size
parameter (default is 300):
backward 400
repeat 80
forward 10
side-track
turn-left 90
forward (noise 0..200 size=100)
end-side-track
end-repeat
The noise function also has a frequency
parameter.
To better see what’s happening, try this code and play with the numbers:
backward 500
turn-left 90
backward 500
pen-up
set-thickness 10
repeat 100
forward 10
side-track
turn-right 90
repeat 100
pen-down
set-lightness (noise -30..30 size=300 f=20)
forward 10
end-repeat
end-side-track
end-repeat
Oh, there’s a new set-thickness
command. You can probably guess what it does.
Here’s a fun trick: if you move the turtle iteratively based on noise, the next value of noise will change as well (since noise depends on turtle’s location), which in turn will influence the next movement, and so on. This creates a feedback loop that creates quite an unpredictable and heterogenous movement:
repeat 100
forward (noise 100..300)
turn-left 90
end-repeat
Computational art allows almost limitless complexity, and it’s up to you to decide how wild you want to go! You don’t need to know what will happen before you try it out – in fact, the last example belongs to the category of chaotic algorithms where it’s mathematically impossible to predict the outcome – without running the code somehow.
Here’s a little extra: you can change the phase of a wave with the phase
(or p
) parameter. This way you can create waves that have the same frequency but are out of sync. Phase is measured in percentage of the wave cycle, so 0 is the beginning, 50 is the middle, and 100 is the end.
backward 400
repeat 80
forward 10
side-track
turn-left 90
forward (wave 0..200 p=(random 0..50))
end-side-track
end-repeat
Or:
repeat 720
turn-left 0.5
side-track
forward (wave 20..400 p=(random 0..100 skew=120))
end-side-track
end-repeat
Phase can also be used with linear
and noise
.
In this chapter we talked about animations and randomness. You can change any number in the code with one or more of these functions:
wave
– oscillates between two valueslinear
– gradually increases from one value to another, then jumps back to the first valuerandom
– picks a random value between two valuesnoise
– picks a semi-random value between two values, but the value depends on the current location of the turtle. The noise value also changes smoothly over time.We also learned about the side-track
block and various parameters, like frequency
, phase
and size
.
In the next chapter we’ll look at how to make tree fractals by cloning the turtle. (coming soon)