1
00:00:00,060 --> 00:00:02,910
All right. So now that we've learned all about inheritance,

2
00:00:03,000 --> 00:00:06,300
it's time to apply the theory to our snake game,

3
00:00:06,570 --> 00:00:09,900
and we're going to use it to detect collision with food.

4
00:00:10,470 --> 00:00:13,590
Our snake should be able to head a piece of food,

5
00:00:13,860 --> 00:00:17,580
which is just going to be a blue circle. And every time it touches the food,

6
00:00:17,790 --> 00:00:21,480
the circle moves to a new, random location on the screen.

7
00:00:22,480 --> 00:00:23,940
If we take a look at our code,

8
00:00:24,270 --> 00:00:27,780
you can see that the main.py controls the entire game.

9
00:00:27,930 --> 00:00:32,640
It dictates how the screen should behave and how the snake behaves.

10
00:00:33,150 --> 00:00:35,160
Now, everything that's to do with a snake,

11
00:00:35,190 --> 00:00:40,190
it's a parent's and behavior, is all captured inside a class.

12
00:00:40,650 --> 00:00:43,950
So everything snake related is inside the snake class.

13
00:00:44,460 --> 00:00:49,460
So what we want to be able to do is to create a new food.py file

14
00:00:51,510 --> 00:00:55,320
and this food.py is going to be its own class.

15
00:00:55,890 --> 00:01:00,890
And the food class is going to know how to render itself as a small circle on

16
00:01:01,170 --> 00:01:04,530
the screen. And then every time the snake touches the food,

17
00:01:04,950 --> 00:01:09,030
then that food is going to move to a new random location.

18
00:01:09,690 --> 00:01:13,410
So let's create the initializer for this food class.

19
00:01:14,010 --> 00:01:18,450
And one of the things that we're going to need to do is we're going to need to

20
00:01:18,480 --> 00:01:21,990
import turtle. So from the turtle module,

21
00:01:21,990 --> 00:01:23,880
let's import the turtle class.

22
00:01:24,570 --> 00:01:29,570
And this piece of food that we're going to see onscreen is going to be a turtle

23
00:01:30,240 --> 00:01:34,320
object. Instead of creating it as an attribute in this class,

24
00:01:34,320 --> 00:01:37,710
so self.food = turtle like this,

25
00:01:38,010 --> 00:01:43,010
what we want to be able to do is we actually want this class, food, to inherit

26
00:01:43,500 --> 00:01:44,790
from the turtle class.

27
00:01:45,300 --> 00:01:50,280
So that way this food class is going to have all of the capabilities of the

28
00:01:50,280 --> 00:01:51,120
turtle class,

29
00:01:51,450 --> 00:01:55,170
but it's also going to have some specific things that we're going to tell it

30
00:01:55,200 --> 00:01:59,070
how to do so that it behaves like an actual piece of food.

31
00:01:59,370 --> 00:02:02,700
Here's a quick challenge. From what you learned in the last lesson,

32
00:02:02,730 --> 00:02:07,650
can you figure out how to make this food class inherit from the turtle class?

33
00:02:07,980 --> 00:02:09,300
Pause the video and give that a

34
00:02:09,410 --> 00:02:10,243
go.

35
00:02:12,920 --> 00:02:13,310
All right.

36
00:02:13,310 --> 00:02:17,780
So we mentioned that there's only two steps we need to do. First is after the

37
00:02:17,780 --> 00:02:18,710
name of the class

38
00:02:18,740 --> 00:02:22,940
we add some parentheses and then put in the name of the class that we want to

39
00:02:22,940 --> 00:02:26,030
inherit from. So in this case, it's the turtle class.

40
00:02:26,630 --> 00:02:31,520
And then the next thing we need to do is we need to call the turtle's init

41
00:02:31,520 --> 00:02:34,550
method inside the food's init method.

42
00:02:35,150 --> 00:02:39,470
And you can see that as soon as you've added this inheritance here, this init

43
00:02:39,470 --> 00:02:44,090
starts giving us a warning. And when you click on it, you can see

44
00:02:44,090 --> 00:02:47,360
it says call to __init__ of superclass is missed.

45
00:02:47,690 --> 00:02:49,970
So it actually knows what we need to do next.

