How Angry Birds Uses Physics: A Look at Box2D in Game Development

This lecture explores the physics behind Angry Birds, focusing on the Box2D library used for realistic collisions, gravity, and material interactions. It covers dynamic, static, and kinematic bodies, fixtures, and collision callbacks, with practical examples in Lua and Love2D.

English Transcript:

Hello world, this is CS 52D lecture 6. Today we're going to take a break away from the older NES titles, even as pleasant and nostalgic as they are for me, and we're going to venture back towards more modern mobile oriented games in particular, which what we looked at with Match 3 previously, Candy Crush being a good example of that, and Angry Birds is an example of another franchise that is very popular. This is an example from one of the mainline titles, Angry Birds 1 or 2. Originally it wasn't quite as large as this. This looks like it was probably done on a tablet thereabout, but it encompasses the overall gist of the game,

which is essentially that you're controlling the slingshot here, which you have a bunch of these angry birds, as the name of the game suggests, that are trying to get revenge on these pigs that have sort of started to build forces or whatnot to take over their territory. Not entirely sure of the exact lore behind the game, if any such exists, but the pigs are sort of blocked by these obstacles here made of various materials, wood, glass, ice. Me and you have varying types of birds that you can use to effect damage onto these structures and ultimately the pigs whereby if you do a certain, if you were able to take out the pigs with a certain number of birds or without, you know,

depleting a certain number of your limited birds, you can see here the person has 3 sort of pieces of ammunition in the form of birds left before they run out in that level you can accomplish getting higher scores for that level in the form of stars. Typically you can aim for 3 stars or you can get 2 or 1 depending on your performance. And there are many iterations of the franchise. This is another version which is set in a more tropical setting, and there's all kinds of different versions. There's a Star Wars one, and I'm not entirely sure how far the franchise has gone in recent days.

I know they even have TV shows and the like, very popular franchise, one of the first mobile series I ever played, really big fan on iOS, especially in the early days of the platform, and this allows us to really look at in a unique way physics that we haven't really looked at in games thus far where we've sort of done everything ourselves with, you know, simplistic. Overall physics calculations with velocity and manipulating positions directly and sort of approximating collisions and bouncing and whatnot, but Box 2D is this sort of library that love 2D embeds within it. Box 2D is the separate library that you can actually embed in any compiled framework or use in any situation that you want to.

It's just a set of code, a set of functions for modeling physical interactions. It's very popular and Love 2D exposes it as a set of these wrapper functions. That essentially defer to the underlying box 2D functions that you might normally expect to see in something like C or C++. And so today we'll be looking at box 2D as our main focus with a bunch of various underlying parts including bodies and fixtures and shapes and joints and things like that. And then we'll also be looking at because we're dealing with Angry Birds, which is a sort of mobile game that has this mouse or finger touch-based input in order to drag the bird on the slingshot and then release it and send the bird flying,

we'll look at for the first time this. Just clicking how to actually use mouse movement with X and Y and track key released and key pressed and so on and so forth. And so our goal is to approximate Angry Birds per the screenshot that we showed previously of those titles with a very simplistic version, but nonetheless we do see we have an alien creature here. We are using another canny sort of open source Creative Commons title set that allows us to use to accomplish the same thing but with a different aesthetic we're using a sort of aliens aesthetic is how they term it in the Sprite pack, I believe.

And so we have this sort of alien here, a circle which is our character, and then we have a square-based enemy alien there in the obstacles. Then we have of course these obstacles here that are protecting it very much in the same vein as we saw previously with the first slide. These obstacles will be able to be deleted by colliding with them and then they'll break, thereby exposing the alien on the right, which after a certain collision, or should the obstacle collide with the alien itself, the alien will be defeated, removed from the game world, and then we will therefore achieve victory in our play state. And so this being our goal, why don't we ask tradition,

take a look at an actual implementation of it and do a demo if we could get a volunteer that could maybe come up on the stage? Don't believe in that. Hi David. Ah nice to meet you. Thanks. OK, so let's go ahead and run this here. And we'll see we've got the window there because see we clicked the start for the first time maybe OK. I can drag. Oh, so it does detect, it does detect if you are gonna, uh, shoot the, the sort of bird slash alien to the left on this example, but as you can see, very nice, you're able to, uh, defeat the, uh,

it does detect collisions and then the boxes and whatnot will break if they hit your alien or there's a velocity calculation between the two objects that's past a certain threshold. So and then it restarts after a certain period of time. You can try again if you want. It was very quick. We can see there's sort of a randomization occurring too with the alien there nice so then that breaks the top part so then that won't end up fully defeating the alien this time but after a moment once the velocity sort of begins to get really slow, you'll notice that yeah that's just like the real one.

Here we go, how about a little lower this time? Very nice. And then you'll have another shot here. We're, we're very generous with this implementation where we give the user unlimited birds, but sometimes you might run out of birds at this point then the level you would sort of lose. Alright, well I think I should put an end to this game here we go. Very nice achieved victory. Excellent thanks for calling thanks so much.

And so We saw a great many pieces there that we haven't really looked at yet. Certainly it's very different than what we've done so far, although on the surface, you know, we might look at something like that and see, oh, OK, we're doing AABB in some form that we usually done. We haven't really dealt with circles as much, uh, so that part might be a little bit different, but overall we might, you know, presume that OK, the circle maybe is using its own rectangle and doing AABB in that way. But in fact, really there's not a whole lot. Of manual physics we have to do this time. Thankfully, Box 2D, as we will see shortly, is going to take care of a lot of these things for us and allow us to do very interesting physical things without having

to worry necessarily about so much of the underlying mathematics in detail. But to get started, I think it's important to point to our spreadsheet as is tradition as well, what we're actually going to work with. So we saw that we had a few different things. On the screen we have the ground which is ultimately just this repeated tile here and as we'll see we don't actually have a physical ground that we're modeling as much as we have an edge and then we're going to be drawing a bunch of ground underneath it, something that Box Studio lets us do. We have varying shapes and colors of aliens, circular and squares, circular to be our alien character, square to be the sort of enemies that we're going to be targeting. And then we have all these different

amazing tiles set for various types of obstacles that we could add to the game, and it is named as such in the distro. We're only using a couple of very simple examples, those being sort of these vertical blocks here, but you'll notice there are some sort of cracked version of these which will use will be expected to be used in. Problem set, which is currently as folks probably observed, the birds, the bird or the alien, if it were to collide with any of those wooden pieces, is going to just instantly destroy it and have that despawn from the game world. And what we really would probably want is different materials and for those materials

to have differing values for how much they can take damage wise and so. Part of the problem set will be OK, detect based on the hit, based on the material, if it's a lighter material like glass, maybe break it in one hit, but if it's wood, maybe have it take two hits and have the first hit trigger it into being some sort of this cracked variant herein and thankfully all of the tile sets that we'll be using of the different materials that are also included have all these for you. So some useful links for folks if they're digging into Box 2D will be the following all thankfully located, the first two located on Love 2D's actual documentation, a very handy blog with a lot of Box 2D information which I consulted and many folks point

to on the internet is this I iForce 2D.net blog which has a ton of really useful, deeply detailed articles on Box 2D and its mechanics and some of the algorithms you can use to do various things. But the very first thing we should begin to talk about with Box 2D is this idea of the world. And so box 2D is ultimately just a rigid body physics simulator of sorts where everything that exists in the world is this sort of rigid defined body, the sort of entity that takes a shape and can collide with other entities, and there are various coefficients and multipliers for various things. You can perform impulses on things and get angular.

