1
00:00:00,630 --> 00:00:05,630
In the last lesson, we managed to create our snake's body by creating three

2
00:00:05,640 --> 00:00:10,260
squares that were each turtle objects. Now in this lesson,

3
00:00:10,290 --> 00:00:14,280
we're going to move on to the next step where we actually move our snake

4
00:00:14,520 --> 00:00:18,570
automatically across the screen without having to do anything.

5
00:00:19,050 --> 00:00:24,050
So this way the snake is continuously moving forwards and all we have to do as

6
00:00:24,120 --> 00:00:27,570
the user is just to change its direction. Now,

7
00:00:27,600 --> 00:00:30,990
how would we go about moving the snake? Well,

8
00:00:31,020 --> 00:00:36,000
we've already got these different segments that are created, but at the moment,

9
00:00:36,030 --> 00:00:39,360
there's no way of organizing all the segments.

10
00:00:39,720 --> 00:00:42,480
They're kind of just created and placed on screen.

11
00:00:43,140 --> 00:00:47,310
So let's put them into a list called segments,

12
00:00:47,820 --> 00:00:52,020
and let's start out that list as an empty list. And then later on,

13
00:00:52,020 --> 00:00:54,180
once we've created each new segment,

14
00:00:54,420 --> 00:00:57,300
we go ahead and append it to this list.

15
00:00:58,770 --> 00:01:02,250
If we want something to continuously happen in our program,

16
00:01:02,700 --> 00:01:05,910
the way that we've usually done that is through a while loop.

17
00:01:06,510 --> 00:01:11,510
So let's create a new variable called game_is_on and let's set it to true.

18
00:01:14,520 --> 00:01:16,680
And while game is on,

19
00:01:17,100 --> 00:01:20,280
then we're going to move each of the segments.

20
00:01:20,670 --> 00:01:25,440
The simplest way that I could think of to move this segment is to loop through

21
00:01:25,560 --> 00:01:29,190
each of the segments in our list of segments,

22
00:01:29,730 --> 00:01:34,730
and then to get each of these to go ahead and move forward.

23
00:01:35,640 --> 00:01:38,160
So let's say we move forwards by 20 pixels.

24
00:01:38,580 --> 00:01:41,340
Let's go ahead and run this program and see what we get.

25
00:01:42,450 --> 00:01:46,290
The first thing we notice is that the behavior is very weird.

26
00:01:46,710 --> 00:01:49,080
We've got a line that's being drawn

27
00:01:49,470 --> 00:01:52,260
and that comes from each of the segments

28
00:01:52,620 --> 00:01:55,320
which are individual turtles.

29
00:01:55,410 --> 00:01:57,810
And they're all drawing this line as they're moving.

30
00:01:58,590 --> 00:02:00,690
The first thing we want to fix is that line.

31
00:02:00,960 --> 00:02:03,630
So when we create each new segment,

32
00:02:03,750 --> 00:02:07,020
before we tell it to go to its position,

33
00:02:07,410 --> 00:02:11,760
let's go ahead and tell it to pull the pen up. This way

34
00:02:11,760 --> 00:02:13,260
it won't actually draw

35
00:02:13,470 --> 00:02:16,950
and all that we'll see is the actual turtle pieces.

36
00:02:19,110 --> 00:02:24,110
So now we see our three turtle pieces scurrying along like some sort of weird

37
00:02:24,960 --> 00:02:28,500
Caterpillar, but definitely not in a snake like way.

38
00:02:29,420 --> 00:02:30,620
How can we fix this?

39
00:02:31,490 --> 00:02:36,490
One of the things that you notice about turtle is it will first create the

40
00:02:37,400 --> 00:02:39,500
turtle when it runs this line,

41
00:02:39,800 --> 00:02:44,780
the turtle will get created at the center positions, so coordinate (0, 0).

42
00:02:45,530 --> 00:02:49,730
And then it will be moved to whatever position we tell it to go to.

43
00:02:49,940 --> 00:02:54,890
For example, for the third segment, it starts out life at (0, 0)

