WEBVTT

0
00:00.630 --> 00:05.630
In the last lesson, we managed to create our snake's body by creating three

1
00:05.640 --> 00:10.260
squares that were each turtle objects. Now in this lesson,

2
00:10.290 --> 00:14.280
we're going to move on to the next step where we actually move our snake

3
00:14.520 --> 00:18.570
automatically across the screen without having to do anything.

4
00:19.050 --> 00:24.050
So this way the snake is continuously moving forwards and all we have to do as

5
00:24.120 --> 00:27.570
the user is just to change its direction. Now,

6
00:27.600 --> 00:30.990
how would we go about moving the snake? Well,

7
00:31.020 --> 00:36.000
we've already got these different segments that are created, but at the moment,

8
00:36.030 --> 00:39.360
there's no way of organizing all the segments.

9
00:39.720 --> 00:42.480
They're kind of just created and placed on screen.

10
00:43.140 --> 00:47.310
So let's put them into a list called segments,

11
00:47.820 --> 00:52.020
and let's start out that list as an empty list. And then later on,

12
00:52.020 --> 00:54.180
once we've created each new segment,

13
00:54.420 --> 00:57.300
we go ahead and append it to this list.

14
00:58.770 --> 01:02.250
If we want something to continuously happen in our program,

15
01:02.700 --> 01:05.910
the way that we've usually done that is through a while loop.

16
01:06.510 --> 01:11.510
So let's create a new variable called game_is_on and let's set it to true.

17
01:14.520 --> 01:16.680
And while game is on,

18
01:17.100 --> 01:20.280
then we're going to move each of the segments.

19
01:20.670 --> 01:25.440
The simplest way that I could think of to move this segment is to loop through

20
01:25.560 --> 01:29.190
each of the segments in our list of segments,

21
01:29.730 --> 01:34.730
and then to get each of these to go ahead and move forward.

22
01:35.640 --> 01:38.160
So let's say we move forwards by 20 pixels.

23
01:38.580 --> 01:41.340
Let's go ahead and run this program and see what we get.

24
01:42.450 --> 01:46.290
The first thing we notice is that the behavior is very weird.

25
01:46.710 --> 01:49.080
We've got a line that's being drawn

26
01:49.470 --> 01:52.260
and that comes from each of the segments

27
01:52.620 --> 01:55.320
which are individual turtles.

28
01:55.410 --> 01:57.810
And they're all drawing this line as they're moving.

29
01:58.590 --> 02:00.690
The first thing we want to fix is that line.

30
02:00.960 --> 02:03.630
So when we create each new segment,

31
02:03.750 --> 02:07.020
before we tell it to go to its position,

32
02:07.410 --> 02:11.760
let's go ahead and tell it to pull the pen up. This way

33
02:11.760 --> 02:13.260
it won't actually draw

34
02:13.470 --> 02:16.950
and all that we'll see is the actual turtle pieces.

35
02:19.110 --> 02:24.110
So now we see our three turtle pieces scurrying along like some sort of weird

36
02:24.960 --> 02:28.500
Caterpillar, but definitely not in a snake like way.

37
02:29.420 --> 02:30.620
<v 1>How can we fix this?</v>

38
02:31.490 --> 02:36.490
<v 0>One of the things that you notice about turtle is it will first create the</v>

39
02:37.400 --> 02:39.500
turtle when it runs this line,

40
02:39.800 --> 02:44.780
the turtle will get created at the center positions, so coordinate (0, 0).

41
02:45.530 --> 02:49.730
And then it will be moved to whatever position we tell it to go to.

42
02:49.940 --> 02:54.890
For example, for the third segment, it starts out life at (0, 0)

43
02:55.070 --> 03:00.040
and then as soon as it gets told to go to this position, it goes to (-40, 0).

44
03:00.580 --> 03:03.310
Now we can see that happening on screen.

45
03:03.940 --> 03:05.920
When we created our snake body,

46
03:06.190 --> 03:10.960
you could see each individual piece being created and then moved to their

47
03:10.960 --> 03:14.560
location. Now, if we wanted to turn off that animation,

48
03:14.800 --> 03:18.670
then we would have to use one of the screen class'

49
03:18.670 --> 03:23.670
methods called tracer. And tracer takes a number as a input,

50
03:26.050 --> 03:28.870
and it turns the animation on or off.

51
03:29.140 --> 03:31.570
And when the tracer is turned off,

