7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial
FREELessons: 22Length: 2.6 hours

Next lesson playing in 5 seconds

Cancel
  • Overview
  • Transcript

3.7 Difference Between Winning and Losing

To this point, we've come quite aways in the creation of our break out clone game. But now, it' time to figure out how to end the game. And in this case, there are two ways to actually end the game. That is to actually make all of the blocks disappear. In that case, you win. Or if you have the ball actually touch behind your paddle, then you lose. So, if I run our game here. At this point, we have a very simplistic game where it's going to bounce around, and it's ultimately going to break our blocks. And once we get it to break all of them, like now, at this point we should win. The game should be over. But before we do that, if the ball actually touches the bottom like it did just there, then we should lose. So, those are the two situations we need to start checking for, so how could we do that? Well, let's start with the winning one because that's a little more straightforward. So, in order for us to determine if we've actually won the game, we have to keep track of the number of blocks are currently on the screen at this particular level. And if that block count gets down to zero, ultimately we have just won the game. So, we're gonna create a simple variable here called block count [SOUND]. And, we'll just default it to zero at this point, so that's going to be our starting point. We have zero blocks. And a s we go through our didMoveToView method here, we are going to create these blocks. We're gonna create four of them in this instance. So, we're going to do all of this work on the physics body, and then add that child. After we've added that child, we'll go ahead and increment that block count. [SOUND] So, we'll simply increment it by one. So now once we're done adding our blocks, we'll have a total count, in this case four. And now, we have to figure out when we've actually destroyed that block, or hit it so that its disappeared from our screen. Let's decrement that block count. So, let's see. Down here in our didBeginontact, if this is case where the ball came into contact with a block. And we remove it from our parent. In this case, we want to actually decrement, blockCount -= 1. So after we've done that, lets go ahead and check to see if blockCount is equal to zero. And in this case, if it is, then we're simply just going to write now anyway, we're going to write here that we won. So, we'll save that and that's just going to print out to our output screen. So, we'll go ahead and we'll run our game, and we'll see if we've got this setup correctly. We're going to bounce around here. We're going to try to hit our blocks. And once we've done so, if we are set up properly, there we go, we have won the game. So at that point, we're gonna have to do something additional because now the ball keeps bouncing around. So, we're going to have to stop the execution of the game at that point. Maybe display something to the user say you know, you won, or, or something along those lines. And also, on the opposite end of that spectrum, if before we've done that, the ball actually bounces down and hits the bottom of the screen. Then, we have to detect that as well, and signify that we've actually lost that game. Now, this is a little bit more interesting. And, let's take a look and think about why this might be. Well, early on in this game when we were creating it, we created this border. And, it's an SKPhysicsBody, and we gave it the frame of, or the rectangle around the actual screen using its frame. So, what that's gonna do is it's gonn conti, it's gonn create that rectangular view around the screen, that rectangle. And, those are going to be, that's going to be our border. And we did set up. Or we could, I guess we could set up a border category to check for when we've come in contact with the border. But, the problem with that is that no matter where the ball hits, whether it's on the right side, the top, the left side or the bottom, we're going to see that contact. There's no way for us to distinguish between the right border and the left border, and the top order and the bottom border, since it's all one physics body. So, that's a bit of a problem. So in order to get around that, we're actually going to introduce another category into our level or our game at this point. So, we're going to start by creating a BottomCategory. [SOUND] And, this is once again gonna be a uint32, nothing new here. And, we're going to initialize this to one. We're gonna shift it left three, and then we'll go ahead just to be consistent here, so you can visualize this, because it's going to become important shortly. So, there is our bitwise value for the bottom category. Now, lets create something that's going to represent the bottom, so something that we don't want the ball to touch within our game. So, lets come down here. After we've created this border, let's go ahead and create another rectangle and put it on the bottom. So let's go ahead and create a rectangle, and we're gonna use the CGRect to make helper method. Now, we need to give this an x and y coordinate to start at a width, as well as a height. So in order to kind of make this a little bit easier for us, we're once again going to use these scenes' frame. But in this case, we're going to use the origin. And in this case, the origin where the screen actually starts when it's being drawn, by default, is gonna be the bottom left corner. So that being the case, we're going to use the x and y, which is going to give us zero and zero for both of those values. And then, we're going to give it a width, and we're going to use the screen width. So we'll say, frame.size.width, and then we are going to give it a height. And in this case, we're just gonna give it one. So, we're just gonna give it, just enough height to kinda stand out and make it possible to actually hit that particular rectangle. But, we can't actually hit a rectangle. So in Sprite Kit, a rectangle is not a physics body. So, we need something that can contain. So we're going to create this, and we're going to say let bottom = SKNode. And, we're going to set its physicsBody.categoryBitMask just like we've done before to the bottom category. Now, once we have this all set up, this is all fine and dandy, but it's not actually on the screen yet. So to do that, we're going to add a child to our scene, and it's going to be bottom. So we'll go ahead and say that. So now, we have kind of a, an additional border, if you will, at the very bottom of the screen. So now, once we've got that there, we need to be able to also do contact tests for that particular bit mask with our ball, very similarly to how we've done down here. When we set it to say, I want to know when the ball comes in contact with a block, but how do we do that? Well, we're just setting this value to BlockCategory. How can we say I want to check for both of those things? Well, that's where the beauty of these bit masks comes into play. So, what we can do because these are all unique values and they're combinations, or they're logical operations on them can be unique as well. What we're going to do is we're going to take the block category and the bottom category, and we're going to combine them into a unique state that's going to represent both of those using a logical or. So, we can come down here. We can say that we're going to set our contactTestBitMask = BlockCategory or BottomCategory. And for those of you who are unfamiliar with this basic bit wise arithmetic, what's going to happen here. And, I'm just going to show this to you ever so quickly. What we're going to wind up doing is combining these two values using a logical or. And, what that's going to do is it's going to look at all the values of these two, all the bits of these two numbers, and or them together. So say, are either one of these first two values here one? And they're not, so that's gonna be false. What about the second two values? Are either one of them one? No, they are not. So, that's maintain zero. Are either one of the third ones? In this case, yes. So, we're gonna set this to true. And, the same for the fourth position here, zero and one, so yes. So, this is what the value is going to contain within this contactTestBitMask ,so this is a way to represent state using very simple binary numbers. It's extremely powerful, extremely fast when it comes to processors on certain devices to determine whether this is actually happening. So, that's a very nice trick to have in your bag. So now, that we have that set up we'll save that. Now that we can test for those things, we're all set to come down into our didBeginContact. And what's going to happen here, because now we're testing for multiple categories, multiple bit masks. And, depending on how things happen, and how, which, technically speaking, which body context, which one, we could have to do all sorts of combinations of these. So, we'd have to, we could have to say, well, if bodyA is ball and bodyB is block or vice versa, and now we're gonna add in the bottom. Is bodyA the ball and bodyB the bottom, and vice versa? Let's, let's clean that up a little bit to make our lives a little bit easier, especially if we begin to expand upon this logic in here a little bit. So, what we're gonna do here is we're going to make sure that we're always dealing with them in the same order from least to greatest. Or, you could sa, check from greatest to least either way as long as you're consistent all the way across. So, you only have to check these values in one direction. So, what does that look like? Well, what I want to do is I want to create two of these physics bodies. So we'll say first, [SOUND] is going to be an SKPhysicsBody, and second is going to be an SKPhysicsBody. And, we'll go ahead and save that. So now, we're just gonna do a very simple test. We'll say if contact.bodyA.categoryBitMask then we're going to say that first = contact.bodyA. And then obviously, second is going to be contact.bodyB. And then, the else of this is simply going to be the other way around. So, we'll just copy these, paste these, and we will just switch them around. Now, notice that this is not required, you dont have to do it this way, but it's going to cut down on the number of checks that you're gonna have to do here. Since we're always checking in the same direction ,we always now that the body with the lowest bit mask is going to be able to be checked first. So, we can always say, in this case, we can say if first.category.bitmask is the ball. And second.categoryBitMask is the block, do this. Then, we can also say else if first.categoryBitMask = BallCategory. And, the second.categoryBitMask = Bottom Category. If that's the case, then we're simply going to print a line here that says, we lost. Now like I said, you don't have to do it this way. But if you choose to do it the other way, then depending on which body is represented first within this contact parameter, you may have to check this both ways for bottom first, and ball second, and ball first, and bottom second. So, take it for what you will. So there we have it. So now, let's go ahead and run our application again and see what we get. So now, our ball is going to run, and we have set something incorrectly here. Yes. And, I hope you may have saw this as I was going through this, but I got a little bit ahead, a little bit ahead of myself at this point. Where I started to use this physics body before I actually set it to anything. So, we're going to say, bottom.physicsBody = SKphysicsBody, and we're going to use the edge loop from rect. So, this is where we're going to actually use this rectangle. Got a little excited about finishing off our game here before I actually finished setting things up properly. So now, the physics body property on our bottom node is going to have the parameter, or at least the dimensions that we set up for our rectangle. And then, we can set the category bit mask and go on our merry, merry way. So, let's stop that, and run our application again, and hopefully we'll get past that point. And, we do, so now, the ball's gonna bounce around a little bit. It's going to break some blocks, and hopefully we're going to see we lost once we hit the bottom. And of course, we did. Now, once again, we're gonna wanna make sure that at this point, we stop the execution of the game. And so, we don't see a bunch, a bunch of we lost or whatever is going to represent losing. And then, maybe after that, say a win. So now, we need to introduce a new way to stop the game, and we're going to do that by introducing a new scene or a transition into a new scene. So, we can display it to the user that, hey, you won the game, or hey, you lost the game.

Back to the top