44
00:02:55,070 --> 00:03:00,040
and then as soon as it gets told to go to this position, it goes to (-40, 0).

45
00:03:00,580 --> 00:03:03,310
Now we can see that happening on screen.

46
00:03:03,940 --> 00:03:05,920
When we created our snake body,

47
00:03:06,190 --> 00:03:10,960
you could see each individual piece being created and then moved to their

48
00:03:10,960 --> 00:03:14,560
location. Now, if we wanted to turn off that animation,

49
00:03:14,800 --> 00:03:18,670
then we would have to use one of the screen class'

50
00:03:18,670 --> 00:03:23,670
methods called tracer. And tracer takes a number as a input,

51
00:03:26,050 --> 00:03:28,870
and it turns the animation on or off.

52
00:03:29,140 --> 00:03:31,570
And when the tracer is turned off,

53
00:03:32,020 --> 00:03:37,020
then we can use the update method to tell our program when to refresh and redraw

54
00:03:38,380 --> 00:03:43,150
the screen. When we think back to the old TV monitors,

55
00:03:43,180 --> 00:03:46,360
the cathode ray tube monitors or CRT monitors,

56
00:03:46,720 --> 00:03:51,720
the way that they worked is by painting on a strip of color line by line

57
00:03:53,920 --> 00:03:57,550
by line, slowly covering the entire screen.

58
00:03:58,060 --> 00:04:02,020
And then once it's done one screen, it's going to go back to the top

59
00:04:02,110 --> 00:04:07,090
and then it's going to paint the pixels for the next scene. And effectively,

60
00:04:07,090 --> 00:04:10,240
it's kind of like how a GIF animation works.

61
00:04:10,420 --> 00:04:14,380
A gif animation is composed of many images. So for example,

62
00:04:14,380 --> 00:04:15,730
if we wanted to animate,

63
00:04:15,730 --> 00:04:20,730
we would increase this line and then we would start drawing out a leaf until

64
00:04:21,339 --> 00:04:25,900
eventually we end up with an animation like this. Now,

65
00:04:26,020 --> 00:04:29,170
when that's all combined and played back very quickly,

66
00:04:29,200 --> 00:04:33,460
then this is the animation you see. In our game

67
00:04:33,490 --> 00:04:38,490
what we could do is we could describe each of these scenes and tell our program

68
00:04:40,900 --> 00:04:43,270
when it should redraw each picture.

69
00:04:44,140 --> 00:04:49,140
So that way we could start out with one picture and then hit update and then do

70
00:04:50,260 --> 00:04:51,610
something else on screen,

71
00:04:51,640 --> 00:04:56,260
maybe move each of our segments and then tell the screen to update again

72
00:04:56,260 --> 00:04:58,180
to show the user the new result.

73
00:04:58,660 --> 00:05:01,900
And then each time we make the changes we want to happen

74
00:05:02,230 --> 00:05:05,500
and then call that update method to tell the screen

75
00:05:05,590 --> 00:05:10,590
to show a new image each time. Let's first turn off the tracer.

76
00:05:11,770 --> 00:05:14,770
So the tracer is a method in the screen class

77
00:05:15,220 --> 00:05:18,670
and in order to turn it off, we're going to set it to zero.

78
00:05:19,210 --> 00:05:23,470
So now once the tracer is off, if we actually try to run our program,

79
00:05:23,710 --> 00:05:26,890
you can see it's just a black screen and nothing will happen.

80
00:05:27,400 --> 00:05:32,260
Even though we've got our while loop and we've got our for loop and lots of

81
00:05:32,260 --> 00:05:35,980
things are meant to be happening, but until we call update,

82
00:05:36,160 --> 00:05:39,700
the screen is not going to refresh and it's not going to show us what's been

83
00:05:39,700 --> 00:05:41,110
happening in our code.

84
00:05:41,680 --> 00:05:46,680
So let's say that we decide to call update after all of the segments have been

85
00:05:48,820 --> 00:05:53,200
created, so right about here. Let's call screen.

86
00:05:53,350 --> 00:05:56,620
update. And now if I hit run,