Velocity and linear velocity for things and damping and so on and so forth and these things allow you to do all kinds of very complicated physics realistically modeled without having to necessarily know every single thing about the math to do it and so it empowers people to all beyond that also just create very interesting assortments of shapes that model physical sort of more complicated engineering projects that allow you to do very complicated things which we will. Only briefly allude to, but for example, you could get very creative and create things like cars and things like automated systems and pulleys and whatnot.

They do all sorts of really sophisticated things, but the place that we begin is the world and that's where the physics actually gets simulated. There's this overarching, and we've sort of thought about it in our own way with place dates and levels and dungeons and whatnot. You can think of the world as this box 2D container for all of your bodies in the world, which we'll look at in a moment. And the world's job is to just update periodically with you pass it in DT just like you would

pass in DT to update anything and it will actually take charge of performing all of the collision detection, including continuous collision detection for very fast moving things to make sure that they don't clip through each other depending on whether you've set certain bodies as dynamic, kinematic, or static. And so the function that you would use to create this new world would indeed be love.physics.neworld. You'd pass in gravity. Remember that we did have gravity in our own world with Mario, for example, in that it had a positive Y value that would apply to anything that was sort of in the world period,

and that would affect things moving downwards unless they hit the ground and then their velocity would be set to zero, for example, but you could jump and same with Flappy Bird and then have this positive Y. Value cumulatively affect your actual y axis value and therefore change your velocity and therefore change your movement over time. Box City takes care of that for you, but you pass that in at world time and you can set an X gravity and a Y gravity. And if you are doing a top down game, for example, you might not have either of those set to anything and you might instead

be doing everything without gravity but still performing physics calculations in some 2D plane, which is totally possible with box 2D. And so before we can, we'll we'll shortly start to look at some code examples, but the first thing we need to talk about is, well, we've alluded to, we have the world we know we have this simulator that's going to exist, that's going to perform all these calculations for us, all this physics that we don't necessarily have to worry about as much and at least in terms of the nitty gritty, but we do need to actually have things that can operate in this physical space.

The first step towards that is defining a body, and so what a body is essentially this abstract container that can hold these things called fixtures that apply shapes, and the body's job is to essentially take those physics calculations and then perform just basic mechanics without a shape, without any sort of idea of mass or any particular friction or anything. It's sort of this invisible thing that can have physics. To it almost like a particle, but it can be affixed to. It can have fixtures affixed to it that therefore influence its shape and therefore allow it to perform collisions with other entities.

And so the bodies are sort of like the nucleus behind all of the things that actually interact in your world. They are the things that you build pieces on top of fix things too to create behavior in your world space. And to do that, you'll again with a similar API you'll call love.physics.newbody which takes in the world itself so that the world has a reference to it, and then an X and a Y and then a type and the type is very important. So here we're going to transition to the next slide which we'll talk about the three different types of bodies, and this is essentially the core behind behavior besides efficient and applying forces and whatnot to your objects, but you can think of 3 different types of bodies as being static.

Dynamic and kinematic and so if a static body you can think of something that literally will just not have physics essentially applied to it. It's there it's statically there it's position is fixed. It doesn't do anything to anything else really. It can still affect things in the sense that it can be, uh, it can still have physics applied to it and things can bounce off of it, but it will itself not be affected by other objects. A and it cannot move. It is fixed. It will not change. A dynamic body will actually move and perform bounces off of things and affect other things, and it is by its nature a dynamic body in the world,

the opposite of a static body. A kinematic body is similar to a static body in that it can move around and influence behavior, but it does not get the usual behavior affected towards it. It cannot be influenced by other objects colliding with it. It isn't affected by gravity and so you might have something like a moving platform that is kinematic and actually affects other objects should they collide with it, but it itself is not being, for example, affected by gravity. It is not falling like a dynamic body would if you had a dynamic platform, it wouldn't really work, but it would fall to the ground because it would be affected by gravity or it could be affected by other objects. And lastly,

before we actually look at some code, we'll look at fixtures. Fixtures are you have a body, sure you can move it around, or you can, you can know that it will apply physics or not be applied physics to in your world, but on top of that you need to have some sort of shape. You need to have some sort of idea, OK, how, how much friction does this body have? How does it actually affect things before we can actually see something on the screen? How does it what does it look like?

What are its edges? And so to do that it needs to take a shape and to take a shape it needs this thing called a fixture. A fixture will essentially literally be you can envision a car which has sort of this nucleus and then you can imagine the chassis being the first fixture on the car and then having more fixtures for the wheels where now OK, you've got places where you can start to put wheels and you can start to envision this object being built up with shapes but you need places to actually put those shapes and that's what.

Fixtures allow you to do and therefore after you define a fixture you can then decide, OK, now I want to put these various kinds of shapes onto that object to give it form to allow it to actually collide with things in the way that a rectangle would or a circle would or so on and so forth, therefore allowing you to finally visualize what these physics operations are doing in your game world. So a lot of detail before we can actually get to some code, but now we'll take a look at some examples and we can see what this looks like in practice. So I'm transition over here and we're going to look very first at static. So we looked at, we talked about static bodies being sort of the simplest thing,

which is just the static thing that's not going to move. It's going to be fixed in space. It's not affected by gravity or anything like that. It's not affected by other objects and it can't move. It's just there in space. So if we look here, I'm going to run it. And we will indeed see we have this square being rendered right in the middle of the screen. It's a white, we're rendering it as just a white square. It's not doing anything. It's not really all that different really from the Pong paddle that we're the pong ball that we created in week zero, which is just a rectangle that's in the middle of space,

but the difference is that we are actually this is being rendered and done in box 2D in LuA era in love's physics system, Box 2D's physics system. So let's go ahead and look at what we're doing to accomplish this. And so you can see here we have a world which is being instantiated with no gravity on the X axis and a 300 pixel application of gravity on the Y axis and then if you were to look down here. And see that we and this would be this 300 would essentially be so love 2D's physics space has a 30 pixel per meter approximation for gravity and if you assume 9.8 m per 2nd, 9.8 times 30 is almost 300, so we just kind of round up to 300 to apply roughly Earth-like

gravity if we assume the 30 pixel per meter approach to gravity. And so here we can see and we'll use that relatively consistently throughout the rest of the examples, but this is that's a tunable parameter just like any else we have here the first instantiation of a body, so we're calling love.physics.newbody, which takes the world that we just find up here. We're gonna put it right in the center of the screen. Notice that we aren't shifting backwards by X or Y. Everything in Box 2D is relative to its center, unlike Love 2D's default, which everything is relative to its top left corner.

So there is a little bit of difference in how things should be rendered and how physics. Should be sort of looked at in box 2D versus the AABB stuff that we've looked at so far, but it's a relatively simple shift and if anything, it's simpler in a lot of ways thinking in terms of the center points of objects and notice that we are passing static as the string value to the end to tell love 2D that this box body should indeed just be some static thing that we have in our screen. Now we're going to create the shape first, so we're just going to say, OK, I want a rectangle shape which is going to be 10 by 10 pixels, and then I want a fixture that's going to apply the shape, the second parameter to the body relative to its center point,

meaning that now it's going to know. All physics calculations will be based on the sort of edges that take place within this rectangle, and it will know based on whatever shape that we pass to it if it's a circle, if it's some other shape, it knows how to actually calculate all of the physics, even if it's not as simple as ABB anymore to properly affect, especially when we get past static examples, things interacting and colliding in very interesting ways, which we'll see some examples of. You can see an update. We're just updating the world itself. It will defer all of the necessary physics calculations and then here, which is common if we're not rendering a circle, you could just render a circle for most circular