52
03:32.020 --> 03:37.020
then we can use the update method to tell our program when to refresh and redraw

53
03:38.380 --> 03:43.150
the screen. When we think back to the old TV monitors,

54
03:43.180 --> 03:46.360
the cathode ray tube monitors or CRT monitors,

55
03:46.720 --> 03:51.720
the way that they worked is by painting on a strip of color line by line

56
03:53.920 --> 03:57.550
by line, slowly covering the entire screen.

57
03:58.060 --> 04:02.020
And then once it's done one screen, it's going to go back to the top

58
04:02.110 --> 04:07.090
and then it's going to paint the pixels for the next scene. And effectively,

59
04:07.090 --> 04:10.240
it's kind of like how a GIF animation works.

60
04:10.420 --> 04:14.380
A gif animation is composed of many images. So for example,

61
04:14.380 --> 04:15.730
if we wanted to animate,

62
04:15.730 --> 04:20.730
we would increase this line and then we would start drawing out a leaf until

63
04:21.340 --> 04:25.900
eventually we end up with an animation like this. Now,

64
04:26.020 --> 04:29.170
when that's all combined and played back very quickly,

65
04:29.200 --> 04:33.460
then this is the animation you see. In our game

66
04:33.490 --> 04:38.490
what we could do is we could describe each of these scenes and tell our program

67
04:40.900 --> 04:43.270
when it should redraw each picture.

68
04:44.140 --> 04:49.140
So that way we could start out with one picture and then hit update and then do

69
04:50.260 --> 04:51.610
something else on screen,

70
04:51.640 --> 04:56.260
maybe move each of our segments and then tell the screen to update again

71
04:56.260 --> 04:58.180
to show the user the new result.

72
04:58.660 --> 05:01.900
And then each time we make the changes we want to happen

73
05:02.230 --> 05:05.500
and then call that update method to tell the screen

74
05:05.590 --> 05:10.590
to show a new image each time. Let's first turn off the tracer.

75
05:11.770 --> 05:14.770
So the tracer is a method in the screen class

76
05:15.220 --> 05:18.670
and in order to turn it off, we're going to set it to zero.

77
05:19.210 --> 05:23.470
So now once the tracer is off, if we actually try to run our program,

78
05:23.710 --> 05:26.890
you can see it's just a black screen and nothing will happen.

79
05:27.400 --> 05:32.260
Even though we've got our while loop and we've got our for loop and lots of

80
05:32.260 --> 05:35.980
things are meant to be happening, but until we call update,

81
05:36.160 --> 05:39.700
the screen is not going to refresh and it's not going to show us what's been

82
05:39.700 --> 05:41.110
happening in our code.

83
05:41.680 --> 05:46.680
So let's say that we decide to call update after all of the segments have been

84
05:48.820 --> 05:53.200
created, so right about here. Let's call screen.

85
05:53.350 --> 05:56.620
update. And now if I hit run,

86
05:56.890 --> 06:01.280
you'll notice that pretty much immediately. As soon as you run the program,

87
06:01.610 --> 06:04.970
our snake body will show up, not piece by piece,

88
06:05.060 --> 06:08.930
but in its entirety. Now, if on the other hand

89
06:09.020 --> 06:14.020
I move our screen.update line of code into the while loop so that once each

90
06:16.940 --> 06:20.600
segment moves, I get the screen to update,

91
06:20.930 --> 06:22.850
then this is what you're going to see.

92
06:23.210 --> 06:26.840
You see each of the pieces moving along one by one.

93
06:27.290 --> 06:29.810
Now it's not really clear what's happening.

94
06:29.840 --> 06:31.730
So I'm going to slow it down a little bit.

95
06:32.210 --> 06:35.240
And I'm going to do this by importing the time module.

96
06:35.690 --> 06:40.690
Now I'm going to add the time.sleep and I'm going to get it to sleep by one

97
06:41.900 --> 06:42.733
second.

98
06:42.830 --> 06:47.830
So this basically just add a one-second delay after each segment moves.

99
06:49.280 --> 06:52.040
So each segment moves, the screen updates,

100
06:52.190 --> 06:55.670
and then we sleep for a second before the next time this happens.

101
06:56.240 --> 06:58.190
Notice how in this case,

102
06:58.280 --> 07:01.280
our snake is moving piece by piece.

103
07:01.520 --> 07:04.730
So first this first piece, and then the second piece,