87
00:05:56,890 --> 00:06:01,280
you'll notice that pretty much immediately. As soon as you run the program,

88
00:06:01,610 --> 00:06:04,970
our snake body will show up, not piece by piece,

89
00:06:05,060 --> 00:06:08,930
but in its entirety. Now, if on the other hand

90
00:06:09,020 --> 00:06:14,020
I move our screen.update line of code into the while loop so that once each

91
00:06:16,940 --> 00:06:20,600
segment moves, I get the screen to update,

92
00:06:20,930 --> 00:06:22,850
then this is what you're going to see.

93
00:06:23,210 --> 00:06:26,840
You see each of the pieces moving along one by one.

94
00:06:27,290 --> 00:06:29,810
Now it's not really clear what's happening.

95
00:06:29,840 --> 00:06:31,730
So I'm going to slow it down a little bit.

96
00:06:32,210 --> 00:06:35,240
And I'm going to do this by importing the time module.

97
00:06:35,690 --> 00:06:40,690
Now I'm going to add the time.sleep and I'm going to get it to sleep by one

98
00:06:41,900 --> 00:06:42,733
second.

99
00:06:42,830 --> 00:06:47,830
So this basically just add a one-second delay after each segment moves.

100
00:06:49,280 --> 00:06:52,040
So each segment moves, the screen updates,

101
00:06:52,190 --> 00:06:55,670
and then we sleep for a second before the next time this happens.

102
00:06:56,240 --> 00:06:58,190
Notice how in this case,

103
00:06:58,280 --> 00:07:01,280
our snake is moving piece by piece.

104
00:07:01,520 --> 00:07:04,730
So first this first piece, and then the second piece,

105
00:07:04,760 --> 00:07:08,810
the third piece with a one-second delay between each movement.

106
00:07:09,440 --> 00:07:09,800
Now,

107
00:07:09,800 --> 00:07:14,800
what happens if we move this screen.update to outside this for-loop?

108
00:07:16,490 --> 00:07:18,920
So basically we only update the screen

109
00:07:19,190 --> 00:07:21,770
once all of the segments have moved forwards.

110
00:07:21,950 --> 00:07:26,950
Now notice how our snake is moving forwards as an entire piece.

111
00:07:27,590 --> 00:07:32,180
It's going to move all three segments forward before the update gets triggered

112
00:07:32,450 --> 00:07:34,160
and we refresh the graphics.

113
00:07:34,370 --> 00:07:38,870
So it looks like as if the whole snake is moving as one piece. Now,

114
00:07:38,900 --> 00:07:43,580
instead of getting it to delay by one second after each segment has moved,

115
00:07:43,880 --> 00:07:45,950
if I move this up here

116
00:07:46,190 --> 00:07:48,950
then it's only going to be delayed by one second

117
00:07:49,220 --> 00:07:52,550
after all three segments have moved. This way

118
00:07:52,580 --> 00:07:56,990
our snake is moving a little bit faster. And we can make it move faster still

119
00:07:57,050 --> 00:07:59,690
if we cut the amount of time that we're sleeping.

120
00:08:00,080 --> 00:08:02,840
So let's change it to 0.1 second sleep

121
00:08:03,290 --> 00:08:06,470
and you can see our snake is now moving at a reasonable speed.

122
00:08:06,890 --> 00:08:11,270
Now you might think that we've solved the challenge and we've now got our snake

123
00:08:11,270 --> 00:08:15,800
to move automatically forwards, but there's a problem.

124
00:08:16,040 --> 00:08:17,780
How do we turn our snake?

125
00:08:18,170 --> 00:08:22,280
Let's see what would happen if we control the snake head and change direction.

126
00:08:22,910 --> 00:08:27,680
Let's say that at some point, we want to turn the snake so that it turns left.

127
00:08:28,280 --> 00:08:29,750
Well, what happens then?

128
00:08:30,380 --> 00:08:33,409
So this first piece is now facing up,

129
00:08:33,770 --> 00:08:38,299
the second piece is going to continue moving forwards as does the third piece.

130
00:08:39,020 --> 00:08:42,590
Now on the next iteration of that for loop,