46
00:02:50,120 --> 00:02:51,950
That means if we click on the light bulb,

47
00:02:52,190 --> 00:02:56,930
we can actually automatically just add in the superclass' call. This,

48
00:02:56,990 --> 00:03:00,010
of course, you could just type it out and it's good for practice,

49
00:03:00,340 --> 00:03:03,280
but in case you're ever wondering if you get these warnings,

50
00:03:03,490 --> 00:03:06,850
you can always take a look at what PyCharm is recommending.

51
00:03:07,660 --> 00:03:12,660
Now we've actually created our food class and we've inherited from the turtle

52
00:03:12,700 --> 00:03:13,533
class.

53
00:03:13,690 --> 00:03:18,580
What that means is we can now start using things that are from the turtle class.

54
00:03:19,360 --> 00:03:22,750
For example, I can straight up say self.shape,

55
00:03:22,960 --> 00:03:24,460
and it knows what shape is.

56
00:03:24,760 --> 00:03:29,470
This is a method that the turtle class has that I'm now going to modify in my

57
00:03:29,470 --> 00:03:33,070
food class. So when I initialize a new piece of food,

58
00:03:33,370 --> 00:03:36,160
I'm going to make sure that it has a circular shape,

59
00:03:36,820 --> 00:03:40,780
and I'm also going to get it to pen up so that it doesn't draw.

60
00:03:41,410 --> 00:03:44,020
And then I'm going to define it's size.

61
00:03:44,470 --> 00:03:47,290
And there's something called a shape size which I can use.

62
00:03:47,860 --> 00:03:52,860
And what this allows me to do is to stretch the turtle along its length and

63
00:03:52,990 --> 00:03:56,890
along its width. Now I'm not actually going to stretch it bigger than it is.

64
00:03:57,130 --> 00:03:59,350
It's normally 20 by 20 pixels,

65
00:03:59,680 --> 00:04:02,860
but I wanna turn it into 10 by 10 pixels.

66
00:04:03,340 --> 00:04:06,160
So I'm going to stretch the length by 0.5,

67
00:04:06,160 --> 00:04:07,780
so I'm basically going to half it.

68
00:04:08,200 --> 00:04:11,260
And then I'm going to stretch the width also by 0.5.

69
00:04:11,740 --> 00:04:15,400
So now it should be a 10 by 10 circle

70
00:04:15,700 --> 00:04:19,240
which I've created by defining the shape size. Now,

71
00:04:19,269 --> 00:04:21,490
remember all of these methods, shape, size,

72
00:04:21,490 --> 00:04:26,380
pen up, shape, comes from this turtle superclass and we're only able to use it

73
00:04:26,650 --> 00:04:31,650
because we're inheriting from the superclass so that our food class is now also

74
00:04:32,980 --> 00:04:37,780
sort of a turtle, but it's more like a souped-up turtle. Finally,

75
00:04:37,780 --> 00:04:41,740
it let's go ahead and define the color which I'm going to set as blue,

76
00:04:42,070 --> 00:04:44,620
but of course, feel free to set it as anything you like.

77
00:04:45,190 --> 00:04:50,190
And I'm also going to set the speed of my turtle to fastest. This way

78
00:04:51,310 --> 00:04:55,720
I don't have to look at the animation of the food being created at the center of

79
00:04:55,720 --> 00:04:58,840
the screen, and then moving to the location that I want it to.

80
00:04:59,560 --> 00:05:03,580
Speaking of moving, we're going to need to use the goto to get it

81
00:05:03,580 --> 00:05:06,790
to go to a random X, Y location.

82
00:05:07,150 --> 00:05:11,950
So let's import the random module and let's create a random X,

83
00:05:13,420 --> 00:05:18,420
which is going to be random.randint. Remember that our screen is 600 by 600

84
00:05:20,500 --> 00:05:24,820
so that means our X-axis goes from -300 to +300

85
00:05:25,090 --> 00:05:29,560
and our Y-axis goes from +300 to -300.

86
00:05:30,010 --> 00:05:33,430
Now we don't want our food to be right at the edge of the screen,

87
00:05:33,430 --> 00:05:37,450
cause it will be really hard to get the snake to go to right at the edge.

88
00:05:37,480 --> 00:05:39,430
It'll probably just die on the wall.

