1
00:00:06,320 --> 00:00:07,991
Hi.
Welcome to this new video.

2
00:00:07,991 --> 00:00:12,597
We're going to continue working
on our ecosystem simulation.

3
00:00:12,597 --> 00:00:16,145
In this second video, we're going to
be writing the herbivore class,

4
00:00:16,145 --> 00:00:18,214
which is going to be an entity, an agent.

5
00:00:18,214 --> 00:00:23,301
Let's think of it as an animal that
would potentially eat the food,

6
00:00:23,301 --> 00:00:26,335
and it would create kind of a symbiosis or

7
00:00:26,335 --> 00:00:31,404
a relationship between the food supply and
its population.

8
00:00:31,404 --> 00:00:35,322
So let's think of it
the herbivore represents

9
00:00:35,322 --> 00:00:40,196
a plant-eating organism
differently than a particle.

10
00:00:40,196 --> 00:00:42,612
It would actually have its own
internal logic of movement.

11
00:00:42,612 --> 00:00:45,964
And in further videos, we're going to be
looking at the brain of the herbivore.

12
00:00:45,964 --> 00:00:50,774
But right now, we really want to create
this entity in the world and have it move

13
00:00:50,774 --> 00:00:56,312
around a little bit, and gradually, we'll
build up some complexity to it, right?

14
00:00:56,312 --> 00:00:58,944
So let's think of this class.

15
00:00:58,944 --> 00:01:02,236
Similar to a particle,
it would have a position, but

16
00:01:02,236 --> 00:01:06,920
it would have specific variables of
internal regulations, for instance,

17
00:01:06,920 --> 00:01:11,895
a hunger level or a lifespan, and then
functions like seeking food and eating and

18
00:01:11,895 --> 00:01:14,744
wandering around and things like that.

19
00:01:14,744 --> 00:01:18,776
So with this in mind, let's start
writing that herbivore simulation.

20
00:01:18,776 --> 00:01:23,684
So I'm going to continue where
we left off in processing.

21
00:01:23,684 --> 00:01:26,275
So this,
as we have done in previous weeks,

22
00:01:26,275 --> 00:01:30,548
we are kind of building on top of what
we've done in the previous video.

23
00:01:30,548 --> 00:01:33,388
So by all means, start from video one.

24
00:01:33,388 --> 00:01:37,694
I'm going to go into this new tab here and
type herbivore.

25
00:01:41,707 --> 00:01:48,087
And let's write, So import random,

26
00:01:48,087 --> 00:01:52,575
as we do class Herbivore, and

27
00:01:52,575 --> 00:01:57,609
let's define the constructor.

28
00:02:02,144 --> 00:02:07,520
Let's only require the position
to start with, right?

29
00:02:07,520 --> 00:02:12,463
So, Position equals position.

30
00:02:13,643 --> 00:02:16,923
So we have the position.

31
00:02:16,923 --> 00:02:19,015
Let's also create a velocity,

32
00:02:19,015 --> 00:02:23,043
because we do want this entity
to have some locomotion.

33
00:02:23,043 --> 00:02:27,363
I'm not going to add an acceleration
as we've done with the particles.

34
00:02:30,043 --> 00:02:34,843
And we could say for
now, it could be random.

35
00:02:34,843 --> 00:02:39,374
So let's do something like random,
the uniform.

36
00:02:41,074 --> 00:02:45,583
So from (-1,1).

37
00:02:50,095 --> 00:02:55,860
To, let's just copy that
to save a bit of time.

38
00:02:55,860 --> 00:02:57,416
So that's going to be a random velocity.

39
00:02:57,416 --> 00:03:01,490
So every kind of herbivore that we
create is going to start with a random

40
00:03:01,490 --> 00:03:02,530
orientation.

41
00:03:02,530 --> 00:03:10,192
Velocity would dictate, it's going to
be like it's looking at vector, right?

42
00:03:10,192 --> 00:03:12,922
The orientation of the velocity
is going to determine

43
00:03:12,922 --> 00:03:17,474
the direction in which this herbivore is
looking at, so at some directionality.

44
00:03:17,474 --> 00:03:20,730
So let's do a run function
as we have been doing a run.

45
00:03:20,730 --> 00:03:28,447
It's going to be our outline of the other
functions that we're going to be doing.