131
00:08:43,010 --> 00:08:47,780
that first piece is going to keep moving towards North while the second and

132
00:08:47,780 --> 00:08:51,950
third pieces are going to keep moving forward because they're not going to

133
00:08:51,950 --> 00:08:53,210
change their own heading.

134
00:08:53,750 --> 00:08:58,590
We'll get this strange behavior because our snake segments are not linked. To

135
00:08:58,590 --> 00:09:03,270
illustrate this, let me go ahead and change the first segment,

136
00:09:03,270 --> 00:09:08,270
so the segment at index zero, and get it to turn left by 90 degrees.

137
00:09:10,350 --> 00:09:12,180
And notice when I run the code,

138
00:09:12,570 --> 00:09:16,380
you see how that head is moving in a circle all by itself,

139
00:09:16,710 --> 00:09:21,300
and the body has completely left the head and has continued to go forward.

140
00:09:21,950 --> 00:09:24,290
So how can we solve this? Well,

141
00:09:24,380 --> 00:09:29,240
we have to rethink the way that we move our segments. Again,

142
00:09:29,270 --> 00:09:34,040
we have our three segments, but if instead of moving everything forwards,

143
00:09:34,460 --> 00:09:38,840
what if we get our last segment, so segment_3

144
00:09:38,840 --> 00:09:43,340
in this case, to move to the position of the second to last segment,

145
00:09:43,760 --> 00:09:48,650
and then the second segment to move to the position of the first segment,

146
00:09:49,040 --> 00:09:53,570
and then the first segment itself to go forward by 20 paces?

147
00:09:53,900 --> 00:09:58,400
And if we go back to that situation where we're trying to turn our snake,

148
00:09:58,880 --> 00:10:02,060
then in this method, it will still continue to work.

149
00:10:02,390 --> 00:10:04,970
So we've got our three segments, one, two, and three.

150
00:10:05,480 --> 00:10:08,840
Our third segment goes to where the second segment used to be,

151
00:10:09,050 --> 00:10:11,300
second goes to where the one used to be,

152
00:10:11,570 --> 00:10:15,620
and then the one is going to turn and then move to the left.

153
00:10:15,980 --> 00:10:18,710
Now the next turn is the interesting part

154
00:10:19,070 --> 00:10:21,680
because at this point we saw how

155
00:10:21,770 --> 00:10:24,680
if these two pieces just continue moving forward,

156
00:10:24,980 --> 00:10:28,610
they're going to move away from the head of the snake and it's going to move in

157
00:10:28,610 --> 00:10:31,610
opposite directions. But using this method,

158
00:10:31,880 --> 00:10:36,110
our third segment is going to move to where the second segment used to be,

159
00:10:36,380 --> 00:10:38,750
the second goes to where the first used to be,

160
00:10:38,990 --> 00:10:42,560
and the first continues moving forward. This way,

161
00:10:42,560 --> 00:10:47,270
our snake has pretty much straightened out as you would expect this snake to

162
00:10:47,270 --> 00:10:51,980
behave. Now, it's just the matter of actually implementing this,

163
00:10:52,010 --> 00:10:53,090
which is the hard part.

164
00:10:53,600 --> 00:10:57,500
So I'm going to go ahead and delete the part where I told the snake to turn left

165
00:10:58,040 --> 00:11:00,620
and I'm going to delete this for loop

166
00:11:00,650 --> 00:11:05,330
which just moved each of the segments in our list of segments forward by 20

167
00:11:05,330 --> 00:11:09,980
paces. Now, instead, what I'm going to do is I'm going to create a for loop,

168
00:11:10,340 --> 00:11:15,340
but this time I'm going to loop through each of the segments going from the last

169
00:11:15,980 --> 00:11:18,170
segment to the first segment,

170
00:11:18,380 --> 00:11:22,040
so basically in reverse order. Now to do this,

171
00:11:22,040 --> 00:11:24,710
I'm going to use the range type of for-loop.

172
00:11:24,950 --> 00:11:29,950
So I'm going to say for segment number or seg_num in the range,

173
00:11:31,490 --> 00:11:34,020
and this range is going to have