shapes and based on rotation it won't matter. Everything's fine. But in the case of love.graphics. rectangle, if you were to rotate that rectangle, then it won't quite work because love. rectangle doesn't quite work very easily with rotations, but instead if we just say, OK, we're going to render a polygon at that particular spot in the game space, we can do what's called box with this body get world points function. It expects its shape. It needs to know its shape and then it can based on its body and the shape, get you back. All of the XY pairs that will approximate well not approximate, all the XY pairs that will equal the polygon's shape for drawing to the world.

Love.graphics.polygon essentially can take any number of XY pairs, and it will create a polygon based on those vertices and connect all of them, so whatever shape you pass into it. It will just like it can take in a line or fill string just like love. graphics. rectangle, but unlike love.graphics. rectangle, it can take any number of vertices 345, however many and this will return all of the points for whatever that shape happens to be. And so you end up with the result that you get this square render. Right in the middle of the screen, nothing really fancy is happening.

We can't really tell that we're doing anything meaningfully different other than rendering a rectangle as before, but we're actually using a polygon rendering function instead, and we're doing it all based on getting love 2D, or rather box 2D's values for the body based on that body's shape that we gave to it. So that is the static example. Now, as we talked about, there are also dynamic bodies and kinematic bodies. So the next step will be, let's take a look at a dynamic body. So we saw what a static body is. Some folks might even be able to anticipate what the dynamic example is going to look like, but let's just run the dynamic example and we'll see indeed rather than the sort of static rectangle being fixed

to the middle of the screen and just there, the whole. Time not moving, not affected by gravity, we can now start to see the equivalent to when we started applying gravity and prior examples in our own games being applied and done for us by Love 2D's world, and it's really not all that different than just doing all the same code that we did previously. Only now we're passing in the string dynamic to the constructor for a new body. We're not calling static and then we get all of that functionality. All the gravity, everything for free, presuming that we define gravity as some positive value on the x axis here and you can manipulate these values to affect any

kind of gravitational effect that you want, we're going to presume and assume a sort of consistent feel for it based on Mario, based on Angry Birds and the like bypassing in 300 as our example there. So not all that different, very different behavior. Now what we can do recall that we have static and dynamic bodies, and then kinematic is the sort of different type of body and this is a common type of body used in a lot of games. Folks might be aware of many obstacles in games or things moving around that seem to affect other objects but themselves are sort of like defying the laws of physics and that's kind of when I think of a kinematic body that's sort of what I think of. In fact,

if you were to think about the paddles and pong for. For example, those are sort of these kinematic bodies that can have their positions directly affected but themselves are not affected by gravity. Meanwhile, the ball, for example, can sort of be affected by gravity in a sense, but it too can be modeled as a kinematic object if you were to think about it in a particular way like that. But it could be thought of as a dynamic or kinematic body. Paddles are based on the fact that they're very confined in a non-gravitation. sense to the y axis and are also hand controlled and not sort of moved by any sort of impulses or forces.

Those can be thought of as very classic textbook kinematic bodies. And so I came up with a fun little example here to illustrate what a kinematic body and a static and a dynamic body altogether might look like if we were to run this example in kinematic. We'll see that we get very funnily sort of the green ball falling to the bottom of the screen there. We've got this red line at the bottom of the screen, which is a static edge shaped body. Then we have on top or in the middle of the screen these three rotating rectangles, and we haven't even done rotational collision typically because it tends to be quite a bit more complicated than just AABB collision detection.

Not that it was working just fine. The game was detecting the rotation and which parts of the rectangles were affecting the green rectangle. The blue rectangles are affecting the green rectangle. The green rectangle here is dynamic. It fell down. It was affected by these kinematic bodies, and then it eventually fell to the bottom of the screen. It hit the red plane, and then it just came to a stop. It even had some sort of friction. You saw it slide at the very end there, another thing that box to us for free, but these blue.

Bodies in the middle of the screen, they're just statically there, at least in terms of their X and the Y, but they are rotating constantly. They're not falling. They're not affected by gravity, but they do have this effect onto the green body which is that they were able to sort of bounce it around and then make it fall to the bottom of the screen, and this, I think, illustrates the difference between what a static body is this floor at the bottom which doesn't move, but it can still be, it can still have things, for example, fall and touch it and be affected. But it's static.

It is there. It's fixed. It's not going to move. We have these kinematic bodies which are not technically fully static in that they are rotating. They're constantly moving, but they are imparting force onto other objects. The green body there, that dynamic rectangle that fell down, was affected by those rotations. It was affected by the vertices of those rectangles of sort of applying some force to it, and then it fell to the bottom of the screen and then it sort of came to rest eventually after a certain period of friction.

We'll run it one more time just so folks can see that happen. So it falls down very briefly, it gets bounced around a little bit. There's rotating forces applying to the rectangle, and then it comes to stop again. There's a little bit of sort of chaos and randomness that affects exactly where it ends up landing and how the rotation affects things, but you can see that it does function very all three of these function in very different ways. So let's take a look at the code real quick and see what we're doing for that.

It's not really all that complicated, which is kind of the fun part. So we have the classic as usual, the world. We've got the actual. Dynamic body here for the rectangle. We've got the shape of the rectangle as usual as we're using a fixture for it. The ground is this static body which is an edge shape, so love or rather box 2D and therefore love 2D by extension gives us this thing called an edge shape which is just a really nice way to sort of allow us to think. Of planes, for example, the ground and Angry Birds is also an edge shape. But just if you have borders in your game, they're often very well approximated with edge shapes.

They don't really need depth. They're just kind of this hard barrier for things. And so we're using the edge shape here. We're just using the same fixture applying to a body in that way. And then so if we have also these set of kinematic bodies that we want to render, we're going to need 3, and so we're just creating a loop here. We'll create 3 bodies, 3 fixtures, and we can actually use the same shape. The same shape can be used across multiple fixtures, multiple bodies, and it will just essentially, it's essentially just going to copy whatever that data is for

that shape and then reuse it across the different fixtures, the different bodies. but everybody is going to move their copy of that shape around and therefore be able to calculate sort of how the what the polygonal vertices of that should be if we were to try to get its position in the world at any given time for any individual body. So you'll see here what we're doing is we're just creating 3 of those bodies. We're just going to shift 3 shift them kind of like relative to the center a little bit. And have them sort of offset and then we're applying this angular velocity so that we do essentially a full spin per second,

which we're multiplying by degrees to radiance. The most of the functions in box 2D will take radiances as their sort of unit for rotation, which sometimes can be less user friendly to think of in terms of degrees, but thankfully these are constants that I was able to acquire online, but you have the degrees to ra. And radiance to degrees sort of constants here, these multipliers that you can use if you want to be able to think in degrees but then pass in some value into a function that accepts radiances or vice versa, you have a couple of constants here that are handily being used. And so here what we do is we essentially just say for every one of those kinematic bodies we can set its actual angular velocity,

meaning it's how it's spinning, how fast it's going to spin. And there's a lot of these kinds of methods across all of the bodies in box 2D and love 2D things like angular velocity, linear velocity, so on and so forth, friction and all kinds of different fields that affect how things physically modeled should affect each other and so we'll see a handful of those, but folks are encouraged to explore the. to see all of them. There's a great many of them that we won't have time to explore in tremendous detail. But lastly we do see we have the love. graphics. polygon actually drawing all of our various types of boxes in the ground as well,

