2.7 Detecting Collisions
For most games, ours included, it will be very important for you to know when objects come in contact with each other. In this lesson we will discuss how to identify and react to those events.
1.Introduction3 lessons, 07:37
2.Introducing SpriteKit7 lessons, 54:48
3.Building a Game11 lessons, 1:30:25
4.Conclusion1 lesson, 01:49
2.7 Detecting Collisions
As you progress in your world of sprite kit, not only along the lessons in this course, but also on your own. Eventually, you're going to need to know when some sort of sprite comes in contact with another one. And, that's just the way it is. And, it's going to be very important for you to you programmatically get access to that information. So that you can execute or do something in response to what's known as a collision. So, how do we, how do we know when that collision takes place, and how do we do that? Well, there's a little magic that goes into this and that you need to understand a little bit of math. You don't necessarily need to understand it completely, but you just need to know that this is how it works in the world Sprite Kit. So right now we're dealing with two sprites. We have the ball, and we have the paddle. So now, we wanna know when this object, this entity comes in contact with this other one. So, how do we do that? Well, the way that Sprite Kit does that is with what are known as bit masks. And if you're unfamiliar with bit masks, I'm gonna show you in just a moment. It's, it's quite simple really. Then. it's just a, a binary mechanism to be able to notice when there is some sort of combination of these binary or bit values. So, let's start by creating these, and you're going to see as I walk through this, how this is going to work. So, we first need to create what are known as categories, that are basically just bit masks that represent, that uniquely represent the objects or sprites within our scene. So, I'm gonna start by creating two of these. [SOUND] I'm gonna create a ball category, and you'll see why I'm naming it that way in a moment. And, this is gonna be an unsigned int 32, so I'm gonna specifically make this a 32 bit unsigned integer. And, I'm gonna set this equal to the bit value of one, and I'm gonna do a left shift zero. Now, what is that really mean? So that, actually, if you're looking at it from a binary perspective, looks something like this. So, I have a 32 bit integer an unsigned 32 bit integer, and I have it set to one. So, I'm just using this hexadecimal representation to assign a value to a bit. And then, I'm shifting it left 0. So, that's gonna put that 1 in that first position, so this is actually just a value of 1, if that's the way you want to look at it. So now, if I come in here and I create another one called the paddle category. Once again, this is gonna be an unsigned int32. And, I'm going to set this, once again, to that hexadecimal one, but this time I'm going to shift it left by one. So, what does that look like? Well, that looks like the same as before, only this time, I've pushed that one over another space. So now, this is actually a binary value of two. So, depending on how many objects or sprites you have within your scene that you're concerned about, at least understanding when a collision or a contacts occurs. Then, you need to create a category in a similar fashion to this. So if I had another one, I would shift it left two spaces, and then three space, and then four spaces, for as many of these as I had. So, I could obviously create a awful lot of these if I choose to. So, now that I have these categories, what is it exactly that I do with them? Well, I need to assign these categories to my sprites. So, the first thing I'm going to do is I'm actually going to assign it to my ball, since I already have this. So, I can say, ball and I can get its physics body, and this is an optional, so I need to use the exclamation point. And, there's a property out here called the category bit mask, and that's where that word category comes from. So, this is going to take a bit mask, and I'm going to set that equal to my ball category. So now, what we're saying here is that my paddle has a unique category bit mask identifier of this value here. So next, we're going to do the same thing for the paddle. So, we're going to get, go get our paddle, just how we've done before. We're going to use our child node with name method. And we're going to say, I want the child with name paddle, and we're going to cast this as an SK sprite node. And we'll do the same thing, we'll say paddle.physicsBody, and we're gonna set its categoryBiMask = PaddleCategory. So now, these individual sprites have categories assigned to them, have bit masks assigned to them. So now if I wanted to detect when a certain sprite comes in contact with another one, I need to explicitly state that I want to be checking or testing for that contact. And, the way that we do that is I'm going to want to detect when the ball comes in contact with my paddle. So, we'll say ball.physicsBody. And, we want to be checking for the contactTestBitMask. And, I want to check when that is PaddleCategory. So this is saying, I want to be testing for when my ball comes in contact with the paddle via this particular category. So that's great, but now what? So I've got all these things wired up, how do I actually get my code in there to be able to handle this? Well, you have to add one additional thing to your game scene to let it know that you're gonna handle those contacts. So up here at your class decoration, where it says Game Scene, and the, which is a subclass of SK Scene. We're going to ad to this that it is also going to be an SKPhysicsContactDelegate. So by doing this, we're gonna get access, or we're going to say that we agree to handle any sort of actions that should be associated with this contact delegate. And he one that's going to be of importance here, is going to be a function known as didBeginContact. So now, because I'm implementing this delegate, and I'm saying that I want my scene to handle contacts. It will execute this function every single time there is a contact, that we are pers, or that we are subscribing to watch. And in this case, we wanna see when the ball comes in contact with the category. But before this will actually work, I'll have to come in here to my didMoveToView method. And we'll go underneath our gravity, underneath the setting of gravity property, and we're gonna say self.PhysicsWorld. And, I need to set its contactDelegate = self. So now, we're actually saying that I am going, this particular scene is gonna handle these contacts. So now, every time the ball comes in contact with the paddle, this didBeginContact will execute. And for simplicity's sake, we're just gonna print some information out to our output down here again. So, we'll say if, [SOUND] and you don't really necessarily have to do this step. But this is just gonna be best practice as we go forward, as we're going to introduce more sprites later on. And, we're gonna care differently for how a contact happens when it, a ball hits say the wall, or the paddle, or another block, or something like that. But, what you get is this contact parameter, and there are two bodies associated with that. You have a bodyA and a bodyB. So, we'll say that if our bodyA.categoryBitMask = BallCategory && contact.bodyB.categoryBitMask = PaddleCategory. So if that is true, then I'm simply going to just print a line here, print a line on text that says [SOUND] the ball hit the paddle. Now once again, this is not a very interesting example, but at least for, to this point you're going to see that you can start to handle and detect when things actually hit each other. So, I'll go ahead and run my application. So now as you see, when the ball hits the paddle, I get in My Output down here The ball hit the paddle. So if it doesn't, and if it just hits the wall, then nothing happens. But then, if I move my paddle around and follow the ball, eventually, once it hits the paddle, I'm again going to get that print out down to the bottom of the screen. So now, this is the same process we're going to use throughout the rest of the course, as we begin to actually build our game. To know when the ball hits either the walls, the bottom of the screen, the paddle, or additional blocks found within our game.