174
00:11:34,160 --> 00:11:37,580
a start, a stop,

175
00:11:38,150 --> 00:11:40,340
and also a step.

176
00:11:40,820 --> 00:11:44,420
So the start is the number that we're going to start

177
00:11:44,420 --> 00:11:47,450
the range from, the stop is where the range is going to end,

178
00:11:47,810 --> 00:11:52,370
and the step is how we're going to get from the start to the stop. For example,

179
00:11:52,400 --> 00:11:56,710
if we wanted a range of 1, 2, 3, then of course start is going to be 1,

180
00:11:56,920 --> 00:12:01,480
stop is going to be 3 and step is going to be +1. Now,

181
00:12:01,480 --> 00:12:05,770
if we wanted a range of 3, 2, 1, however,

182
00:12:05,830 --> 00:12:07,870
then the start is going to be 3,

183
00:12:08,140 --> 00:12:12,730
the stop is going to be 1 and the step is going to be -1.

184
00:12:13,420 --> 00:12:14,230
In our case,

185
00:12:14,230 --> 00:12:18,640
what we actually want is actually to go from 2,

186
00:12:19,120 --> 00:12:21,040
1, 0.

187
00:12:21,550 --> 00:12:26,550
So the start will be 2, the stop will be 0, and the step will be -1.

188
00:12:28,960 --> 00:12:33,400
Now, unfortunately, even though we have these named parameters,

189
00:12:33,760 --> 00:12:38,560
because the range function in Python is actually something that's not quite pure

190
00:12:38,560 --> 00:12:41,860
Python, it's something that comes from the C language,

191
00:12:42,220 --> 00:12:45,520
it doesn't actually let us use these names.

192
00:12:45,820 --> 00:12:49,180
I'll show you when we run our code, this is actually going to give us an error.

193
00:12:49,480 --> 00:12:50,710
But for the time being,

194
00:12:50,740 --> 00:12:55,240
it's actually much easier to visualize this as we write the code inside this

195
00:12:55,240 --> 00:12:57,610
for-loop. So in this case,

196
00:12:57,640 --> 00:13:02,640
the segment number is going to be equal to 2, and then 1,

197
00:13:03,430 --> 00:13:04,870
and then finally 0.

198
00:13:05,440 --> 00:13:10,440
Now we're going to use that to get hold of the last segment from our list of

199
00:13:11,620 --> 00:13:12,453
segments.

200
00:13:12,580 --> 00:13:16,720
So we can tap into that list and then get hold of the last one

201
00:13:16,990 --> 00:13:18,580
using that seg_num.

202
00:13:19,060 --> 00:13:23,860
And then we're going to set it to go to a particular X and Y position.

203
00:13:24,380 --> 00:13:29,380
Now the X and Y position that we want it to go to is going to be the second to

204
00:13:30,370 --> 00:13:32,200
last segment's position.

205
00:13:32,680 --> 00:13:35,800
So how can we get hold of the second to last segment? Well,

206
00:13:36,040 --> 00:13:40,720
we're going to get hold of the segments and then pass in seg_num but then 

207
00:13:40,720 --> 00:13:44,230
-1. So when we first start out, we start out with 2.

208
00:13:44,530 --> 00:13:49,120
So the segment at position two is going to be the last segment.

209
00:13:49,480 --> 00:13:54,400
And then the segment at 2 - 1 is going to be the second to last segment.

210
00:13:54,850 --> 00:13:58,450
Now this one we're going to get hold of it's X coordinate

211
00:13:59,050 --> 00:14:03,250
and we're going to set this to a variable called new_x,

212
00:14:03,760 --> 00:14:08,760
and then we're going to do the same and get hold of the new_y.

213
00:14:09,820 --> 00:14:13,660
So we're going to get hold of the second to last segment's Y coordinate,

214
00:14:14,020 --> 00:14:19,020
and then we're going to use these coordinates, new_x and new_y to tell this last

215
00:14:19,600 --> 00:14:24,040
segment to go to the position of the second to last segment.

216
00:14:24,790 --> 00:14:26,260
Now, as I mentioned before,