104
07:04.760 --> 07:08.810
the third piece with a one-second delay between each movement.

105
07:09.440 --> 07:09.800
Now,

106
07:09.800 --> 07:14.800
what happens if we move this screen.update to outside this for-loop?

107
07:16.490 --> 07:18.920
So basically we only update the screen

108
07:19.190 --> 07:21.770
once all of the segments have moved forwards.

109
07:21.950 --> 07:26.950
Now notice how our snake is moving forwards as an entire piece.

110
07:27.590 --> 07:32.180
It's going to move all three segments forward before the update gets triggered

111
07:32.450 --> 07:34.160
and we refresh the graphics.

112
07:34.370 --> 07:38.870
So it looks like as if the whole snake is moving as one piece. Now,

113
07:38.900 --> 07:43.580
instead of getting it to delay by one second after each segment has moved,

114
07:43.880 --> 07:45.950
if I move this up here

115
07:46.190 --> 07:48.950
then it's only going to be delayed by one second

116
07:49.220 --> 07:52.550
after all three segments have moved. This way

117
07:52.580 --> 07:56.990
our snake is moving a little bit faster. And we can make it move faster still

118
07:57.050 --> 07:59.690
if we cut the amount of time that we're sleeping.

119
08:00.080 --> 08:02.840
So let's change it to 0.1 second sleep

120
08:03.290 --> 08:06.470
and you can see our snake is now moving at a reasonable speed.

121
08:06.890 --> 08:11.270
Now you might think that we've solved the challenge and we've now got our snake

122
08:11.270 --> 08:15.800
to move automatically forwards, but there's a problem.

123
08:16.040 --> 08:17.780
How do we turn our snake?

124
08:18.170 --> 08:22.280
Let's see what would happen if we control the snake head and change direction.

125
08:22.910 --> 08:27.680
Let's say that at some point, we want to turn the snake so that it turns left.

126
08:28.280 --> 08:29.750
Well, what happens then?

127
08:30.380 --> 08:33.410
So this first piece is now facing up,

128
08:33.770 --> 08:38.300
the second piece is going to continue moving forwards as does the third piece.

129
08:39.020 --> 08:42.590
Now on the next iteration of that for loop,

130
08:43.010 --> 08:47.780
that first piece is going to keep moving towards North while the second and

131
08:47.780 --> 08:51.950
third pieces are going to keep moving forward because they're not going to

132
08:51.950 --> 08:53.210
change their own heading.

133
08:53.750 --> 08:58.590
We'll get this strange behavior because our snake segments are not linked. To

134
08:58.590 --> 09:03.270
illustrate this, let me go ahead and change the first segment,

135
09:03.270 --> 09:08.270
so the segment at index zero, and get it to turn left by 90 degrees.

136
09:10.350 --> 09:12.180
And notice when I run the code,

137
09:12.570 --> 09:16.380
you see how that head is moving in a circle all by itself,

138
09:16.710 --> 09:21.300
and the body has completely left the head and has continued to go forward.

139
09:21.950 --> 09:24.290
<v 2>So how can we solve this? Well,</v>

140
09:24.380 --> 09:29.240
we have to rethink the way that we move our segments. Again,</v>

141
09:29.270 --> 09:34.040
we have our three segments, but if instead of moving everything forwards,

142
09:34.460 --> 09:38.840
what if we get our last segment, so segment_3

143
09:38.840 --> 09:43.340
in this case, to move to the position of the second to last segment,

144
09:43.760 --> 09:48.650
and then the second segment to move to the position of the first segment,

145
09:49.040 --> 09:53.570
and then the first segment itself to go forward by 20 paces?

146
09:53.900 --> 09:58.400
And if we go back to that situation where we're trying to turn our snake,

147
09:58.880 --> 10:02.060
then in this method, it will still continue to work.

148
10:02.390 --> 10:04.970
So we've got our three segments, one, two, and three.

149
10:05.480 --> 10:08.840
Our third segment goes to where the second segment used to be,

150
10:09.050 --> 10:11.300
second goes to where the one used to be,

151
10:11.570 --> 10:15.620
and then the one is going to turn and then move to the left.

152
10:15.980 --> 10:18.710
Now the next turn is the interesting part

153
10:19.070 --> 10:21.680
because at this point we saw how

154
10:21.770 --> 10:24.680
if these two pieces just continue moving forward,

