-
Notifications
You must be signed in to change notification settings - Fork 0
/
ch8.tex
542 lines (444 loc) · 16.4 KB
/
ch8.tex
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
% ch8.tex
% This work is licensed under the Creative Commons Attribution-Noncommercial-Share Alike 3.0 New Zealand License.
% To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/nz
% or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
\chapter{Turtles galore}\index{turtle!advanced}\label{ch:turtlesgalore}
Let's get back to the \code{turtle} module we started looking at in Chapter~\ref{ch:turtles}. Remember that to setup the canvas for the turtle to draw on, we need to import the module and the create the `Pen' object:
\begin{listing}
\begin{verbatim}
>>> import turtle
>>> t = turtle.Pen()
\end{verbatim}
\end{listing}
We can now use basic functions to move the turtle around the canvas and draw simple shapes, but it's more interesting to use some of what we've already covered in the previous chapters. For example, the code we used to create a square earlier was:
\begin{listing}
\begin{verbatim}
>>> t.forward(50)
>>> t.left(90)
>>> t.forward(50)
>>> t.left(90)
>>> t.forward(50)
>>> t.left(90)
\end{verbatim}
\end{listing}
\noindent
We can rewrite this using a for-loop:
\begin{listing}
\begin{verbatim}
>>> t.reset()
>>> for x in range(1,5):
... t.forward(50)
... t.left(90)
...
\end{verbatim}
\end{listing}
This is certainly less typing, but for something a bit more interesting, try the following:
\begin{listing}
\begin{verbatim}
>>> t.reset()
>>> for x in range(1,9):
... t.forward(100)
... t.left(225)
...
\end{verbatim}
\end{listing}
This code produces the 8-point star shown in figure~\ref{fig20} (the turtle turns 225 degrees, each time it goes forward 100 pixels).
\begin{figure}
\begin{center}
\includegraphics[width=72mm]{figure20.eps}
\end{center}
\caption{The turtle drawing an 8-point star.}\label{fig20}
\end{figure}
\noindent
With a different angle (175 degrees), and a longer loop (37 times), we can make a star with even more points (shown in figure~\ref{fig21}):
\begin{listing}
\begin{verbatim}
>>> t.reset()
>>> for x in range(1,38):
... t.forward(100)
... t.left(175)
...
\end{verbatim}
\end{listing}
\begin{figure}
\begin{center}
\includegraphics[width=72mm]{figure21.eps}
\end{center}
\caption{A star with a lot more points.}\label{fig21}
\end{figure}
\noindent
Or how about the following code, which produces the spiral-like star figure~\ref{fig22}.
\begin{listing}
\begin{verbatim}
>>> for x in range(1,20):
... t.forward(100)
... t.left(95)
...
\end{verbatim}
\end{listing}
\begin{figure}
\begin{center}
\includegraphics[width=72mm]{figure22.eps}
\end{center}
\caption{A star with a lot more points.}\label{fig22}
\end{figure}
\noindent
Here's something a bit more complicated:
\begin{listing}
\begin{verbatim}
>>> t.reset()
>>> for x in range(1,19):
... t.forward(100)
... if x % 2 == 0:
... t.left(175)
... else:
... t.left(225)
...
\end{verbatim}
\end{listing}
In the above code, we check to see if the variable \code{x} contains an even number. To do this we use what is called a modulo operator (\%)\index{modulo operator}, in the expression: \code{x \% 2 == 0}.
\par
x \% 2 is equal to zero, if the number in variable \code{x} can be divided by two, with nothing left over (no remainder)---if this doesn't make much sense, don't worry too much about it, just remember you can use `\code{x \% 2 == 0}' to check if a number in a variable is an even number. The result of running this code is the 9-point star in figure~\ref{fig23}.
\begin{figure}
\begin{center}
\includegraphics[width=84mm]{figure23.eps}
\end{center}
\caption{A 9-point star.}\label{fig23}
\end{figure}
You don't have to just draw stars and simple geometric shapes, using a combination of the functions calls, your turtle can draw many different things. For example:
\begin{listing}
\begin{verbatim}
t.color(1,0,0)
t.begin_fill()
t.forward(100)
t.left(90)
t.forward(20)
t.left(90)
t.forward(20)
t.right(90)
t.forward(20)
t.left(90)
t.forward(60)
t.left(90)
t.forward(20)
t.right(90)
t.forward(20)
t.left(90)
t.forward(20)
t.end_fill()
t.color(0,0,0)
t.up()
t.forward(10)
t.down()
t.begin_fill()
t.circle(10)
t.end_fill()
t.setheading(0)
t.up()
t.forward(90)
t.right(90)
t.forward(10)
t.setheading(0)
t.begin_fill()
t.down()
t.circle(10)
t.end_fill()
\end{verbatim}
\end{listing}
\noindent
Which is a long, long, long, drawn-out way to draw the rather ugly and primitive-looking car in figure~\ref{fig24}. But it does demonstrate a couple of other turtle functions: \code{color}, to change the colour of the pen being used by the turtle; \code{fill}, which fills in an area of the canvas; and \code{circle}, to draw a circle of a particular size.
\begin{figure}
\begin{center}
\includegraphics[width=80mm]{figure24.eps}
\end{center}
\caption{The turtle is terrible at drawing cars!}\label{fig24}
\end{figure}
\section{Colouring in}
The \code{color}\index{turtle!color} function takes 3 parameters. The first parameter is a value for red, the second is a value for green, and the last is a value for blue.
\par
\emph{Why red, green and blue?}
\par
If you've ever played around with different colours of paint, you'll already know part of the answer to that question. When you mix two different paint colours, you get another colour\footnote{Actually, the three \textbf{primary} paint colours are red, yellow and blue, and not the red/green/blue (RGB) on a computer.}. When you mix blue and red together, you get purple$\ldots$ and when you mix too many colours together, you usually get a muddy brown. On a computer you can mix colours together in a similar fashion---put red and green together to get yellow---except with a computer, we are combining colours of light, not colours of paint.
Even though we're not using paint, for a moment, think about 3 large pots of paint. One red, one green, and one blue. Each pot is full, so we'll say that a full pot of paint has a value of 1 (or 100\%). We then pour all of the red paint (100\%) into a vat, followed by all of the green paint (again 100\%). After a bit of mixing, we get a yellow colour. Let's draw a yellow circle using turtle:
\begin{listing}
\begin{verbatim}
>>> t.color(1,1,0)
>>> t.begin_fill()
>>> t.circle(50)
>>> t.end_fill()
\end{verbatim}
\end{listing}
So in the above example, we call the color function with 100\% for red, 100\% for green and 0\% for blue (in other words, 1, 1, and 0). To make it easier to experiment with different colours, let's turn that into a function:
\begin{listing}
\begin{verbatim}
>>> def mycircle(red, green, blue):
... t.color(red, green, blue)
... t.begin_fill()
... t.circle(50)
... t.end_fill()
...
\end{verbatim}
\end{listing}
\noindent
We can draw a bright green circle, by using all of the green paint (1 or 100\%):
\begin{listing}
\begin{verbatim}
>>> mycircle(0, 1, 0)
\end{verbatim}
\end{listing}
\noindent
And we can draw a darker green circle, by using only half the green paint (0.5 or 50\%):
\begin{listing}
\begin{verbatim}
>>> mycircle(0, 0.5, 0)
\end{verbatim}
\end{listing}
Here's where thinking about paint doesn't make much sense any more. In the real world, if you've got a pot of green paint, it doesn't matter how much you use, it's still going to look the same. With colours on a computer, because we're playing with light, using less of that colour generally results in a darker shade. It's the same as if you shine a torch at night, you get a yellowish light---when the batteries start to run out and the light begins to fade, the yellow colour gets darker and darker. Just to see for yourself, try drawing a circle with full red and half red (1 and 0.5), and full blue and half blue.
\begin{listing}
\begin{verbatim}
>>> mycircle(1, 0, 0)
>>> mycircle(0.5, 0, 0)
>>> mycircle(0, 0, 1)
>>> mycircle(0, 0, 0.5)
\end{verbatim}
\end{listing}
\noindent
Different combinations of red, green and blue will produce a huge variety of colours. You can get a gold colour by using 100\% of red, 85\% of green and no blue:
\begin{listing}
\begin{verbatim}
>>> mycircle(1, 0.85, 0)
\end{verbatim}
\end{listing}
\noindent
A light pink colour can be achieved by combining 100\% red, 70\% green and 75\% blue:
\begin{listing}
\begin{verbatim}
>>> mycircle(1, 0.70,0.75)
\end{verbatim}
\end{listing}
\noindent
And you get orange by combining 100\% red and 65\% green; and brown by combining 60\% red, 30\% green and 15\% blue:
\begin{listing}
\begin{verbatim}
>>> mycircle(1, 0.65, 0)
>>> mycircle(0.6, 0.3, 0.15)
\end{verbatim}
\end{listing}
\noindent
Don't forget, you can clear the canvas by using \code{t.clear()}.
\section{Darkness}\index{turtle!color!black}
Here's a question for you: What happens when you turn all the lights off at night? Everything goes black.
\par
The same thing happens with colours on a computer. No light equals no colour. So a circle with 0 for red, 0 for green and 0 for blue:
\begin{listing}
\begin{verbatim}
>>> mycircle(0, 0, 0)
\end{verbatim}
\end{listing}
Produces the black spot in figure~\ref{fig25}.
\begin{figure}
\begin{center}
\includegraphics[width=85mm]{figure25.eps}
\end{center}
\caption{A black hole!}\label{fig25}
\end{figure}
The opposite is true; if you use 100\% red, 100\% green and 100\% blue, you get white. Use the following code and the black circle will be wiped out again:
\begin{listing}
\begin{verbatim}
>>> mycircle(1,1,1)
\end{verbatim}
\end{listing}
\section{Filling things}\index{turtle!fill}
You've probably figured out by now that the fill function is switched on by passing the parameter `1', then switched off again with `0'. When you switch it off, the function actually fills in the area you've drawn---assuming you've drawn at least part of a shape. So we can easily draw a filled in square by using code we created earlier. First, let's turn it into a function. To draw a square with turtle we do:
\begin{listing}
\begin{verbatim}
>>> t.forward(50)
>>> t.left(90)
>>> t.forward(50)
>>> t.left(90)
>>> t.forward(50)
>>> t.left(90)
>>> t.forward(50)
>>> t.left(90)
\end{verbatim}
\end{listing}
So as a function, we might want to pass the size of the square as a parameter. This makes the function a little more flexible:
\begin{listing}
\begin{verbatim}
>>> def mysquare(size):
... t.forward(size)
... t.left(90)
... t.forward(size)
... t.left(90)
... t.forward(size)
... t.left(90)
... t.forward(size)
... t.left(90)
\end{verbatim}
\end{listing}
\noindent
We can test our function by calling:
\begin{listing}
\begin{verbatim}
>>> mysquare(50)
\end{verbatim}
\end{listing}
That's a start, but it's not quite perfect. If you look at the code above, you'll see a pattern. We repeat: \code{forward(size)} and \code{left(90)} four times. That's a waste of typing. So we can use a for-loop to do it for us (pretty much the same as we did earlier):
\begin{listing}
\begin{verbatim}
>>> def mysquare(size):
... for x in range(0,4):
... t.forward(size)
... t.left(90)
\end{verbatim}
\end{listing}
That's a big improvement on the previous version. You can test the function with different sizes:
\begin{listing}
\begin{verbatim}
>>> t.reset()
>>> mysquare(25)
>>> mysquare(50)
>>> mysquare(75)
>>> mysquare(100)
>>> mysquare(125)
\end{verbatim}
\end{listing}
And the turtle should draw something like figure~\ref{fig26}.
\begin{figure}
\begin{center}
\includegraphics[width=72mm]{figure26.eps}
\end{center}
\caption{Lots of squares.}\label{fig26}
\end{figure}
\noindent
Now we can try a filled square. First of all, reset the canvas once again:
\begin{listing}
\begin{verbatim}
>>> t.reset()
\end{verbatim}
\end{listing}
\noindent
Then, turn on filling, and call the square function again:
\begin{listing}
\begin{verbatim}
>>> t.begin_fill()
>>> mysquare(50)
\end{verbatim}
\end{listing}
\noindent
You'll still see an empty square until you turn filling off:
\begin{listing}
\begin{verbatim}
>>> t.end_fill()
\end{verbatim}
\end{listing}
\noindent
Which produces something like the square in figure~\ref{fig27}.
\begin{figure}
\begin{center}
\includegraphics[width=72mm]{figure27.eps}
\end{center}
\caption{A black square.}\label{fig27}
\end{figure}
How about changing the function so that we can either draw a filled or an unfilled square? We need another parameter, and slightly more complicated code, to do this:
\begin{listing}
\begin{verbatim}
>>> def mysquare(size, filled):
... if filled == True:
... t.begin_fill()
... for x in range(0,4):
... t.forward(size)
... t.left(90)
... if filled == True:
... t.end_fill()
...
\end{verbatim}
\end{listing}
The first two lines check to see if the value of parameter `filled' is set to True. If it is, then filling is turned on. We then loop four times to draw the four sides of the rectangle, before checking a second time whether the parameter `filled' is True, and if so, turn filling off once again. You can now draw a filled square by calling:
\begin{listing}
\begin{verbatim}
>>> mysquare(50, True)
\end{verbatim}
\end{listing}
\noindent
And an unfilled square by calling:
\begin{listing}
\begin{verbatim}
>>> mysquare(150, False)
\end{verbatim}
\end{listing}
\noindent
Which causes our turtle to draw the image in figure~\ref{fig28}$\ldots$ $\ldots$which, now that I think about it, looks like a weird square eye.
\begin{figure}
\begin{center}
\includegraphics[width=72mm]{figure28.eps}
\end{center}
\caption{A square eye.}\label{fig28}
\end{figure}
You can draw all sorts of shapes and fill them with colour. Let's turn the star, we drew earlier, into a function. The original code looked like this:
\begin{listing}
\begin{verbatim}
>>> for x in range(1,19):
... t.forward(100)
... if x % 2 == 0:
... t.left(175)
... else:
... t.left(225)
...
\end{verbatim}
\end{listing}
We can use the same if-statements from the mysquare function, and use the size parameter in the \code{forward} function.
\begin{listing}
\begin{verbatim}
1. >>> def mystar(size, filled):
2. ... if filled:
3. ... t.begin_fill()
4. ... for x in range(1,19):
5. ... t.forward(size)
6. ... if x % 2 == 0:
7. ... t.left(175)
8. ... else:
9. ... t.left(225)
10. ... if filled:
11. ... t.end_fill()
\end{verbatim}
\end{listing}
In lines 2 and 3, we switch filling on, depending upon the value of the parameter \code{filled} (turn filling on, if the parameter is set to True, turn it off, if the parameter is set to False). We do the reverse in lines 10 and 11 (switch filling back off again). The other difference about this function is that we pass the size of the star in the parameter \code{size}, and use this value in line 5.
\par
Now let's set the colour to gold (you might remember that gold can be made by using 100\% of red, 85\% of green and no blue), and then call the function:
\begin{listing}
\begin{verbatim}
>>> t.color(1, 0.85, 0)
>>> mystar(120, True)
\end{verbatim}
\end{listing}
\noindent
The turtle should draw the gold star in figure~\ref{fig29}. We can add an outline for the star, by changing the colour again (this time to black) and redrawing the star with filling turned off
\begin{figure}
\begin{center}
\includegraphics[width=85mm]{figure29.eps}
\end{center}
\caption{A gold star.}\label{fig29}
\end{figure}
\begin{listing}
\begin{verbatim}
>>> t.color(0,0,0)
>>> mystar(120, False)
\end{verbatim}
\end{listing}
\noindent
Thus the star now looks like figure~\ref{fig30}.
\begin{figure}
\begin{center}
\includegraphics[width=85mm]{figure30.eps}
\end{center}
\caption{A star with an outline.}\label{fig30}
\end{figure}
\section{Things to try}
\emph{In this chapter we learned about the turtle module, using it to draw a few basic geometric shapes. We used functions in order to re-use some of our code, to make it easier to draw shapes with different colours.}
\subsection*{Exercise 1}
We've drawn stars, squares and rectangles. How about an octagon? An octagon is an 8 sided shape.
(Hint: try turning 45 degrees).
\subsection*{Exercise 2}
Now convert the octagon drawing code into a function which will fill it with a colour.
\newpage