Hi. Welcome to this new video. We're going to continue working on our ecosystem simulation. In this second video, we're going to be writing the herbivore class, which is going to be an entity, an agent. Let's think of it as an animal that would potentially eat the food, and it would create kind of a symbiosis or a relationship between the food supply and its population. So let's think of it the herbivore represents a plant-eating organism differently than a particle. It would actually have its own internal logic of movement. And in further videos, we're going to be looking at the brain of the herbivore. But right now, we really want to create this entity in the world and have it move around a little bit, and gradually, we'll build up some complexity to it, right? So let's think of this class. Similar to a particle, it would have a position, but it would have specific variables of internal regulations, for instance, a hunger level or a lifespan, and then functions like seeking food and eating and wandering around and things like that. So with this in mind, let's start writing that herbivore simulation. So I'm going to continue where we left off in processing. So this, as we have done in previous weeks, we are kind of building on top of what we've done in the previous video. So by all means, start from video one. I'm going to go into this new tab here and type herbivore. And let's write, So import random, as we do class Herbivore, and let's define the constructor. Let's only require the position to start with, right? So, Position equals position. So we have the position. Let's also create a velocity, because we do want this entity to have some locomotion. I'm not going to add an acceleration as we've done with the particles. And we could say for now, it could be random. So let's do something like random, the uniform. So from (-1,1). To, let's just copy that to save a bit of time. So that's going to be a random velocity. So every kind of herbivore that we create is going to start with a random orientation. Velocity would dictate, it's going to be like it's looking at vector, right? The orientation of the velocity is going to determine the direction in which this herbivore is looking at, so at some directionality. So let's do a run function as we have been doing a run. It's going to be our outline of the other functions that we're going to be doing. So let's write a move function and display. Actually, I'm going to comment this out because we don't have them yet. So we could start just with the display. Right, and the display, let's just do something simple. As an ellipse, right? Just going to create some corner here. And when we draw the ellipse, we're going to use our position. So everything that I'm doing here, I'm not going in too much detail because we are kind of repeating something that we've done several times already, right? So we have a very simple class that has a position and a velocity. It displays itself in the screen. And that's it so far. So let's add this to the world, right, as we've done with the food system. Remember, like we actually have in our world, we have a way of creating food items. So let's just also, from herbivore, import herbivore. Let's just spell that, right? Because we're going to get errors if we don't, herbivore and herbivore. So we want to create in the world, let's create a collection called self dot all herbivores. And that's going to be an empty list, right? And now what we could do is actually just copy paste this function, right? And this function, currently it's for creating food. We're going to call it create_herbivore. Right, and if we go with a similar idea, we're going to artificially create new herbivores in the system. So here we need to change this. Instead of saying new_food, we're going to say new_herbivore. And we're going to use the Herbivore class, Which only requires a position, right? So I'm kind of adapting the constructor here. We are providing a random position in the world. Maybe instead of doing it, yeah, let's just keep it as it is. Random is fine, right? We could decide that our herbivore is going to be placed in the center. But this is kind of a placeholder function because we don't have a reproduction system for herbivores or plants to kind of spawn each other. We're actually just introducing them. So this is kind of a little bit fake, a way of introducing some entities into the system. And here, finally, we have to also append our herbivores to the herbivore collection and making sure that the object that we're passing in to append is actually the herbivore that we just created here, right? So basically replicating the same function, but in this case, for herbivores, you could potentially just do maybe one function out of these two. But we're just going to go with a simpler version of just copy pasting those two as different ones, right? So we also want to create the run_herbivore function that will be called every frame, right? So you can copy this. And we're going to say let's loop. So run_herbivore. And let's just loop through all herbivores. Let's call them h. So for entity h in the herbivore on the all herbivore list, let's run that herbivore, right? And now that we have this, basically we're repeating exactly the same thing that we've done with the food, right, self.run all herbivores. There we go, right? So at this point, we should have a new entity in our system that grows that appears at a certain rate. We are not calling that entity yet, actually, let's just look at how we are. So here, we are running the herbivores, we have to create as well, right? So let's just do make sure that we're calling the create_herbivores function, otherwise, we're not going to get any of them in the world. So self.create_herbivore. And here, let's just do herbivores at a slower rate. This is arbitrary because these are kind of placeholder functions, right? So let's see if we're running into any errors at this point. So we see the plants appearing. I think let's just make the color of the herbivores a little bit more prominent because we might not be seeing them in the screen very clearly. So I'm going to make them, Red for now, right? We can revisit the display of them. So there we go. And that's herbivore entity, right? That's all good. The size, I want to make them slightly bigger than the food, but I also would like to add a little bit of, you know, what we've done already with the forces in the world. I'm going to repeat the code that we have used for drawing an arrow because I want to just give some clarity to the direction. So I'm going to pushMatrix, popMatrix. Right, and here, we're going to do a line that goes from 0,0, let's call a variable arrow_size, 0, right? Let's just create a little bit more space to work here. Let's create a variable. If we just use, variable doesn't exist yet. Let's make sure we create that, so arrow_size is going to be 10. And we covered how to do this drawing of an arrow. In all honesty, we should have done it as a function and then copy paste the function from our previous scripts here, which, again, code reusability. We're going to do this zero. And this little series of numbers help us construct a straight line, but also two kind of diagonal lines that go back from the front of the arrow. So that's fine. In this pushMatrix kind of space, we need to translate using the self.position. Right, and then the only thing that we're missing is the angle, the orientation, right? So if you remember from the vector field tutorial for doing that, we actually wrote a function which is called get_angle. And get_angle, it takes a vector, so which is going to be, in this case, the velocity vector, and it's going to return the equation, the atan2. So the math equation that we need to calculate the angle in radians from the velocity vector or any vector. So it's a very handy function to have, so get_angle. And we could have copy paste that from another script, but I'm trying not to copy paste content that comes from outside into our script. So we're just writing that here as we go, right? So now we have that, we could say angle get_angle, or basically self.get_angle. I keep forgetting the self part of writing code here in Python. Self.velocity, right? So we're going to be getting the angle of the velocity, and with that, we could say rotate(angle), right? So if this is not having any errors, then hopefully we would be able to see, not only the red representation of the herbivore, but also an arrow that would dictate off the orientation. And as we can see, this is working. It's a little bit small. If you see it that it's a bit small, we could say arrow_size, let's do with 20. You could also give that size to the magnitude of speed of that velocity. That would be more representative of maybe the speed of motion, if that's something that you want to see, right? But again, we're just setting up the world. We have our food decaying and we have our herbivores with their orientation set at random, and already a world where these kind of two populations are growing. So we're going to see how we can start building some behaviors in between them and then kind of a symbiotic relationship that would manage the total amount of, yeah, the total amount of entities that exist within this world. So I'll see you in the next video.