46
00:03:28,447 --> 00:03:32,764
So let's write a move function and
display.

47
00:03:36,059 --> 00:03:39,524
Actually, I'm going to comment this
out because we don't have them yet.

48
00:03:39,524 --> 00:03:46,851
So we could start just with the display.

49
00:03:49,896 --> 00:03:55,300
Right, and the display,
let's just do something simple.

50
00:03:56,707 --> 00:03:58,779
As an ellipse, right?

51
00:04:03,834 --> 00:04:08,023
Just going to create some corner here.

52
00:04:11,794 --> 00:04:14,614
And when we draw the ellipse,
we're going to use our position.

53
00:04:16,874 --> 00:04:20,996
So everything that I'm doing here, I'm
not going in too much detail because we

54
00:04:20,996 --> 00:04:25,254
are kind of repeating something that
we've done several times already, right?

55
00:04:27,894 --> 00:04:32,294
So we have a very simple class that
has a position and a velocity.

56
00:04:32,294 --> 00:04:35,400
It displays itself in the screen.

57
00:04:35,400 --> 00:04:37,078
And that's it so far.

58
00:04:37,078 --> 00:04:42,910
So let's add this to the world, right,
as we've done with the food system.

59
00:04:42,910 --> 00:04:48,140
Remember, like we actually
have in our world,

60
00:04:48,140 --> 00:04:52,350
we have a way of creating food items.

61
00:04:52,350 --> 00:04:55,684
So let's just also,

62
00:04:55,684 --> 00:05:01,624
from herbivore, import herbivore.

63
00:05:04,884 --> 00:05:06,284
Let's just spell that, right?

64
00:05:06,284 --> 00:05:12,852
Because we're going to get errors if
we don't, herbivore and herbivore.

65
00:05:12,852 --> 00:05:17,742
So we want to create in the world,
let's create

66
00:05:17,742 --> 00:05:22,524
a collection called self
dot all herbivores.

67
00:05:25,384 --> 00:05:28,050
And that's going to be an empty list,
right?

68
00:05:30,544 --> 00:05:35,364
And now what we could do is actually
just copy paste this function, right?

69
00:05:36,504 --> 00:05:43,440
And this function,
currently it's for creating food.

70
00:05:43,440 --> 00:05:45,507
We're going to call it create_herbivore.

71
00:05:50,724 --> 00:05:53,721
Right, and if we go with a similar idea,

72
00:05:53,721 --> 00:05:58,584
we're going to artificially create
new herbivores in the system.

73
00:05:59,844 --> 00:06:01,676
So here we need to change this.

74
00:06:01,676 --> 00:06:03,995
Instead of saying new_food,
we're going to say new_herbivore.

75
00:06:06,724 --> 00:06:10,465
And we're going to use
the Herbivore class,

76
00:06:11,983 --> 00:06:14,488
Which only requires a position, right?

77
00:06:14,488 --> 00:06:18,224
So I'm kind of adapting
the constructor here.

78
00:06:18,224 --> 00:06:20,776
We are providing a random
position in the world.

79
00:06:20,776 --> 00:06:27,200
Maybe instead of doing it, yeah,
let's just keep it as it is.

80
00:06:27,200 --> 00:06:28,400
Random is fine, right?

81
00:06:28,400 --> 00:06:32,336
We could decide that our herbivore
is going to be placed in the center.

82
00:06:32,336 --> 00:06:37,503
But this is kind of a placeholder
function because we don't have

83
00:06:37,503 --> 00:06:43,818
a reproduction system for herbivores or
plants to kind of spawn each other.

84
00:06:43,818 --> 00:06:45,706
We're actually just introducing them.

85
00:06:45,706 --> 00:06:47,480
So this is kind of a little bit fake,

86
00:06:47,480 --> 00:06:50,754
a way of introducing some
entities into the system.

87
00:06:50,754 --> 00:06:56,157
And here, finally, we have to also
append our herbivores to the herbivore

88
00:06:56,157 --> 00:07:01,047
collection and making sure that
the object that we're passing in to

89
00:07:01,047 --> 00:07:06,364
append is actually the herbivore
that we just created here, right?

90
00:07:06,364 --> 00:07:09,727
So basically replicating the same
function, but in this case, for

91
00:07:09,727 --> 00:07:13,812
herbivores, you could potentially just
do maybe one function out of these two.