which is just a line that we're drawing here across the bottom of the screen. And then again another polygon for all the kinematic bodies that are spinning in the middle of the screen which uh will just because they're we're gonna get all their points and they're just rectangles it'll all it won't even need to worry about rotation it'll just give us all of their individual points as such. So with that now we've been able to look at all three main body types here which is pretty cool. I think that example illustrates the difference between them, although it's a little bit underwhelming. So what I've gone ahead and done is added an even more illustrative example which I thought was super fun, which is called Ball Pit

and if we go ahead and run ball pit here. We'll see Quite a different example and notice just also the sheer number of these bodies that are currently in our scene here. If I go ahead and hit space bar, you'll notice that there was a sort of heavier object, the square that's like semi rotated now towards the bottom left. If I hit space, it's programmed such that we will hard set the X and Y to a different position. So we can simulate the sort of physics occurring and I'll just go ahead and do this a few times and we'll see we can just keep repeatedly doing this and sort of everything sort of perturbs and.

It's kind of a fun Way to see a little bit more chaos, but. I enjoy it quite a bit because it illustrates, I think, some of the power in having such a robust physics system that's pretty flexible. All of these circles here are also differently modeled than squares. They're all circular shapes and they're all very closely touching each other, and some folks might even notice that just in a very organic sense, for example, as we just let the whole pile sort of like resolve itself, you'll see these physics calculations and these larger sort of like almost fluid type.

Movements occurring within this corpus of objects here and there are a lot of things possible with physically modeling things in this way that are harder to achieve and certainly less obvious to achieve if we were thinking a bit more literally with physics like we've done previously where we've gone through and we've sort of modeled our X and Y velocity and things sort of bounce off at particular angles and so on and so. Forth here everything is just kind of automatically figured out in that way and we're able to focus more on the emergent behavior which I think is super fun but this also is the same example just taken to the next level we've got

all these dynamic bodies that are in the center we've got this sort of like static bottom floor edge plane and technically the square here is actually also a dynamic body. Um, there was not necessarily utility in it being kinematic, but folks could imagine there being platforms in the middle of all of these that do illustrate sort of like the kinematic presence of objects with all of these moving around dynamics sort of like if you're in a ball pit as a kid, some folks might remember or have had this experience of just like jumping into something like this and it's just kind of fun.

Uh, and there's really the sky is the limit with something like this or like a gumball machine or something. I just, I think about something like this and just get somehow get a little bit of dopamine from it, but there are a lot of really the sky is the limit with stuff like this. There is, and this is just essentially using the fundamentals too because as we'll see later, there are things like joints which allow us to do a tremendous more, but I would say that even with just these pieces we've essentially got a lot of the things that we might need to think about in terms of box. in order to create Angry Birds, right, because if you think about just the alien as a

circle shape that can get launched in a direction, we'll look at something called an actual impulse, right, which will actually set a linear velocity on an object or we'll apply an impulse to something to send it in a particular direction, but that will have the effect of that thing then being taken over by the physics system by box 2D, at which point it will. As usual, gravity will fall down or gravity will apply a force that makes the object fall down, and then it will end up colliding with something in the world. We haven't talked about how to resolve collisions in a way that does things that are not just the usual bouncing off of each other because as you recall with Angry Birds, right,

if we pay attention to ball pit, for example, all of these things are sort of moving around and they're staying existent and they're they're bouncing and they're doing all these things, but they're not, none of them are disappearing per se. And that is kind of an important detail with Angry Birds, right, as you're playing Angry Birds and you're throwing the bird from one place to another, you have this effect where the bird is actually, depending on how fast it's moving, it might destroy the obstacle or it might destroy the pig or slash the enemy alien. And so we're gonna need a way to resolve that. And so let's take a look at a couple of things to sort of take us closer to that direction and then we

can actually start diving into the code itself for Angry Birds before we take a look at things like joints. So a couple of functions that we should look at first is love.mouse press, which we haven't really looked at. So it takes an X and a Y and then a key, and then we briefly might have looked at this, but essentially this is what we're also going to look at in conjunction with mouse released, which is if you press the mouse at an XY and then the key, you'll have this result where you'll know exactly on the screen where you clicked and therefore assuming that you then. Maintain a state of OK now we're clicking and dragging you can take that XY and hold on to it and this is what we do with the slingshot, right?

If folks recall as you're clicking and holding the bird on the left and you're moving it around, it's sort of manipulating the trajectory and then once you release, which is what this then gets looked at when this fires, which is another love call back that very similar to the sort of the keyboard and mouse that we've looked at before. This will actually have a different function that will fire on key release which is when we want to finally buy also extension release the bird and therefore have it perform send it on its way. And then perform the collision should it hit something in our game space. And so that brings us to what is how does collision actually work in box 2D in a way that allows us to do this?

Well, essentially there are a set of callbacks that Box 2D will hold a reference for us that will then fire and we can define those not all too dissimilar from the callbacks that we can define for love's main functions like key pressed or mouse pressed or key released or mouse released. Except they're a little bit different in that they have different points at which they occur at a collision. There's a begin contact, end contact presolve and post solved set of callbacks. There's 4 stages of essentially resolving callbacks that you can decide to place your resolving code on.

Now we'll only actually need. Begin contact in today's example, but there are instances where you might need to determine at the beginning and at the end certain things should take place, and these all have different sorts of parameters and conditions within their use, and you can refer to them here at this link on Le2D if you want more detail on them. We'll only use begin contact and so you can see here world set callbacks takes in 4 functions, those being just anonymous or named functions that we define. And so it'll store those functions in memory and call those every time

some object in our scene collides with some other object, some body collides with some other body in our scene and therefore if we can determine by that like OK if this body is a bird and it's colliding with. An obstacle. OK, cool. How fast was the bird moving? Was it moving fast enough to collide with it and destroy it? Was it moving fast enough to deal a point of damage if we were looking at different materials? Did it collide? Did the player collide with the enemy? And if so, was the player moving fast enough to defeat the enemy, you know? And if so, despawn the enemy, increment our actual score, or go to the next level, so on and so forth.

And you can do the same thing for is it an obstacle colliding with the enemy because every object should be considered relative to every other type of object, and we'll differentiate those we'll see how we differentiate those in our code, but you can see here they're all just 4 different functions that take place at different times. So that brings us to the close of the core concepts we'll need to talk about Angry Birds conceptually and now we'll spend a couple of minutes looking through all of the pieces that actually bring this together so I'm gonna go ahead and close all of these examples. And then most of all of this will be an angry 50 and then we'll just run it again. And then we'll see we got a start state here

which decides to for fun create a bunch of these aliens that are squares. These are the enemy aliens that fill the space much the same way that the ball pit did. It's kind of the same logic, but we see we're using it again here just for fun, like, oh, here's all the enemies, right? Click to start. And then these obstacles here are essentially 3 bodies. Everything is dynamic here, at least in terms of the player and the alien and the obstacles. And so what they're going to do is be

they can have their X and Y and their velocity set and updated manually, which is what we're doing, but at the time that we actually launch the bird, or rather the alien as a dynamic body, it will perform physics and collide with things like the obstacle and the player. And therefore trigger those callbacks we talked about, but right now we've essentially just hard set these obstacles such that they form this structure that's stable nothing is colliding with anything else technically speaking, everything is sort of there it's dynamic, it's resolved, it's fine. But things are ready to be collided with and as soon as I do this,

