1 00:00:00,000 --> 00:00:16,511 2 00:00:16,511 --> 00:00:17,510 COLTON OGDEN: All right. 3 00:00:17,510 --> 00:00:18,510 Good evening, everybody. 4 00:00:18,510 --> 00:00:19,600 Welcome back to GD50. 5 00:00:19,600 --> 00:00:21,040 This is lecture six. 6 00:00:21,040 --> 00:00:23,980 And today we're going to be venturing out of the 8-bit world 7 00:00:23,980 --> 00:00:26,350 and back into a more modern era of gaming. 8 00:00:26,350 --> 00:00:28,432 We're talking about Angry Birds today. 9 00:00:28,432 --> 00:00:30,640 I have pretty fond memories of Angry Birds, actually. 10 00:00:30,640 --> 00:00:33,640 It was the first mobile game that I remember 11 00:00:33,640 --> 00:00:38,870 playing where I realized that mobile was actually a viable platform for gaming. 12 00:00:38,870 --> 00:00:42,100 I played it, I think, back in 2009, was when it was first released. 13 00:00:42,100 --> 00:00:43,440 And I really enjoyed it. 14 00:00:43,440 --> 00:00:45,340 It has a very simple formula. 15 00:00:45,340 --> 00:00:47,870 The goal, if you're unfamiliar, is you have 16 00:00:47,870 --> 00:00:52,030 birds that you control by a sling shot on the left side of the screen. 17 00:00:52,030 --> 00:00:54,610 And then these pigs that have stolen your eggs, 18 00:00:54,610 --> 00:00:56,830 you're trying to destroy them or kill them 19 00:00:56,830 --> 00:01:01,080 by knocking down their fortresses made out of various materials, wood, glass, 20 00:01:01,080 --> 00:01:02,195 metal. 21 00:01:02,195 --> 00:01:03,820 And you get a few different bird types. 22 00:01:03,820 --> 00:01:08,350 But the gist of it is, basically, just sling shot a bird into some structure, 23 00:01:08,350 --> 00:01:09,280 knock it down. 24 00:01:09,280 --> 00:01:12,850 And the whole entire underlying mechanism 25 00:01:12,850 --> 00:01:15,130 for how things work is via a physics engine, 26 00:01:15,130 --> 00:01:18,190 which we'll talk about today in lecture, called Box2D Probably 27 00:01:18,190 --> 00:01:21,280 the most ubiquitous 2D physics engine. 28 00:01:21,280 --> 00:01:24,070 But that's the overall structure of the game. 29 00:01:24,070 --> 00:01:27,960 It's literally just throwing things into structures, knocking them down. 30 00:01:27,960 --> 00:01:32,906 And then that tactile and fun game play makes for really great mobile gaming. 31 00:01:32,906 --> 00:01:34,530 And I enjoyed it a lot back in the day. 32 00:01:34,530 --> 00:01:38,980 This is a screenshot of the first level in the first Angry Birds, which 33 00:01:38,980 --> 00:01:41,410 most people I think have probably seen. 34 00:01:41,410 --> 00:01:44,020 This is a sample from one of their newer games. 35 00:01:44,020 --> 00:01:48,020 As you can see, it's taken a whole new layer here. 36 00:01:48,020 --> 00:01:54,400 There's stone and a bunch of intricately varying structures and new creatures 37 00:01:54,400 --> 00:01:55,330 and stuff like that. 38 00:01:55,330 --> 00:01:57,996 The game has changed a lot, but the formula has stayed the same. 39 00:01:57,996 --> 00:02:02,250 And today we'll explore the foundation of what makes this game work. 40 00:02:02,250 --> 00:02:04,960 And the topics today, a smaller than usual. 41 00:02:04,960 --> 00:02:09,009 But Box2D, we can consider as being a pretty large topic. 42 00:02:09,009 --> 00:02:11,200 We'll be talking about Box2D, which is the physics 43 00:02:11,200 --> 00:02:13,430 engine we'll be using today in lecture. 44 00:02:13,430 --> 00:02:16,674 And via Love2D, which has its own wrapper for Box2D. 45 00:02:16,674 --> 00:02:19,840 And we'll also talk a little bit about mouse input, which you haven't really 46 00:02:19,840 --> 00:02:20,560 done a lot. 47 00:02:20,560 --> 00:02:23,680 But it's very apt, especially in the context of mobile gaming. 48 00:02:23,680 --> 00:02:28,960 Because mouse input and touch input are synonymous. 49 00:02:28,960 --> 00:02:30,460 But first, let's get a lecture demo. 50 00:02:30,460 --> 00:02:34,750 If we have a volunteer come up on stage to showcase 51 00:02:34,750 --> 00:02:35,990 what I've put together here. 52 00:02:35,990 --> 00:02:38,395 So let me make sure I'm in the right directory here. 53 00:02:38,395 --> 00:02:42,960 54 00:02:42,960 --> 00:02:45,220 So whenever you're ready, go ahead and press Enter. 55 00:02:45,220 --> 00:02:49,450 56 00:02:49,450 --> 00:02:54,727 So this is a little demo I put together to demonstrate the concepts we'll 57 00:02:54,727 --> 00:02:55,810 talk about today in class. 58 00:02:55,810 --> 00:02:57,700 This is just the Start screen, but it already 59 00:02:57,700 --> 00:03:02,950 shows Box2D representing a bunch of these square shaped aliens, which 60 00:03:02,950 --> 00:03:05,880 we'll actually be what we're trying to target in the game. 61 00:03:05,880 --> 00:03:08,740 But notice that they all fell and had their own collision 62 00:03:08,740 --> 00:03:12,970 and their own physics that took place, and I didn't have to manually code 63 00:03:12,970 --> 00:03:14,290 rotation and stuff like this. 64 00:03:14,290 --> 00:03:17,539 This is all stuff that Box2D takes care of for us. 65 00:03:17,539 --> 00:03:19,330 And we'll see it used to great effect soon. 66 00:03:19,330 --> 00:03:20,960 If you go ahead and just click anywhere on the screen, 67 00:03:20,960 --> 00:03:22,970 we'll go to the main part of the game. 68 00:03:22,970 --> 00:03:26,422 So this is a very simple representation of what Angry Birds is. 69 00:03:26,422 --> 00:03:28,130 You start on the left side of the screen. 70 00:03:28,130 --> 00:03:29,880 You have a bird, in this case an alien, we 71 00:03:29,880 --> 00:03:33,100 used a free art pack that uses aliens instead of birds, 72 00:03:33,100 --> 00:03:34,540 but it's the same concept. 73 00:03:34,540 --> 00:03:36,487 You have an alien that you can click and drag. 74 00:03:36,487 --> 00:03:38,320 So if you click it and then drag around, you 75 00:03:38,320 --> 00:03:43,070 can see the trajectory that you'll have when you let go of the mouse. 76 00:03:43,070 --> 00:03:46,840 So we're simulating where it's going to go via these purple circles. 77 00:03:46,840 --> 00:03:50,605 And then the goal in Angry Birds is to throw the bird into, 78 00:03:50,605 --> 00:03:53,980 or the alien, into the fortress guarding the pigs, 79 00:03:53,980 --> 00:03:56,170 or in this case, square shaped aliens. 80 00:03:56,170 --> 00:03:59,086 So if you go ahead and just launch the bird by letting go of the mouse 81 00:03:59,086 --> 00:04:00,124 you'll see. 82 00:04:00,124 --> 00:04:00,790 Oh, there we go. 83 00:04:00,790 --> 00:04:02,980 And we knocked down the. 84 00:04:02,980 --> 00:04:04,330 OK. 85 00:04:04,330 --> 00:04:08,890 What happened was we shot the alien into the structure. 86 00:04:08,890 --> 00:04:16,360 It destroyed one of the wooden blocks guarding the other alien. 87 00:04:16,360 --> 00:04:19,540 And then, as soon as that happened, the top box, 88 00:04:19,540 --> 00:04:23,590 because these are all being simulated via Box2D's physics engine, 89 00:04:23,590 --> 00:04:27,190 that other box was detected as being unsupported. 90 00:04:27,190 --> 00:04:29,290 So it fell down, it hit the other alien. 91 00:04:29,290 --> 00:04:31,960 And we've coded it so that when a collision occurs 92 00:04:31,960 --> 00:04:35,950 between an obstacle and our alien of sufficient speed, 93 00:04:35,950 --> 00:04:37,060 it should kill the alien. 94 00:04:37,060 --> 00:04:38,800 Which is how it works in Angry Birds. 95 00:04:38,800 --> 00:04:40,210 So if you'll try it again. 96 00:04:40,210 --> 00:04:42,470 And this time we hit both of those at the same time. 97 00:04:42,470 --> 00:04:44,890 So it triggered both of those being deleted. 98 00:04:44,890 --> 00:04:46,540 But this guy is still alive. 99 00:04:46,540 --> 00:04:50,110 So after it stops moving, which is similar to how 100 00:04:50,110 --> 00:04:54,430 it behaves in the original game, it's going to let us try again to shoot. 101 00:04:54,430 --> 00:04:57,440 So if we try one more time. 102 00:04:57,440 --> 00:05:00,800 And then we launch and hit it, we kill it and then we get a victory. 103 00:05:00,800 --> 00:05:04,690 So that's the overall underlying foundation for what Angry Birds is. 104 00:05:04,690 --> 00:05:06,850 Obviously we're using a very simple representation. 105 00:05:06,850 --> 00:05:09,340 It doesn't have a lot of the frill that Angry Birds does. 106 00:05:09,340 --> 00:05:13,000 But we could easily build upon this and create a fully fleshed out 107 00:05:13,000 --> 00:05:14,811 game very similar to Angry Birds. 108 00:05:14,811 --> 00:05:15,560 So thanks, Steven. 109 00:05:15,560 --> 00:05:17,300 I appreciate the demonstration. 110 00:05:17,300 --> 00:05:25,800 111 00:05:25,800 --> 00:05:26,880 So that's our goal today. 112 00:05:26,880 --> 00:05:33,540 We'll be talking about how to construct a very basic but functional simulation 113 00:05:33,540 --> 00:05:35,610 of what Angry Birds is at its core. 114 00:05:35,610 --> 00:05:38,760 Which is just flinging things into obstacles, destroying them, 115 00:05:38,760 --> 00:05:41,820 and ultimately destroying the things that they're protecting, 116 00:05:41,820 --> 00:05:46,364 the aliens, the pigs that are in the base game. 117 00:05:46,364 --> 00:05:49,530 So here's a shot of what the different sprite sheets we're going to be using 118 00:05:49,530 --> 00:05:50,250 are. 119 00:05:50,250 --> 00:05:53,730 There's a really great sprite sheet that I got off of Open Game Art. 120 00:05:53,730 --> 00:05:54,690 Kenny is the artist. 121 00:05:54,690 --> 00:05:56,040 He makes a lot of great art. 122 00:05:56,040 --> 00:05:58,260 If you notice, it's very similar looking to the art 123 00:05:58,260 --> 00:06:01,020 that we use in the Mario lecture. 124 00:06:01,020 --> 00:06:02,520 Actually, it's the same artist. 125 00:06:02,520 --> 00:06:06,210 So if you're ever looking for assets, he's got a ton of awesome assets 126 00:06:06,210 --> 00:06:07,200 on open game art. 127 00:06:07,200 --> 00:06:10,110 So we have a set of aliens, square and round shaped. 128 00:06:10,110 --> 00:06:14,130 I decided just arbitrarily we made the round shaped aliens the birds. 129 00:06:14,130 --> 00:06:17,880 So we shoot those into the structures that are 130 00:06:17,880 --> 00:06:19,380 protecting the square shaped aliens. 131 00:06:19,380 --> 00:06:23,662 The square shape aliens will be the bad guys in this case. 132 00:06:23,662 --> 00:06:26,620 And then we have another sprite sheet down here below on the left side. 133 00:06:26,620 --> 00:06:30,360 Which just, I used the tile here just to make a ground element. 134 00:06:30,360 --> 00:06:33,510 The rest of these you could easily include in the game if you wanted to, 135 00:06:33,510 --> 00:06:36,060 but we're only using the ground here. 136 00:06:36,060 --> 00:06:38,400 And then notice here, we have this large sprite sheet 137 00:06:38,400 --> 00:06:42,930 which has a bunch of different shapes and sizes of materials. 138 00:06:42,930 --> 00:06:47,040 The whole sprite sheet comes with metal and explosive and glass sheets as well. 139 00:06:47,040 --> 00:06:49,500 But just for simplicity we only use the wood here. 140 00:06:49,500 --> 00:06:53,190 But notice that we have entirely whole pieces 141 00:06:53,190 --> 00:06:55,470 and then we have pieces that are partially destroyed 142 00:06:55,470 --> 00:06:57,120 and then pieces that are hollow. 143 00:06:57,120 --> 00:07:00,540 You could easily model all of these in your game and use them. 144 00:07:00,540 --> 00:07:04,200 But we only decided to use just a couple of these, 145 00:07:04,200 --> 00:07:07,020 which was just the horizontal and the vertical ones that 146 00:07:07,020 --> 00:07:09,630 are completely whole. 147 00:07:09,630 --> 00:07:14,370 These, unfortunately, don't have quite the same systematic layout 148 00:07:14,370 --> 00:07:16,170 as the sprites that we used before. 149 00:07:16,170 --> 00:07:18,820 They're not laid out in a grid evenly spaced. 150 00:07:18,820 --> 00:07:22,740 So in this case, in util dot Lua, I ended up hard 151 00:07:22,740 --> 00:07:26,160 coding the different XY width and height quads 152 00:07:26,160 --> 00:07:29,160 for each of these, which is what you have to do in a situation 153 00:07:29,160 --> 00:07:31,780 where you're interacting not with tiles per se, 154 00:07:31,780 --> 00:07:33,960 but with more organic shaped objects. 155 00:07:33,960 --> 00:07:36,390 So it can take a little more time to end up 156 00:07:36,390 --> 00:07:39,205 constructing all of the quads for your objects 157 00:07:39,205 --> 00:07:40,830 when you have a sprite sheet like this. 158 00:07:40,830 --> 00:07:43,560 But, fortunately, you only have to do it once. 159 00:07:43,560 --> 00:07:46,890 Here's a few useful links before we get started in talking about what Box2D is 160 00:07:46,890 --> 00:07:50,190 and how to use it, and basically how it's called love dot 161 00:07:50,190 --> 00:07:52,670 physics, effectively, in love2D. 162 00:07:52,670 --> 00:07:56,325 The first two links are documentation for love 2D, 163 00:07:56,325 --> 00:07:58,950 what the functions and objects are that we'll be talking about. 164 00:07:58,950 --> 00:08:01,324 And a simple tutorial that talks about how to make a ball 165 00:08:01,324 --> 00:08:05,070 bounce in love 2D using Box2D. 166 00:08:05,070 --> 00:08:07,950 The third is a great resource that I used actually 167 00:08:07,950 --> 00:08:11,250 to learn most of what I know about Box2D, especially 168 00:08:11,250 --> 00:08:13,984 in the context of this lecture. 169 00:08:13,984 --> 00:08:15,900 So it talks about a lot of different concepts. 170 00:08:15,900 --> 00:08:17,290 It talks about all the things that we'll be talking about. 171 00:08:17,290 --> 00:08:19,710 And then it goes into a lot more detail about how 172 00:08:19,710 --> 00:08:24,540 you can go about constructing a lot of really cool, crazy things like tanks 173 00:08:24,540 --> 00:08:27,150 and pulleys and a whole bunch of different things 174 00:08:27,150 --> 00:08:30,030 that are worth looking into if you're looking into potentially making 175 00:08:30,030 --> 00:08:31,230 a physics based game. 176 00:08:31,230 --> 00:08:35,429 Obviously we won't be going into things of that complexity here. 177 00:08:35,429 --> 00:08:37,169 But you could easily do it with Box2D. 178 00:08:37,169 --> 00:08:40,350 It makes it very, very possible. 179 00:08:40,350 --> 00:08:43,620 So the very first thing that we should talk 180 00:08:43,620 --> 00:08:47,100 about when we want to construct a game, or simulation, 181 00:08:47,100 --> 00:08:50,490 or whatever we want to do, with Box2D is we 182 00:08:50,490 --> 00:08:55,320 need some sort of system that will actually perform the simulation for us. 183 00:08:55,320 --> 00:09:02,670 And the fundamental core of what a Box2D app or game is, the core is the world 184 00:09:02,670 --> 00:09:03,280 object. 185 00:09:03,280 --> 00:09:06,780 So there is a world that you can think of as sort of being your world, 186 00:09:06,780 --> 00:09:12,810 but what it effectively is is a machine that simulates all of the pieces 187 00:09:12,810 --> 00:09:16,200 that you've told it interact with each other in Box2D. 188 00:09:16,200 --> 00:09:20,310 So Box2D has a set of objects called fixtures and bodies. 189 00:09:20,310 --> 00:09:22,820 Those perform the physical interactions. 190 00:09:22,820 --> 00:09:25,650 And it's up to the world to update all of those 191 00:09:25,650 --> 00:09:28,680 and apply the relevant forces and physics calculations 192 00:09:28,680 --> 00:09:32,450 that resolve collisions and do all sorts of things. 193 00:09:32,450 --> 00:09:35,487 All of the things that Box2D does for us, the world 194 00:09:35,487 --> 00:09:36,570 takes care of this for us. 195 00:09:36,570 --> 00:09:40,050 So we don't have to manually go through and update every single object 196 00:09:40,050 --> 00:09:43,020 with its velocity that we've done before and check for collisions. 197 00:09:43,020 --> 00:09:45,240 The world does this for us, and resolves them 198 00:09:45,240 --> 00:09:48,120 based on how we tell it to resolve them. 199 00:09:48,120 --> 00:09:51,120 And the world also possesses, like an actual world 200 00:09:51,120 --> 00:09:53,730 would, gravity on the x and y-axis. 201 00:09:53,730 --> 00:09:57,630 In this case, we have gravity applied on the y-axis going down, 202 00:09:57,630 --> 00:09:59,820 so it's a positive value. 203 00:09:59,820 --> 00:10:03,420 We set it to 300 in this distro, but you can set it to whatever you want. 204 00:10:03,420 --> 00:10:05,610 Setting a lower gravity would have the effect 205 00:10:05,610 --> 00:10:08,110 of making it feel like we're on the moon or something. 206 00:10:08,110 --> 00:10:10,110 Making it feel like we're on a different planet. 207 00:10:10,110 --> 00:10:11,276 So that's what the world is. 208 00:10:11,276 --> 00:10:12,650 The world simulates everything. 209 00:10:12,650 --> 00:10:14,400 And we'll go through just a few terms here 210 00:10:14,400 --> 00:10:15,990 before we look at some source code. 211 00:10:15,990 --> 00:10:20,250 But there's a few terms that we need to understand before we can really 212 00:10:20,250 --> 00:10:22,930 understand what Box2D is doing. 213 00:10:22,930 --> 00:10:26,490 And this is the function that we use to create a new world in love2D. 214 00:10:26,490 --> 00:10:29,730 Very simple, love dot physics dot new world. 215 00:10:29,730 --> 00:10:33,510 And this love dot physics is just a name space that 216 00:10:33,510 --> 00:10:41,410 encapsulates all of the Box2D functions and objects that love2D has access to. 217 00:10:41,410 --> 00:10:44,220 So anything that you see in love dot physics is effectively 218 00:10:44,220 --> 00:10:47,100 a wrapper for Box2D. 219 00:10:47,100 --> 00:10:51,330 And to clarify about Box2D, Box2D is just a library that's written in C++ 220 00:10:51,330 --> 00:10:54,240 that you can plug-in pretty much anywhere you want to. 221 00:10:54,240 --> 00:10:58,080 Unity uses it and, actually, most 2D game engines 222 00:10:58,080 --> 00:11:03,420 that I've ever seen including Live GDX, for example, which is a very large Java 223 00:11:03,420 --> 00:11:05,880 2D game framework uses Box2D. 224 00:11:05,880 --> 00:11:07,920 You can use it anywhere. 225 00:11:07,920 --> 00:11:11,640 In this case we're using love2D's own wrapper for it. 226 00:11:11,640 --> 00:11:15,270 So the people that created love 2D, they took Box2D 227 00:11:15,270 --> 00:11:17,490 and then they just put a bunch of Lua functions 228 00:11:17,490 --> 00:11:19,650 around them, around all the objects and functions 229 00:11:19,650 --> 00:11:22,620 to make it possible to use it in the same style 230 00:11:22,620 --> 00:11:24,592 that we use the rest of the framework. 231 00:11:24,592 --> 00:11:26,050 This is how you create a new world. 232 00:11:26,050 --> 00:11:29,310 This is the first step in getting your Box2D simulation working. 233 00:11:29,310 --> 00:11:32,460 So any questions so far as to how we can get that going? 234 00:11:32,460 --> 00:11:34,050 OK. 235 00:11:34,050 --> 00:11:39,240 So beyond the world object, which is the foundation, sort of sets up our stage, 236 00:11:39,240 --> 00:11:42,540 you can think of it as our stage, we need bodies 237 00:11:42,540 --> 00:11:44,770 to actually interact with each other. 238 00:11:44,770 --> 00:11:47,880 So a body is just an abstract container. 239 00:11:47,880 --> 00:11:52,650 It basically holds a position and a velocity. 240 00:11:52,650 --> 00:11:56,190 And you attach things to it via what are called fixtures 241 00:11:56,190 --> 00:12:00,612 that allow you to give the body a shape, and therefore a collision box, 242 00:12:00,612 --> 00:12:02,820 and therefore allow it to interact with other things. 243 00:12:02,820 --> 00:12:07,590 But a body is essentially all the disparate things in your scene interact 244 00:12:07,590 --> 00:12:09,510 with each other and move around. 245 00:12:09,510 --> 00:12:14,160 And so to create a new body we just do love dot physics dot new body. 246 00:12:14,160 --> 00:12:17,610 We pass in the world, so therefore when we do this, 247 00:12:17,610 --> 00:12:19,950 the world has a reference to this body now. 248 00:12:19,950 --> 00:12:22,440 And every time we call update on our world, which 249 00:12:22,440 --> 00:12:25,230 we'll see in the source code, it will know, OK, 250 00:12:25,230 --> 00:12:29,280 I have a reference to this body, perform all of the relevant checks 251 00:12:29,280 --> 00:12:33,660 on the collision for that body and all the fixtures that it contains. 252 00:12:33,660 --> 00:12:38,770 Update its position, updates velocity, and so forth. 253 00:12:38,770 --> 00:12:41,700 And not only a world, but it also gets an x and a y, 254 00:12:41,700 --> 00:12:45,900 which will place it in the world on instantiation. 255 00:12:45,900 --> 00:12:48,970 The last parameter here, type. 256 00:12:48,970 --> 00:12:51,330 There are three fundamental types of bodies 257 00:12:51,330 --> 00:12:56,130 which we'll see in love 2D, static, dynamic, and kinematic. 258 00:12:56,130 --> 00:12:59,580 And that basically influences how it'll interact with the other objects, 259 00:12:59,580 --> 00:13:01,810 the other bodies, in our scene. 260 00:13:01,810 --> 00:13:04,860 So we have the world, which encapsulates everything, 261 00:13:04,860 --> 00:13:06,900 all the bodies, all the fixtures. 262 00:13:06,900 --> 00:13:10,380 And then we have the bodies, which are the entities in our game world 263 00:13:10,380 --> 00:13:14,310 that have position and velocity, effectively. 264 00:13:14,310 --> 00:13:18,180 The last key ingredient here that will allow 265 00:13:18,180 --> 00:13:23,820 us to create interactions between the bodies that we have are fixtures. 266 00:13:23,820 --> 00:13:28,680 And fixtures, all a fixture is, is this abstract object 267 00:13:28,680 --> 00:13:31,650 that will allow you to attach a shape to a body. 268 00:13:31,650 --> 00:13:34,740 So bodies are shapeless by default. They don't have a shape. 269 00:13:34,740 --> 00:13:39,930 They are just a container that has position velocity, effectively. 270 00:13:39,930 --> 00:13:42,010 But they don't interact with anything else. 271 00:13:42,010 --> 00:13:44,260 And they don't know how to interact with anything else 272 00:13:44,260 --> 00:13:46,290 until you give them a fixture. 273 00:13:46,290 --> 00:13:50,170 And the fixture you will give the body and a shape. 274 00:13:50,170 --> 00:13:52,860 So for example, if you want the bird that we 275 00:13:52,860 --> 00:13:56,715 were looking at earlier, the alien, the round alien, we create a body for it 276 00:13:56,715 --> 00:13:59,880 in our world, which doesn't mean anything yet. 277 00:13:59,880 --> 00:14:03,810 But we say, I'm going to attach a fixture to that alien. 278 00:14:03,810 --> 00:14:05,760 I'm going to give it a circle shape. 279 00:14:05,760 --> 00:14:08,970 And it'll then know whenever it performs any calculations, 280 00:14:08,970 --> 00:14:13,170 that that alien should interact with things as if it were round. 281 00:14:13,170 --> 00:14:16,410 And therefore trigger collisions based on a circular hitbox, 282 00:14:16,410 --> 00:14:21,180 as opposed to a rectangular or polygonal hitbox, as we'll see. 283 00:14:21,180 --> 00:14:24,390 Fixtures, in addition to attaching shapes 284 00:14:24,390 --> 00:14:27,300 to bodies, which will, as said here, influence 285 00:14:27,300 --> 00:14:32,010 how they collide with other bodies, they have density, which we'll see. 286 00:14:32,010 --> 00:14:34,110 So that things with higher density obviously 287 00:14:34,110 --> 00:14:38,704 will fall faster, or not fall faster, but they will influence things 288 00:14:38,704 --> 00:14:39,870 as if they have more weight. 289 00:14:39,870 --> 00:14:43,660 They will push things farther when they collide with them. 290 00:14:43,660 --> 00:14:46,110 They also have friction and they have restitution. 291 00:14:46,110 --> 00:14:48,120 Restitution is bounciness. 292 00:14:48,120 --> 00:14:51,810 So if something, if we had our alien, no restitution when it hits the ground 293 00:14:51,810 --> 00:14:53,590 it'll just fall flat. 294 00:14:53,590 --> 00:14:55,410 But if we give it a higher restitution it 295 00:14:55,410 --> 00:14:58,080 will actually bounce when it hits the ground. 296 00:14:58,080 --> 00:15:02,380 And therefore interact with the world a little bit differently. 297 00:15:02,380 --> 00:15:08,000 So when we want to take a fixture and apply a shape to a body, 298 00:15:08,000 --> 00:15:09,750 we have a few different shapes that we can 299 00:15:09,750 --> 00:15:12,930 apply to it that are given to us by default in love 2D. 300 00:15:12,930 --> 00:15:15,340 So circle shape, rectangle shape, edge shape. 301 00:15:15,340 --> 00:15:18,520 These are just, effectively, how we define how 302 00:15:18,520 --> 00:15:20,680 our bodies interact with other bodies. 303 00:15:20,680 --> 00:15:24,010 How, for example, if it's something that's circular 304 00:15:24,010 --> 00:15:26,680 it should roll when it's moving along the ground. 305 00:15:26,680 --> 00:15:29,680 Or when it hits something the corner obviously of it 306 00:15:29,680 --> 00:15:32,990 won't hit something because it's rounded, as opposed to something 307 00:15:32,990 --> 00:15:36,670 that has a square hit box, it'll affect things in a slightly different way. 308 00:15:36,670 --> 00:15:40,840 And we can define arbitrarily shaped hit boxes, thanks to the polygon shape. 309 00:15:40,840 --> 00:15:45,560 If we want something to be shaped like a pentagon, for example, 310 00:15:45,560 --> 00:15:47,870 and have it roll around and behave like such, 311 00:15:47,870 --> 00:15:51,730 we can just define a polygon via a set of vertices. 312 00:15:51,730 --> 00:15:54,820 And then affix that to a body and it will 313 00:15:54,820 --> 00:15:57,900 behave as if it were pentagon shaped. 314 00:15:57,900 --> 00:16:00,280 And this is how you would instantiate just as we've 315 00:16:00,280 --> 00:16:03,940 seen with love dot physics dot new world and love dot physics dot new body, 316 00:16:03,940 --> 00:16:07,180 love dot physics dot new fixture takes in a body and a shape, 317 00:16:07,180 --> 00:16:10,180 and will apply that shape to the body. 318 00:16:10,180 --> 00:16:14,779 And the world after that will know exactly how to collide with things. 319 00:16:14,779 --> 00:16:16,570 And so the last thing, the last slide we'll 320 00:16:16,570 --> 00:16:19,229 look at here before we start looking at source code 321 00:16:19,229 --> 00:16:20,770 is what the different body types are. 322 00:16:20,770 --> 00:16:25,600 So I alluded to having three different body types before, static, dynamic, 323 00:16:25,600 --> 00:16:26,710 and kinematic. 324 00:16:26,710 --> 00:16:32,080 So a static body will exist in our world but not actually be affected by gravity 325 00:16:32,080 --> 00:16:34,090 or the collision of anything else. 326 00:16:34,090 --> 00:16:36,730 Things can hit it and bounce off of it and do their own thing, 327 00:16:36,730 --> 00:16:39,790 but the static body will never be influenced by something else. 328 00:16:39,790 --> 00:16:43,817 It exists as some sort of permanent structure, almost like the ground. 329 00:16:43,817 --> 00:16:46,900 You don't really affect the ground by moving into it and bouncing into it, 330 00:16:46,900 --> 00:16:49,360 unless you do it with enough force. 331 00:16:49,360 --> 00:16:55,090 But in our Box2D world, a static body cannot be influenced by anything else. 332 00:16:55,090 --> 00:16:57,770 A dynamic body is the opposite. 333 00:16:57,770 --> 00:17:03,310 It has the full simulation of Box2D. 334 00:17:03,310 --> 00:17:06,790 Gravity affects it, things collide into it, it will bounce off of them. 335 00:17:06,790 --> 00:17:09,010 It'll do what you would expect a normal body to do. 336 00:17:09,010 --> 00:17:13,150 If I throw a ball in this room and it hits the wall, it's a dynamic body. 337 00:17:13,150 --> 00:17:15,940 The walls are the static bodies in this case. 338 00:17:15,940 --> 00:17:19,720 And then a kinematic body is a hybrid between the two. 339 00:17:19,720 --> 00:17:24,109 It's something that can move and can rotate and do things, 340 00:17:24,109 --> 00:17:28,400 but it's not influenced by other objects colliding with it. 341 00:17:28,400 --> 00:17:32,860 So, for example, if I have a platform that's just spinning indefinitely, 342 00:17:32,860 --> 00:17:36,940 but it's not being affected by gravity and it doesn't move when I hit it, 343 00:17:36,940 --> 00:17:38,170 that's a kinematic body. 344 00:17:38,170 --> 00:17:42,400 It's still moving and it's semi-static and it influences other things, 345 00:17:42,400 --> 00:17:43,660 but it's not purely static. 346 00:17:43,660 --> 00:17:47,197 It does have a little bit of behavior that it can grant it. 347 00:17:47,197 --> 00:17:49,030 So let's go ahead and look at a few examples 348 00:17:49,030 --> 00:17:53,030 now and see how this actually looks in code. 349 00:17:53,030 --> 00:17:56,380 So I'm going to go into an example, if you're looking in the distro, 350 00:17:56,380 --> 00:17:58,600 there is an example called static. 351 00:17:58,600 --> 00:18:02,227 So we'll take a look here and see what a static body looks like in our scene. 352 00:18:02,227 --> 00:18:04,560 And for all of these examples leading up to Angry Birds, 353 00:18:04,560 --> 00:18:08,320 we're just going to render everything with shapes for simplicity. 354 00:18:08,320 --> 00:18:14,350 But this, as anti-climactic as it is, is a full Box2D world 355 00:18:14,350 --> 00:18:17,020 with just a single static body. 356 00:18:17,020 --> 00:18:19,410 And it's just this square here, colored white. 357 00:18:19,410 --> 00:18:21,620 The static body doesn't move, it doesn't do anything. 358 00:18:21,620 --> 00:18:25,000 Nothing can influence how it moves or behaves. 359 00:18:25,000 --> 00:18:27,190 But it exists in our world as a permanent fixture. 360 00:18:27,190 --> 00:18:30,370 And if we had dynamic bodies and we threw a dynamic body at it, 361 00:18:30,370 --> 00:18:32,770 for example, the dynamic body would bounce off, 362 00:18:32,770 --> 00:18:34,872 the static body would stay there permanently. 363 00:18:34,872 --> 00:18:36,580 So let's go ahead and take a look at what 364 00:18:36,580 --> 00:18:38,200 the source code looks like for that. 365 00:18:38,200 --> 00:18:42,820 So I'm here in main dot Lua of our static file. 366 00:18:42,820 --> 00:18:46,630 And just as we've seen before, we needed to find a world. 367 00:18:46,630 --> 00:18:49,270 So I have a world here on line 45. 368 00:18:49,270 --> 00:18:52,960 Love dot physics dot new world, no x-able gravity, 369 00:18:52,960 --> 00:18:57,910 but we are going to have 300 units of positive gravity on the y-axis, which 370 00:18:57,910 --> 00:19:01,720 is going from top to bottom. 371 00:19:01,720 --> 00:19:06,460 We need a body for our square that's in our game world, our static square. 372 00:19:06,460 --> 00:19:08,800 So we're going to go ahead and define a new body here. 373 00:19:08,800 --> 00:19:11,251 Love dot physics dot new body takes in the world, 374 00:19:11,251 --> 00:19:14,500 recall, because that's how our world's going to have a reference to that body, 375 00:19:14,500 --> 00:19:18,117 doesn't know about it unless we pass it into here, our new body constructor. 376 00:19:18,117 --> 00:19:20,950 And then I'm just going to put it right in the middle of the screen. 377 00:19:20,950 --> 00:19:25,030 So virtual width divided by 2 and virtual height divided by 2. 378 00:19:25,030 --> 00:19:29,020 The difference between Box2D bodies and things 379 00:19:29,020 --> 00:19:31,270 that we've drawn before or seen before is 380 00:19:31,270 --> 00:19:34,690 that everything is defined by its center point, as opposed to its top left. 381 00:19:34,690 --> 00:19:37,150 So I'm able to say virtual width divided by 2 382 00:19:37,150 --> 00:19:39,270 and virtual height divided by 2 here. 383 00:19:39,270 --> 00:19:42,790 But I don't actually need to say virtual width divided by 2 minus whatever 384 00:19:42,790 --> 00:19:44,800 the half of that square is. 385 00:19:44,800 --> 00:19:50,740 By default, the center point is the XY of that object. 386 00:19:50,740 --> 00:19:55,600 And this last string here in the constructor for our new body, static, 387 00:19:55,600 --> 00:19:58,810 tells the constructor that this is going to be a static body specifically, 388 00:19:58,810 --> 00:20:02,960 not a dynamic body and not a kinematic body. 389 00:20:02,960 --> 00:20:05,962 So we have a body and it's static, but it doesn't have a shape, 390 00:20:05,962 --> 00:20:08,920 it doesn't really know how to interact with anything else in our world. 391 00:20:08,920 --> 00:20:10,270 So we're going to give it a-- 392 00:20:10,270 --> 00:20:12,340 we're going to create a new shape first. 393 00:20:12,340 --> 00:20:18,347 So love gives us a few functions in the form of new X shape. 394 00:20:18,347 --> 00:20:20,930 We have new rectangle shape, new circle shape, new edge shape, 395 00:20:20,930 --> 00:20:22,620 a few other ones. 396 00:20:22,620 --> 00:20:26,380 We're just going to create a new rectangle of width and height of 10. 397 00:20:26,380 --> 00:20:28,420 So that's what the 10 and 10 are here. 398 00:20:28,420 --> 00:20:31,070 Then we're going to create a new fixture. 399 00:20:31,070 --> 00:20:37,370 We're going to affix the box shape to our body with this function. 400 00:20:37,370 --> 00:20:44,420 And then once we do that, all we have to do is then render a polygon with fill 401 00:20:44,420 --> 00:20:48,950 and then we get the coordinates for our-- or the vertices for our polygon 402 00:20:48,950 --> 00:20:52,190 by saying, body get world points. 403 00:20:52,190 --> 00:20:55,940 So that's a function off of any Box2D body 404 00:20:55,940 --> 00:21:01,400 that will basically get where it is in the world and all of its vertices. 405 00:21:01,400 --> 00:21:04,730 And then you just pass in the shape that you want to get the points for. 406 00:21:04,730 --> 00:21:08,300 And that will end up just exploding here into a set of vertices 407 00:21:08,300 --> 00:21:10,790 that fill up this love dot graphics dot polygon. 408 00:21:10,790 --> 00:21:17,090 And the end result of that is we get a square. 409 00:21:17,090 --> 00:21:21,275 And we specifically use polygon instead of love 410 00:21:21,275 --> 00:21:24,566 dot graphics dot new rectangle because that's what the get 411 00:21:24,566 --> 00:21:26,690 world points function explodes out to. 412 00:21:26,690 --> 00:21:32,150 It doesn't explode out to the number of arguments that would satisfy 413 00:21:32,150 --> 00:21:35,040 love dot graphics dot rectangle. 414 00:21:35,040 --> 00:21:37,460 So not a very exciting example. 415 00:21:37,460 --> 00:21:43,110 But this is basically the foundation of a full Box2D application. 416 00:21:43,110 --> 00:21:46,411 So any questions as to how this works at all? 417 00:21:46,411 --> 00:21:47,036 AUDIENCE: Yeah. 418 00:21:47,036 --> 00:21:48,032 I'm wondering. 419 00:21:48,032 --> 00:21:52,514 How does it determine the center of a abnormal shape? 420 00:21:52,514 --> 00:21:54,804 Not like a polygon, square, rectangle, or circle. 421 00:21:54,804 --> 00:21:56,720 COLTON OGDEN: The center of an abnormal shape. 422 00:21:56,720 --> 00:21:57,710 I'm not entirely sure. 423 00:21:57,710 --> 00:22:00,774 The circle is just-- 424 00:22:00,774 --> 00:22:01,680 AUDIENCE: [INAUDIBLE] 425 00:22:01,680 --> 00:22:02,471 COLTON OGDEN: Yeah. 426 00:22:02,471 --> 00:22:04,790 I'm not entirely sure about a polygon though. 427 00:22:04,790 --> 00:22:06,790 I haven't looked into that into too much detail. 428 00:22:06,790 --> 00:22:08,040 I can explore that and see. 429 00:22:08,040 --> 00:22:11,320 That's something that I think Box2D is-- 430 00:22:11,320 --> 00:22:14,300 the actual library implements that and calculates that. 431 00:22:14,300 --> 00:22:18,029 Probably based upon calculating the area of-- 432 00:22:18,029 --> 00:22:20,570 and to repeat for the camera if I didn't repeat already, it's 433 00:22:20,570 --> 00:22:25,340 how does Box2D calculate the center point of something non-symmetrical, 434 00:22:25,340 --> 00:22:27,860 like a polygon? 435 00:22:27,860 --> 00:22:33,230 And best I can understand is that it would do an area calculation off of it 436 00:22:33,230 --> 00:22:38,567 and figure out where all the vertices tend towards, I guess. 437 00:22:38,567 --> 00:22:41,150 But, yeah, that's something that's implemented in the library. 438 00:22:41,150 --> 00:22:42,170 I'm not entirely sure. 439 00:22:42,170 --> 00:22:46,469 I can look into it and see and then I'll post in the Slack. 440 00:22:46,469 --> 00:22:48,718 AUDIENCE: It seems like [INAUDIBLE] you did have that, 441 00:22:48,718 --> 00:22:52,940 it would be difficult to place in a very precise spot. 442 00:22:52,940 --> 00:22:55,010 COLTON OGDEN: Yeah. 443 00:22:55,010 --> 00:22:56,810 If it were-- yeah. 444 00:22:56,810 --> 00:23:00,220 If we did have an odd shape to get it placed in a exact spot. 445 00:23:00,220 --> 00:23:01,440 Yeah, I'm not entirely sure. 446 00:23:01,440 --> 00:23:04,450 I'd have to explore that a little bit. 447 00:23:04,450 --> 00:23:05,450 Interesting idea though. 448 00:23:05,450 --> 00:23:07,980 449 00:23:07,980 --> 00:23:13,444 But, yeah, that's essentially how we get a Box2D world up and running. 450 00:23:13,444 --> 00:23:14,360 We have a static body. 451 00:23:14,360 --> 00:23:16,580 It's not terribly interesting. 452 00:23:16,580 --> 00:23:19,130 But with one change-- 453 00:23:19,130 --> 00:23:23,150 so I have a separate example called dynamic in the source code distro. 454 00:23:23,150 --> 00:23:26,760 But all we need to do to really see the difference 455 00:23:26,760 --> 00:23:32,360 between a static and dynamic body is on line 48, just change static to dynamic, 456 00:23:32,360 --> 00:23:35,660 save it, and then rerun it. 457 00:23:35,660 --> 00:23:38,300 And then we'll immediately see that it's affected by gravity 458 00:23:38,300 --> 00:23:41,930 and it moves downwards as we've told the world that our gravity is 459 00:23:41,930 --> 00:23:43,880 set to positive 300. 460 00:23:43,880 --> 00:23:47,000 And so that behaves how we would expect it to. 461 00:23:47,000 --> 00:23:50,730 Now, there's nothing else in the scene so it's not particularly interesting. 462 00:23:50,730 --> 00:23:55,220 So I've created a another example called ground. 463 00:23:55,220 --> 00:23:58,110 So let's go ahead and look at that. 464 00:23:58,110 --> 00:24:02,970 465 00:24:02,970 --> 00:24:09,408 So if we want more interesting behavior, what do we need to do in a nutshell? 466 00:24:09,408 --> 00:24:11,719 AUDIENCE: Have more shapes and make a ground. 467 00:24:11,719 --> 00:24:13,760 COLTON OGDEN: Some more shapes and make a ground. 468 00:24:13,760 --> 00:24:14,600 Exactly. 469 00:24:14,600 --> 00:24:17,330 That's a simple way we can start to get instantly 470 00:24:17,330 --> 00:24:19,490 a sense of how powerful Box2D is. 471 00:24:19,490 --> 00:24:22,940 Just introduce more shapes that interact with each other in different ways. 472 00:24:22,940 --> 00:24:28,540 So ground is an example that just introduces a ground into our scene, 473 00:24:28,540 --> 00:24:33,590 so that we can see the box fall down and actually collide with something else. 474 00:24:33,590 --> 00:24:36,480 And Love2D makes this nice and easy. 475 00:24:36,480 --> 00:24:37,190 Excuse me. 476 00:24:37,190 --> 00:24:40,640 They have a actual edge shape that will allow us 477 00:24:40,640 --> 00:24:44,150 to basically form where the ground is. 478 00:24:44,150 --> 00:24:48,710 Anything that collides with this-- it's effectively a line. 479 00:24:48,710 --> 00:24:52,430 But no matter how fast anything moves in are scene, 480 00:24:52,430 --> 00:24:56,690 the body will not move past that line. 481 00:24:56,690 --> 00:25:00,100 So it's a nice, easy way of getting a ground in our scene 482 00:25:00,100 --> 00:25:03,560 without having to implement a polygon that maybe has two vertices going 483 00:25:03,560 --> 00:25:05,387 left to right on the screen. 484 00:25:05,387 --> 00:25:06,470 So that's what we do here. 485 00:25:06,470 --> 00:25:11,720 We have a ground body, which is a static body, recall. 486 00:25:11,720 --> 00:25:14,150 Because the ground shouldn't move. 487 00:25:14,150 --> 00:25:18,101 We're going to change the box into a dynamic body, 488 00:25:18,101 --> 00:25:19,350 but the ground shouldn't move. 489 00:25:19,350 --> 00:25:21,183 The ground should be unaffected by anything. 490 00:25:21,183 --> 00:25:23,210 It's going to be static in our scene. 491 00:25:23,210 --> 00:25:25,400 And it's going to have an edge shape. 492 00:25:25,400 --> 00:25:28,850 So notice here, we take 0, 0 as the XY. 493 00:25:28,850 --> 00:25:31,220 And then a virtual width is zero. 494 00:25:31,220 --> 00:25:35,510 So with shapes, when we define them here, 495 00:25:35,510 --> 00:25:39,690 it's not going to draw the shape at 0, 0, at virtual width in 0. 496 00:25:39,690 --> 00:25:42,680 This is relative to wherever the body is located. 497 00:25:42,680 --> 00:25:45,350 So wherever our body is, this shape will be 498 00:25:45,350 --> 00:25:49,460 drawn with these coordinates, this X and Y and this width and height, 499 00:25:49,460 --> 00:25:50,930 relative to that. 500 00:25:50,930 --> 00:25:56,130 And specifically, relative to the center point of wherever we place a body. 501 00:25:56,130 --> 00:26:01,440 So if this ground is set to 0, 0 at virtual width and zero, 502 00:26:01,440 --> 00:26:03,440 where do we need to place the actual body for it 503 00:26:03,440 --> 00:26:08,125 to render the ground appropriately? 504 00:26:08,125 --> 00:26:09,829 AUDIENCE: The middle bottom. 505 00:26:09,829 --> 00:26:12,370 COLTON OGDEN: Yeah, so we place it towards the middle bottom. 506 00:26:12,370 --> 00:26:18,670 So we actually end up placing the body itself here at virtual height minus 30. 507 00:26:18,670 --> 00:26:21,850 And when we affix this edge shape to the body, we'll end up, 508 00:26:21,850 --> 00:26:24,280 even though it says 0, 0 virtual width zero, 509 00:26:24,280 --> 00:26:27,070 it's relative to wherever the body's XY are. 510 00:26:27,070 --> 00:26:31,210 So it's actually going to be 0 virtual height minus 30, 511 00:26:31,210 --> 00:26:35,800 virtual width zero will be where that edge exists. 512 00:26:35,800 --> 00:26:37,990 And then lastly, just as we did with our box, 513 00:26:37,990 --> 00:26:41,980 we need a ground fixture so that the ground body knows how 514 00:26:41,980 --> 00:26:43,820 it should interact with other things. 515 00:26:43,820 --> 00:26:47,350 So we're going to affix the edge shape, which is just a line, 516 00:26:47,350 --> 00:26:49,870 to our ground body. 517 00:26:49,870 --> 00:26:53,410 And then here we do love dot graphics-- just 518 00:26:53,410 --> 00:26:58,030 as we did with the love dot graphics dot polygon for our box, 519 00:26:58,030 --> 00:27:00,931 we're going to do love dot graphics dot line for our ground body. 520 00:27:00,931 --> 00:27:03,430 And we're going to do the exact same thing, get world points 521 00:27:03,430 --> 00:27:06,510 and get points passing the edge shape here. 522 00:27:06,510 --> 00:27:09,850 And I'm also setting a line width of 2 just 523 00:27:09,850 --> 00:27:11,920 so we can see it a little bit better. 524 00:27:11,920 --> 00:27:13,580 And I'm going to color it red. 525 00:27:13,580 --> 00:27:17,770 Again, I colored the box up here green. 526 00:27:17,770 --> 00:27:20,570 So go ahead take a look at what this looks like. 527 00:27:20,570 --> 00:27:24,280 So I'm going to go into ground. 528 00:27:24,280 --> 00:27:27,120 529 00:27:27,120 --> 00:27:30,460 And so notice-- and I also added a little bit of restitution 530 00:27:30,460 --> 00:27:33,910 to the-- as I said before, restitution is a quality that a fixture can 531 00:27:33,910 --> 00:27:35,890 have which gives it bounciness. 532 00:27:35,890 --> 00:27:38,350 So rather than just falling flat down onto the ground, 533 00:27:38,350 --> 00:27:39,740 it bounces a little bit as well. 534 00:27:39,740 --> 00:27:42,323 And we can see the interaction, so I'll play it one more time. 535 00:27:42,323 --> 00:27:43,630 It starts in the middle. 536 00:27:43,630 --> 00:27:46,600 And then as soon as it hits the ground body 537 00:27:46,600 --> 00:27:49,840 that we created before, the edge shape, it bounces a couple of times. 538 00:27:49,840 --> 00:27:54,580 But it shows that the box is dynamic, but the ground is static. 539 00:27:54,580 --> 00:27:57,040 Nothing influences the position of the ground. 540 00:27:57,040 --> 00:28:01,900 It gets hard set and will stay there permanently. 541 00:28:01,900 --> 00:28:05,260 So that shows a nice, easy simple demonstration 542 00:28:05,260 --> 00:28:09,820 of an interaction between a static and a dynamic body. 543 00:28:09,820 --> 00:28:13,250 I'm going to go ahead and pull up another example here. 544 00:28:13,250 --> 00:28:18,460 So kinematic, recall, what was the difference between a kinematic 545 00:28:18,460 --> 00:28:21,298 and a static or dynamic body? 546 00:28:21,298 --> 00:28:23,798 AUDIENCE: Kinematic can move but not influence other shapes. 547 00:28:23,798 --> 00:28:24,714 COLTON OGDEN: Correct. 548 00:28:24,714 --> 00:28:26,030 So a kinematic body can move. 549 00:28:26,030 --> 00:28:31,000 You can ascribe it positional velocity or angular velocity, it's rotation. 550 00:28:31,000 --> 00:28:35,290 But when something collides with it, it's not going to be influenced by it. 551 00:28:35,290 --> 00:28:38,530 It's going to influence the body that it collides with. 552 00:28:38,530 --> 00:28:40,780 It's going to affect it in some way, but nothing 553 00:28:40,780 --> 00:28:42,700 colliding with the kinematic body is going 554 00:28:42,700 --> 00:28:45,790 to have an effect on its position or its velocity. 555 00:28:45,790 --> 00:28:48,970 It's something that exists and does something programmed 556 00:28:48,970 --> 00:28:50,920 and will just do that indefinitely, but it 557 00:28:50,920 --> 00:28:55,260 will interact with other dynamic bodies as we have programmed. 558 00:28:55,260 --> 00:28:57,760 And it will not interact with other kinematic bodies either. 559 00:28:57,760 --> 00:29:00,280 They will almost pretend that each other doesn't exist. 560 00:29:00,280 --> 00:29:03,785 If you overlap a static and a kinematic body or kinematic and a kinematic body, 561 00:29:03,785 --> 00:29:06,160 they render on top of each other, but they don't actually 562 00:29:06,160 --> 00:29:09,470 influence each other's position or anything like that. 563 00:29:09,470 --> 00:29:13,695 So I'm going to go ahead and run the kinematic example. 564 00:29:13,695 --> 00:29:19,550 565 00:29:19,550 --> 00:29:23,780 So here we have a few things going on. 566 00:29:23,780 --> 00:29:27,410 We have the box body that we had before, the dynamic box that 567 00:29:27,410 --> 00:29:29,520 falls from the middle of the screen. 568 00:29:29,520 --> 00:29:31,700 We have the ground on the very bottom to catch it. 569 00:29:31,700 --> 00:29:35,240 But we have three kinematic boxes in the very center that 570 00:29:35,240 --> 00:29:39,440 are spinning that influence the green box 571 00:29:39,440 --> 00:29:41,700 when the green box collides with them. 572 00:29:41,700 --> 00:29:44,510 So as you can see, it tosses it around and then 573 00:29:44,510 --> 00:29:46,610 the green body falls back to the bottom. 574 00:29:46,610 --> 00:29:49,070 And in this example I've taken away its restitution. 575 00:29:49,070 --> 00:29:53,300 So as soon as it hits the ground, it just falls flat. 576 00:29:53,300 --> 00:29:54,870 Just like that. 577 00:29:54,870 --> 00:29:57,330 And so, as you can see, these blue bodies, they're moving. 578 00:29:57,330 --> 00:30:00,830 They have angular velocity indefinitely. 579 00:30:00,830 --> 00:30:04,940 Specifically 360 degrees per second. 580 00:30:04,940 --> 00:30:09,080 And they will stay in that exact position and rotate in that exact way 581 00:30:09,080 --> 00:30:10,080 forever. 582 00:30:10,080 --> 00:30:13,370 But as soon as they interact with a dynamic body, 583 00:30:13,370 --> 00:30:16,670 they actually cause a collision with that dynamic body. 584 00:30:16,670 --> 00:30:19,550 And the collision resolves and this green body 585 00:30:19,550 --> 00:30:21,710 gets tossed around because it's dynamic. 586 00:30:21,710 --> 00:30:27,350 It will basically do whatever it can to interact with the game world 587 00:30:27,350 --> 00:30:30,590 as long as it's interacting with other bodies 588 00:30:30,590 --> 00:30:32,270 and resolving its collision that way. 589 00:30:32,270 --> 00:30:34,800 590 00:30:34,800 --> 00:30:39,860 And so that's the key example between what the three different bodies are 591 00:30:39,860 --> 00:30:40,580 fundamentally. 592 00:30:40,580 --> 00:30:45,182 And with these three body types you can construct pretty much any scene 593 00:30:45,182 --> 00:30:45,890 that you want to. 594 00:30:45,890 --> 00:30:50,180 And obviously the bodies and the fixtures can get insanely complex. 595 00:30:50,180 --> 00:30:55,010 I mean, we can look back here at this first example. 596 00:30:55,010 --> 00:31:05,780 These structures are a composition of many different types of dynamic bodies 597 00:31:05,780 --> 00:31:11,330 that have been given anchors and joints and all sorts of other things 598 00:31:11,330 --> 00:31:15,170 to make them look as if they're big constructions. 599 00:31:15,170 --> 00:31:18,370 But at the end, they're all just a bunch of little bodies 600 00:31:18,370 --> 00:31:20,870 that are welded together, fixtures that are welded together. 601 00:31:20,870 --> 00:31:23,480 602 00:31:23,480 --> 00:31:27,710 And these fundamental building blocks are how you construct scenes like this. 603 00:31:27,710 --> 00:31:32,210 Put a bunch of these blocks together, weld them together with joints, 604 00:31:32,210 --> 00:31:33,050 in this case. 605 00:31:33,050 --> 00:31:35,840 We won't cover joints in the context of this lecture. 606 00:31:35,840 --> 00:31:39,290 But if you're wondering how all of these individual things 607 00:31:39,290 --> 00:31:44,729 can be collideable while still constructing these massive scenes 608 00:31:44,729 --> 00:31:46,520 and having physics applied to them, they're 609 00:31:46,520 --> 00:31:51,140 just jointed together using weld joints or other types of joints, pulley joints 610 00:31:51,140 --> 00:31:52,640 depending on what they are. 611 00:31:52,640 --> 00:31:58,760 In this case, there is two circle shapes here, circle fixtures, 612 00:31:58,760 --> 00:32:01,190 that are the wheels on this cart and then 613 00:32:01,190 --> 00:32:06,740 they're welded to the flat constructions here. 614 00:32:06,740 --> 00:32:09,980 Allowing those to be dynamic allows the wheels to roll, and therefore 615 00:32:09,980 --> 00:32:12,650 carry the other load with it. 616 00:32:12,650 --> 00:32:14,390 Same with this bridge. 617 00:32:14,390 --> 00:32:18,710 I forget the exact name of the joint, but it's a chain of fixtures together 618 00:32:18,710 --> 00:32:20,720 that are welded by a specific kind of joint. 619 00:32:20,720 --> 00:32:23,090 And by putting them together in this way, 620 00:32:23,090 --> 00:32:27,740 you get a bridge and all sorts of things that you could think of, 621 00:32:27,740 --> 00:32:33,830 including tanks, which is in the notes here. 622 00:32:33,830 --> 00:32:36,080 This third link, one of them talks about how 623 00:32:36,080 --> 00:32:37,970 to implement a tank by having treads going 624 00:32:37,970 --> 00:32:40,580 around circles and then a massive body. 625 00:32:40,580 --> 00:32:45,156 You could do anything with Box2D, it's an awesome library. 626 00:32:45,156 --> 00:32:47,030 In the context of Angry Birds, really we just 627 00:32:47,030 --> 00:32:49,400 scratched the surface for what is possible here. 628 00:32:49,400 --> 00:32:52,470 629 00:32:52,470 --> 00:32:54,590 So I'm going to demo now. 630 00:32:54,590 --> 00:32:59,480 Actually, I enjoyed, I think, this demo, this bit of code, 631 00:32:59,480 --> 00:33:03,410 more than I enjoyed the Angry Birds implementation. 632 00:33:03,410 --> 00:33:06,400 And it's a program that I wrote called Ball Pit. 633 00:33:06,400 --> 00:33:08,160 Oh, by the way, before I get into that. 634 00:33:08,160 --> 00:33:11,840 So I'll leave that as a little teaser, I guess. 635 00:33:11,840 --> 00:33:15,440 Looking at kinematic, really quickly. 636 00:33:15,440 --> 00:33:18,590 We're going to look and see that I've created 637 00:33:18,590 --> 00:33:23,450 a table for the kinematic bodies, a table for the fixtures, 638 00:33:23,450 --> 00:33:24,802 and then one shape. 639 00:33:24,802 --> 00:33:26,510 Because you only need one shape actually, 640 00:33:26,510 --> 00:33:28,400 and you can apply one shape to as many bodies 641 00:33:28,400 --> 00:33:32,960 as you want to as long as they all have the same shape. 642 00:33:32,960 --> 00:33:35,690 I just create three kinematic bodies here. 643 00:33:35,690 --> 00:33:39,590 So spacing them out relative to the center with this math here. 644 00:33:39,590 --> 00:33:41,019 They get the string kinematic. 645 00:33:41,019 --> 00:33:42,560 And that's really the key difference. 646 00:33:42,560 --> 00:33:45,830 And then before finishing, I make sure that I 647 00:33:45,830 --> 00:33:47,920 set them to have an angular velocity. 648 00:33:47,920 --> 00:33:49,400 So this is how you spin something. 649 00:33:49,400 --> 00:33:51,483 If you want to set something to spin indefinitely, 650 00:33:51,483 --> 00:33:52,730 just set an angular velocity. 651 00:33:52,730 --> 00:33:56,540 In this case, 360 times degrees to radians. 652 00:33:56,540 --> 00:34:01,880 And that's just a formula written out as a constant, which is just the number-- 653 00:34:01,880 --> 00:34:05,942 I forget offhand what exactly the formula is. 654 00:34:05,942 --> 00:34:06,650 But it's up here. 655 00:34:06,650 --> 00:34:13,070 It's degrees to radians 0.01745329, et cetera. 656 00:34:13,070 --> 00:34:15,949 But just like pi, it's a number that you can 657 00:34:15,949 --> 00:34:19,540 use to multiply a number in degrees, and you'll get a number in radians. 658 00:34:19,540 --> 00:34:22,120 And there's the reverse up there as well. 659 00:34:22,120 --> 00:34:26,949 We have to do this because Box2D expects, for any types of rotation, 660 00:34:26,949 --> 00:34:28,239 it expects it in radians. 661 00:34:28,239 --> 00:34:30,050 I prefer thinking in degrees. 662 00:34:30,050 --> 00:34:33,370 So I passed in 360 times degrees to radians. 663 00:34:33,370 --> 00:34:37,340 And so we render down here, just as we did with the box body. 664 00:34:37,340 --> 00:34:42,790 We render the kinematic bodies, polygon fill, kinematic bodies at i 665 00:34:42,790 --> 00:34:45,639 get world points kinematic shape get points. 666 00:34:45,639 --> 00:34:47,179 Nothing terribly different. 667 00:34:47,179 --> 00:34:50,949 The only real key difference is that we've added kinematic as a string 668 00:34:50,949 --> 00:34:53,659 to the constructor for the body. 669 00:34:53,659 --> 00:34:55,810 And we've added some angular velocity. 670 00:34:55,810 --> 00:34:58,082 And recall, this will make it spin indefinitely, 671 00:34:58,082 --> 00:35:00,790 but it will never be influenced-- its angular velocity will never 672 00:35:00,790 --> 00:35:03,850 be influenced, its position will never be influenced 673 00:35:03,850 --> 00:35:06,310 by anything else in our scene. 674 00:35:06,310 --> 00:35:10,060 So now with that out of the way, I'm going to pull up Ball Pit. 675 00:35:10,060 --> 00:35:13,170 676 00:35:13,170 --> 00:35:15,590 And maybe I'm just a little bit too excited about this. 677 00:35:15,590 --> 00:35:18,160 But I enjoyed this a lot. 678 00:35:18,160 --> 00:35:22,300 So what it is, is this is like a bigger demonstration 679 00:35:22,300 --> 00:35:24,680 of putting all these pieces together. 680 00:35:24,680 --> 00:35:26,994 We have a bunch of circle shapes. 681 00:35:26,994 --> 00:35:28,660 They're all interacting with each other. 682 00:35:28,660 --> 00:35:29,770 They all have physics. 683 00:35:29,770 --> 00:35:33,190 And then I have a larger shape here, this square, 684 00:35:33,190 --> 00:35:35,510 which has a higher density than everything else. 685 00:35:35,510 --> 00:35:38,660 And by pressing Spacebar I can just dive into-- 686 00:35:38,660 --> 00:35:41,440 throw it into the ball pit, and it'll cause an interaction 687 00:35:41,440 --> 00:35:42,670 with everything else. 688 00:35:42,670 --> 00:35:46,780 And a bug slash feature that I discovered 689 00:35:46,780 --> 00:35:51,070 about this is that if you press Spacebar over and over again, 690 00:35:51,070 --> 00:35:53,510 it never resets its velocity. 691 00:35:53,510 --> 00:35:55,854 So it just slams down into the ball pit. 692 00:35:55,854 --> 00:35:58,270 So it's just kind of fun, and I think there might actually 693 00:35:58,270 --> 00:36:00,580 be possibly a game idea in here. 694 00:36:00,580 --> 00:36:02,710 But, I mean, well, what are the pieces here? 695 00:36:02,710 --> 00:36:04,000 What's different about this? 696 00:36:04,000 --> 00:36:07,388 697 00:36:07,388 --> 00:36:10,949 AUDIENCE: They're all dynamic shapes. 698 00:36:10,949 --> 00:36:11,740 COLTON OGDEN: Yeah. 699 00:36:11,740 --> 00:36:13,490 So they're all dynamic shapes. 700 00:36:13,490 --> 00:36:15,410 Except for the ground at the very bottom. 701 00:36:15,410 --> 00:36:21,994 And also, hidden from view are actually two more static shapes 702 00:36:21,994 --> 00:36:22,910 on the left and right. 703 00:36:22,910 --> 00:36:25,160 Because if we didn't have those, all of the balls 704 00:36:25,160 --> 00:36:28,520 would fall to the side out of view. 705 00:36:28,520 --> 00:36:33,020 But yeah, we have the static delimiters for our scene. 706 00:36:33,020 --> 00:36:38,420 But we have a bunch of dynamic bodies, the balls are all dynamic. 707 00:36:38,420 --> 00:36:42,470 And then the square is also dynamic. 708 00:36:42,470 --> 00:36:45,387 And then, like I said before, the only real difference between them 709 00:36:45,387 --> 00:36:47,220 is that obviously the square is a rectangle. 710 00:36:47,220 --> 00:36:49,200 But it also just has a higher density. 711 00:36:49,200 --> 00:36:53,027 And so by giving it a higher density it pushes everything else-- oh, 712 00:36:53,027 --> 00:36:53,860 what happened there? 713 00:36:53,860 --> 00:36:54,485 That was weird. 714 00:36:54,485 --> 00:36:57,410 It pushes-- I think it went to sleep because we didn't do anything 715 00:36:57,410 --> 00:36:57,980 for a while. 716 00:36:57,980 --> 00:37:01,550 But it's able to fall through everything else 717 00:37:01,550 --> 00:37:05,960 because it knows that it's heavier, and that it should push and apply 718 00:37:05,960 --> 00:37:09,800 a larger force to everything else that's around it. 719 00:37:09,800 --> 00:37:14,030 And so by using these fundamental building blocks of what Box2D is, 720 00:37:14,030 --> 00:37:18,320 you can construct a lot of really cool simulations and other fun programs 721 00:37:18,320 --> 00:37:20,840 and actually get interesting game ideas. 722 00:37:20,840 --> 00:37:25,010 I'm inclined to believe that Angry Birds started out as somebody messing around 723 00:37:25,010 --> 00:37:27,780 with the Box2D, or physics engine like this. 724 00:37:27,780 --> 00:37:31,430 And it was inspired by some other game that I should look into a little bit. 725 00:37:31,430 --> 00:37:34,837 But the creators of that game, presumably, found this physics engine 726 00:37:34,837 --> 00:37:36,170 and were like, oh, this is cool. 727 00:37:36,170 --> 00:37:39,650 I'm going to put a tower of blocks here and just throw something at it. 728 00:37:39,650 --> 00:37:42,130 And then they realized, oh, we can make a game out of this. 729 00:37:42,130 --> 00:37:46,890 And so I encourage you, if you're ever curious to just experiment with things 730 00:37:46,890 --> 00:37:47,390 like that. 731 00:37:47,390 --> 00:37:49,040 We could probably turn this into a game. 732 00:37:49,040 --> 00:37:49,581 I don't know. 733 00:37:49,581 --> 00:37:50,480 I like this a lot. 734 00:37:50,480 --> 00:38:00,050 It's a good segue from the abstract, for lack of a better word, examples 735 00:38:00,050 --> 00:38:05,030 that we used earlier, and merges it more into the realm 736 00:38:05,030 --> 00:38:09,230 of how can we make something fun with this? 737 00:38:09,230 --> 00:38:14,570 And so that's how we're going to start moving into the distro today. 738 00:38:14,570 --> 00:38:21,320 So the main topic of today's lecture is Box2D and how we use it to make a game. 739 00:38:21,320 --> 00:38:23,780 Another thing that we should consider is mouse input. 740 00:38:23,780 --> 00:38:25,480 We haven't really used it yet. 741 00:38:25,480 --> 00:38:29,450 And I believe I've mentioned it before, slightly offhand. 742 00:38:29,450 --> 00:38:31,060 But Love2D makes it super easy. 743 00:38:31,060 --> 00:38:33,761 It's just like we do with keyboard input. 744 00:38:33,761 --> 00:38:36,260 We just have a couple of callbacks that are in main dot Lua, 745 00:38:36,260 --> 00:38:38,390 mouse pressed and mouse released. 746 00:38:38,390 --> 00:38:41,705 The difference between these and key pressed and key 747 00:38:41,705 --> 00:38:45,500 released is that they also get an X and a Y. Because usually, 748 00:38:45,500 --> 00:38:47,420 when you click the mouse or release the mouse, 749 00:38:47,420 --> 00:38:49,461 you want to know where it happened because that's 750 00:38:49,461 --> 00:38:53,250 obviously pertinent to what you're doing when you're using a mouse. 751 00:38:53,250 --> 00:38:58,940 So these are fired by Love2D every time you click or release a mouse button. 752 00:38:58,940 --> 00:39:01,670 And they get the X the Y and the key, and you 753 00:39:01,670 --> 00:39:03,350 can do whatever you want with those. 754 00:39:03,350 --> 00:39:05,900 And just as we've done in prior lectures so 755 00:39:05,900 --> 00:39:10,220 that we can use mouse input in other modules besides main dot Lua, 756 00:39:10,220 --> 00:39:13,505 there's a function called love dot mouse dot key pressed and key 757 00:39:13,505 --> 00:39:15,341 released that I implemented in main dot Lua. 758 00:39:15,341 --> 00:39:16,340 You can check those out. 759 00:39:16,340 --> 00:39:20,540 They're very similar to how we did the input tables for the keyboard before. 760 00:39:20,540 --> 00:39:24,020 But they allow us to use this functionality inside 761 00:39:24,020 --> 00:39:30,350 of other functions, other modules, besides main dot Lua. 762 00:39:30,350 --> 00:39:35,180 So let's go ahead and start looking at-- 763 00:39:35,180 --> 00:39:42,140 this is where we're going to start looking at the distro for Angry Birds 764 00:39:42,140 --> 00:39:46,489 and how we can take all these pieces and form them into an actual game. 765 00:39:46,489 --> 00:39:49,530 So the first thing we'll do, we'll take a look at just a couple of things 766 00:39:49,530 --> 00:39:51,530 and then we'll take a short break and then we'll 767 00:39:51,530 --> 00:39:53,150 get more into the meat of it. 768 00:39:53,150 --> 00:39:55,820 But let me go ahead and clear out all of these. 769 00:39:55,820 --> 00:39:58,800 770 00:39:58,800 --> 00:40:02,460 And then we're going to pull up-- so the distro is in Angry 50. 771 00:40:02,460 --> 00:40:06,270 And so main dot Lua is here. 772 00:40:06,270 --> 00:40:08,280 So not a whole lot is different in here. 773 00:40:08,280 --> 00:40:11,700 So we have two states in our game. 774 00:40:11,700 --> 00:40:14,490 So we had a start and a play state, as we saw before. 775 00:40:14,490 --> 00:40:16,810 The start state is like we've done before. 776 00:40:16,810 --> 00:40:20,070 The only difference is in this start state, well, for one, 777 00:40:20,070 --> 00:40:22,020 it's running a Box2D simulation. 778 00:40:22,020 --> 00:40:25,800 And two, we're actually using mouse input. 779 00:40:25,800 --> 00:40:27,780 So actually, let's look at main so you can 780 00:40:27,780 --> 00:40:31,540 see where I've added this, which is different than before. 781 00:40:31,540 --> 00:40:35,310 So we have love dot key pressed, as we've seen before. 782 00:40:35,310 --> 00:40:38,520 But we also have mouse pressed and mouse released. 783 00:40:38,520 --> 00:40:40,660 And then mouse was pressed and mouse was released. 784 00:40:40,660 --> 00:40:44,340 So those are the main differences in main dot Lua this time, as opposed 785 00:40:44,340 --> 00:40:49,020 to last prior lectures, which we only had keyboard input. 786 00:40:49,020 --> 00:40:53,490 And as you can see here, we have input tables for keys pressed and released 787 00:40:53,490 --> 00:40:54,570 on the mouse. 788 00:40:54,570 --> 00:40:57,870 And so we initialized those to empty on every update frame 789 00:40:57,870 --> 00:41:00,840 just like we've done with the keyboard. 790 00:41:00,840 --> 00:41:05,820 And then the input tables get updated in the callback functions 791 00:41:05,820 --> 00:41:07,517 as we've done before. 792 00:41:07,517 --> 00:41:10,600 And so that's basically all that's different about main dot Lua this time. 793 00:41:10,600 --> 00:41:15,540 And that's how we've tied together the new mouse functions that we've just 794 00:41:15,540 --> 00:41:17,040 looked at into our game. 795 00:41:17,040 --> 00:41:19,830 796 00:41:19,830 --> 00:41:24,270 The states that exist in our game are play state and start state. 797 00:41:24,270 --> 00:41:25,110 So very simple. 798 00:41:25,110 --> 00:41:27,480 Very similar to last week where we looked at Zelda, 799 00:41:27,480 --> 00:41:31,470 we only basically had a start state and a play state. 800 00:41:31,470 --> 00:41:37,860 The start state, we can see here, just to tie together 801 00:41:37,860 --> 00:41:41,160 the last bit of our usage of the mouse. 802 00:41:41,160 --> 00:41:43,920 Love dot mouse dot was pressed 1. 803 00:41:43,920 --> 00:41:46,695 Does anybody know what this 1 is? 804 00:41:46,695 --> 00:41:48,120 AUDIENCE: Is that left click? 805 00:41:48,120 --> 00:41:49,411 COLTON OGDEN: It is left click. 806 00:41:49,411 --> 00:41:53,850 So Love2D assigns integer values to all of your mouse buttons. 807 00:41:53,850 --> 00:41:58,230 And 1 is traditionally the default value for left click. 808 00:41:58,230 --> 00:42:00,420 Some frameworks will use 0. 809 00:42:00,420 --> 00:42:06,300 But Lua, 1 index so start with 1 instead of 0. 810 00:42:06,300 --> 00:42:10,810 The thing about the start state here that's kind of cool and interesting. 811 00:42:10,810 --> 00:42:18,030 So I'm going to go ahead and play it again, the game. 812 00:42:18,030 --> 00:42:21,440 So we start off and right off the gate, just to make things interesting 813 00:42:21,440 --> 00:42:23,940 rather than just have a static screen that says 814 00:42:23,940 --> 00:42:28,050 Anger 50 click to start, we're actually running a Love2D, 815 00:42:28,050 --> 00:42:30,790 a Box2D simulation here. 816 00:42:30,790 --> 00:42:33,720 It's a world with a bunch of squares. 817 00:42:33,720 --> 00:42:37,812 And so what kind of bodies are all of these? 818 00:42:37,812 --> 00:42:38,810 AUDIENCE: [INAUDIBLE]. 819 00:42:38,810 --> 00:42:40,518 COLTON OGDEN: They're all dynamic bodies. 820 00:42:40,518 --> 00:42:44,210 And we've encapsulated them all, just as we did before in the ball pit example, 821 00:42:44,210 --> 00:42:47,895 with some invisible static bodies on the left, right, and bottom of the screen. 822 00:42:47,895 --> 00:42:49,770 Because if we didn't have those static bodies 823 00:42:49,770 --> 00:42:52,980 they would just fall all the way down. 824 00:42:52,980 --> 00:42:56,100 And the nice thing is we don't actually have to render anything. 825 00:42:56,100 --> 00:43:01,850 So if you want maybe an invisible barrier for something in your game, 826 00:43:01,850 --> 00:43:04,364 or you want to encapsulate something, something physical, 827 00:43:04,364 --> 00:43:05,780 you don't have to render anything. 828 00:43:05,780 --> 00:43:10,160 You can just have arbitrarily shaped and positioned static bodies. 829 00:43:10,160 --> 00:43:11,977 And that will act as a container. 830 00:43:11,977 --> 00:43:13,310 So that's all we're doing there. 831 00:43:13,310 --> 00:43:17,960 We have a container set for all of our little square alien guys. 832 00:43:17,960 --> 00:43:22,580 And by creating, I think, a hundred of them and just letting them drop, 833 00:43:22,580 --> 00:43:27,140 we have this interesting visual start to our game 834 00:43:27,140 --> 00:43:29,310 with very, very minimal effort. 835 00:43:29,310 --> 00:43:31,340 So we can take a look at this. 836 00:43:31,340 --> 00:43:36,260 So in our start state init, as I said before, we have a world. 837 00:43:36,260 --> 00:43:38,570 We obviously need a member of new world. 838 00:43:38,570 --> 00:43:40,670 Anytime we do any Box2D stuff you have to start 839 00:43:40,670 --> 00:43:43,185 by having a love dot physics dot new world, 840 00:43:43,185 --> 00:43:46,730 else you won't be able to run any simulations. 841 00:43:46,730 --> 00:43:51,740 Going to create a ground, walls, and then a bunch of aliens. 842 00:43:51,740 --> 00:43:57,630 So this here, we can see that we have a table that we're inserting aliens into. 843 00:43:57,630 --> 00:44:00,980 But we have a class called alien. 844 00:44:00,980 --> 00:44:04,520 So anybody want to ballpark what an alien class ultimately 845 00:44:04,520 --> 00:44:05,930 encapsulates or ultimately is? 846 00:44:05,930 --> 00:44:10,421 847 00:44:10,421 --> 00:44:15,694 AUDIENCE: Probably the way it looks, like the skin. 848 00:44:15,694 --> 00:44:18,110 COLTON OGDEN: It is, yeah, that's definitely a part of it. 849 00:44:18,110 --> 00:44:19,880 So the way it looks, or it's skin. 850 00:44:19,880 --> 00:44:23,210 So it does have a reference to that. 851 00:44:23,210 --> 00:44:31,970 And then more functionally, it also possesses a body and a fixture. 852 00:44:31,970 --> 00:44:35,000 So rather than having a bunch of bodies and fixtures 853 00:44:35,000 --> 00:44:38,780 that are separated out and maybe just in tables 854 00:44:38,780 --> 00:44:44,240 at the surface level of whatever, our level, just wrap them in a class. 855 00:44:44,240 --> 00:44:46,370 And then we just can maintain a reference 856 00:44:46,370 --> 00:44:50,630 to each individual alien's body and fixture that way. 857 00:44:50,630 --> 00:44:53,240 So it's a little bit more encapsulated. 858 00:44:53,240 --> 00:44:57,500 It's a little bit more object oriented, little bit cleaner in my opinion. 859 00:44:57,500 --> 00:45:03,230 The alien class can take square or round as its-- 860 00:45:03,230 --> 00:45:05,900 well, it can take anything you want to as its type. 861 00:45:05,900 --> 00:45:09,290 So this will ultimately decide how it's rendered and what shape it gets. 862 00:45:09,290 --> 00:45:13,670 But if it's square, which is the default, so if you just 863 00:45:13,670 --> 00:45:18,020 create an alien with no type, it will get 864 00:45:18,020 --> 00:45:21,350 a love dot physics dot rectangle shape. 865 00:45:21,350 --> 00:45:23,720 So as we saw before, that's just a box. 866 00:45:23,720 --> 00:45:26,510 And then if not, we just default to circle shape. 867 00:45:26,510 --> 00:45:29,450 But you could program it to take in whatever shape you want, 868 00:45:29,450 --> 00:45:30,980 and then just give it that shape. 869 00:45:30,980 --> 00:45:33,230 And you don't really have to do much in terms 870 00:45:33,230 --> 00:45:36,890 of coding how it interacts with anything else in terms of collision, at least. 871 00:45:36,890 --> 00:45:40,220 Because, thankfully, Box2D will know, OK, it's a circle. 872 00:45:40,220 --> 00:45:43,790 It should spin around and interact with things like a circle. 873 00:45:43,790 --> 00:45:47,090 Or it's a rectangle so it should interact with things like it's a box. 874 00:45:47,090 --> 00:45:48,680 Just nice and convenient. 875 00:45:48,680 --> 00:45:52,070 And then we'll just create a fixture here. 876 00:45:52,070 --> 00:45:55,860 This set user data function here is important 877 00:45:55,860 --> 00:46:01,850 because we'll see in the context of how we actually resolve collisions 878 00:46:01,850 --> 00:46:05,300 in a customized way, we'll need user data 879 00:46:05,300 --> 00:46:08,840 to be able to differentiate what gets collided in our world. 880 00:46:08,840 --> 00:46:14,900 But at the moment you can just know that this basically allows us to pass in-- 881 00:46:14,900 --> 00:46:17,720 to set arbitrary data onto a fixture. 882 00:46:17,720 --> 00:46:22,850 So we can say, fixture set user data alien, the string alien. 883 00:46:22,850 --> 00:46:28,520 And what that means is that fixture has some customized metadata about it that 884 00:46:28,520 --> 00:46:30,290 says, this is an alien. 885 00:46:30,290 --> 00:46:31,892 It's whatever we want to do with it. 886 00:46:31,892 --> 00:46:33,350 We could give this a table as well. 887 00:46:33,350 --> 00:46:35,570 We could just say, the user data is a table 888 00:46:35,570 --> 00:46:40,190 and then has a bunch of information that we can then use at collision time 889 00:46:40,190 --> 00:46:42,050 to perform different work on it. 890 00:46:42,050 --> 00:46:44,210 But this set user data function is how we 891 00:46:44,210 --> 00:46:48,900 are able to resolve collisions between obstacles and aliens differently than, 892 00:46:48,900 --> 00:46:53,460 say players and aliens, or even the alien and the ground. 893 00:46:53,460 --> 00:46:57,110 Because when we do any Box2D collision, right, the world's 894 00:46:57,110 --> 00:46:59,150 taking care of the collisions for us. 895 00:46:59,150 --> 00:47:04,460 How do we tell the world, OK, when I hit the ground I want to play a sound, 896 00:47:04,460 --> 00:47:05,810 but not do anything. 897 00:47:05,810 --> 00:47:10,130 If I hit this box at this velocity, I want it to destroy it. 898 00:47:10,130 --> 00:47:12,860 If I hit the alien, I want the alien to disappear 899 00:47:12,860 --> 00:47:16,280 and I want to show a victory label. 900 00:47:16,280 --> 00:47:18,890 How do we do all these different things? 901 00:47:18,890 --> 00:47:21,770 We do that with what are called collision callbacks 902 00:47:21,770 --> 00:47:23,400 in the context of Box2D. 903 00:47:23,400 --> 00:47:24,720 And we'll see how that works. 904 00:47:24,720 --> 00:47:30,870 But suffice to say, user data will be very important coming forward. 905 00:47:30,870 --> 00:47:33,350 And then this launched false, actually we don't end up 906 00:47:33,350 --> 00:47:34,910 using this so this is irrelevant. 907 00:47:34,910 --> 00:47:43,190 But it has a render function here, which just takes in the bodies X and Y 908 00:47:43,190 --> 00:47:46,242 and will draw it at the angle that it's at. 909 00:47:46,242 --> 00:47:47,450 So that's an important thing. 910 00:47:47,450 --> 00:47:52,400 When we before, what we were doing is drawing things via shapes. 911 00:47:52,400 --> 00:47:55,790 So love dot graphics dot polygon, love dot graphics dot circle, 912 00:47:55,790 --> 00:47:57,710 love dot graphics dot line. 913 00:47:57,710 --> 00:48:03,440 But if we want to draw a sprite instead, we 914 00:48:03,440 --> 00:48:06,440 need to draw it at the right position, first of all, right? 915 00:48:06,440 --> 00:48:09,890 And then things also rotate in Box2D. 916 00:48:09,890 --> 00:48:13,500 So we need to draw it at the right angle. 917 00:48:13,500 --> 00:48:17,270 So what we do is we can actually query the body for its X. 918 00:48:17,270 --> 00:48:21,770 We can query the body for its Y. And we can also query the body for its angle. 919 00:48:21,770 --> 00:48:24,560 And then we can draw the texture and the quad 920 00:48:24,560 --> 00:48:28,470 that we want to using those XY and the angle, 921 00:48:28,470 --> 00:48:33,560 and that will have the effect of drawing a sprite in the world that 922 00:48:33,560 --> 00:48:37,190 mirrors what's going on in Box2D, rather than just a simple shape. 923 00:48:37,190 --> 00:48:42,260 So that's as simple as it is for drawing a sprite instead of a shape. 924 00:48:42,260 --> 00:48:46,230 You can see here, the 17.5 17.5. 925 00:48:46,230 --> 00:48:48,404 Does anybody know what that's for? 926 00:48:48,404 --> 00:48:49,240 AUDIENCE: Not sure. 927 00:48:49,240 --> 00:48:52,940 COLTON OGDEN: So 17.5 17.5 at the end is half of the width 928 00:48:52,940 --> 00:48:56,030 and half of the height of the aliens. 929 00:48:56,030 --> 00:48:58,670 So aliens are 35 by 35 in this game. 930 00:48:58,670 --> 00:49:00,050 We pass those in. 931 00:49:00,050 --> 00:49:02,450 This is the center of origin. 932 00:49:02,450 --> 00:49:05,600 So when we rotate something by center of origin, 933 00:49:05,600 --> 00:49:11,620 it basically describes where the rotation is going to take place. 934 00:49:11,620 --> 00:49:15,237 So if it's rotated about the top left and we rotate something, 935 00:49:15,237 --> 00:49:17,570 it's going to have the effect of the sprite going around 936 00:49:17,570 --> 00:49:20,150 in a circle in sort of an odd way. 937 00:49:20,150 --> 00:49:23,960 If we rotate the sprite based on the center of origin of the actual sprite 938 00:49:23,960 --> 00:49:28,760 itself, that will have the effect of rotating the sprite on its center. 939 00:49:28,760 --> 00:49:31,520 So you can set that origin wherever you want to 940 00:49:31,520 --> 00:49:35,180 and it'll perform a 360 degree rotation about that point. 941 00:49:35,180 --> 00:49:37,590 And we're setting that point to half-- 942 00:49:37,590 --> 00:49:40,040 to basically the middle of where we're drawing the sprite. 943 00:49:40,040 --> 00:49:42,720 So that will have the effect of when we give it this angle here, 944 00:49:42,720 --> 00:49:46,880 self dot body to get angle, the rotation will take place in place. 945 00:49:46,880 --> 00:49:50,570 It won't take place-- it won't be some sort of weird about the top left corner 946 00:49:50,570 --> 00:49:52,770 rotation, which is not what we want. 947 00:49:52,770 --> 00:49:55,840 So when you see center of origin being modified like that, 948 00:49:55,840 --> 00:49:58,610 you can assume that it's because we have an offset 949 00:49:58,610 --> 00:50:01,550 and we're trying to find the center of where we're drawing 950 00:50:01,550 --> 00:50:04,980 and rotate about that to do an in place rotation. 951 00:50:04,980 --> 00:50:08,720 But not necessarily, you could also draw something. 952 00:50:08,720 --> 00:50:12,800 You could also, maybe you want something some sort of magical ball of energy 953 00:50:12,800 --> 00:50:15,230 to rotate about a rod or something. 954 00:50:15,230 --> 00:50:17,780 And so you want it to rotate around a different center, 955 00:50:17,780 --> 00:50:20,660 or whatever you want arbitrarily. 956 00:50:20,660 --> 00:50:23,840 But typically, at least mostly that I've seen, 957 00:50:23,840 --> 00:50:27,950 this is useful for making sure that your rotations, your in place rotations, 958 00:50:27,950 --> 00:50:29,360 are accurately rendered. 959 00:50:29,360 --> 00:50:33,320 So any questions about how the alien class works? 960 00:50:33,320 --> 00:50:36,860 961 00:50:36,860 --> 00:50:38,340 All right. 962 00:50:38,340 --> 00:50:40,650 So that's the alien class. 963 00:50:40,650 --> 00:50:44,160 That's the basically the fundamental building block of our game. 964 00:50:44,160 --> 00:50:48,120 The other part is the obstacle. 965 00:50:48,120 --> 00:50:50,280 We have obstacles and we have aliens. 966 00:50:50,280 --> 00:50:53,610 The obstacles and aliens are actually very similar. 967 00:50:53,610 --> 00:50:55,560 So what's the difference between-- 968 00:50:55,560 --> 00:50:58,080 I mean, ultimately, how are they similar? 969 00:50:58,080 --> 00:51:03,470 970 00:51:03,470 --> 00:51:05,430 AUDIENCE: They're both dynamic [INAUDIBLE].. 971 00:51:05,430 --> 00:51:07,580 COLTON OGDEN: They're both dynamic bodies, yeah. 972 00:51:07,580 --> 00:51:11,720 Really, the only thing that's different about a obstacle and an alien 973 00:51:11,720 --> 00:51:14,570 is what we do with them in our scene and how they're rendered. 974 00:51:14,570 --> 00:51:16,760 But they function very similarly. 975 00:51:16,760 --> 00:51:18,950 They're just dynamic bodies that we give a shape to 976 00:51:18,950 --> 00:51:21,200 and we render them with that shape. 977 00:51:21,200 --> 00:51:24,680 978 00:51:24,680 --> 00:51:28,670 In this case, the obstacle constructor, we've 979 00:51:28,670 --> 00:51:33,540 decided to design it such that it could take a shape horizontal or vertical, 980 00:51:33,540 --> 00:51:36,620 which is similar to the type that we saw before with the alien, 981 00:51:36,620 --> 00:51:38,840 where it could be square or circular. 982 00:51:38,840 --> 00:51:45,860 In this case, if we look back at our sprite sheet back here, 983 00:51:45,860 --> 00:51:48,124 we can see there's a ton of different shapes. 984 00:51:48,124 --> 00:51:51,290 But the only two shapes that we're going to use in the context of this game, 985 00:51:51,290 --> 00:51:55,970 just for this demonstration, are the horizontal, clean wooden shape here 986 00:51:55,970 --> 00:51:59,150 and the vertical one that's right here. 987 00:51:59,150 --> 00:52:02,120 And so in order to find those out I had to open up 988 00:52:02,120 --> 00:52:05,567 basically this sprite in my sprite editor, 989 00:52:05,567 --> 00:52:08,150 figure out where the XY width and height were, and then create 990 00:52:08,150 --> 00:52:10,340 a quad manually off of that. 991 00:52:10,340 --> 00:52:14,120 And then I edited the util dot Lua-- or not util dot Lua, 992 00:52:14,120 --> 00:52:17,480 the dependencies dot Lua here. 993 00:52:17,480 --> 00:52:21,050 Normally we just create gframes and then we use generate quads. 994 00:52:21,050 --> 00:52:25,460 And you can do that like with the aliens and with the tiles, the tiles 995 00:52:25,460 --> 00:52:28,190 being this sprite sheet that-- 996 00:52:28,190 --> 00:52:29,510 this one right here. 997 00:52:29,510 --> 00:52:31,310 These are 35 by 35. 998 00:52:31,310 --> 00:52:32,720 These are 35 by 35. 999 00:52:32,720 --> 00:52:34,130 These are not 35 by 35. 1000 00:52:34,130 --> 00:52:38,280 These are a bunch of different shapes and sizes. 1001 00:52:38,280 --> 00:52:47,840 So I went through and gframes wood is for manually created quads here. 1002 00:52:47,840 --> 00:52:53,540 And then there's four because I also added the semi broken shapes as well. 1003 00:52:53,540 --> 00:52:55,820 But we don't actually use those. 1004 00:52:55,820 --> 00:53:03,100 But you could decide to turn these into these on collision, 1005 00:53:03,100 --> 00:53:06,350 perhaps maybe if the velocity isn't strong enough to break it necessarily, 1006 00:53:06,350 --> 00:53:09,740 but you want to have some sort of feedback that you collided with it. 1007 00:53:09,740 --> 00:53:15,140 You can just set maybe the frame to 1 or 2 on collision for that object, 1008 00:53:15,140 --> 00:53:18,950 instead of 2 and render it appropriately. 1009 00:53:18,950 --> 00:53:21,380 But if you're dealing with a sprite sheet 1010 00:53:21,380 --> 00:53:26,450 and that sprite sheet has odd distribution of its sprites, 1011 00:53:26,450 --> 00:53:29,480 sometimes you have to figure out where the offsets are manually 1012 00:53:29,480 --> 00:53:31,190 and do it that way. 1013 00:53:31,190 --> 00:53:34,910 The ideal is that you don't have to and that you can do it programmatically. 1014 00:53:34,910 --> 00:53:38,270 But it really depends on the game, what your domain is 1015 00:53:38,270 --> 00:53:42,090 and what objects you're interacting with in the scene. 1016 00:53:42,090 --> 00:53:44,950 Any questions on the why or how as to that? 1017 00:53:44,950 --> 00:53:47,700 1018 00:53:47,700 --> 00:53:48,320 Cool. 1019 00:53:48,320 --> 00:53:51,780 So back to the obstacle. 1020 00:53:51,780 --> 00:53:54,020 So they're horizontal or vertical, and what that does 1021 00:53:54,020 --> 00:53:55,730 is it sets the frame to 2 or 4. 1022 00:53:55,730 --> 00:54:02,180 And the 2 or 4 being in gframes that would, the 4 quads that I had a hand, 1023 00:54:02,180 --> 00:54:03,620 figure out the coordinates for. 1024 00:54:03,620 --> 00:54:06,350 1025 00:54:06,350 --> 00:54:09,800 And really, it's not a whole lot different at that point. 1026 00:54:09,800 --> 00:54:15,260 If it's a horizontal or a vertical shape, 1027 00:54:15,260 --> 00:54:17,690 then we need to set its width and height appropriately. 1028 00:54:17,690 --> 00:54:19,820 Because it's going to have a different width and a different height. 1029 00:54:19,820 --> 00:54:22,770 If it's vertical, obviously the height is higher than the width. 1030 00:54:22,770 --> 00:54:25,910 And if it's horizontal, the opposite is true. 1031 00:54:25,910 --> 00:54:27,929 But they're both a rectangle shape. 1032 00:54:27,929 --> 00:54:29,720 So you can pass in the width and the height 1033 00:54:29,720 --> 00:54:32,520 after you calculate that, and give it the right shape, 1034 00:54:32,520 --> 00:54:33,770 and then ascribe it a fixture. 1035 00:54:33,770 --> 00:54:37,310 And then set user data in this case, we set user data to obstacle. 1036 00:54:37,310 --> 00:54:40,760 So now that obstacle, the fixture specifically, 1037 00:54:40,760 --> 00:54:45,080 knows that it's an obstacle, as opposed to being an alien, as opposed 1038 00:54:45,080 --> 00:54:47,510 to being anything else, as opposed to being the ground. 1039 00:54:47,510 --> 00:54:54,500 And so when we explore in a few minutes what the custom collision, world 1040 00:54:54,500 --> 00:54:56,420 collision callbacks, that we can actually 1041 00:54:56,420 --> 00:54:58,940 define all this interesting collision behavior for, 1042 00:54:58,940 --> 00:55:01,370 this user data is going to be relevant. 1043 00:55:01,370 --> 00:55:08,310 And then we render it just like we render the alien as before. 1044 00:55:08,310 --> 00:55:10,875 So any questions on obstacles and aliens, how they differ, 1045 00:55:10,875 --> 00:55:11,750 how they're the same? 1046 00:55:11,750 --> 00:55:14,588 1047 00:55:14,588 --> 00:55:15,750 Cool. 1048 00:55:15,750 --> 00:55:16,250 All right. 1049 00:55:16,250 --> 00:55:18,500 Let's take a five minute now. 1050 00:55:18,500 --> 00:55:21,710 When we get back, we're going to actually look at the play state. 1051 00:55:21,710 --> 00:55:23,870 We're going to look at what makes a level. 1052 00:55:23,870 --> 00:55:27,650 And we're going to actually look at how we can customize the world 1053 00:55:27,650 --> 00:55:32,480 to resolve collisions in ways that are relevant to our game behavior. 1054 00:55:32,480 --> 00:55:36,080 As in, how to make things break when we collide with them, 1055 00:55:36,080 --> 00:55:40,310 how to make the victory screen pop up when we've destroyed the bird, 1056 00:55:40,310 --> 00:55:41,240 so on and so forth. 1057 00:55:41,240 --> 00:55:43,971 1058 00:55:43,971 --> 00:55:44,470 All right. 1059 00:55:44,470 --> 00:55:45,250 Welcome back. 1060 00:55:45,250 --> 00:55:47,110 So before we took a break, we were talking 1061 00:55:47,110 --> 00:55:51,120 about the aliens and obstacles that are in our game 1062 00:55:51,120 --> 00:55:52,880 world that interact with each other. 1063 00:55:52,880 --> 00:55:58,900 They are the backbone of what makes our games slash Angry Birds work. 1064 00:55:58,900 --> 00:56:02,170 You throw aliens into the obstacles, obstacles break, 1065 00:56:02,170 --> 00:56:07,660 the bad pigs slash aliens die and then you score points. 1066 00:56:07,660 --> 00:56:10,120 But we actually have to model these interactions 1067 00:56:10,120 --> 00:56:13,030 and we have to tell our game, our world, what 1068 00:56:13,030 --> 00:56:16,900 to do when these collisions happen in order for things more interesting 1069 00:56:16,900 --> 00:56:19,354 than just things bouncing off each other to work. 1070 00:56:19,354 --> 00:56:20,520 That's the default behavior. 1071 00:56:20,520 --> 00:56:26,230 Box2D's goal, by default, is when two things overlap, 1072 00:56:26,230 --> 00:56:29,170 assuming that they're dynamic or at least one of them is dynamic, 1073 00:56:29,170 --> 00:56:34,840 is to push the dynamic bodies away until they no longer overlap 1074 00:56:34,840 --> 00:56:38,950 via either position or rotation. 1075 00:56:38,950 --> 00:56:42,640 But that's not the gist or the goal of our game. 1076 00:56:42,640 --> 00:56:45,490 Because what we want to have happen is different things happen 1077 00:56:45,490 --> 00:56:49,330 and certain things to disappear and to break and all sorts of other things 1078 00:56:49,330 --> 00:56:52,210 to happen when different kinds of objects 1079 00:56:52,210 --> 00:56:56,290 interact with different kinds of objects at differing speeds. 1080 00:56:56,290 --> 00:57:00,790 So in order to do this, we need to define collision callbacks 1081 00:57:00,790 --> 00:57:01,630 for our world. 1082 00:57:01,630 --> 00:57:04,810 So a callback, recall, is a function that gets 1083 00:57:04,810 --> 00:57:06,850 called back when something happens. 1084 00:57:06,850 --> 00:57:12,950 It's just something that will get called at a specific time or later on. 1085 00:57:12,950 --> 00:57:16,090 And we can define these callbacks for our world 1086 00:57:16,090 --> 00:57:19,210 such that when two things collide with each other, 1087 00:57:19,210 --> 00:57:23,350 it will execute this call back and then perform the corresponding logic 1088 00:57:23,350 --> 00:57:25,750 that we've defined therein. 1089 00:57:25,750 --> 00:57:30,850 And with every collision in Box2D, there are four callbacks that take place. 1090 00:57:30,850 --> 00:57:35,770 There's begin contact, so when two things begin to overlap 1091 00:57:35,770 --> 00:57:37,630 or begin to contact one another. 1092 00:57:37,630 --> 00:57:40,480 End contact, so once that ends, once two objects 1093 00:57:40,480 --> 00:57:42,990 are pushed away from each other. 1094 00:57:42,990 --> 00:57:46,270 Presolved, which happens right before the collision actually gets 1095 00:57:46,270 --> 00:57:50,200 solved in Box2D, meaning that the things get pushed away from each other. 1096 00:57:50,200 --> 00:57:54,130 And then postsolved, meaning right after they get pushed away from each other. 1097 00:57:54,130 --> 00:57:58,040 And the postsolved in particular is interesting 1098 00:57:58,040 --> 00:58:02,540 because it gets the information about how the collision needed to resolve. 1099 00:58:02,540 --> 00:58:08,650 So how much velocity or rotation needed to happen within that interaction. 1100 00:58:08,650 --> 00:58:12,340 And we will not be using end contact, presolve, or postsolve. 1101 00:58:12,340 --> 00:58:15,370 We will only be using begin contact because, really, that's 1102 00:58:15,370 --> 00:58:18,612 all we need in order to model the behavior that we're looking for. 1103 00:58:18,612 --> 00:58:20,320 Because anything that happens in our game 1104 00:58:20,320 --> 00:58:23,170 we can just figure it out as soon as two objects touch each other. 1105 00:58:23,170 --> 00:58:25,730 1106 00:58:25,730 --> 00:58:28,600 And these are things, if you're interested in a tutorial that 1107 00:58:28,600 --> 00:58:31,420 goes over these in perhaps a little bit more detail, 1108 00:58:31,420 --> 00:58:33,520 there's a link here in the slides. 1109 00:58:33,520 --> 00:58:38,470 But I'll show you how to actually implement these callbacks yourself. 1110 00:58:38,470 --> 00:58:42,040 You do this via a function called world set callbacks, 1111 00:58:42,040 --> 00:58:45,110 in this case, F1, F2, F3, F4. 1112 00:58:45,110 --> 00:58:47,770 And recall, because Lua is a dynamic language where functions 1113 00:58:47,770 --> 00:58:52,210 are first class objects, you can pass in functions as arguments 1114 00:58:52,210 --> 00:58:53,300 to other functions. 1115 00:58:53,300 --> 00:58:54,260 And that's what we're doing here. 1116 00:58:54,260 --> 00:58:56,218 So this is assuming that we have four functions 1117 00:58:56,218 --> 00:59:00,820 we've defined called begin contact, end contact. presolve, or postsolve. 1118 00:59:00,820 --> 00:59:03,250 Their actual names don't matter at all. 1119 00:59:03,250 --> 00:59:05,881 These are just the de facto names for them. 1120 00:59:05,881 --> 00:59:09,130 What matters is that you have the logic there and you pass in function objects 1121 00:59:09,130 --> 00:59:11,170 that perform something. 1122 00:59:11,170 --> 00:59:15,130 And you can pass in all empty functions and Box2D will still behave as normal. 1123 00:59:15,130 --> 00:59:20,680 These are only for when you want more complicated behavior out of your game 1124 00:59:20,680 --> 00:59:23,320 than just things bouncing off of each other 1125 00:59:23,320 --> 00:59:26,200 and moving relative to one another. 1126 00:59:26,200 --> 00:59:29,620 So does that make sense? 1127 00:59:29,620 --> 00:59:32,020 So we'll see how this actually works. 1128 00:59:32,020 --> 00:59:34,390 We're going to go ahead and open up level dot Lua. 1129 00:59:34,390 --> 00:59:37,090 So level dot Lua is a container class that 1130 00:59:37,090 --> 00:59:40,120 basically has our game level in it, including 1131 00:59:40,120 --> 00:59:42,430 the world and all the entities. 1132 00:59:42,430 --> 00:59:47,391 And we update it and are able to model, effectively, 1133 00:59:47,391 --> 00:59:48,640 like a level from Angry Birds. 1134 00:59:48,640 --> 00:59:50,080 That's really what it is. 1135 00:59:50,080 --> 00:59:51,220 It has a world. 1136 00:59:51,220 --> 00:59:55,720 So the level has its own world with 300 positive Y gravity, as we saw before. 1137 00:59:55,720 --> 00:59:58,630 It has a table called destroyed bodies. 1138 00:59:58,630 --> 01:00:01,160 And we'll see that in a second. 1139 01:00:01,160 --> 01:00:02,710 And then here we have four functions. 1140 01:00:02,710 --> 01:00:06,730 Starting on line 22, we have begin contact, which is a long function. 1141 01:00:06,730 --> 01:00:09,510 And then we have end contact, presolve, and postsolve. 1142 01:00:09,510 --> 01:00:11,590 Those are the four callback functions that I 1143 01:00:11,590 --> 01:00:14,659 alluded to just a few seconds ago. 1144 01:00:14,659 --> 01:00:16,450 They take in slightly different signatures. 1145 01:00:16,450 --> 01:00:19,150 The first three take A, B, and collision. 1146 01:00:19,150 --> 01:00:23,260 And then the last one takes in A, B, collision, and then a normal impulse 1147 01:00:23,260 --> 01:00:26,680 and a tangent impulse, which are the forces that it needed to apply in order 1148 01:00:26,680 --> 01:00:29,620 to push apart the two objects. 1149 01:00:29,620 --> 01:00:31,840 Like I said, we won't be using these three functions. 1150 01:00:31,840 --> 01:00:36,550 But there might be a situation where you need to use those functions. 1151 01:00:36,550 --> 01:00:40,330 Maybe you want end contact because, in your game, two objects attached 1152 01:00:40,330 --> 01:00:43,640 to one another, when they collide maybe they're magnetic or something, 1153 01:00:43,640 --> 01:00:46,550 and then once they pull apart maybe you want a particle effect 1154 01:00:46,550 --> 01:00:50,690 or something to show that they've separated or something. 1155 01:00:50,690 --> 01:00:52,310 And then presolve and postsolve. 1156 01:00:52,310 --> 01:00:54,980 Presolve, offhand I can't think of a use case, 1157 01:00:54,980 --> 01:00:59,360 but postsolve could be useful for, depending on your game, 1158 01:00:59,360 --> 01:01:03,552 whether you need to just figure out maybe the amount of force 1159 01:01:03,552 --> 01:01:04,760 that they needed to separate. 1160 01:01:04,760 --> 01:01:11,540 Maybe you multiply that by some amount and cause some sort of dramatic effect. 1161 01:01:11,540 --> 01:01:14,120 Those are ultimately dependent on the domain of your game. 1162 01:01:14,120 --> 01:01:16,120 The important function that we'll be using today 1163 01:01:16,120 --> 01:01:18,830 is the first one, begin contact. 1164 01:01:18,830 --> 01:01:21,050 And notice, that we've defined these four functions, 1165 01:01:21,050 --> 01:01:23,460 even if these three are just empty. 1166 01:01:23,460 --> 01:01:27,080 But we pass in, as I said before, the set callbacks 1167 01:01:27,080 --> 01:01:29,510 function takes in those four functions. 1168 01:01:29,510 --> 01:01:33,410 And notice another interesting thing, because of Lua's dynamic nature, line 1169 01:01:33,410 --> 01:01:35,330 11 you can see that we have level init, which 1170 01:01:35,330 --> 01:01:37,820 is the constructor for our level class. 1171 01:01:37,820 --> 01:01:41,060 Within the constructor we are defining more functions. 1172 01:01:41,060 --> 01:01:45,020 You can define functions as many layers deep as you want to. 1173 01:01:45,020 --> 01:01:47,690 And you can even return functions from functions, which 1174 01:01:47,690 --> 01:01:50,959 are called higher order functions. 1175 01:01:50,959 --> 01:01:52,250 Really do whatever you want to. 1176 01:01:52,250 --> 01:01:55,730 In this case we're just defining the collision callbacks here inside 1177 01:01:55,730 --> 01:01:56,321 of our init. 1178 01:01:56,321 --> 01:01:58,320 But you could put the most anywhere you want to. 1179 01:01:58,320 --> 01:02:01,370 You can have them outside of the class, you can have them wherever you want. 1180 01:02:01,370 --> 01:02:03,828 You can have them be global functions in your main dot Lua, 1181 01:02:03,828 --> 01:02:05,660 which I don't know how I feel about that. 1182 01:02:05,660 --> 01:02:08,930 But you can do whatever you want to as long as the functions exist 1183 01:02:08,930 --> 01:02:11,180 and you can reference their symbols, you can pass them 1184 01:02:11,180 --> 01:02:14,540 into self dot world set callbacks. 1185 01:02:14,540 --> 01:02:19,490 And now, whenever a collision happens in the world period, 1186 01:02:19,490 --> 01:02:22,640 it's going to call all four of those functions 1187 01:02:22,640 --> 01:02:26,040 at each stage of each collision. 1188 01:02:26,040 --> 01:02:29,960 So you could see that potentially getting a little bit 1189 01:02:29,960 --> 01:02:33,810 hairy if you were to scale high enough with all of your logic. 1190 01:02:33,810 --> 01:02:36,100 If you had a million lines of code in each of these 1191 01:02:36,100 --> 01:02:38,796 and its executing million lines of code per collision, 1192 01:02:38,796 --> 01:02:39,920 you could run into trouble. 1193 01:02:39,920 --> 01:02:43,910 But, fortunately, we're not going anywhere near that. 1194 01:02:43,910 --> 01:02:49,100 The gist of begin contact, so it takes in an A and a B and a collision. 1195 01:02:49,100 --> 01:02:53,100 We don't end up using the collision itself, we just use the A and the B 1196 01:02:53,100 --> 01:02:56,060 because that's all we need for our game world. 1197 01:02:56,060 --> 01:02:58,868 The A and the B are what? 1198 01:02:58,868 --> 01:03:00,368 Do we know what the A and the B are? 1199 01:03:00,368 --> 01:03:02,000 AUDIENCE: Probably the two objects [INAUDIBLE].. 1200 01:03:02,000 --> 01:03:02,810 COLTON OGDEN: The two objects. 1201 01:03:02,810 --> 01:03:04,685 Do you know whether it's a body or a fixture? 1202 01:03:04,685 --> 01:03:08,749 1203 01:03:08,749 --> 01:03:10,040 AUDIENCE: It would the fixture. 1204 01:03:10,040 --> 01:03:11,623 COLTON OGDEN: It would be the fixture. 1205 01:03:11,623 --> 01:03:14,640 The fixtures collide with each other, not the bodies. 1206 01:03:14,640 --> 01:03:18,420 So when you have a body, recall that the fixture attaches the shape to a body. 1207 01:03:18,420 --> 01:03:22,830 The body is just a position and velocity container for a bunch of fixtures, 1208 01:03:22,830 --> 01:03:24,150 the body is. 1209 01:03:24,150 --> 01:03:27,810 Each individual fixture collides with other things, 1210 01:03:27,810 --> 01:03:30,150 other fixtures in your game world. 1211 01:03:30,150 --> 01:03:33,700 And so, recall that before we had fixture 1212 01:03:33,700 --> 01:03:36,480 set user data because that's what we ended up 1213 01:03:36,480 --> 01:03:39,720 needing to have data on when we do the collisions. 1214 01:03:39,720 --> 01:03:43,650 We check to see via get user data what something is 1215 01:03:43,650 --> 01:03:46,230 or what metadata we've given to that fixture. 1216 01:03:46,230 --> 01:03:51,690 And then we can then separate different classes of objects this way. 1217 01:03:51,690 --> 01:03:55,630 We can say, oh, this object was an alien, or this object was an obstacle, 1218 01:03:55,630 --> 01:03:56,880 or this object was the ground. 1219 01:03:56,880 --> 01:03:59,129 And then we can say, oh, did we collide with an alien? 1220 01:03:59,129 --> 01:04:01,830 Was the collision between an alien and the ground? 1221 01:04:01,830 --> 01:04:04,620 If it was, OK, let's play a bounce sound effect. 1222 01:04:04,620 --> 01:04:07,230 And if it was between an alien and the other alien, the player 1223 01:04:07,230 --> 01:04:10,170 and the other alien, and the velocity was fast enough, 1224 01:04:10,170 --> 01:04:11,820 OK, the alien should die. 1225 01:04:11,820 --> 01:04:12,420 Right? 1226 01:04:12,420 --> 01:04:15,810 We can do arbitrary things. 1227 01:04:15,810 --> 01:04:19,320 And so the way that I've programmed it here such that we 1228 01:04:19,320 --> 01:04:21,870 can see what two things interacted with each other, 1229 01:04:21,870 --> 01:04:26,280 and this is a very simple use of user data. 1230 01:04:26,280 --> 01:04:31,020 All we we're doing in this code base is just assigning strings to fixtures, 1231 01:04:31,020 --> 01:04:34,770 but you could assign tables to fixtures with arbitrary amounts of data 1232 01:04:34,770 --> 01:04:36,780 and do all sorts of things. 1233 01:04:36,780 --> 01:04:39,120 In this case, we're only using strings. 1234 01:04:39,120 --> 01:04:42,960 So I create a table, an empty table, and then I just 1235 01:04:42,960 --> 01:04:47,490 assign at table, at that string, true. 1236 01:04:47,490 --> 01:04:49,360 And then I can just query that table. 1237 01:04:49,360 --> 01:04:52,200 Do I have a key player and a key alien? 1238 01:04:52,200 --> 01:04:56,324 Do I have a key obstacle and a key obstacle? 1239 01:04:56,324 --> 01:04:58,740 This is how you can figure out what your two objects were. 1240 01:04:58,740 --> 01:05:02,242 Because A could be a player and B can be an obstacle. 1241 01:05:02,242 --> 01:05:04,200 A can be an obstacle and B could be the player. 1242 01:05:04,200 --> 01:05:08,050 So you have to take both of that into consideration. 1243 01:05:08,050 --> 01:05:12,990 So it allows us to do if types obstacle and types player, so 1244 01:05:12,990 --> 01:05:20,370 a collision between the player and an obstacle, if it's fast enough, then we 1245 01:05:20,370 --> 01:05:22,750 can destroy the obstacle. 1246 01:05:22,750 --> 01:05:23,880 This is what we do here. 1247 01:05:23,880 --> 01:05:29,760 So I take the absolute value of the velocity on the X and Y. 1248 01:05:29,760 --> 01:05:33,790 So I do vel X vel Y gets the body's linear velocity. 1249 01:05:33,790 --> 01:05:37,220 So linear velocity is just where it's moving in the world. 1250 01:05:37,220 --> 01:05:42,360 And it returns two values because velocity has an X and Y component. 1251 01:05:42,360 --> 01:05:48,810 And then we sum it here by taking its absolute value of both parts 1252 01:05:48,810 --> 01:05:50,230 and adding it together. 1253 01:05:50,230 --> 01:05:54,450 So if it's moving fast on the x-axis, but not fast on the y-axis, 1254 01:05:54,450 --> 01:05:57,420 or if it's not moving fast on either, or if it's moving fast on both, 1255 01:05:57,420 --> 01:06:02,220 we have a sense, in general, what's the average velocity of our object. 1256 01:06:02,220 --> 01:06:04,620 If it's moving fast on any of the axes, we 1257 01:06:04,620 --> 01:06:08,580 can assume that that's sufficient force to cause an object 1258 01:06:08,580 --> 01:06:10,500 to get destroyed, right? 1259 01:06:10,500 --> 01:06:14,250 So we do if the velocity is greater than 20, just an arbitrary value 1260 01:06:14,250 --> 01:06:16,680 that I came up with that seemed appropriate, 1261 01:06:16,680 --> 01:06:19,370 then we're going to do this. 1262 01:06:19,370 --> 01:06:24,280 Table dot insert self dot destroyed bodies, which we saw earlier. 1263 01:06:24,280 --> 01:06:25,860 And then the obstacles body. 1264 01:06:25,860 --> 01:06:30,030 Now, why are we inserting that value here as 1265 01:06:30,030 --> 01:06:33,968 opposed to, maybe just destroying it inside this function? 1266 01:06:33,968 --> 01:06:38,155 1267 01:06:38,155 --> 01:06:39,530 AUDIENCE: Destroying the fixture. 1268 01:06:39,530 --> 01:06:41,080 COLTON OGDEN: Destroying the body. 1269 01:06:41,080 --> 01:06:43,490 The fixture, yeah, in this case. 1270 01:06:43,490 --> 01:06:45,110 AUDIENCE: I mean the fixture, sorry. 1271 01:06:45,110 --> 01:06:47,360 Because you're still referencing it later in the code. 1272 01:06:47,360 --> 01:06:49,735 COLTON OGDEN: You're still referencing later in the code. 1273 01:06:49,735 --> 01:06:52,070 Box2D maintains a reference to all of the bodies, all 1274 01:06:52,070 --> 01:06:58,820 of the fixtures in your world, regardless of 1275 01:06:58,820 --> 01:07:00,440 whether you've deleted them or not. 1276 01:07:00,440 --> 01:07:03,470 But if you delete them while it's in the middle of a, 1277 01:07:03,470 --> 01:07:06,950 like checking for collision, it'll try to do another collision 1278 01:07:06,950 --> 01:07:12,100 with that destroyed body and you'll get a crash or a stack overflow error. 1279 01:07:12,100 --> 01:07:14,300 I found I experienced both of those. 1280 01:07:14,300 --> 01:07:19,940 You don't want to ever delete or destroy anything while inside a collision 1281 01:07:19,940 --> 01:07:21,260 callback for your world. 1282 01:07:21,260 --> 01:07:24,192 It will cause horrible things to happen. 1283 01:07:24,192 --> 01:07:26,900 So what we do is we maintain a reference to everything that we're 1284 01:07:26,900 --> 01:07:29,480 going to destroy by just inserting it. 1285 01:07:29,480 --> 01:07:37,220 So if we do table dot insert the body of whatever we want into destroyed bodies, 1286 01:07:37,220 --> 01:07:40,250 we can then loop over that after the world updates. 1287 01:07:40,250 --> 01:07:45,750 And then just destroy them one by one outside of the update function. 1288 01:07:45,750 --> 01:07:49,760 And the reason that we are passing in the body and not the fixture 1289 01:07:49,760 --> 01:07:55,430 is when we destroy a body, it destroys all the fixtures 1290 01:07:55,430 --> 01:07:57,451 associated with that body as well. 1291 01:07:57,451 --> 01:07:59,700 So we're just destroying the top level container here. 1292 01:07:59,700 --> 01:08:04,970 In this case, it doesn't matter too much whether we destroy a fixture or a body 1293 01:08:04,970 --> 01:08:09,090 because it's a one to one relationship. 1294 01:08:09,090 --> 01:08:14,012 But if you had, let's say, a body that has five fixtures on it. 1295 01:08:14,012 --> 01:08:16,220 And if that entire thing collides with something else 1296 01:08:16,220 --> 01:08:18,080 and you want to destroy that entire thing, 1297 01:08:18,080 --> 01:08:20,479 you want to destroy the body, not an individual fixture. 1298 01:08:20,479 --> 01:08:24,410 Because when you destroy the body, it destroys all the fixtures, not just 1299 01:08:24,410 --> 01:08:25,760 the one fixture. 1300 01:08:25,760 --> 01:08:29,990 So that's we're deleting the body, adding the body to destroyed bodies, 1301 01:08:29,990 --> 01:08:34,189 and then later performing a delete off of that. 1302 01:08:34,189 --> 01:08:39,740 The function is destroy here. 1303 01:08:39,740 --> 01:08:42,350 So on line 157-- 1304 01:08:42,350 --> 01:08:45,859 well, 155 to 159, this is where we actually 1305 01:08:45,859 --> 01:08:48,310 iterate over everything that we wanted to flag, 1306 01:08:48,310 --> 01:08:51,560 or that we've flagged as destroyed, and we destroy it. 1307 01:08:51,560 --> 01:08:55,910 So if not body is destroyed, destroy it. 1308 01:08:55,910 --> 01:09:01,790 And then once we destroy it, we're going to go down here and end up 1309 01:09:01,790 --> 01:09:05,420 actually removing the obstacle and the alien class 1310 01:09:05,420 --> 01:09:09,410 from our list of aliens and obstacles. 1311 01:09:09,410 --> 01:09:12,479 Because that maintains a reference to what we're drawing 1312 01:09:12,479 --> 01:09:13,979 and we want to also delete that. 1313 01:09:13,979 --> 01:09:17,450 So not only do we want to delete the object from the world, 1314 01:09:17,450 --> 01:09:19,970 we want to delete the objects that we've created 1315 01:09:19,970 --> 01:09:23,090 that are a wrapper for the bodies and fixtures 1316 01:09:23,090 --> 01:09:26,540 and also the drawing of our aliens so it no longer gets drawn to the scene, 1317 01:09:26,540 --> 01:09:27,388 basically. 1318 01:09:27,388 --> 01:09:30,020 1319 01:09:30,020 --> 01:09:36,410 So yeah, don't ever delete a body or a fixture inside your callbacks. 1320 01:09:36,410 --> 01:09:39,109 Always flag them and delete them afterwards. 1321 01:09:39,109 --> 01:09:43,700 Basically, don't delete in the middle of a world update function 1322 01:09:43,700 --> 01:09:45,410 call, which we see here. 1323 01:09:45,410 --> 01:09:49,550 Notice that this takes place, 152, were doing self world update. 1324 01:09:49,550 --> 01:09:55,850 And then on 155 to 159, we've populated destroyed bodies via the collision 1325 01:09:55,850 --> 01:09:57,780 callback that we defined up above. 1326 01:09:57,780 --> 01:10:00,650 So in here, this is where we can actually destroy everything. 1327 01:10:00,650 --> 01:10:04,920 This is outside of the update function, here, the world update function. 1328 01:10:04,920 --> 01:10:08,210 We don't need to worry about stack overflow or a segfault, which 1329 01:10:08,210 --> 01:10:13,070 we get by deleting something while it's in the middle 1330 01:10:13,070 --> 01:10:16,280 of processing its collisions. 1331 01:10:16,280 --> 01:10:17,390 So unfortunate bug. 1332 01:10:17,390 --> 01:10:21,620 If you ever find yourself running into stack overflows or segfaults 1333 01:10:21,620 --> 01:10:25,680 in your collision callbacks, make sure you're not deleting anything. 1334 01:10:25,680 --> 01:10:28,430 But we can see here, it's very similar, the behavior 1335 01:10:28,430 --> 01:10:32,960 we defined between obstacles and the player, between obstacles and aliens, 1336 01:10:32,960 --> 01:10:34,940 and between the player and alien. 1337 01:10:34,940 --> 01:10:38,480 Ultimately, it's check to see whether the average of its velocity 1338 01:10:38,480 --> 01:10:41,000 is greater than a certain number, in this case, 20. 1339 01:10:41,000 --> 01:10:44,627 And if it is, flag it as destroyed. 1340 01:10:44,627 --> 01:10:46,460 So if the player hits the alien, destroy it. 1341 01:10:46,460 --> 01:10:48,560 If a obstacle hits the alien, destroy it. 1342 01:10:48,560 --> 01:10:51,230 And it's similar to how it works in Angry Birds. 1343 01:10:51,230 --> 01:10:57,020 When you throw something at a structure in Angry Birds and a piece of debris 1344 01:10:57,020 --> 01:11:00,740 falls off of it and hits the pig, usually kills the pig too. 1345 01:11:00,740 --> 01:11:04,331 And if your bird hits the pig, that usually kills the pig. 1346 01:11:04,331 --> 01:11:06,830 But if you're not moving fast enough or if a piece of debris 1347 01:11:06,830 --> 01:11:09,530 isn't moving fast enough, it'll just nudge the pig, 1348 01:11:09,530 --> 01:11:11,000 it won't actually kill the pig. 1349 01:11:11,000 --> 01:11:13,820 So that's why we're taking all of this into consideration. 1350 01:11:13,820 --> 01:11:18,780 We're not just doing a blind delete off of the body's in our code, 1351 01:11:18,780 --> 01:11:22,540 we're actually making sure, is it also moving fast enough, i.e. 1352 01:11:22,540 --> 01:11:24,170 does it have enough force? 1353 01:11:24,170 --> 01:11:28,890 And if it does, then perform the code, then perform the deletion or flag it 1354 01:11:28,890 --> 01:11:30,210 as being deleted. 1355 01:11:30,210 --> 01:11:33,110 And so once again, that's why user data is important. 1356 01:11:33,110 --> 01:11:37,920 Because that's how we're able to-- because notice in the callback 1357 01:11:37,920 --> 01:11:41,820 we just get an A and a B. And those are always going to be fixtures. 1358 01:11:41,820 --> 01:11:44,520 Fixtures, in order for it to know what kind of a fixture 1359 01:11:44,520 --> 01:11:48,000 it is, whether it belongs to a player or an alien, 1360 01:11:48,000 --> 01:11:50,010 we need to give it some information. 1361 01:11:50,010 --> 01:11:55,090 So the set user data flags the fixtures as being of a specific type. 1362 01:11:55,090 --> 01:11:58,170 And then we can fetch it here with get user data 1363 01:11:58,170 --> 01:12:02,490 and then actually perform the relevant game logic. 1364 01:12:02,490 --> 01:12:05,424 Any questions as to how this works? 1365 01:12:05,424 --> 01:12:11,412 AUDIENCE: Are you checking for if two obstacles knock into each other? 1366 01:12:11,412 --> 01:12:14,370 COLTON OGDEN: Am I checking with two obstacles collide with each other? 1367 01:12:14,370 --> 01:12:15,570 I might not be. 1368 01:12:15,570 --> 01:12:18,720 In that case-- you should. 1369 01:12:18,720 --> 01:12:21,930 In that case, since we're not, they'll just bump into each other. 1370 01:12:21,930 --> 01:12:24,780 But, yeah, if we wanted two wooden obstacles 1371 01:12:24,780 --> 01:12:27,240 to destroy each other if they hit fast enough, 1372 01:12:27,240 --> 01:12:29,340 you would just do the same thing here. 1373 01:12:29,340 --> 01:12:32,850 If types obstacle, I guess. 1374 01:12:32,850 --> 01:12:35,490 But in this case, because they're both the same key, 1375 01:12:35,490 --> 01:12:39,342 you would have to do if types-- 1376 01:12:39,342 --> 01:12:40,800 let's see how we're doing it again. 1377 01:12:40,800 --> 01:12:45,310 So types obstacles is true, types obstacles is true. 1378 01:12:45,310 --> 01:12:50,740 You would say if types obstacle and not types alien, not types player, not-- 1379 01:12:50,740 --> 01:12:52,300 there's a cleaner way to do it. 1380 01:12:52,300 --> 01:12:54,390 AUDIENCE: Like a series of [INAUDIBLE] statements. 1381 01:12:54,390 --> 01:12:54,630 COLTON OGDEN: Yeah. 1382 01:12:54,630 --> 01:12:55,800 AUDIENCE: [INAUDIBLE] statements. 1383 01:12:55,800 --> 01:12:56,591 COLTON OGDEN: Yeah. 1384 01:12:56,591 --> 01:12:57,330 That's true. 1385 01:12:57,330 --> 01:12:59,680 Yeah, there's a lot of ways. 1386 01:12:59,680 --> 01:13:02,702 And if I were to re-engineer this, I would also abstract out this code 1387 01:13:02,702 --> 01:13:03,660 and make it a function. 1388 01:13:03,660 --> 01:13:07,620 Because it's pretty much the same code between all three of these. 1389 01:13:07,620 --> 01:13:09,630 But just to illustrate and just for simplicity 1390 01:13:09,630 --> 01:13:12,080 because it's pretty similar interactions, 1391 01:13:12,080 --> 01:13:15,420 didn't really put too much engineering forethought into it. 1392 01:13:15,420 --> 01:13:20,580 Definitely if you expand upon it, I would recommend doing that. 1393 01:13:20,580 --> 01:13:26,070 But that's the gist of making our world behave beyond just resolving 1394 01:13:26,070 --> 01:13:28,620 collisions and pushing obstacles away from each other, which 1395 01:13:28,620 --> 01:13:31,690 is the default behavior. 1396 01:13:31,690 --> 01:13:33,090 So we set the callbacks. 1397 01:13:33,090 --> 01:13:33,630 We're good. 1398 01:13:33,630 --> 01:13:36,671 Now things, when we interact with each other, they'll behave differently, 1399 01:13:36,671 --> 01:13:39,210 they'll trigger different behavior. 1400 01:13:39,210 --> 01:13:42,270 We have this thing called a launch marker, an alien launch marker. 1401 01:13:42,270 --> 01:13:43,711 Anybody know what that might be? 1402 01:13:43,711 --> 01:13:47,559 1403 01:13:47,559 --> 01:13:50,697 AUDIENCE: Is that the little dots that show the trajectory? 1404 01:13:50,697 --> 01:13:53,280 COLTON OGDEN: Yeah, so it's the dots that show the trajectory. 1405 01:13:53,280 --> 01:13:56,220 It's one, the alien being rendered on the left side of the screen 1406 01:13:56,220 --> 01:14:00,180 without any physics applied to it, that's click and dragable. 1407 01:14:00,180 --> 01:14:02,040 And it also renders a trajectory. 1408 01:14:02,040 --> 01:14:07,050 And when you release the mouse, it launches an actual Box2D alien 1409 01:14:07,050 --> 01:14:12,630 traveling in the direction that that trajectory foretells. 1410 01:14:12,630 --> 01:14:19,024 If we look at alien launch marker here, it basically maintains a reference to 1411 01:14:19,024 --> 01:14:20,190 whether we're aiming or not. 1412 01:14:20,190 --> 01:14:21,600 So it's got a couple of states. 1413 01:14:21,600 --> 01:14:25,190 It's got a launch state and an aiming state. 1414 01:14:25,190 --> 01:14:27,960 An alien that we'll have a reference to eventually, which 1415 01:14:27,960 --> 01:14:30,400 will spawn and will give it an impulse. 1416 01:14:30,400 --> 01:14:36,420 So an impulse is effectively setting its velocity immediately to some value, 1417 01:14:36,420 --> 01:14:38,160 as opposed to something over time. 1418 01:14:38,160 --> 01:14:40,170 We can apply force to an object, which would 1419 01:14:40,170 --> 01:14:43,230 be like you driving your car up against something 1420 01:14:43,230 --> 01:14:46,110 and then gradually accelerating, that's applying force. 1421 01:14:46,110 --> 01:14:49,920 And we can also apply impulse by going full speed with our car 1422 01:14:49,920 --> 01:14:52,230 and hitting an object, and that will have 1423 01:14:52,230 --> 01:14:56,220 the effect of applying an impulse at a certain velocity. 1424 01:14:56,220 --> 01:15:00,450 When we drag our alien and then we release it, 1425 01:15:00,450 --> 01:15:03,480 we want to apply an impulse in the opposite direction of where we're 1426 01:15:03,480 --> 01:15:06,060 dragging based on a certain amount. 1427 01:15:06,060 --> 01:15:10,500 I scaled it by 10, but you can have it be arbitrary. 1428 01:15:10,500 --> 01:15:14,550 And then the trajectory models where it's going. 1429 01:15:14,550 --> 01:15:20,110 And the trajectory is calculated via these lines here. 1430 01:15:20,110 --> 01:15:22,250 So from line 90 to 104. 1431 01:15:22,250 --> 01:15:25,620 There is a formula for, in that Box2D set 1432 01:15:25,620 --> 01:15:27,390 of tutorials, that actually shows you how 1433 01:15:27,390 --> 01:15:31,890 to calculate an estimated trajectory given a starting impulse and a starting 1434 01:15:31,890 --> 01:15:33,900 position. 1435 01:15:33,900 --> 01:15:36,060 Which is this formula here. 1436 01:15:36,060 --> 01:15:38,190 It's semi-complicated. 1437 01:15:38,190 --> 01:15:40,500 The article goes into detail as to how it works, 1438 01:15:40,500 --> 01:15:45,420 but it effectively calculates 1/60 of a second, 1439 01:15:45,420 --> 01:15:48,580 assuming that we're running our simulation at 1/60 of a second, 1440 01:15:48,580 --> 01:15:52,810 it will, over 90 iterations here, 1 to 90, 1441 01:15:52,810 --> 01:15:56,310 calculate each individual step of that simulation. 1442 01:15:56,310 --> 01:15:58,900 And then I only render every 5 here. 1443 01:15:58,900 --> 01:16:03,180 So if i is mod 5 s 0, then I'll actually end up 1444 01:16:03,180 --> 01:16:05,640 drawing a circle at trajectory X, trajectory 1445 01:16:05,640 --> 01:16:07,830 Y. Trajectory X and Y being here. 1446 01:16:07,830 --> 01:16:10,950 Shifted X, shifted Y being the starting location. 1447 01:16:10,950 --> 01:16:15,180 And then we multiply i by 1/60 of a second, which will give us 1448 01:16:15,180 --> 01:16:19,860 the scalar for this impulse here. 1449 01:16:19,860 --> 01:16:23,600 And then with gravity we have to do this i squared plus 1450 01:16:23,600 --> 01:16:31,530 i times 1/2 times the gravity on the y-axis times 1/60 squared. 1451 01:16:31,530 --> 01:16:34,530 The article goes into a little bit more detail as to how it works. 1452 01:16:34,530 --> 01:16:38,910 But that's it converted into source code. 1453 01:16:38,910 --> 01:16:41,010 But it's effectively a gravity simulation 1454 01:16:41,010 --> 01:16:44,490 and a velocity simulation over time. 1455 01:16:44,490 --> 01:16:47,670 And by rendering it based on 90 iterations, which 1456 01:16:47,670 --> 01:16:51,210 is one and a half seconds, at 1/60 of a second 1457 01:16:51,210 --> 01:16:54,750 we can forecast where exactly we're going. 1458 01:16:54,750 --> 01:17:00,620 And then when we apply this impulse, X and Y, the ball will actually travel, 1459 01:17:00,620 --> 01:17:04,690 the alien will actually travel in that direction at that exact trajectory. 1460 01:17:04,690 --> 01:17:09,050 1461 01:17:09,050 --> 01:17:12,050 That's the complicated part of the launch marker. 1462 01:17:12,050 --> 01:17:16,550 The other part is that it has a couple of states, like I said before. 1463 01:17:16,550 --> 01:17:20,180 So when we click and we're not launched, it should go into aiming mode. 1464 01:17:20,180 --> 01:17:25,790 And so if we're aiming then we're going to set a rotation to-- 1465 01:17:25,790 --> 01:17:31,610 actually, rotation is not relevant because this was before I ended up 1466 01:17:31,610 --> 01:17:34,760 using the predictive trajectory method. 1467 01:17:34,760 --> 01:17:39,470 The shift at X and Y though, those are relevant because that's the starting 1468 01:17:39,470 --> 01:17:41,240 location for your trajectory. 1469 01:17:41,240 --> 01:17:43,084 That's wherever your mouse is. 1470 01:17:43,084 --> 01:17:45,500 And we clamp it so that it doesn't go past a certain limit 1471 01:17:45,500 --> 01:17:49,730 on the left or the right, so that it stays within a box area. 1472 01:17:49,730 --> 01:17:52,160 But this will be whenever you let go of the mouse, that 1473 01:17:52,160 --> 01:17:55,670 will be where we spawn the Box2D alien and apply 1474 01:17:55,670 --> 01:17:59,460 an impulse in a negative direction relative to where we move the mouse. 1475 01:17:59,460 --> 01:18:01,820 So if we move the mouse to the left and down, 1476 01:18:01,820 --> 01:18:05,620 it's going to negate that with an impulse going up 1477 01:18:05,620 --> 01:18:08,330 and to the right, if that makes sense. 1478 01:18:08,330 --> 01:18:10,378 And that's what's shown by the trajectory. 1479 01:18:10,378 --> 01:18:13,130 1480 01:18:13,130 --> 01:18:15,560 And then, aside from that, it renders different things 1481 01:18:15,560 --> 01:18:16,827 depending on whether or not-- 1482 01:18:16,827 --> 01:18:17,660 what state we're in. 1483 01:18:17,660 --> 01:18:20,600 So if we haven't launched, it will render just the alien. 1484 01:18:20,600 --> 01:18:23,660 If we're in aiming mode then it should actually render and calculate 1485 01:18:23,660 --> 01:18:24,710 the trajectory. 1486 01:18:24,710 --> 01:18:27,080 Otherwise, it would just render the alien. 1487 01:18:27,080 --> 01:18:34,130 And so once we release the mouse, so was released 1 and were aiming, 1488 01:18:34,130 --> 01:18:35,960 launched is true, spawn an alien. 1489 01:18:35,960 --> 01:18:40,610 So we create a new alien with self world, it's round. 1490 01:18:40,610 --> 01:18:43,400 We started at shifted X and shifted Y. We 1491 01:18:43,400 --> 01:18:48,720 set its linear velocity to the same values that we calculated before. 1492 01:18:48,720 --> 01:18:51,960 So it's base X minus shifted X times 10. 1493 01:18:51,960 --> 01:18:53,450 So the times 10 is a scalar amount. 1494 01:18:53,450 --> 01:18:56,450 1495 01:18:56,450 --> 01:19:03,421 And then the base X is where we've moved it, effectively. 1496 01:19:03,421 --> 01:19:03,920 Or, no. 1497 01:19:03,920 --> 01:19:07,970 Base X is where it starts and shifted X is where we've moved it. 1498 01:19:07,970 --> 01:19:11,390 And so by subtracting shifted from the base, 1499 01:19:11,390 --> 01:19:16,280 we get the negative direction that we want to effect the impulse. 1500 01:19:16,280 --> 01:19:21,560 And then the impulse is set here with linear velocity. 1501 01:19:21,560 --> 01:19:26,660 And then we also set it to have a restitution of 0.4. 1502 01:19:26,660 --> 01:19:29,420 Recall, restitution is bounciness. 1503 01:19:29,420 --> 01:19:32,450 So our alien bounces a little bit when it hits the ground. 1504 01:19:32,450 --> 01:19:37,170 And then anybody know what angular damping might be? 1505 01:19:37,170 --> 01:19:39,680 Any guesses? 1506 01:19:39,680 --> 01:19:45,860 Angular damping is when it rotates, basically, friction on its rotation. 1507 01:19:45,860 --> 01:19:49,520 So that when it rotates on the ground, it doesn't roll indefinitely. 1508 01:19:49,520 --> 01:19:52,997 If we don't set that, it'll just roll forever and ever and ever and ever. 1509 01:19:52,997 --> 01:19:54,080 Which is not what we want. 1510 01:19:54,080 --> 01:19:56,990 We want it to stop at a certain point because once it stops, 1511 01:19:56,990 --> 01:20:00,170 we know, OK, now we can get the next alien ready to launch. 1512 01:20:00,170 --> 01:20:03,170 1513 01:20:03,170 --> 01:20:05,420 And that's the gist behind the launch marker. 1514 01:20:05,420 --> 01:20:07,294 How we render trajectory. 1515 01:20:07,294 --> 01:20:10,460 For the math on that, a little bit more in detail, I would explore that URL. 1516 01:20:10,460 --> 01:20:12,740 It goes into it into pretty good detail. 1517 01:20:12,740 --> 01:20:18,156 I use that as a reference for creating this bit of code here. 1518 01:20:18,156 --> 01:20:20,030 But yeah, effectively, is it's just rendering 1519 01:20:20,030 --> 01:20:24,470 a bunch of circles with that trajectory and calculating it 1520 01:20:24,470 --> 01:20:30,770 over 90 ticks, 90 frame iterations. 1521 01:20:30,770 --> 01:20:32,860 Back to the level. 1522 01:20:32,860 --> 01:20:37,402 Sorry, any questions overall as to how the launch marker works? 1523 01:20:37,402 --> 01:20:38,334 AUDIENCE: No. 1524 01:20:38,334 --> 01:20:40,000 COLTON OGDEN: Cool. 1525 01:20:40,000 --> 01:20:40,500 All right. 1526 01:20:40,500 --> 01:20:44,190 So then we have an alien's table, an obstacles table, 1527 01:20:44,190 --> 01:20:47,580 edge shape for the ground. 1528 01:20:47,580 --> 01:20:50,660 And then we just create an alien to destroy. 1529 01:20:50,660 --> 01:20:52,140 Spawn a few obstacles here. 1530 01:20:52,140 --> 01:20:56,280 So in this case, two vertical obstacles and a horizontal one. 1531 01:20:56,280 --> 01:20:59,580 Positioned such that the horizontal one is over the vertical ones 1532 01:20:59,580 --> 01:21:04,730 and they're spaced apart such that the aliens are in the middle of them. 1533 01:21:04,730 --> 01:21:08,980 Then the ground here, we give the ground some friction, 0.5. 1534 01:21:08,980 --> 01:21:12,280 And that's pretty much it for setting up our level. 1535 01:21:12,280 --> 01:21:18,330 So if we wanted to, after this point, we have the foundation 1536 01:21:18,330 --> 01:21:24,030 necessary to really spawn arbitrary levels with admittedly simple obstacles 1537 01:21:24,030 --> 01:21:24,900 at this point. 1538 01:21:24,900 --> 01:21:26,970 But we could set-- 1539 01:21:26,970 --> 01:21:30,270 because all we're doing here is just simple insertions to our aliens 1540 01:21:30,270 --> 01:21:36,030 and obstacles table, we could create pretty much any level just by, maybe 1541 01:21:36,030 --> 01:21:40,710 in data, specifying level could be like a table 1542 01:21:40,710 --> 01:21:44,220 and then aliens could be another table. 1543 01:21:44,220 --> 01:21:53,100 And then maybe all it is just a like X equals some value, 1544 01:21:53,100 --> 01:21:55,170 and then Y equals some value. 1545 01:21:55,170 --> 01:21:59,340 And then obstacles is the same thing. 1546 01:21:59,340 --> 01:22:02,640 And then all we do is just we iterate over this level definition 1547 01:22:02,640 --> 01:22:07,440 and we just say, new alien for every table here. 1548 01:22:07,440 --> 01:22:09,390 And then new obstacle for every table in here. 1549 01:22:09,390 --> 01:22:11,640 And then now your levels are data driven. 1550 01:22:11,640 --> 01:22:13,260 It's easy just to make levels. 1551 01:22:13,260 --> 01:22:15,134 You don't have to code, really, much. 1552 01:22:15,134 --> 01:22:16,800 And you can put this in a separate file. 1553 01:22:16,800 --> 01:22:21,240 Be like, levels dot Lua, and then just load individual levels at a time. 1554 01:22:21,240 --> 01:22:28,020 Level 1 equals-- levels would be the top level container. 1555 01:22:28,020 --> 01:22:33,720 And then you would have 1 equals all of this, and then 2 1556 01:22:33,720 --> 01:22:36,004 equals another one, 3 equals another one. 1557 01:22:36,004 --> 01:22:37,920 And then you're not really programming as much 1558 01:22:37,920 --> 01:22:40,170 as you are just laying things out in data. 1559 01:22:40,170 --> 01:22:41,640 Super nice and concise. 1560 01:22:41,640 --> 01:22:44,980 That's a nice thing about a language like Lua, is that you can, 1561 01:22:44,980 --> 01:22:47,130 and it's the same thing in JavaScript with JSON, 1562 01:22:47,130 --> 01:22:50,970 you can just define things as data and then write 1563 01:22:50,970 --> 01:22:54,630 a script to go over it and construct your actual relevant data structures 1564 01:22:54,630 --> 01:22:55,760 that way-- 1565 01:22:55,760 --> 01:22:57,240 in your code that way. 1566 01:22:57,240 --> 01:22:59,580 When you have the foundation like we have now 1567 01:22:59,580 --> 01:23:02,340 where you can think in terms of obstacles and aliens, 1568 01:23:02,340 --> 01:23:04,650 you can construct levels like so. 1569 01:23:04,650 --> 01:23:07,170 And obviously you could go a lot more complicated with this. 1570 01:23:07,170 --> 01:23:14,280 All we're doing is having very simple almost boring static obstacles. 1571 01:23:14,280 --> 01:23:17,280 They're not static in a technical sense because they're dynamic objects, 1572 01:23:17,280 --> 01:23:21,520 but all they really do is just stand there and then fall over. 1573 01:23:21,520 --> 01:23:25,890 But if you wanted a pulley system or maybe 1574 01:23:25,890 --> 01:23:29,520 something that's shaped in a giant head or something, 1575 01:23:29,520 --> 01:23:36,880 you can create arbitrarily complex objects that way using joints. 1576 01:23:36,880 --> 01:23:40,050 And if you're curious, I recommend to look into the documentation for Love2D 1577 01:23:40,050 --> 01:23:40,980 a little bit more. 1578 01:23:40,980 --> 01:23:44,340 Especially their weld joints are what you would use 1579 01:23:44,340 --> 01:23:47,970 to combine pieces in arbitrary shapes. 1580 01:23:47,970 --> 01:23:50,820 But you could easily take this to the next level 1581 01:23:50,820 --> 01:23:56,520 and start to create in that same level definition, arbitrarily shaped, 1582 01:23:56,520 --> 01:24:01,495 welded together obstacles. 1583 01:24:01,495 --> 01:24:03,870 But that would be, I think, a next step if you're looking 1584 01:24:03,870 --> 01:24:06,990 to take this beyond just one level. 1585 01:24:06,990 --> 01:24:12,510 I would say, think in terms of, how can I get my game world represented 1586 01:24:12,510 --> 01:24:14,850 in a very simple data like way? 1587 01:24:14,850 --> 01:24:17,670 Because not only does it make it easier for you to create content, 1588 01:24:17,670 --> 01:24:20,430 it allows you to shift that burden to somebody else 1589 01:24:20,430 --> 01:24:23,002 and allow you to give the task of creating levels 1590 01:24:23,002 --> 01:24:24,960 less to a programmer and maybe more to somebody 1591 01:24:24,960 --> 01:24:28,290 who has just a design background who isn't as comfortable writing code. 1592 01:24:28,290 --> 01:24:31,920 And allow you to create the engine that constructs the game world based off 1593 01:24:31,920 --> 01:24:34,440 of this data. 1594 01:24:34,440 --> 01:24:40,560 Any questions as to how we've set things up here? 1595 01:24:40,560 --> 01:24:41,877 OK. 1596 01:24:41,877 --> 01:24:43,710 So we have the ground, we have a background. 1597 01:24:43,710 --> 01:24:47,550 A background is just a simple class that renders a static image 1598 01:24:47,550 --> 01:24:49,860 that you can scroll the image with left or right, 1599 01:24:49,860 --> 01:24:51,930 but we don't end up using it much. 1600 01:24:51,930 --> 01:24:55,590 It's relevant in Angry Birds because in Angry Birds they have a camera, 1601 01:24:55,590 --> 01:25:00,540 and the camera pans left to right depending on how far away 1602 01:25:00,540 --> 01:25:02,790 the fortress is from your sling shot. 1603 01:25:02,790 --> 01:25:06,660 So that's in there if you want to experiment with it at all, 1604 01:25:06,660 --> 01:25:08,160 and experiment with a moving camera. 1605 01:25:08,160 --> 01:25:11,280 Maybe use timer dot tween to tween the camera 1606 01:25:11,280 --> 01:25:15,690 or just to have it track the alien if you want larger worlds. 1607 01:25:15,690 --> 01:25:19,320 But we don't end up using it in the distro as much. 1608 01:25:19,320 --> 01:25:20,890 Our update function is simple. 1609 01:25:20,890 --> 01:25:23,070 We update the launch marker, update the world, 1610 01:25:23,070 --> 01:25:26,280 and then we process all the bodies that we flagged as being destroyed, 1611 01:25:26,280 --> 01:25:27,680 which we've already seen. 1612 01:25:27,680 --> 01:25:29,640 We reset destroyed bodies to an empty table 1613 01:25:29,640 --> 01:25:31,740 because we've processed all of them. 1614 01:25:31,740 --> 01:25:38,504 We actually remove from our level the obstacle objects 1615 01:25:38,504 --> 01:25:40,670 so that they're no longer rendered, and we no longer 1616 01:25:40,670 --> 01:25:44,650 try to reference the bodies that are destroyed. 1617 01:25:44,650 --> 01:25:49,160 And then notice here too, when we destroy the obstacle, 1618 01:25:49,160 --> 01:25:52,050 we're playing a sound effect inside this bit of code. 1619 01:25:52,050 --> 01:25:54,650 So we can just do g sounds. 1620 01:25:54,650 --> 01:25:57,260 I put five wooden sound effects in there just for variability. 1621 01:25:57,260 --> 01:25:58,280 It'll pick a random one. 1622 01:25:58,280 --> 01:26:00,650 And then using to string at the number, just 1623 01:26:00,650 --> 01:26:03,020 create break one, two, three, four, five here. 1624 01:26:03,020 --> 01:26:06,420 And then stop and play it. 1625 01:26:06,420 --> 01:26:07,197 Same thing here. 1626 01:26:07,197 --> 01:26:09,530 I have a sound called kill for when we destroy an alien. 1627 01:26:09,530 --> 01:26:14,240 So when we flag an alien as destroyed and we remove it from the scene, 1628 01:26:14,240 --> 01:26:16,910 we should also call that sound effect. 1629 01:26:16,910 --> 01:26:27,050 And then if the alien stops moving in our scene, the player, 1630 01:26:27,050 --> 01:26:31,430 we can get a reference to it here, self dot launch marker dot alien, 1631 01:26:31,430 --> 01:26:33,667 as opposed to any aliens in our scene. 1632 01:26:33,667 --> 01:26:36,125 When it stops moving, so we get the average of its velocity 1633 01:26:36,125 --> 01:26:38,510 and if it's less than 1.5, so not perfectly 1634 01:26:38,510 --> 01:26:43,610 still, because it's tedious to wait that long, but almost still, 1635 01:26:43,610 --> 01:26:48,950 we destroy the alien and then we create a new launch marker. 1636 01:26:48,950 --> 01:26:52,439 We destroy the alien so that the world doesn't keep a reference to it 1637 01:26:52,439 --> 01:26:54,230 and then we just create a brand new marker, 1638 01:26:54,230 --> 01:27:00,530 which has the effect of instantiating a new alien there when we relaunch. 1639 01:27:00,530 --> 01:27:04,369 And then here, if there are no more aliens in our scene, 1640 01:27:04,369 --> 01:27:07,410 if we've destroyed all of the aliens, in this case there's only ever one, 1641 01:27:07,410 --> 01:27:09,800 but there could easily, with a little more work, 1642 01:27:09,800 --> 01:27:13,040 be a few more aliens in the scene, if it's set to zero, 1643 01:27:13,040 --> 01:27:14,630 then go back to the start. 1644 01:27:14,630 --> 01:27:18,160 Which we saw before when we finally killed the alien. 1645 01:27:18,160 --> 01:27:19,910 And then all we're doing here is deferring 1646 01:27:19,910 --> 01:27:26,090 rendering to the individual objects we want to render, the launch marker, 1647 01:27:26,090 --> 01:27:27,650 the alien, the obstacle. 1648 01:27:27,650 --> 01:27:29,420 We render ground tiles. 1649 01:27:29,420 --> 01:27:34,070 So recall, from our ground example before we were just using a line, 1650 01:27:34,070 --> 01:27:36,200 an edge shape to represent the ground. 1651 01:27:36,200 --> 01:27:44,630 But if we look at our game, it's a little hard to see because I'm in 720, 1652 01:27:44,630 --> 01:27:49,250 but there's actually a ground tile here at the very bottom, a bunch of them. 1653 01:27:49,250 --> 01:27:52,760 And even though we have all of those tiles, 1654 01:27:52,760 --> 01:27:56,090 all we're doing to detect collision is just an edge shape. 1655 01:27:56,090 --> 01:28:02,720 So what we're doing is just beyond having the edge shape in our scene, 1656 01:28:02,720 --> 01:28:09,530 we draw that tile, which is frame 12 in our sprite sheet 1657 01:28:09,530 --> 01:28:11,930 from negative virtual width to virtual times 2. 1658 01:28:11,930 --> 01:28:13,850 So three screen widths total. 1659 01:28:13,850 --> 01:28:16,130 And then we just do it in increments of 35 pixels 1660 01:28:16,130 --> 01:28:17,630 because that's how wide the tile is. 1661 01:28:17,630 --> 01:28:19,856 And that'll just create a bunch of the same tile 1662 01:28:19,856 --> 01:28:21,230 at the very bottom of our screen. 1663 01:28:21,230 --> 01:28:24,660 1664 01:28:24,660 --> 01:28:28,130 So just a graphical thing, not really necessarily functional. 1665 01:28:28,130 --> 01:28:31,190 We have the edge shape already in our scene, but just to make the ground 1666 01:28:31,190 --> 01:28:35,540 look a little larger than one pixel tall. 1667 01:28:35,540 --> 01:28:38,300 And then if we haven't launched anything, 1668 01:28:38,300 --> 01:28:40,610 we should display some instructions here. 1669 01:28:40,610 --> 01:28:45,050 And then if we're at no aliens left, then we 1670 01:28:45,050 --> 01:28:47,570 should display the victory screen. 1671 01:28:47,570 --> 01:28:51,650 And the victory thing will last for just a little bit of time, 1672 01:28:51,650 --> 01:28:55,370 because even though self dot aliens is zero, this bit of code 1673 01:28:55,370 --> 01:28:59,840 doesn't register until after the velocity of our moving alien 1674 01:28:59,840 --> 01:29:01,520 slows down sufficiently. 1675 01:29:01,520 --> 01:29:05,420 So this will get called when we're just about to finally stop moving, 1676 01:29:05,420 --> 01:29:09,500 and then we check to see, oh, OK, do we indeed have no aliens left? 1677 01:29:09,500 --> 01:29:12,380 If not, time to go back to the start. 1678 01:29:12,380 --> 01:29:13,475 We've completed a level. 1679 01:29:13,475 --> 01:29:15,350 And then you obviously would just change this 1680 01:29:15,350 --> 01:29:19,179 to go to be next level if you ended up implementing more 1681 01:29:19,179 --> 01:29:20,720 levels in your game besides just one. 1682 01:29:20,720 --> 01:29:23,600 1683 01:29:23,600 --> 01:29:27,550 Beyond that, that's pretty much all of the code that's in this example. 1684 01:29:27,550 --> 01:29:32,300 It's fairly, I would say, unsophisticated relative 1685 01:29:32,300 --> 01:29:33,260 to prior examples. 1686 01:29:33,260 --> 01:29:35,630 But mainly, the burden is learning how to use 1687 01:29:35,630 --> 01:29:38,960 the physics engine, the Box2D physics engine, which 1688 01:29:38,960 --> 01:29:42,240 itself is quite a few functions. 1689 01:29:42,240 --> 01:29:47,060 It's some of the longest documentation on Love2D's wiki, I think. 1690 01:29:47,060 --> 01:29:50,270 But the principles are pretty simple, in my opinion. 1691 01:29:50,270 --> 01:29:54,905 I think it's actually quite easy to get rolling with a lot of cool features. 1692 01:29:54,905 --> 01:29:57,617 1693 01:29:57,617 --> 01:30:00,200 The vast majority of which I don't think we even really cover, 1694 01:30:00,200 --> 01:30:03,920 at least in terms of what you can do with compound objects and joints 1695 01:30:03,920 --> 01:30:06,260 and things like that, which really start to go 1696 01:30:06,260 --> 01:30:12,260 into the world of more sophisticated and interesting physical simulations. 1697 01:30:12,260 --> 01:30:16,130 Things like I alluded to before, pulleys and tanks and other things like that. 1698 01:30:16,130 --> 01:30:19,580 Some features that we could look at potentially expanding upon 1699 01:30:19,580 --> 01:30:21,920 if we wanted to make our game more interesting, 1700 01:30:21,920 --> 01:30:24,430 is more shapes for our objects. 1701 01:30:24,430 --> 01:30:28,280 So if we look at our sprite sheet here, we 1702 01:30:28,280 --> 01:30:33,290 can see there are things like roofs and circles and things like that. 1703 01:30:33,290 --> 01:30:36,710 So more interesting obstacles beyond just square rectangular 1704 01:30:36,710 --> 01:30:37,590 shaped obstacles. 1705 01:30:37,590 --> 01:30:40,790 1706 01:30:40,790 --> 01:30:44,540 Go back to-- like I said before, compound obstacles. 1707 01:30:44,540 --> 01:30:47,240 So a bunch of things put together via joints. 1708 01:30:47,240 --> 01:30:51,210 So pulleys, there's motors, weld joints, which you can use to-- you 1709 01:30:51,210 --> 01:30:56,840 can affix a roof to a square and then have two pieces that are tied together. 1710 01:30:56,840 --> 01:30:59,330 And you can make arbitrarily complex and shaped things 1711 01:30:59,330 --> 01:31:01,010 and just be really interesting. 1712 01:31:01,010 --> 01:31:03,890 And that big thing, that body with all these fixtures, 1713 01:31:03,890 --> 01:31:09,740 will collide just as any other thing would, thanks to Box2D. 1714 01:31:09,740 --> 01:31:13,670 As I alluded to before, instead of having levels to be hard coded 1715 01:31:13,670 --> 01:31:19,100 into our level class, maybe define them in a Lua file called levels dot Lua. 1716 01:31:19,100 --> 01:31:22,070 And then just have aliens be a table, obstacles 1717 01:31:22,070 --> 01:31:23,870 be a table, and then whatever else, however 1718 01:31:23,870 --> 01:31:25,869 more complicated you want to get with your game. 1719 01:31:25,869 --> 01:31:27,260 You can add more things. 1720 01:31:27,260 --> 01:31:32,409 But just have it be represented as simple data structures. 1721 01:31:32,409 --> 01:31:34,700 So aliens that maybe have different shooting mechanics. 1722 01:31:34,700 --> 01:31:37,280 So if you've played Angry Birds you're familiar with the fact 1723 01:31:37,280 --> 01:31:40,070 that some birds will split off into multiple birds. 1724 01:31:40,070 --> 01:31:44,150 Some birds will dive and go super fast and break through all the obstacles 1725 01:31:44,150 --> 01:31:45,290 in their path. 1726 01:31:45,290 --> 01:31:48,020 Some birds will explode, and then their explosion 1727 01:31:48,020 --> 01:31:50,610 affects all of the obstacles around them. 1728 01:31:50,610 --> 01:31:52,970 So there's a lot of different game play mechanics 1729 01:31:52,970 --> 01:31:57,240 you can implement using different types of birds or aliens. 1730 01:31:57,240 --> 01:32:01,670 And then different obstacle materials is another direction we could go. 1731 01:32:01,670 --> 01:32:04,280 And it's supported out of the box with the sprite sheet 1732 01:32:04,280 --> 01:32:08,300 that I provided because it has sheets for metal 1733 01:32:08,300 --> 01:32:10,080 and glass and explosive material. 1734 01:32:10,080 --> 01:32:12,080 So there's a lot of different interesting things 1735 01:32:12,080 --> 01:32:15,800 you could do just by changing up what materials you're using in the game. 1736 01:32:15,800 --> 01:32:19,250 And obviously those will have different densities and behave in different ways. 1737 01:32:19,250 --> 01:32:21,450 So assignment five is a fairly simple assignment. 1738 01:32:21,450 --> 01:32:24,320 So this is just as I alluded to before. 1739 01:32:24,320 --> 01:32:27,620 The task here is to split the bird that you 1740 01:32:27,620 --> 01:32:31,850 shoot by pressing Spacebar when it's in the bird-- the alien, when 1741 01:32:31,850 --> 01:32:35,360 it's in the air, press Spacebar and have it split into three. 1742 01:32:35,360 --> 01:32:37,680 So you have your one that you're shooting already. 1743 01:32:37,680 --> 01:32:39,470 So it should just shoot off two more. 1744 01:32:39,470 --> 01:32:41,600 One that's angled higher, one that's angled lower. 1745 01:32:41,600 --> 01:32:45,945 And all of those should be interactable with your game world. 1746 01:32:45,945 --> 01:32:46,820 And that's really it. 1747 01:32:46,820 --> 01:32:48,944 So if you can do that then it'll show that you know 1748 01:32:48,944 --> 01:32:52,580 how to effect the Box2D game world. 1749 01:32:52,580 --> 01:32:55,574 Next time, next lecture, we'll be talking about-- 1750 01:32:55,574 --> 01:32:57,365 the theme is going to be Pokemon, but we'll 1751 01:32:57,365 --> 01:33:03,057 be talking about more generally RPGs and turn-based games of that nature. 1752 01:33:03,057 --> 01:33:05,390 It won't maybe necessarily look quite as pretty as this. 1753 01:33:05,390 --> 01:33:08,390 But we'll be striving for a similar over world 1754 01:33:08,390 --> 01:33:11,937 that we can walk around and then engage in fairly simple turn-based battles 1755 01:33:11,937 --> 01:33:12,770 and stuff like that. 1756 01:33:12,770 --> 01:33:15,530 And also, we'll be talking about user interfaces and things 1757 01:33:15,530 --> 01:33:18,080 like dialogue and stuff like that. 1758 01:33:18,080 --> 01:33:20,332 But that was it for lecture six, Angry Birds. 1759 01:33:20,332 --> 01:33:21,290 I'll see you next time. 1760 01:33:21,290 --> 01:33:23,140 Thank you. 1761 01:33:23,140 --> 01:33:24,251