92
00:07:13,812 --> 00:07:18,403
But we're just going to go with a simpler
version of just copy pasting those two as

93
00:07:18,403 --> 00:07:19,944
different ones, right?

94
00:07:21,804 --> 00:07:25,896
So we also want to
create the run_herbivore

95
00:07:25,896 --> 00:07:30,660
function that will be called every frame,
right?

96
00:07:30,660 --> 00:07:32,590
So you can copy this.

97
00:07:36,834 --> 00:07:38,780
And we're going to say let's loop.

98
00:07:41,434 --> 00:07:43,169
So run_herbivore.

99
00:07:48,474 --> 00:07:53,594
And let's just loop
through all herbivores.

100
00:07:53,594 --> 00:07:54,778
Let's call them h.

101
00:07:54,778 --> 00:08:00,379
So for entity h in the herbivore
on the all herbivore list,

102
00:08:00,379 --> 00:08:03,935
let's run that herbivore, right?

103
00:08:03,935 --> 00:08:08,795
And now that we have this,
basically we're repeating exactly the same

104
00:08:08,795 --> 00:08:14,564
thing that we've done with the food,
right, self.run all herbivores.

105
00:08:14,564 --> 00:08:16,124
There we go, right?

106
00:08:16,124 --> 00:08:21,216
So at this point,
we should have a new entity in our

107
00:08:21,216 --> 00:08:26,484
system that grows that
appears at a certain rate.

108
00:08:26,484 --> 00:08:30,313
We are not calling that entity yet,

109
00:08:30,313 --> 00:08:34,914
actually, let's just look at how we are.

110
00:08:36,334 --> 00:08:42,022
So here, we are running the herbivores,
we have to create as well, right?

111
00:08:42,022 --> 00:08:46,369
So let's just do make sure that we're
calling the create_herbivores function,

112
00:08:46,369 --> 00:08:49,478
otherwise, we're not going to
get any of them in the world.

113
00:08:49,478 --> 00:08:52,174
So self.create_herbivore.

114
00:08:52,174 --> 00:08:58,811
And here,
let's just do herbivores at a slower rate.

115
00:08:58,811 --> 00:09:03,114
This is arbitrary because these are kind
of placeholder functions, right?

116
00:09:03,114 --> 00:09:07,404
So let's see if we're running
into any errors at this point.

117
00:09:09,754 --> 00:09:12,060
So we see the plants appearing.

118
00:09:15,994 --> 00:09:21,303
I think let's just make the color
of the herbivores a little

119
00:09:21,303 --> 00:09:28,647
bit more prominent because we might not be
seeing them in the screen very clearly.

120
00:09:28,647 --> 00:09:33,794
So I'm going to make them,
Red for now, right?

121
00:09:33,794 --> 00:09:38,094
We can revisit the display of them.

122
00:09:39,794 --> 00:09:40,490
So there we go.

123
00:09:40,490 --> 00:09:43,254
And that's herbivore entity, right?

124
00:09:45,154 --> 00:09:46,754
That's all good.

125
00:09:46,754 --> 00:09:54,184
The size, I want to make them
slightly bigger than the food,

126
00:09:54,184 --> 00:09:59,426
but I also would like
to add a little bit of,

127
00:09:59,426 --> 00:10:07,452
you know, what we've done already
with the forces in the world.

128
00:10:07,452 --> 00:10:11,293
I'm going to repeat the code
that we have used for

129
00:10:11,293 --> 00:10:17,413
drawing an arrow because I want to just
give some clarity to the direction.

130
00:10:20,114 --> 00:10:24,596
So I'm going to pushMatrix, popMatrix.

131
00:10:26,135 --> 00:10:34,622
Right, and here, we're going to
do a line that goes from 0,0,

132
00:10:34,622 --> 00:10:42,214
let's call a variable arrow_size,
0, right?

133
00:10:42,214 --> 00:10:45,428
Let's just create a little
bit more space to work here.

134
00:10:45,428 --> 00:10:46,557
Let's create a variable.

135
00:10:46,557 --> 00:10:50,014
If we just use,
variable doesn't exist yet.

136
00:10:50,014 --> 00:10:53,634
Let's make sure we create that,
so arrow_size is going to be 10.