you'll notice we have this predicted trajectory being rendered which is using a sort of algorithm that's calculating the application of gravity over time to every frame from now until the time it would collide with which is about 1.5. Seconds that sort of end point of the trajectory if I release it, dynamic operations will occur. We collided with two things. They both instantly called that begin contact callback function. They resolved, they got eliminated if folks recall from previously, if I were to restart this.

Run this and then if I were to aim for instead notice we have some randomization visually occurring as well just for fun folks might also notice that we have this ground at the bottom of the screen. It is a static edge shape that we're just essentially rendering tiles underneath, but if I were to aim for that bottom piece, notice that the top piece because it's dynamic, it will automatically just fall knowing that there's not an actual support for it. It falls, it collides. Everything rotates and functions exactly as it ought to, and so all the pieces are there for us to do some pretty sophisticated, pretty sophisticated physics simulation with pretty simple parts, nothing,

none of which you haven't really seen minus the callback function portion which we will take a look at. So most of this as usual occurs in the play state, but really there's not a whole lot in the play state that's of note. There is an additional feature that we added for folks. In case the bird kind of scrolls off screen a little bit, I added the ability to, if you were to press left and right, you can scroll on the screen and you can see the offsets of things for fun. And so that's something that we get for the play state, not of tremendous necessarily relevant value, but sometimes the bird or whatnot will transition.

You could set this to scroll automatically if the bird were detected past a certain point if you wanted to, but that's all the play state's essentially doing. Most of the bulk of the work is actually in a level, so if we're to look at level, for example. We'll come all the way up here folks might see some of the callback functions taking place there, but notice that again as usual we have the world we have a set of destroyed bodies we're gonna to take charge of like which bodies should we destroy. Love 2D does not want you to destroy bodies during the actual call backs as they're being processed because if it's the way it internally

does call back internally does physics calculations you. To do all the removals after all of the callbacks have resolved, otherwise you run into some issues that can crash the library and so this is something that you want to not do in the actual callbacks itself. This is documented as creating stack overflows and the like if you were to not do this, uh, if you were to do it directly, delete your stuff directly, typically want to do all your deletions not in your callbacks you want to do it in some sort of clean up post stage. And so, but notice here we are defining begin contact which is the function that we saw previously or the, the name that we saw previously.

We're then defining end contact, pre-solve, and post solve. These are just empty because we're not using them. We don't need to use them for our purposes the folks could choose to use them. And there's references throughout of blog articles on iForce 2D that showcase different parts if folks want to dig into more detail for their own applications, should they want to pursue more complicated collision or resolving of collisions, we're only going to use the sort of begin contact stage which is literally when two objects that are colliding begin contact. And then you can notice that we have this sort of like types and then we have this thing where we're getting the user data of each AB object,

the two objects that are colliding, and we're setting it to true in our sort of table, and this is where we can gather information about OK, what are the two things that collided, and then based on that, OK, if it was an obstacle and if it was a player, then we'd want to do some maybe slightly different code than if it was the player in the alien or the obstacle in the alien. And so there's reason why we want to separate those two. And so before we maybe even fully look through the begin contact function in detail, why don't we take a look at Alien first, which is going to be the sort of class for anything that is interactive or rather our player

that is actually being moved around on the screen. We're actually using both of them for the player and for the enemy, but we're. Flag one as the player and one as the enemy and that's how we're gonna get that piece of information that metadata that allows us to differentiate between the two of them, but it takes a reference to the world as usual and then we're just creating the new body here. It's dynamic we're creating based on whether it's a square or a circle and this is a piece of information that we pass in to it as its type because we want to differentiate visually between whether we.

Are a bird in the case of Angry Birds or whether it's an enemy in the case of a pig in the case of Angry Birds. Our tile set uses square and circle shaped aliens, so sort of arbitrarily I've decided, OK, we'll make the circles, the player and the squares the aliens, and then you could do any sort of version thereof if you wish to as long as you can visually differentiate them and they have semantic differences, that's really all that matters. Self. Sprite is just going to be like a quad index, same thing as we've always done before. We create a fixture and then here we have this set user data variable here, the set user data function, and what set user data does is allows you to

actually put a piece of information onto a fixture, and fixtures are besides just attaching shapes to your body, they also. Represent various aspects of this sort of way that collisions should behave and they can house metadata so that your objects can do fancy things like this of flagging OK this thing is an enemy versus this thing is a my player this thing is an obstacle, this thing is this breakable, this thing is this much strength has this much health so on and so forth you can pass in the actual user data to this function and we're passing it into the constructor here on alien in it. So

then lastly the important thing we should take a look at is when we render the alien we recall that we rendered everything previously as sort of these shapes so we had squares that we were rendering or circles that we were rendering previously in the ball pit or in the kinematic example and in the case of a circle you can just render a circle, but in the case of a rectangle you have to render a polygon for rotations. But when you're rendering quads it's a little bit different in that you can't really all quads are thought of in square shapes and they are square portions of your textures by the way that they're designed by their nature and so you have to render a quad as a rectangle and then you. To perform a rotation

in order to achieve the same effect whether it's a circle, whether it's a square you still have to draw a quad of your texture at a particular place and then perform a rotation on that quad and so that's all we do here we do a sort of. this get this self. body get angle will actually perform that for us. It'll actually get the angle of whatever the body is currently in its data by the box 2D's world said to have. It will actually give us that which we can then pass in to the render function or the draw function of love.graphics.draw.

It will then perform that rotation, recall anything we draw that has a rotation should be in order to be affixed to its. Center it needs to have its offset be at its center point and so that's what we do here. Everything is 35 by 35 pixels in the case of all of these sprites for aliens at least and so we draw everything relative to its center at 17.5, which then rotates based on the center point. If we were to not do that, it would rotate based on this top left, which would have this weird sort of this alien sort of moving in a circle or whatnot, which is not the behavior that we want.

And so that's why that's what we have to do in order. To draw the actual sprite at even though we might be drawing circular aliens, it's a square in the texture in the actual quad that we're drawing onto the screen. It therefore needs to be rotated at that stage and notice that we also have this get X and get Y that we can call on the body in order to get its actual X and Y world space. Everything in box is relative to its center, so we don't have to do anything complicated there to just we can literally just use the XY. But with that we now have the ability to draw render the alien and also the last thing too in alien is that

we have this new circle shape that we're creating here which we only looked at rectangles before, but we can also do this. We can create a new circle shape with a radius of 17.5 and then you know that's 35 in either direction which gives us the 35 by 35 pixel alien. And so therefore we now have this ability to create aliens in a way that works in our game world. So then if we go back to the level that we were looking at previously. And then if we recall we were looking at this get user data function which this is essentially the crux of how our collisions are going to work.

We're going to launch the bird at a certain point, to launch our alien at a certain point. It's gonna then have to collide with fixed with our obstacles and then with the other alien and of course this means that we need to differentiate between the types as I alluded to previously. And so in order to do that if I scroll down here past all of our callbacks. We'll see that we do have a sort of like list of aliens in our scene that we're going to care about. And then here if we look at for example when we do a table. insert of our self. aliens, this is sort of setting up the scene,

but we do have this sort of constructor for an alien which takes the world that should be square as we saw previously that was for our alien and we're gonna place it right about here which is kind of to the right side of the screen more or less, and then this last parameter here is that user data parameter that we saw in Alien which essentially just defers to call. set user data of a body or of a fixture rather on that body and so what this allows us to do is then say OK if I get that user data which can be just about anything you want, but we're choosing to make it a string and we're just gonna set strings on various types of entities in our world to set them