155
10:24.980 --> 10:28.610
they're going to move away from the head of the snake and it's going to move in

156
10:28.610 --> 10:31.610
opposite directions. But using this method,

157
10:31.880 --> 10:36.110
our third segment is going to move to where the second segment used to be,

158
10:36.380 --> 10:38.750
the second goes to where the first used to be,

159
10:38.990 --> 10:42.560
and the first continues moving forward. This way,

160
10:42.560 --> 10:47.270
our snake has pretty much straightened out as you would expect this snake to

161
10:47.270 --> 10:51.980
behave. Now, it's just the matter of actually implementing this,

162
10:52.010 --> 10:53.090
which is the hard part.

163
10:53.600 --> 10:57.500
So I'm going to go ahead and delete the part where I told the snake to turn left

164
10:58.040 --> 11:00.620
and I'm going to delete this for loop

165
11:00.650 --> 11:05.330
which just moved each of the segments in our list of segments forward by 20

166
11:05.330 --> 11:09.980
paces. Now, instead, what I'm going to do is I'm going to create a for loop,

167
11:10.340 --> 11:15.340
but this time I'm going to loop through each of the segments going from the last

168
11:15.980 --> 11:18.170
segment to the first segment,

169
11:18.380 --> 11:22.040
so basically in reverse order. Now to do this,

170
11:22.040 --> 11:24.710
I'm going to use the range type of for-loop.

171
11:24.950 --> 11:29.950
So I'm going to say for segment number or seg_num in the range,

172
11:31.490 --> 11:34.020
and this range is going to have

173
11:34.160 --> 11:37.580
a start, a stop,

174
11:38.150 --> 11:40.340
and also a step.

175
11:40.820 --> 11:44.420
So the start is the number that we're going to start

176
11:44.420 --> 11:47.450
the range from, the stop is where the range is going to end,

177
11:47.810 --> 11:52.370
and the step is how we're going to get from the start to the stop. For example,

178
11:52.400 --> 11:56.710
if we wanted a range of 1, 2, 3, then of course start is going to be 1,

179
11:56.920 --> 12:01.480
stop is going to be 3 and step is going to be +1. Now,

180
12:01.480 --> 12:05.770
if we wanted a range of 3, 2, 1, however,

181
12:05.830 --> 12:07.870
then the start is going to be 3,

182
12:08.140 --> 12:12.730
the stop is going to be 1 and the step is going to be -1.

183
12:13.420 --> 12:14.230
In our case,

184
12:14.230 --> 12:18.640
what we actually want is actually to go from 2,

185
12:19.120 --> 12:21.040
1, 0.

186
12:21.550 --> 12:26.550
So the start will be 2, the stop will be 0, and the step will be -1.

187
12:28.960 --> 12:33.400
Now, unfortunately, even though we have these named parameters,

188
12:33.760 --> 12:38.560
because the range function in Python is actually something that's not quite pure

189
12:38.560 --> 12:41.860
Python, it's something that comes from the C language,

190
12:42.220 --> 12:45.520
it doesn't actually let us use these names.

191
12:45.820 --> 12:49.180
I'll show you when we run our code, this is actually going to give us an error.

192
12:49.480 --> 12:50.710
But for the time being,

193
12:50.740 --> 12:55.240
it's actually much easier to visualize this as we write the code inside this

194
12:55.240 --> 12:57.610
for-loop. So in this case,

195
12:57.640 --> 13:02.640
the segment number is going to be equal to 2, and then 1,

196
13:03.430 --> 13:04.870
and then finally 0.

197
13:05.440 --> 13:10.440
Now we're going to use that to get hold of the last segment from our list of

198
13:11.620 --> 13:12.453
segments.

199
13:12.580 --> 13:16.720
So we can tap into that list and then get hold of the last one

200
13:16.990 --> 13:18.580
using that seg_num.

201
13:19.060 --> 13:23.860
And then we're going to set it to go to a particular X and Y position.

202
13:24.380 --> 13:29.380
Now the X and Y position that we want it to go to is going to be the second to

203
13:30.370 --> 13:32.200
last segment's position.

204
13:32.680 --> 13:35.800
So how can we get hold of the second to last segment? Well,

205
13:36.040 --> 13:40.720
we're going to get hold of the segments and then pass in seg_num but then 

206
13:40.720 --> 13:44.230
-1. So when we first start out, we start out with 2.

207
13:44.530 --> 13:49.120
So the segment at position two is going to be the last segment.