217
00:14:26,650 --> 00:14:30,790
this range function comes from the C language.

218
00:14:31,060 --> 00:14:34,330
So if we run it with these keyword arguments

219
00:14:34,630 --> 00:14:36,430
it's actually going to give us an error

220
00:14:36,550 --> 00:14:40,840
and it tells us that this range function takes no keyword arguments.

221
00:14:41,260 --> 00:14:44,410
So while it's really nice to use it to visualize it,

222
00:14:44,440 --> 00:14:48,040
if we actually want it to work, we have to delete these.

223
00:14:48,220 --> 00:14:50,200
But just before I delete it,

224
00:14:50,470 --> 00:14:55,190
I want to this so that we're no longer using these hard-coded numbers.

225
00:14:55,310 --> 00:14:57,560
So instead of going from 2 to 0,

226
00:14:57,980 --> 00:15:02,570
we want to go to the length of the segments.

227
00:15:02,600 --> 00:15:06,410
So in the future, if we had 10 segments or 20 segments,

228
00:15:06,620 --> 00:15:08,660
that our code would still work. Now,

229
00:15:08,660 --> 00:15:11,750
the length of the segment is actually three to begin with.

230
00:15:12,170 --> 00:15:15,800
And we know that lists start counting from zero,

231
00:15:15,800 --> 00:15:20,800
so 0, 1, 2, ... the last position is going to be the length - 1,

232
00:15:21,440 --> 00:15:25,190
and then we're going to stop at the zeroth segment.

233
00:15:25,760 --> 00:15:30,560
So now we can go ahead and delete these named arguments.

234
00:15:33,260 --> 00:15:37,640
And we end up with this. Now we can run our code and we won't get any errors.

235
00:15:38,600 --> 00:15:43,040
Notice how all three of the segments went to the same position,

236
00:15:43,580 --> 00:15:48,560
the position of the first segment. So in addition to moving these segments,

237
00:15:48,590 --> 00:15:53,590
remember that we also have to move the very first segment actually forwards by

238
00:15:55,940 --> 00:16:00,380
say, 20 paces. So at the very end of all of this code

239
00:16:00,560 --> 00:16:01,910
outside of the four loop,

240
00:16:02,180 --> 00:16:06,890
we're going to get hold of the first segment, so segment at position zero,

241
00:16:07,280 --> 00:16:10,700
and then we're going to get it to move forward by 20 paces.

242
00:16:11,420 --> 00:16:12,980
So now when I run this again,

243
00:16:13,010 --> 00:16:17,810
you can see our snake is now moving freely forwards and even if at some point,

244
00:16:17,840 --> 00:16:20,120
the snake needed to turn,

245
00:16:20,450 --> 00:16:23,150
let's say it turned left by 90 degrees,

246
00:16:23,540 --> 00:16:25,880
then our code is still going to work.

247
00:16:25,970 --> 00:16:30,320
Notice how our snake is now turning in a circle and all of the subsequent

248
00:16:30,320 --> 00:16:34,400
pieces are following the head along its path. That's it.

249
00:16:34,670 --> 00:16:39,670
This is the code that will get our snake to automatically move forwards.

250
00:16:40,850 --> 00:16:43,970
Now, there was quite a few concepts mentioned in here,

251
00:16:44,480 --> 00:16:49,480
and you have to think about the segments in terms of how they move in the graph

252
00:16:50,720 --> 00:16:55,610
and also this idea of getting hold of the last segment and then telling it to go

253
00:16:55,610 --> 00:17:00,380
to the position of the second to last segment and then doing this for all of the

254
00:17:00,380 --> 00:17:01,213
segments.

255
00:17:01,370 --> 00:17:05,720
So it's a little bit mind-bending and it might be worth just taking a second

256
00:17:05,720 --> 00:17:10,550
look at this code and going back in the video where I explain how this worked in

257
00:17:10,550 --> 00:17:14,329
the slides, just so that you're really clear with how this works.

258
00:17:14,720 --> 00:17:18,890
Once you are, then you can move forward and head over to the next lesson.