as being whatever it is that we want them to semantically represent, be that the alien, be that the or rather the player or an alien or the or an obstacle or so on and so forth. We can just pass that string in it'll set that in the fixture and then at collision time that is what is happening when we actually look at the get user data function here we're essentially just setting we're gonna essentially at the beginning of our contact which is between two things. In our world at this particular point in time we're then going to say, OK, I'm gonna create a table I'm going to flag true on the key when we're assuming they're strings so they

will effectively be at key alien or key obstacle or key player, whatever. We're gonna set that to true and then we can then say OK if types at obstacle and types at player meaning did we get an obstacle and a player colliding with each other and if we did, then we can get whichever of the two was the player, whichever one was the obstacle here, which is just doing a comparison on that get user data and then setting it to either A or B. Then we can get the velocity of the player fixture here, where it's body rather get the actual because all of these are relative to fixtures. The body can have multiple fixtures that collide and so every AB comparison is technically done between fixtures, which is why we set the

the actual user data on the fixtures and not the body. But so we're going to get essentially get whatever the linear velocity, meaning whatever it's going X and Y value of that fixture, the player in particular, because that's what we care about if the player is moving fast. We want to determine that or fast enough and then we can essentially take the absolute value of that vector and say if it's greater than 20, which is essentially just like meters per second. Cumulatively between the two axes, then we can say, OK, then in this instance then uh we're going to insert into a destroyed bodies table, which is what we cared about before and a lot of these numbers too are tweakable as well.

You can the higher the value is, the faster the bird needs to be moving in order to affect that destruction that you trigger and then this goes to all sorts of variables that we. See that we will see coming up including friction and rest things called like restitution for bounciness and so on and so forth but essentially then if we put this into the destroyed bodies, the fixture, the body rather through the fixture into the destroyed bodies table, this means that we've essentially flagged it for removal from the scene later recall, you're not supposed to do this in the call back because

that causes issues with the way box today does collision attack. It's a no to do that, so don't delete it inside the actual body here, but we're essentially just duplicating this code in multiple places more or less, but we're doing it through different means. We're doing it through different creatures. So we have type obstacle and alien, meaning you know recall we can hit the alien ourselves with the player, and that should of course defeat the pig slash alien, but what. If we, as we saw, defeat that lower maybe that left obstacle, therefore allowing gravity to bring down that top obstacle to also hit that pig, well, that should, as in Angry Birds itself, the game very well does

that should also trigger deletion on that obstacle on that creature, and we can do the same sort of calculation here. It ultimately adds up or amounts to the same thing. And then same thing for the player and the alien. And then player in the ground. So if the player and the ground were to hit at that point we should stop essentially we should just create, we're not really do anything because we don't want to actually stop the player. We don't want to do anything meaningful that'll get taken care of by the physics engine. We'll just bounce, but we probably want to like play a sound effect if we hit the ground recall the ground.

Static. The ground's not gonna move anywhere. Nothing really needs to happen. We're not also going to destroy the player if we were to hit the ground, but we do wanna like trigger some kind of a sound effect just for feedback and in general across all of these sorts of things you wanna typically do feedback in that way and so if we scroll down. Notice also we do have the sort of spawning of obstacles which isn't really too fancy that we've seen so far, although some folks will notice we have the vertical and horizontal flags here which is sort of like set up code in our constructor for obstacle which we'll briefly just look at nothing too fancy that we haven't seen just yet, but in our update.

We can essentially do this function now which is this loop, which is that will iterate over destroyed bodies and update and we'll just call this destroy method which box 2D will then take care of the actual sort of work involved in safely deleting these objects from the scene, ensuring that there's no weird issues or stack overflow type things that might occur if you were to try to. Uh, delete something in the midst of its actual processing of callbacks for every interacting entity. So that's the gist behind how the collision code works.

The other part that folks might care about or have noticed of note in the scene besides just those the actual core, you know, moving the character over to the uh or rather swing or shooting the ball over to the obstacles and affecting. Various collisions and destruction and defeating the enemy, which then triggers victory is the fact that we have this sort of simulated trajectory which is kind of interesting so we can take a look at that and alien launch marker. Also of note is this is where the actual player gets created and added to our world. We're actually simulating that we have an alien in our world on the left.

We don't actually until we let go of the actual sort of mouse click that we saw previously. But if we come down here to update, we'll notice that we have this launched flag which is essentially just like, are we not launched yet, in which case should we render the trajectory if we are actually pressing the key to launch the alien? We're gonna grab our coordinates and then we're going to essentially set aiming to true if we did press, if we did press left click is what one is. And we're not launched. We're just gonna set aiming to true, which is then going to toggle rendering that shows the trajectory relative to where our mouse is. But if we did release one and we're aiming, that means it's time to actually spawn

the alien to go shoot towards the obstacles, or rather to shoot wherever we left off wherever we left where we released the mouse because that's going to set. The impulse that should fire the alien, or rather we set the linear velocity here, you can do this in multiple ways with box 2D. You can hard set velocities. You can apply impulses to objects to allow physics to do it for you, so on and so forth. We are essentially saying, OK, where was your XY?

Was it to the bottom left at this amount or this amount and then depending on where it is, there's gonna be a delta between that and the actual like point where we are rendering the bird, which is the slingshot sort of behavior in the game. In Angry Birds and then so we can apply the sort of difference as linear velocity going in the opposite direction, which affects a kind of similar to when we set a velocity when we jump it's going to set a velocity in Mario or Angry Birds or uh Flappy Bird previously it's going to set an XY that then Box 2D is going to take over because we're essentially instantiating a new alien which is going to, you know, again it takes a reference to the world,

it's gonna create a new box 2D body which. Then takes on all that physics work and it's going to start to be simulated with box's own gravity and physics calculations and the like. There's a couple of flags here like restitution and angular damping. Restitution is like bounciness. The closer to zero, the less you bounce, the closer to 1, like you essentially preserve your bouncing perfectly. There is no lost energy effectively, and then angular damping is like how much your rolling is effectively, uh, is affected by um. Or, or rather, is, your angular damping affects how much your body is

affected by gravity beyond just gravity where you actually lose like there's essentially air friction, um, we, we'll apply that and rotation as well if you're on the ground too. And so we want to set that to one we don't want that affected any more than what the game is already going to do, but this could be effective for making sure your materials are rougher or smoother depending on what you're going for. One is essentially just uh like a very light amount like almost none. And so when we render, if we come down here, we'll notice that we essentially are going to create a an impulse that is based on the difference between.

The base X and Y, which is where the bird gets rendered on the screen statically, I'll, I'll rerun just so we can see what it looks like visually again, which might be a little bit easier to talk about, so I'm gonna run this. And you notice that there's sort of like an alien texture being rendered there that is modeling the base X and Y of the bird and is not going to, it is not actually a physics object that's being manipulated. It is just a representation it's just a drawing we're just drawing the texture there. And so if I click and hold left click that the XY gets preserved wherever that was is preserved.

It's still like essentially keeping track of that position, but now when we move our mouse, the drawing is gonna stay on our mouse. It's gonna keep rendering there, but we're essentially taking the delta between where we are now and where that base X and Y was, and we're going to create an inverse impulse that we're modeling with. era or with this trajectory with this set of magenta colored circles, so we're essentially just saying what's the difference between the XY and our current XY, which will be some sort of negative value right now because we went to the bottom left,