208
13:49.480 --> 13:54.400
And then the segment at 2 - 1 is going to be the second to last segment.

209
13:54.850 --> 13:58.450
Now this one we're going to get hold of it's X coordinate

210
13:59.050 --> 14:03.250
and we're going to set this to a variable called new_x,

211
14:03.760 --> 14:08.760
and then we're going to do the same and get hold of the new_y.

212
14:09.820 --> 14:13.660
So we're going to get hold of the second to last segment's Y coordinate,

213
14:14.020 --> 14:19.020
and then we're going to use these coordinates, new_x and new_y to tell this last

214
14:19.600 --> 14:24.040
segment to go to the position of the second to last segment.

215
14:24.790 --> 14:26.260
Now, as I mentioned before,

216
14:26.650 --> 14:30.790
this range function comes from the C language.

217
14:31.060 --> 14:34.330
So if we run it with these keyword arguments

218
14:34.630 --> 14:36.430
it's actually going to give us an error

219
14:36.550 --> 14:40.840
and it tells us that this range function takes no keyword arguments.

220
14:41.260 --> 14:44.410
So while it's really nice to use it to visualize it,

221
14:44.440 --> 14:48.040
if we actually want it to work, we have to delete these.

222
14:48.220 --> 14:50.200
But just before I delete it,

223
14:50.470 --> 14:55.190
I want to this so that we're no longer using these hard-coded numbers.

224
14:55.310 --> 14:57.560
So instead of going from 2 to 0,

225
14:57.980 --> 15:02.570
we want to go to the length of the segments.

226
15:02.600 --> 15:06.410
So in the future, if we had 10 segments or 20 segments,

227
15:06.620 --> 15:08.660
that our code would still work. Now,

228
15:08.660 --> 15:11.750
the length of the segment is actually three to begin with.

229
15:12.170 --> 15:15.800
And we know that lists start counting from zero,

230
15:15.800 --> 15:20.800
so 0, 1, 2, ... the last position is going to be the length - 1,

231
15:21.440 --> 15:25.190
and then we're going to stop at the zeroth segment.

232
15:25.760 --> 15:30.560
So now we can go ahead and delete these named arguments.

233
15:33.260 --> 15:37.640
And we end up with this. Now we can run our code and we won't get any errors.

234
15:38.600 --> 15:43.040
Notice how all three of the segments went to the same position,

235
15:43.580 --> 15:48.560
the position of the first segment. So in addition to moving these segments,

236
15:48.590 --> 15:53.590
remember that we also have to move the very first segment actually forwards by

237
15:55.940 --> 16:00.380
say, 20 paces. So at the very end of all of this code

238
16:00.560 --> 16:01.910
outside of the four loop,

239
16:02.180 --> 16:06.890
we're going to get hold of the first segment, so segment at position zero,

240
16:07.280 --> 16:10.700
and then we're going to get it to move forward by 20 paces.

241
16:11.420 --> 16:12.980
So now when I run this again,

242
16:13.010 --> 16:17.810
you can see our snake is now moving freely forwards and even if at some point,

243
16:17.840 --> 16:20.120
the snake needed to turn,

244
16:20.450 --> 16:23.150
let's say it turned left by 90 degrees,

245
16:23.540 --> 16:25.880
then our code is still going to work.

246
16:25.970 --> 16:30.320
Notice how our snake is now turning in a circle and all of the subsequent

247
16:30.320 --> 16:34.400
pieces are following the head along its path. That's it.

248
16:34.670 --> 16:39.670
This is the code that will get our snake to automatically move forwards.

249
16:40.850 --> 16:43.970
Now, there was quite a few concepts mentioned in here,

250
16:44.480 --> 16:49.480
and you have to think about the segments in terms of how they move in the graph

251
16:50.720 --> 16:55.610
and also this idea of getting hold of the last segment and then telling it to go

252
16:55.610 --> 17:00.380
to the position of the second to last segment and then doing this for all of the

253
17:00.380 --> 17:01.213
segments.

254
17:01.370 --> 17:05.720
So it's a little bit mind-bending and it might be worth just taking a second

255
17:05.720 --> 17:10.550
look at this code and going back in the video where I explain how this worked in

256
17:10.550 --> 17:14.330
the slides, just so that you're really clear with how this works.

257
17:14.720 --> 17:18.890
Once you are, then you can move forward and head over to the next lesson.