89
00:05:39,850 --> 00:05:42,100
So we want to maybe subtract this a little bit.

90
00:05:42,100 --> 00:05:47,100
So we can go from -280 to +280 and the same on the Y-axis.

91
00:05:47,950 --> 00:05:52,950
So let's generate a random integer from -280 to +280

92
00:05:54,340 --> 00:05:59,330
and let's generate a random Y-integer in the same range.

93
00:05:59,780 --> 00:06:04,780
So now we can tell our food to go to a random X and a random Y. All of this

94
00:06:07,100 --> 00:06:08,180
is going to happen

95
00:06:08,240 --> 00:06:12,590
as soon as we create a new food object from the food class.

96
00:06:12,860 --> 00:06:16,760
Remember, whenever you initialize a new object from the class, the

97
00:06:16,760 --> 00:06:20,420
init gets called. Back in our main.py

98
00:06:20,600 --> 00:06:25,280
right below where we initialized our snake, we're going to initialize our food.

99
00:06:25,490 --> 00:06:29,750
So food equals the food class and then parentheses.

100
00:06:30,290 --> 00:06:35,290
And of course we need to get hold of our Food class from the food file,

101
00:06:36,800 --> 00:06:37,633
like this.

102
00:06:38,270 --> 00:06:42,530
Another thing you'll notice is that this turtle is now grayed out because we're

103
00:06:42,530 --> 00:06:47,360
not using that class anywhere inside the main.py. So we can delete that

104
00:06:47,390 --> 00:06:49,880
which gets rid of all our warnings on this page

105
00:06:50,030 --> 00:06:54,170
and we get the green checkmark. Our food.py looks good,

106
00:06:54,320 --> 00:06:56,330
our snake.py looks good,

107
00:06:56,720 --> 00:07:00,020
and we're now ready to go ahead and run this code.

108
00:07:00,800 --> 00:07:04,760
Notice how we've got our snake moving around on screen.

109
00:07:05,000 --> 00:07:08,030
And at this point it doesn't really matter about the walls.

110
00:07:08,030 --> 00:07:11,630
It's just moving around anywhere it likes. But more importantly,

111
00:07:11,690 --> 00:07:16,580
we've got our food being randomly generated on the screen right here.

112
00:07:17,270 --> 00:07:22,270
Now the next step is how can we detect when the snake and the food have come

113
00:07:22,910 --> 00:07:27,500
into contact and then to tell the food to move itself to a new

114
00:07:27,530 --> 00:07:32,150
random location? Well, we're going to do that inside our main.py.

115
00:07:32,360 --> 00:07:36,920
Right after we've got our screen updating, our snake moving,

116
00:07:36,980 --> 00:07:38,630
then we're going to detect

117
00:07:40,310 --> 00:07:42,410
collision with food.

118
00:07:43,070 --> 00:07:47,600
And we're going to do that by using a method from the turtle class called 

119
00:07:47,630 --> 00:07:48,463
distance.

120
00:07:48,860 --> 00:07:53,860
The distance method works by comparing the distance from this turtle to whatever

121
00:07:55,160 --> 00:07:57,890
it is that you put inside the parentheses.

122
00:07:58,310 --> 00:08:02,720
So the X could be a pair of numbers, X and Y,

123
00:08:03,140 --> 00:08:06,200
or it could simply just be a turtle instance.

124
00:08:06,500 --> 00:08:10,190
So you're comparing this turtle against another turtle,

125
00:08:10,340 --> 00:08:13,670
and you're trying to get hold of the distance between the two turtles.

126
00:08:14,150 --> 00:08:19,150
So what that means is we can check to see if the distance from the first segment

127
00:08:20,990 --> 00:08:21,823
of the snake,

128
00:08:21,980 --> 00:08:26,960
so it remember that would be snake.head.distance,

129
00:08:27,920 --> 00:08:31,850
and then the distance that we want to know is what is the distance from the

130
00:08:31,850 --> 00:08:35,809
snake's head to the food. At this point,

131
00:08:35,809 --> 00:08:39,289
you can check to see if it is less than a certain amount,

132
00:08:39,590 --> 00:08:44,590
then it's pretty likely that the snake head is now colliding with the food.

133
00:08:45,200 --> 00:08:48,260
So we know that the food is 10 by 10.