but we want to invert that and turn that into a positive XY impulse that's going to go or velocity that's going to go to the up and to the right, and we do that no matter where we move relative to that center point, it's going to affect. Trajectory and also just uh again we showed this at the beginning but if you were to go here for example there's some code to just make sure your alien ends up back at the point where you started and doesn't continue doing physics calculations and the like, but it's all relative to this center point here which ultimately we can use that delta to then create a velocity that then lets Box Duty take over and then perform all of its collision detection stuff. But because this is just kind of a weird sort of like UI

limitation where we want to be able to model where we're moving the bird slash alien but still like know where our physics is going, we need to have this not be a physics body. This is just a graphical representation essentially of where our bird is relative to the center point which creates our sort of impulse that then spawns a trajectory which will then get calculated by box 2D. The way that we calculate that trajectory is we essentially do a simulation of what gravity will do to that impulse over time. So if I go back to the alien launch marker.

Over 90 iterations, which is gonna be 90 frames, which is gonna be if we're running at 60 frames a second, that'll be, or rather we're doing this over physics calculations and we're assuming we are always doing 60 physics calculations so this will be consistent no matter what, but essentially over 90 frames of a 60 frames assumed computer we will essentially do. We'll get the trajectory on the X based on that amount of time I over 1/60, and then we're going to multiply whatever the impulse X is and then that's just going to essentially at any given point on that set of I up to 90 we'll calculate where it should be at the X should be at frame I.

We'll do the same thing here with the y axis only and there's a reference here that calculates the or shows the math behind why this works, but you essentially have to perform gravity operating over time, so sort of like pixels applied per second, so acceleration of gravity. Applied to the sort of like sum of all operations that have happened over 2, which is equivalent to like the additive series or like the triangular number of iterations that have occurred up to that point in time, which is going to be the accumulated effect of gravity on the Y axis as it's applied over time over a set of however many frames you want to model it. In this case remodeling it over 90, you could do this over any number of frames or 60 if you wanted to.

And then what we're doing is rather than rendering that XY, that circle every single time, which is essentially be this continuous line of information, we're instead going to mod it by 5 and just draw it every 5 iterations, which comes out to 1890 divided by 5 being 18, which will then just draw a little circle at that XY of radius 3, which then gives us this model trajectory and allows us to know in advance using some math how we're going to actually look at the time. Time that box 2D takes over our algorithm and applies gravity to our ball or our alien rather, and so that's the crux behind the alien launch marker which is sort of like the key

and sort of making sure that things work properly and we looked at that in the context uh obstacles and things calculating as well spawning an object into box 2D. We didn't actually look at the obstacle class itself, so here's what it looks like it's very simple really. Ultimately it can take a horizontal or vertical sort of flag which will then we'll use to determine whether it should be wider than taller and then sign at the right quad as we need to as well. That we take a rectangle shape new fixture, all these things are things we've seen before, but we are setting its user data to obstacle which allows us to now, OK,

this thing will be in the world and we will decide that it will be an obstacle at collision time and therefore takes on sort of new behavior. It doesn't need to really. Be updated or anything Box City will do it for us and we just draw the right frame of assuming that we've spliced up a set of quads called wood here at that particular frame. In this case we assume if it's horizontal it's frame 2 if it's vertical it's frame 4 and we included many different examples of, uh, I should say a few different examples of different materials here.

We have a lot of different stuff if we go to the physics assets here, the spread sheet. There's actually quite a lot of there's quite a lot of things. There's like for example an explosive sort of like warning sprite sheet here and then there's a there's like a glass version if you wanted this to be like a really brittle sort of uh material but then we've got metal for harder materials and then even stone so this is a really cool open source graphical set for Angry Birds or these kind. Of physics games for folks for the problem set to be able to take this on and then add whatever they want for different

materials having different sort of semantic purpose, meaning for their durability, but that's ultimately the crux behind how the game works. You have this alien that launches, physics calculations occur, and then at a certain point if they collide with your alien and The speed of the velocity of the bird is fast enough. If it's cumulatively absolute value added up. Same thing with obstacles you decide that's the threshold you want to allow for that to create a defeated entity, then you can just therefore know if you've defeated all the pigs or whatever in your state just mean you have multiple.

We only have one in this example, but you've got multiple just check, do I have any bodies left that have that user data in the scene? And if so, cool, then we've got a. We got or if not then we've got a victory and if so then just keep iterating and maybe have a limited number of times that you can do it so on and so forth. The problem that's gonna be a little bit different in that there are other things worth exploring in this space and other aspects of Angry Birds even that are worth exploring and so I think it's cool to now transition a little bit to talking about joints

which is going to be sort of the next stage in box 2D and sort of where we're venturing for the problem set as well. So what joints allow us to do is kind of fill in this other missing piece which some folks who have seen Box 2D might have seen, which is that you're capable of much more than just simple shapes moving around, which is you can actually create compound objects of a sort, and there are many types of joints by which we can accomplish this. We'll look at a few simple ones, but certainly. The sky again is the limit. There are just so many ways you can mix and match these things to create and physically model so many different things.

We'll be looking at things like pulleys and welds, revolut joints. You can sort of envision most physical contraptions modelable in box 2D. And here's a nice cool fun example of something somebody made on a blog and just it's a very customizable functioning car device of sorts that's very sort of modeled off with axles and it's got like a suspension. It's got it's there's a lot of really interesting aspects involved in building complicated objects like this and we'll be looking at some ways to do that um so let's go through just kind of a whirlwind tour of some examples that I whipped up that I think will give folks a taste for what's what's possible. In the library and as part of the problem set you'll be required to sort of implement

one of these so you can choose to your discretion but ultimately they'll be a tool for you to sort of impact game play and aesthetics sort of in a joint way an interesting way and this is common even in Angry Birds nowadays as I've seen there are sort of complicated moving things that are interconnected and joined and such. So if we close out some of these things here, I'm gonna close all of these, and if we go to, for example. We won't spend a tremendous amount of time necessarily looking at the code on most of these, but we will just kind of quickly go through them.

The simplest one that we could start looking at, for example, is a weld joint. So if we just go ahead and start this up right here. You'll notice that we've got like these two different objects. They're slightly differently colored one's a lighter blue, one's a darker blue, and there's this red sort of circle right between the two of them, and that is essentially marking the joint, the weld joint, and as the name implies, sort of like they are welded together effectively such that they are two separate bodies but they are in fact affixed to one another such that if I were to apply an impulse to let's say the.

Body by pressing left towards the left, you'll notice that it sort of falls over and it retains its shape overall. It is in fact just hard welded like you would see a big metal structure welded together and I can break the weld if I just press B. You'll notice that. The weld disappears and it becomes two separate physical bodies, rectangular bodies that are just now dynamic rectangles, much like we've seen previously and so this is probably one of the simpler joints to look at if we were to go over here to our code this is gonna go ahead and scroll up just a little bit. You'll see and again we won't spend a tremendous amount of time looking at the specifics of all of these things.

We have a ground much as we did before, which is just a static edge shape. And then if we go down here we can see we have a head body and then a handle body. These are two separate bodies recall we have the actual head. We have the handle. Those are a fixed with a sort of anchor point being the weld in the center between the two of them roughly. And so what we do is we just know as is usual we apply fixtures to them and then we're going to create this new weld joint here which is going to be placed at about the uh start X and start Y plus head H divided by 2 which is going to be

