COLTON OGDEN: So with mario8, we got our hands dirty with a little bit of collision detection-- some very easy collusion detection, just checking above Mario's head such that now he can jump, and hit blocks, and change their appearance. In this update, we are going to actually make certain objects in our scene collidable, which otherwise were not. For example, the column there, as you can see, Mario is actually in the walk animation. I say Mario lightly. It's not really Mario. But Mario is walking towards the right and colliding with the column. So we're going to make the column collidable. We're going to make the tiles collidable below Mario. So basically, we have a whitelist now of titles that we can collide with. And in addition, we need to not only check what's above Mario, to the left and to the right of the corners, but also, we need to look for what's below Mario. So if they're walking and moving left and right, we will always want to be checking what's below them so that we can determine whether they should fall, or also when they're jumping. Same thing with the left and the right. So if we're jumping and we hit a pillar or the like, we should check to make sure that we are not bumping into it. So for example, we can fall down into the walls and not sort of move back and forth and do some weird stuff that way. So that's really it for the preface to mario9. Let's get into the actual code here. So we're going to have a lot of the same stuff that we saw in the last section more or less. We added a few functions here. So the one thing that has remained is that our update function still has this bit of code here for when we're jumping and detecting a block above us. Additionally, in all of the states, we have now added some additional code. So idle doesn't have any additional collision detection code because really, we don't need to check if we're colliding with something or standing perfectly still. But walking, for example, does have a couple of new bits and pieces. So we have two functions, checkRightCollision and checkLeftCollision. And they do exactly as their name-- they check the right side and the left side of Mario, assuming that we are going in that direction. And we also have to see, when we're in the walking state, whether or not there are two tiles below us. And you'll look at this and actually realize that the code here is the exact same, more or less, as it was before, in that we are checking to see if there's a tile at some value. Only this time, we're checking below Mario, as by adding self.height to the y value here. So we're checking to see if there's a tile at self.x, self.y plus self.height. And additionally, we're also using this function self.map:collides. So let's take a look at that. So in Map, we're going to go over down to the collides function. So all this really does is it just has a set of tiles here, so it's just a table of the constants of the tiles that we have determined are solid-- ones that we can collide with. And what we're doing here is actually using some interesting syntax we haven't looked at yet, which is how to iterate over a collection, a table, in Lua. And so what we're doing is we're saying, for every key-value pair in ipairs-- so ipairs is short for iterate pairs. It's a way of iterating over all of the key-value pairs in a table, but you're also given an index, as well, if you want that index. And that's what you get here as the underscore. Doesn't really matter for this particular example. We're not using the key in our loop here. All we're checking to see is if that value has an ID that is equal to v. And what we're doing is we're essentially going over all of the collidables, given this tile here. And if tile.id is equal to v, which is this value, then we're going to return true. And if it's the case that all of those collidables do not match what tile is here, then we're just going to return false, so we have not actually collided with anything. That's the addition to Map that we've made in this section. I'm going to go back to Player. And so what we're doing is we're just checking if map collides with the tile at right below our feet and to the right of our character, because remember, everything is relative to the left side. So we're also checking the tile that's below the right side and one pixel down. Just in case we're between two tiles, we want to make sure of that. And just to illustrate that again, this is a perfect example where we have two tiles here where Mario might be between them. So we want to check not only the tile below this corner, but also the tile below this corner. And we know that we don't span more than two tiles max because our width is only 16 pixels, which it would be impossible to span three tiles in that situation. So I'm going to go back over here. Now, if we do end up falling and we're in the walking animation, the walking state, what we want to do is set our state to jumping, which might be a little bit unintuitive. But really, just because we have that falling behavior and gravity is going to apply to us, it makes sense that our state should become jumping. But we don't have to apply an initial accelerated gravity value of negative whatever because we're not actually jumping. We're just going straight to the gravity hitting us and making us accelerate downwards. Additionally, when we jump, when we're in the jumping state, we want to check to see if there are any tiles below us. In this case, we are checking the tile map, or we're doing the exact same collision as we did before. We're checking self.y plus self.height and self.y plus self.height with x plus self.width minus 1. So we're checking both corners of the bottom. And in that case, if we do hit the ground or some collidable tile-- it could be a mushroom or a block in this case, as well-- we're going to set our dy to 0, set our state to idle, our animation to idle, and also reset our position, taking into consideration the tile that's where our feet are, basically shifting ourselves up by a height as evidenced by this minus self.height. And we do the same thing elsewhere. For example, if we do checkRightCollision and checkLeftCollision, it's sort of the same idea more or less. I'm going to scroll down here. So checkLeftCollision checks for our left and our right side. So LeftCollision checks to see if our dx is less than 0. If it is, we're essentially checking our top left corner and bottom left corner, and the tiles that are there. You're going to look one pixel to the left of them, which is what this is right here. And if it's a collidable tile in that direction, we're going to set our dx to 0, so we stop moving in that direction, and then make sure that we don't clip into the tile by resetting our position to the tile to the right of that's exposition, which will put us right at that position to the right of the tile that we just tried to go to the left of. Same thing for checkRightCollision, but it is the exact opposite, in which case we are moving to the right direction. So if our dx is greater than 0, we're going to check the two tiles that are to our top right and bottom right coordinates. So for you, that's this side, top right and bottom right coordinates-- to the tile that's 1 pixel that way. And we're going to, again, set our dx to 0 and then make sure that we set our character's position to the left, which is minus self.width. We want to set it to the width of our character minus from that tile's position so that we don't clip into it at all. And that's essentially it for this example. And that takes care of the top, the sides, and the bottom. I'm going to just go ahead and run a little example here. So if I jump, I should be able to land on top of the tile just like that, which is pretty cool. I can still jump and hit that. And in addition, let's see if I can land on this column. Yep, I landed on the column, which is great. And I jumped down here. And then eventually, I can finally jump-- if I try-- my speed is a little fast. Let's try doing it this way. There we go, jumped down into the pit below. So that's it for collision. That's really the trickiest part. And it's a lot of numbers, but if you read through it, it's actually not terribly complex. It's very easy to mess this up live coding, though, which is why we didn't do it live. But everything is written here, so do study this and understand it, and it'll make, I think, perfect sense once you get more in tune with it. So that's it for mario9, the collision update. The last bit is a lot simpler. mario10 is sort of callback to Pong, where we looked at adding sound effects. This time, we're going to add sound effects, but we're also going to add music and we'll fly through that one. It'll be a breeze. So looking forward to seeing you in mario10.