137
00:10:56,174 --> 00:11:02,055
And we covered how to do
this drawing of an arrow.

138
00:11:02,055 --> 00:11:07,197
In all honesty, we should have done
it as a function and then copy paste

139
00:11:07,197 --> 00:11:13,311
the function from our previous scripts
here, which, again, code reusability.

140
00:11:13,311 --> 00:11:14,891
We're going to do this zero.

141
00:11:18,194 --> 00:11:23,347
And this little series of numbers help

142
00:11:23,347 --> 00:11:28,018
us construct a straight line, but

143
00:11:28,018 --> 00:11:32,849
also two kind of diagonal lines that

144
00:11:32,849 --> 00:11:37,694
go back from the front of the arrow.

145
00:11:38,794 --> 00:11:41,554
So that's fine.

146
00:11:41,554 --> 00:11:44,752
In this pushMatrix kind of space,

147
00:11:44,752 --> 00:11:49,287
we need to translate
using the self.position.

148
00:11:54,594 --> 00:11:58,362
Right, and then the only thing
that we're missing is the angle,

149
00:11:58,362 --> 00:12:00,050
the orientation, right?

150
00:12:00,050 --> 00:12:05,088
So if you remember from the vector
field tutorial for doing that,

151
00:12:05,088 --> 00:12:10,564
we actually wrote a function
which is called get_angle.

152
00:12:10,564 --> 00:12:16,766
And get_angle, it takes a vector,
so which is going to be,

153
00:12:16,766 --> 00:12:21,070
in this case, the velocity vector, and

154
00:12:21,070 --> 00:12:26,564
it's going to return the equation,
the atan2.

155
00:12:26,564 --> 00:12:32,474
So the math equation that we
need to calculate the angle

156
00:12:32,474 --> 00:12:38,190
in radians from the velocity vector or
any vector.

157
00:12:38,190 --> 00:12:41,914
So it's a very handy function to have,
so get_angle.

158
00:12:43,014 --> 00:12:45,854
And we could have copy paste
that from another script,

159
00:12:45,854 --> 00:12:50,150
but I'm trying not to copy paste content
that comes from outside into our script.

160
00:12:50,150 --> 00:12:53,070
So we're just writing that here as we go,
right?

161
00:12:53,070 --> 00:12:59,332
So now we have that, we could say angle
get_angle, or basically self.get_angle.

162
00:12:59,332 --> 00:13:07,131
I keep forgetting the self part
of writing code here in Python.

163
00:13:09,058 --> 00:13:10,530
Self.velocity, right?

164
00:13:10,530 --> 00:13:14,912
So we're going to be getting
the angle of the velocity, and

165
00:13:14,912 --> 00:13:19,092
with that,
we could say rotate(angle), right?

166
00:13:19,092 --> 00:13:25,786
So if this is not having any errors,
then hopefully we would be able to see,

167
00:13:25,786 --> 00:13:30,678
not only the red representation
of the herbivore, but

168
00:13:30,678 --> 00:13:35,648
also an arrow that would
dictate off the orientation.

169
00:13:35,648 --> 00:13:38,728
And as we can see, this is working.

170
00:13:38,728 --> 00:13:40,704
It's a little bit small.

171
00:13:40,704 --> 00:13:45,680
If you see it that it's a bit small,
we could say arrow_size, let's do with 20.

172
00:13:49,064 --> 00:13:53,800
You could also give that size to
the magnitude of speed of that velocity.

173
00:13:53,800 --> 00:13:58,461
That would be more representative
of maybe the speed of motion,

174
00:13:58,461 --> 00:14:02,103
if that's something that you want to see,
right?

175
00:14:02,103 --> 00:14:04,560
But again,
we're just setting up the world.

176
00:14:04,560 --> 00:14:09,352
We have our food decaying and we have our
herbivores with their orientation set at

177
00:14:09,352 --> 00:14:14,200
random, and already a world where these
kind of two populations are growing.

178
00:14:14,200 --> 00:14:18,511
So we're going to see how we can start
building some behaviors in between them

179
00:14:18,511 --> 00:14:23,021
and then kind of a symbiotic relationship
that would manage the total amount of,

180
00:14:23,021 --> 00:14:26,884
yeah, the total amount of entities
that exist within this world.

181
00:14:26,884 --> 00:14:27,844
So I'll see you in the next video.