right about where we spawned the actual head itself, but it's going to be a slightly in the center between the two or sorry the handle itself but between them a little bit. And then given the handle body and the head body together as parameters to this that will tell the well joined that OK, your goal is to fix these two together in this static way and then if we just were to go over to for example this key pressed here and press B, you can see we just destroy it otherwise it'll for all intents and purposes be treated like one object that now can just kind of move around and be. Physically modeled like anything else, and you can imagine just creating and welding some big thing together this static thing, and

that might work great for something like a building or some sort of larger structure that is composed of these multiple bodies and then maybe by affecting some sort of like force on certain things you can begin to delete some of those welds and then therefore crumble the structure while still maybe preserving the underlying pieces so that's the example of welding. So if we were to for example then. Go to let's say something like a poly device which is fun if we go ahead and run this. You'll see that we've got what looks just like uh a simple pulley.

I can press the arrow keys to move one side or the other. In this case the left box is weighted as twice as dense as the one on the right. So the pulley is going to skew to the left. It's always going to fall to the left, much like a pulley system would work in real life where you've got one thing and another thing that sort of have a sort of like invisible string connecting them that will affect each other's sort of vertical movement and that's effectively what's happening here. If you apply a force to either of these up or down, they're capped at their actual like invisible strings. To speak is capped at a certain length,

and they will always retain that difference between the two of them. And so we can go over to our code here. If I go up to the actual part where we're playing a joint, you can see we've got like two different bodies A and B which are part of the pulley. We're applying a force to them which applies some sort of positive or negative force or impact on a particular axis x or y. We're just doing everything on the y axis for right now. And then this pully joint here effectively takes in a set of parameters, the body, the grounds for the actual places where the strings would be in the pulley effectively,

and then the positions of where the box A and B happen to be, and then that gives you a pully system and there's a lot of these types of again the folks can go to Love 2D's physics, actual documentation, the wiki, and. See all the different joints that Box 2D has and Box 2D's documentation will largely align with uh Love 2Ds, assuming that the version is similar and the Box 2D is up to version 3.something now, and Love ships with either 2.3 or 2.4 and so depending on which version of love that you're using, so some things may be if you're looking at newer box 2D documentation, some things might be uh 2.

New for the what's currently in Love 2D, so I encourage folks to maybe stick to the 2.3 or 2.4 series, but effectively if you stay with the love 2D documentation and love their love. physics namespace or Box 2Ds with and you do the sort of like calculation to get to the love's functions or consult love's wiki for their functions, you can arrive with the same understanding of what the different parameters do. I'm gonna go ahead and open up that was the Poli example. Let's go ahead and open up Pendulum. And if we run this, you'll notice that we have now an anchor point that's kind of in the center of the screen it's kind of

like up to the top you'll notice we're just rendering a line that sort of goes from whatever the anchor is, wherever the joint is effectively to the actual body that the joint is connected to. So if I press left or right, I can start to nudge this pendulum left or right, and I can spam it in multiple directions. You can see it kind of like always staying a sort of you know sort of the same distance radius wise away from that joint as a pendulum would, and eventually I can kind of have some fun and make it go all the way around if I keep doing it or almost did it if I. There we go, got it, got it to do a full rotation and so it stays very fixed to its joint.

It's always gonna be the same radius away from it and so if I stop that we go over to here. You can see we're creating the anchor point and the ball, and then we have the actual it's called a revolute joint that accomplishes this, meaning that whatever the joint is affixed to will revolve around it and so we're accomplishing that again. We have an anchor and a ball and then the anchor X and Y, and these are just various variables that uh it expects in a particular order that you would look at just by looking at the wiki so that's pendulum. Then if we look at the same example, but this one is called rope. If I run this, folks might notice that it looks very similar to the

sort of pendulum idea, but rather than using a revolute joint in this example, we've decided to use a what's called a rope joint, meaning that now no longer will it hard enforce that unilateral distance along that joint. Now if I were to spam some directions and try to get it up close, you'll see. It does function much more like a tether ball where the actual rope is sort of like not hard to find as being that unilateral radius away from that sort of anchor point center which allows you to simulate what a rope would do in something like a tether ball instance or whatever you want to use it for.

It's very similar to a revolut joint in this instance only. It's just. it's functioning like a rope instead of a hard metallic pendulum or the like and so there are many examples of that. And that is essentially the gist behind what Joints are and folks will be required to implement at least one of those for their problem set. There's lots to do obviously beyond what we just did even today. There's, for example, more shapes you there's, you know, with polygons you can model in box to any kind of shape that you want to.

You could have very complicated geometry, for example, and even Angry Birds itself, as we saw in the screenshot, there's like triangular pieces and whatnot, and those can be modeled using polygons in box 2D. You can have levels that are separate. We only had one level, but maybe you have. Table that creates obstacle definitions that you can then instantiate and then load into box 2D every time the level loads and now you've got multiple aliens you've got this big complicated structure that you've defined in code that you've tested as stable.

It's made of different materials, so on and so forth, which we didn't have the chance to do. And then this is also part of the problem set which is that in Angry Birds you have the one bird, the red bird that you start with that just moves in a direction, it hits something, it's velocity will determine whether it breaks something, but maybe you want to spawn off 3. Birds as is the yellow bird or maybe you want to blow up or the blue bird and then you wanna blow up with I think it's the black bird if you press a button after the bird goes forward, it will explode and then cause damage to the surrounding uh blocks and then of course different materials which is also part of the problem set which is can you affect

differing amount of damage to something and cause cracks or the like to represent that you are partially through breaking something but haven't fully broken it. So the assignment for next week will be. When you hit the space bar after you spawn your first bird, you should spawn 3 birds, and they should essentially have the bird go the normal bird that you were shooting should keep going, but then 2 more should spawn off going a certain angle away from that center bird, and all 3 should apply collision in that instance.

You want to also add glass and metal to the world, and they should have differing numbers of hits they should take in order to break. I would propose glass is 1, what is 2, metal is 3, but folks are welcome to choose whatever they want for that. And then also, um, as we talked about, when you do make them take multiple hits for the ones that are not just one hit, the second hit should affect a crack, and the third one can affect a deeper crack should you wish or it should just render the same crack. And then lastly, Incorporate at least one joint in your level in some way that is tied to the mechanics of the game.

It should affect the game either it be an obstacle or something that the player can interact with that could therefore by proxy trigger a collision onto a bird or something or an enemy, so on and so forth. So next time, which will be our last lecture for the course, which it's already come to an end and it feels like it hasn't been that long at all, we're going to look at Pokemon. This is an example of the actual battle mode of Pokemon which. Had a couple of modes to it also has a top down walking view which we'll talk about grid-based movement and sort of locking yourself to this smooth grid-based top down movement much like in Zelda,

which is a classic of Pokemon, but also be an opportunity for us to explore two huge topics that being not just state machines but a state stack, which is an evolution of the state machine that gives us very interesting robust sort of memory behavior from prior states that we were using. Previously like pause states and whatnot, and also it gives us a chance to look at GUI elements as you can see even in this example we've got a text box we've got progress bars and the like, and Pokemon's got a lot of UI and so it'll be a great opportunity for us to break down various UI elements and take a closer look at those. So that was Lecture 6 Angry Birds, where we got to dive into box 2D and very interesting physics.

Look forward to seeing what everyone puts together for their own projects. This is Lecture 6. We'll see you next week.

More Gaming Transcript