134
00:08:48,530 --> 00:08:51,260
So if we add a bit of a buffer, let's just say,

135
00:08:51,440 --> 00:08:56,440
if this snake head is within 15 pixels of the food or even closer,

136
00:08:57,060 --> 00:08:59,790
so if the distance is less than 15,

137
00:09:00,030 --> 00:09:02,760
then we can be pretty much certain that they've collided.

138
00:09:03,090 --> 00:09:06,990
So let's go ahead and print something. I'll just write nom nom nom.

139
00:09:07,440 --> 00:09:12,440
So if we go ahead and run our code and let's just get our snake back into view,

140
00:09:14,160 --> 00:09:18,900
and if I now go and touch this piece of food, if I can,

141
00:09:19,650 --> 00:09:22,890
then you can see nom nom nom being printed in the console.

142
00:09:23,280 --> 00:09:25,830
Now let's go ahead and touch it again. You can see,

143
00:09:25,830 --> 00:09:28,410
as soon as I collide with that food,

144
00:09:28,680 --> 00:09:31,860
I get that print statement executing.

145
00:09:33,630 --> 00:09:36,990
So now, instead of just writing nom nom nom,

146
00:09:37,380 --> 00:09:39,210
let's figure out what we need to do next.

147
00:09:39,240 --> 00:09:44,240
What we want to happen is the food should go to a new random location.

148
00:09:45,390 --> 00:09:48,690
And, of course, that comes from this part of the code.

149
00:09:49,200 --> 00:09:54,200
So why don't we go ahead and create a new method which we'll call refresh.

150
00:09:54,960 --> 00:09:59,960
And this refresh method is going to create a new random X,

151
00:10:00,030 --> 00:10:04,950
a new random Y, and then get the food to go to that new, random location.

152
00:10:05,730 --> 00:10:10,680
Then inside our init, we can simply just call self.refresh.

153
00:10:11,400 --> 00:10:15,420
So be careful that you didn't right reset because that's one of the methods from

154
00:10:15,480 --> 00:10:17,850
the turtle class that we're inheriting from.

155
00:10:18,150 --> 00:10:22,830
But what we actually want is to call this refresh method so that the food goes

156
00:10:22,830 --> 00:10:27,300
to a new random location. And then back inside our main.py,

157
00:10:27,720 --> 00:10:30,360
when the snake head collides with the food,

158
00:10:30,660 --> 00:10:35,130
then we're going to get the food to refresh its own location.

159
00:10:35,610 --> 00:10:39,780
So check this out. Now, when I hit the food,

160
00:10:41,400 --> 00:10:44,820
then you can see the food now appears at a new,

161
00:10:44,880 --> 00:10:48,870
random location. Like that. Now,

162
00:10:48,900 --> 00:10:53,340
depending on how accurate you want the snake to hit the food,

163
00:10:53,730 --> 00:10:55,860
so it might need to hit it dead on,

164
00:10:56,100 --> 00:11:01,100
or if you're happy with it just gliding past and counting that as a collision,

165
00:11:01,440 --> 00:11:06,180
then you could decrease the number here from 15 to 10.

166
00:11:06,540 --> 00:11:11,520
Now I've done a bit of testing and this number seems to be the best distance in

167
00:11:11,520 --> 00:11:13,230
order to get a valid collision,

168
00:11:13,560 --> 00:11:18,060
but feel free to tweak around with the number and see how it goes. There we go.

169
00:11:18,060 --> 00:11:22,110
We've managed to figure out how to create a piece of food by inheriting from the

170
00:11:22,110 --> 00:11:25,620
turtle class, get the food to be generated,

171
00:11:25,830 --> 00:11:28,650
and then to move to a new random location

172
00:11:29,070 --> 00:11:31,650
every time the snake head collides with the food.

173
00:11:32,250 --> 00:11:33,870
Now I know that in the snake game,

174
00:11:33,930 --> 00:11:38,460
the snake segments increase once it hits a piece of food,

175
00:11:38,790 --> 00:11:43,230
but we're only going to add that functionality at the very end of this project

176
00:11:43,530 --> 00:11:46,080
when we're detecting collision with the snake tail.

177
00:11:46,230 --> 00:11:47,910
So don't worry about that for now.

