3.5 Creating the Block
In this lesson, we will use a very basic process to create a target block on the scene for the user to attempt to hit. You will quickly see that this way of adding blocks and building levels is going to become cumbersome and difficult to maintain. Fortunately, there is a better way.
1.Introduction3 lessons, 07:37
2.Introducing SpriteKit7 lessons, 54:48
3.Building a Game11 lessons, 1:30:25
4.Conclusion1 lesson, 01:49
3.5 Creating the Block
So, now that we're to the point where we can start to add some interaction to our game, we have a ball, we have a paddle, things move around, now we want to add a little bit more landscape or substance to our game, and now we're gonna introduce the concept of blocks. So, ultimately, blocks are gonna be another sprite, another body, physics body within our world, within our physics world that the ball is going to interact with so the ball can bounce around the screen. They can come in contact with one of these blocks, and ultimately when that happens, we want to do a couple of things. We need to detect when that contact or that collision happens. And then, we need to maybe update our score, and then we want to remove that block from the scene. So, the first step we're going to do is actually just create one. And now, there's a couple different ways to do this. In this lesson, I'm going to show you kind of a quick and dirty way to do it, which you can absolutely do if you would like. But, it's going to be a little bit more difficult to maintain and enhance into the future. And in the next lesson, I'll actually show you a little bit, maybe of a smarter way to do it that will allow you to kind of dynamically create levels going forward if you would like. But ultimately, the decision is yours. So, we're going to grab one of these color sprites and we're gonna drag it out here again, and we're just gonna give this some size. We're gonna give it a width of 150 and a height of, we'll say 40, and we'll just kind of position that in the middle. Excuse me. Just kind of position that in the middle of the screen, something like that. And we'll give it a different color, just so it looks a little different. We'll give it this horrendous green color, looks kind of retroish. Now, we're gonna select our block, and we're gonna come down and play around with the physics a little bit. Once again, we're gonna select a bounding rectangle, and what you're gonna notice is, this is gonna be very similar to the paddle when we created it, and that we don't want this to be a dynamic body, because we don't want it to move around when the ball hits it. We just want it to be stationary or static. So we're going to uncheck the dynamic box and we are going to, we can just set these values manually. So we'll give friction zero, restitution one, and both on dampings zero. You can ultimately do this in code as well, but just to be kind of quick about this, I'm going to do this here. And then also that reminds me, when we're applying this level and the ball bounces around and hits this block like I said, we want to know when that contact or when that collision occurs to be able to do some things. So in order for us to kind of know when some of that happens and then get a hold of that particular sprite or that block, we need to give it a name. So we're gonna give it a name of block, so we're gonna need that in a little while. So now that we have that kind of set up, we can try to run our app, just to see if we have everything set up well. So we have here. Our ball bouncing around and we're bouncing off the walls, and then it's come back up and it's gonna hit our block and bounce off. So that's ultimately what we want it to do, but once the ball hits that block, we want it to, like I said, disappear and then add to the score here. So let's come back into our GameScene.swift and we have to do a couple of things just like we've done before. So we're going to introduce a new category, so we're gonna have a block category. Once again, UInt32, this is gonna seem very familiar, and that's going to be equal to one and it is going to be shifted to the left twice. And just so you can continue to visualize this, we will go ahead and copy and paste this value down here and it is going to look something like this. So we have a bit wise value of one, two, and four. So now that we have our block categories set up, we need to get an instance of that block and then assign that category to it. So we're gonna say, let block be equal to the child node with name. And that's going to be block, and we need to cast that as an SK sprite node. Now we can take that block, and we can set its physics body dot category bitmask equal to the block category, and save that. So now, now that we have that set up and we can assign that category to the block, we want to know when the ball comes in contact with it. Or, at least we should be testing for that particular contact. So we need to come into our ball, and we need to once again go to it's physics body, and now we want to contact test for this particular bitmask, and we want to know when it is contacting the block category. So, we're going to save that. So now, we have all of these things kind of set up, now we need to actually handle this collision or this contact between the ball object and the block object. So the way that we do that is by doing a little bit of a test here in our did begin contact function. Now, we went over this in a little bit of detail in a previous lesson, but if you didn't catch that, the contact here contains a couple properties that are very useful for us. A body a and a body b that are gonna represent the two contacts or the two physics bodies that are contacting or colliding with each other. So we're gonna do a very simple test in here. We'll say if contact.bodyA.categoryBitMask is equal to our ball category and have contact up body B.category BitMask is equal to our block category. If those two things are true, then we want to say maybe increment the score and then we want to remove the block. And in this case, we're checking for this combination where A is the ball category and B is the block category. Well, if that's the case, then what we can do is, we're assuming now that body B is our block, so now we can use that contact. Once again, we can go into body B, and now we have a known property here, and we can say that we simply want to remove it from the parent. So now if I were to save that and run our application, if everything is done correctly, we cross our fingers, when we run our application and the ball bounces around a little bit here off the different walls, once we hit it the final time and it bounces up to hit that block, it should disappear just like that. And now when we come back in here,and the ball goes past the spot where it was, it should no longer collide with that physics body because we removed it from the parent. So, that's pretty nice. So we can come back in here. Now, if we wanna play around with the score a little bit, we can implement a little bit of logic. So we can go into our game scene, and we're gonna create a variable called Current Score. And we're gonna set that equal to zero, just to kinda get things started. Now, what we wanna be able to do is, we want to be able to, like anything else, we want to be able to go into our scene, and we want to get access to the score. So, just like anything that we wanna touch programmatically, we're gonna have to give this a name. So, we're gonna call this the Score. And we will go ahead and save that. And we will bounce back over into our gamescene.swift file. But before we actually modify something, it is important to note, back in our game scene if we look back at what we were putting in here as this score label up on the top here. When we drag that out here we, this was actually a label, or an SKLabelNode. So, we can come back into our gamescene.swift. And what we would want to do at this point, and we're gonna make some changes to this later on when we start to talk a little bit more about the game loop. But just to kinda take, see an example here, we could say, let scoreLable be equal to, and we're gonna get a child, once again, childNodeWithName. And this one is called Score. And this one, we're gonna cast as an SKLabelNode. And now, we can do something like increment the score. So, let's say this particular block was worth 100 points. And we'll say that the current score is, we're going to increment it by 100. And then, we'll set the ScoreLabel.txtfield equal to, we'll do a little formatting here, score. And we'll append on to that string. And we'll pass in the integer value of currentScore, and then we'll save that. So once we've done that, we can go ahead and run our application again. And now once we bounce around here in our normal fashion, we'll come back around. And once we have that hit, we should now see that the block disappears. And we also get that score incremented to 100. Now, that's not too bad, and going down this route is not terrible once you're kind of getting started and learning to see how these things work. But, let me just kind of throw this idea at you. Let's say you're building a game that has multiple levels, which I think ultimately you will want to do, and in our case, those multiple levels will probably take the shape of a number of different things, like maybe the ball speed or trajectory, maybe the size of the paddle, maybe the size of the blocks, and the number of blocks and kind of lay out our configuration of them. Now, you could absolutely create multiples of these game scene files and have each one for a different level, but then what you're forced to do is to come in and drag these color sprites out, or maybe you create this one. And you copy and paste it all over the place and try to line these things up. And that can be kind of tedious and very difficult to maintain. And ultimately, you're just gonna drive yourself crazy. So, in the next lesson, I'm gonna show you, with just a little bit of math, how you can avoid some of those pitfalls and those headaches in manually doing this enable, and be able to actually recreate a number of different levels and the configurations of your application using just a single scene.