[MUSIC] Okay, this case study we're going to go through and we're going to build the Hello World application of games, which is Pong. Pong is a tennis inspired game. It's one of the first video games that was ever developed for computers. And it consists of just two paddles on the side of a horizontal screen with a ball bouncing between them. Now on a full-fledged game, the ball would bounce back and forth only if it hits the paddles. And if it went past the paddles the opposing player would lose a point. And so the idea would be to score the most points, it's like air hockey or ping pong, but a very simple version. In our case, we're going to do all the work to create the objects and some of the physics, but we're not going to keep score. And this is just to show you a real quick understanding of how to make a game and what it looks like. And then we'll go back through in another case study and look at the components in a little bit more detail. All right so let's get started, and we're going to start with Xcode as normal. And we're going to create a new project. And this new project's going to be a little different because we're going to select Game here for our project as opposed to our Single View application or any of the other ones. Still on iOS application, these are going to give us a template for what we need to do. So we'll call it the pawn demo. And come down here and call it the pawn demo. Now, we're going to be using Objective-C in this example, you can use a different language at some point in the future. And one of the things that we need to do is that we need to make sure that we have the correct game technology listed here. Here are the four that we talked about. OpenGL, Metal, SpriteKit and SceneKit. We're going to use SpriteKit which is the two-dimensional graphics engine. We don't need anything else in here, so we're going to go ahead and click Next to get started. Save it in our work space, maximize the window. All right, now the first thing that you'll notice here is that things look roughly the same, but over here on the left, we have a number of new files. We have all these game controller scenes and game view controllers. We have a launch screen storyboard like before. Let's go ahead and just add something here so that we recognize it when it is being used. Not because we think that this is a great launch board. But we'll just go ahead and put here, Pong is Launching. And we'll get it constraints to put it in the middle of our screen. Option command equal it so it shows up, great. Now if we go to our main storyboard, we'll see that we already have this black game view controller set up. And this is a lot like the template for a Master View controller or for one of the other pre-made controller that we had and we were using UIkit. Only his case, it's been preset such that our application has a GameViewController loaded into it. GameViewController's an alternate view controller so if you come here you can see that it inherits from UIViewController and so that part is kind of similar. Now when you go into the GameViewController, you see a lot of components here that aren't totally different, look pretty similar. Like viewDidLoad, that looks familiar, and should auto rotate, seems self-explanatory. Supported interface orientations looks good. Did receive memory warning, status bar hidden, things like that. We additionally though now have these things called the GameScene, and this GameScene is kind of a sandbox, or a drawing board, where you can put components of your game, if you want to test out different elements of them. Now I've found it's a pretty good place to start, but it doesn't end up being the place where all the details get worked out. We have an app delegate, which is our overall application container, running our code independent from the user interface. And we have our GameScene, which is specific to one scene that it gets loaded into our GameViewController. And in this case, we have one already built for us. So if we run this application, as it stands now let's just see what you get out of the box with the template code alone. Bring up our simulator. Looks like right now we're using an iPhone 6S+. And we're building. Pong is launching. And we just see a label that says Hello, World! If we click, we get this automatic asset which is a spaceship, and it spins around. So that's kind of exciting, because a spaceship is kind of a neat asset. But that's kind of all it does. You see down here we have some debugging information about how fast the animation is rendering. But what we want to do is we want to switch this so that is working as a Pong game, okay. So let's start by going into our SKS scene file. We're going to zoom out a little bit, and you can see that there is a yellow box that's describing the outline of our world. This is the extent of our game board. And what I want to do is I'm going to, like our storyboard you can add things to this too, and I want to add a sprite to this world. A sprite is a basic unit of animation. It's a basic graphic that can get moved around the screen as a unit. It is a node in our SKNode hierarchy. And in particular, it is a node in this particular game scene's hierarchy. So I'm going to come over here and I'm going to make this the ball for our tennis game. Ball, it's parent is in scene. End scene. It's going to have this position, you can see it as you move it around. It's position is oriented like this. Color is too bright for me, I want it to look more like a tennis ball. We'll give it that color. I'm going to set some parameters here associated with the Physics engine first of all I need to establish that it is part of the Physics simulation. So I'm going to make it bound by a rectangle, I want a dynamic so that it is affected by the Physics engine I want it to be able to rotate and I don't want it affected by gravity. I want there to be no friction involved, I want it to bounce with 100% energy, and I don't want it to slow down, either in straight velocity or in angular velocity. And as a reference, I'm going to give it a mass of 1. Okay. Yeah. So that's a start. The ball is in our world. And I want to give it an initial velocity here, let's see. How can I do that? Well, I can give it an initial velocity here by just give it 200 units per second and give it 100 units per second more. 200 in x and 100 in the y. If I come over here and I animate. I can see a basic animation of our world operating and there it goes just flies off the world. So there's a limit to what the animation can do. What I'm going to do is I'm going to put a bounding box on this world and the bounding box on the world is going to be the size of those yellow lines. But I'm going to do it in code, which means that I'm immediately going to cause this scene, what you see is what you get editor to not work very well for our purposes. If I come into GameScene, and I'm going to go put some template code down below and bring it up here. And now the first thing I'm going to do is I'm going to strip what's there now. So this chalkduster label I'm going to get rid of, the font size, and the position, and the bit where we add the label to the scene. This touchesBegan is useful. This is where we sense that touches have happened. But I'm going to take out the parts that puts the space ship's sprite down when we Click on it and that rotates it and that adds it to our hierarchy, let's get rid of that. And instead what I'm going to do is I'm going to grab some other code here. And we'll add this here. Let's go through it line by line. First thing we'll do is we'll make the background color black of our scene. We're going to indicate that we want that our world to fill up the size of the screen if that bounding box, that yellow area isn't matching our screen size, we're going to create a physics body. So this is an element that's going to get animated and we're going to make this classes physics body correspond to a loop going around our frame that defines us. So this is the fence around which we've been drawn, that yellow rectangle. We're going to look in our node hierarchy for a node whose name is ball. We named it ball before. We're going to go ahead and give it a spin. So as it rotates it does something kind of interesting there. And everything else we'll just leave the way it is. And let's go ahead and run it in our simulator and now see what's happened. Okay, that's okay. Pong is usually played horizontally, so let's go ahead and rotate our device. And we can see, I don't know if I like that aspect ratio because it's making our ball not look quite so square. But you can see that the physics engine is operating such that our ball is operating and bouncing off the walls. And it's bouncing with some angular velocity, so that when it hits the wall, sometimes it'll cause it to bounce linearly and sometimes it'll cause the rotation to change. Let's watch it bounce off this wall. Great, there it goes. All right, that's pretty good. I've decided I don't like this ScaleModeFill, let's try ScaleModeFit, see if that operates a little bit better for us. AspectFit, just like with images fitting into a box, you can decide which method you want to fill it in with. All right, that should operate a little bit better. Let's see how that looks. Pong is launching, I like that better. But you can see that the end of the game board comes before the end of the device, and that's okay for now. All right, next thing we're going to do is add some paddles. Let's go back to our scene controller and let's add another color sprite out here. And let's make it look a little more like a paddle. That's pretty good and I like the red color. What else do we want to specify about it? Let's give it a name. Let's call it left_paddle. And let's make it work in the physics engine so the ball will bounce off it. I don't want it to move, though, and I don't want it to rotate. And I don't want it effected by gravity. I want its friction to be zero and I want it to bounce off of things with 100% of energy. I don't want it to slow down. I don't want it to change its angular damping at all. We want to have a mass of one, the same as the ball, and I don't want it to have any initial mass or velocity, okay? Let's run it, just see what we get. And we run it in our simulator. Okay, that looks pretty good. So far so good. All right. I like that. Now if we select our ball, and we change the speed at which it's going. So that it's only in the Y direction, and maybe only slightly down, minus one in the Y direction. Now when we animate it, oops, it's going in the wrong direction. Let's change its direction. Click again so it stops animating. Do minus 200, I thought that's what it was. Animate it again, and you can see that some basic physics get modeled in our world. We can see how the physics operate in the world we've created. You see that that that initial angular velocity that we added in code doesn't show up in this. What you see is what you get [INAUDIBLE]. All right, so let's option drag this paddle and let's create another one. We'll put it over here. This one is located at, let's make it 422. So that we can find it. Then make this one at 422 also so that it matches. And let's change the color so that it is something else. How about a nice dark bright blue color? All right, it is also participating in the physics engine, and let's give it a different name. Let's call it the right_paddle. And let's run it in the what-you-see-is-what-you-get editor, you can see that it bounces appropriately and bounces appropriately and that looks pretty good. Now, if we run it in our simulator. We'll see that the code that we've written has taken effect, and the ball will rotate and bounce off the paddle rotation effect in it. See it hit the blue paddle. Great. All right, that's pretty good. Now the main thing that we have missing now is we're missing any ability to move the paddles. So let's talk about that for a second. In our game scene there's a callback function that handles the touches. And you can see right here that there is this call that says touches began. Well, there's actually several different touches callback. Let's go ahead and grab the different bits here. We have in addition to touchesBegin, we've got touchesMoved, and we have. TouchesEnded. And we have. TouchesCancel. Now the basic idea here is that because we're playing in a game we're going to leverage the multi-touch capability of the device. So at any given time there might be one touch, there might be three touches, there might be ten touches on our screen. And we have to be able to handle each of those different scenarios cleanly. And so what we're going to do is we're going to say that if there is a touch on the left hand side of the screen, we want that to be a movement of the left paddle. And if there's a touch on the right hand side of the screen, we want that to be a movement of the right paddle. And if there are multiple of the touches, we're going to take the last one that comes in our, that gets passed to us in this touchesBegan callback. We get passed this set of touches and so we're going to write a loop in which we go through each one and define what we're going to do in each case. So now the plan here is to say that in any given cycle, we're going to keep track of a local variable. Oops, we need to give ourselves an interface. We're going to keep track of two touches. We're going to keep track of something that is ultimately the touch that's affecting the left paddle, and a touch that's affecting the right paddle. And as we get these callbacks, this'll be where we keep track of the most recent one that's affecting those two paddle touches. First thing we're going to do is we're going to identify where are these touches coming from and do they affect us or not? So we're going to fill out the code here, oops. All right. And let's see, what do I want to do? I want to clean this up, because the indentation's throwing me off. All right so for each touch we're just going to output as a log message. We're going to output the x and y location of the touch, and we're going to output the width and height of the frame that we're working on. That's just for feedback for ourselves for reference. Can use that to help understand what's happening. Then we're going to ask, okay, if this most recent touch is in the left third of our screen, so if the exposition is less than one third of the total width, then we're going to call that our left motivating touch. And we'll assign our left motivating touch property equal to the touch that we just found in our loop, and we'll just output the fact that to log that we received a left side touch. If it's not on the left side, if it's not within one third of the screen, then if it's greater than 70% of the screen or seven-tenths of the screen, we'll say that's a right side touch. In which case we will say that we are going to be motivated, or that our right touch that we are keeping track of is going to be assigned to our property, which is our motivating touch on the right side. And then finally, just to keep the game going, if it turns out that we don't have either of those things, we're going to find the ball in our node hierarchy using this child node with name call. And we're going to increase its velocity. So if you hit in the middle, it's just going to speed up the ball a little bit. How much is it going to speed it up by? Well, it's going to take the current speed in the x direction and double it, and keep the y speed the same. And that's in case the ball gets stuck for the purposes of demonstration right now. That'll help it get unstuck. All right, whoops, and then for now, That's going to be all we're going to do. And we'll run it and we'll watch to see what happens. Notice we're not doing anything with these touches, we're just identifying that we got them. All right so here is our simulator, let's bring up our console in the bottom, go back to our simulator. And you can see that if I touch on the left, I get both where I touched it here, as well as an indication that I had a left touch. If I click here, I get an indication that I did a right touch, and if I click here, I get in the middle, I get the location of the touch, but there's no left or right. Because it doesn't fall before 30% or after 70%. So the next thing we want to do, is we want to move our paddles in responses to those touches. What we're going to do to do that, we're going to write the helper function that causes our paddles to track according to our touches that we just collected. So let's go down and get the template code for that. It's a local variable, and we're going to need one constant as well. So we'll start with this helper function we have that moves our paddles so that they move in the direction of our touch. So we're going to do the following, we are going to, Create a pointer object A, and it is going to be, a node, it's going to be a dictionary, that has a node indication, and a touch indication. And it's going to, the first, let's see. Let's see, how do we specify this? So we are going to go through and create our own data structure. Our data structure is an array, and our array has touches in each one of its elements. So, first element is here. Each element of the array is a dictionary. The key for the dictionary is node or touch. And if it's node, it's going to be that SK node element, the node in our hierarchy which corresponds to the object that we're interested in manipulating. In this case, we're going to find the one whose name is left paddle, and the touch that we're going to work with is going to be the touch that we're keeping track of locally, which is our left mode of anti-touch. And if it doesn't happen to exist, if we haven't set it for some reason, then instead of using left motivating touch we're going to just use a null object. And then the second element in our dictionary, second element in our array is also going to be a dictionary element with the same structure, only now it would be the right paddle and we'll give it the right motivating touch. That's just the data structure that we can work with so that we can go to through and write some arbitrary code here, and then there a lot of ways you could potentially do this. But now that we have our list of touches and objects that we want to respond to, we're going to go through our dictionary and we're going to say okay, the node that we're working with is the node from our dictionary. So we're going to, what this loop does, is it's going to go through every element in our array and it's going to treat it as a dictionary. So that first one is going to be here. And it's going to pull out the eliminate that is labeled node and so node is going to end up being the child node with left paddle the first time. And the touch is going to be the left motivating touch or null. If it's null, then we skip it, but if it's not, we're going to find the Y position of ourself, the touch that we pulled out which is either going to be the left motivating touch or the right motivating touch, we're going to find its x, y. We're going to find it's x, y position relative to the scene. And then we going to pull out the Y position from that relative position and then we're going to calculate how long it's going to take for the particle to move to the place where we touch. Because the idea is that when you touch one on the sides of the screen, you don't want the particle to jump there automatically, you want it to start sliding up there. So how fast is it going to slide? It's going to slide at k track pixels per second. So let's pull that out. I know this is going a little bit fast, and I'm not explaining things very clearly. That's because this is our hello world application. It's enough that you could get something up and running very quickly, if you wanted to. Actually, we're going to keep that in here. Okay. So now we're going to calculate how long it should take the paddle to move there. Now it's going to be our duration, and the way we're going to do that is figure out what is the distance in pixels that it needs to travel and what is our speed in pixels per second? So this is the number of seconds it's going to take for the paddle to get to the location that we've touched. And then we're going to create an action. This is sort of part of the event-driven architecture. We're going to say the action that we want is we want SpriteKit to manage the movement to a y position that we specify by our touch, over a duration that we just calculated in terms of our speed. And then we're going to apply it to whichever node was in our dictionary. So in this case it's going to be the right paddle or the left paddle. And we're just going to name that action moving. So what this structure enables us to do here is to work with many, many objects, potentially, in our game world. In this case we only have two, so the dictionary might be overkill. Then we kind of arbitrarily go through and, or we abstractly go through and we ask SpriteKit to move all of the things that we've touched to the destination in which they've been indicated. Okay so now when we run it in our simulator, And we click on the left. Oops, we got an error. What'd I do? Get an exception. So I'm going to read here in the exception left, terminating due to attempt to insert nil object from objects(0). Hm. Four keys. So I must have not done something correct in my construction here, let's see. Give me one second to debug live with you guys. So I tried to put a nil object Did I not set up my left motivating touch and my right motivating touch correctly? Do I have a left paddle and a right paddle named? Let's see. Left paddle. My right paddle didn't get the name changed for some reason, there we go. Okay. So for some reason, I remember typing right paddle, I must not have had it hit for whatever reason. So what happened was, when I went to look for right paddle, couldn't find it within our scene and we tried to make a dictionary entry with a null entry. It's funny. Xcode drives me nuts when I type stuff in. I know I typed it in, but it didn't take for some reason. All right, so now when I click, I still get an exception. What's my exception now? Did it still not not take. Here's my left paddle, here's my right paddle, so that's good. Go back to my game scene, left paddle, right paddle. Well, let's just put a break point in here, and let's run and see exactly what Where the error occurs. You know what, I didn't do the other callbacks for the touches. So, that could certainly have something to do with it. Let's walk over this before we add the other bits. Okay, so we built our dictionary okay. No, we didn't build our dictionary okay. Something still went wrong with adding right_paddle. All right, let's take a break for a second from debugging this, and let's add the other elements of our touch management here. So our touches began, but our touches also can move, and our touches end. We need to make sure we're taking care of all those different events. So if our touches moved and then we just want to make sure that we update our trackPaddles according to the touchesMoving. So this corresponds if we touch and we move our finger, then that's going to cause our left motivating touch or our right motivating touch to change its position. And so we want to update the movement associated with that touch, so that'll happen if we call our function. Then if the touches end which they will because of this clicking, which must be the problem that I'm having here. The touches end, then I want to clear my touches, so if it is the left touch that ended I want to make my left of any touch. So right one, then I want to make my right motivating touch nil. And then finally the same thing for if the touches are cancelled. All right let's run now having realized I didn't take care of all of my touches. See how we do. Still an exception. Attempting to insert a nil object from object 0. So it's like it's not finding that right object. Let's debug, Hopefully it's useful to you to see me debugging as well. Okay, and we're going to step over that line and step over that line and take a look at what a is down here. A has the left paddle motivating touch object, Doesn't make sense to me A is not a game scene. A is ID. What's going on there, over. The right motivating touch is not finding the right motivating touch. There's my right paddle spelled correctly, left paddle spelled correctly. As if it's not being added to my scene. I feel like I'm just missing something really obvious here. Come back to our code, I'm just going to temporarily add it in here and say SKNode *temp equals that. And then we'll put our debug here. Just have to get that warning to go away so I can put a debug line in it. Come on. All right, let's run it. I'm just trying to see if that right paddle is showing up at all, or if temps getting assigned null. Okay click here. We know right motivating touches is null, but the left Right paddle shouldn't be, so I'm going to step over that, tap is getting no. And, so, for some reason, we're not finding that child in our node hierarchy. Child node with name, it really should be there. Okay well tell you what, I'm going to create a new one. I'm not quite sure why that is happening. Give it a blue color. I'm a little confused by that to be honest. Let's see. Let's make it, this one is going to be 27422, and make this one 422 to make it match. Bit close, 422, and give it the name right paddle okay, and this one's width is, we'll make it 17 so it's even. Make this one 17. This one's height, we'll make it 212. Make this one 212. All right. Give it a bounding rectangle. None of these things are relevant. We want to have zero friction. We want to have 100% bounce. We don't want it to dampen anything, and we don't want angular dampening to be anything. We want to have a mass of one and no, Velocity. So if we bounce everything, looks good, so in my mind, I just created another object. I'm not sure why it didn't work before, but now when we run it, We click on the left side, we're in our code, and we step over that line. Yeah, now attempts finding the object. All right, so if we run it, yeah, there we go, okay. Not everything works perfectly, let's go back to our simulator after taking off the debugs. Now you can see I'm hitting left. And I can move the paddles around as expected. And the ball interacts with the paddle as the physics engine would suggest. If I click in the center, you can see that it speeds up. So you can make it a little more interesting if things slow down. And of course, the only thing that's missing here is some sort of control for making the ball not get too fast and then also a scoring mechanism. But the basic idea is good, although now we don't need this code anymore. All right. Okay, well in summary, you saw how real development goes. What we did was we created a game template, we worked with the game scene controller, and we built some basic controls out, we had some trouble by option controlling the left paddle, just renaming it right paddle, we needed to actually create it fresh in order for it to be found. And then within our game scene code, we did a couple things. In the beginning, we set the background color to a color. We scaled the world. We created a physics body that wasn't present in our scene, what you see is what you get scene editor. We gave our ball some initial angular velocity, and then we handled touches. We handled touches by picking out a touch that would be the thing that moves the left paddle. Be picking out a touch that would be the thing that moves the right paddle. And if we didn't find one of those, we change the velocity of the ball. And then we said hey, go update our paddles according to the touches that we just found. If the touchesMoved, then we don't look for a new touch, we just take the existing touches that have moved, and whose touches have changed position, and updated the animations. If the touchesEnded, meaning the touches are no longer active, then we went through. And if we found out that one of our touches had ended, we would set our left-motivating touch to nil and our right-motivating touch to nil if that one was found. Finally, we did the same thing if one of our touches was cancelled. We're not doing anything on a frame-by-frame basis for this example. And then our code where we track our paddles to meet to our motivating touches involves creating a dictionary that we can treat abstractly. We create a node and a touch, and down here in our dictionary, we pull out our node and our touch without knowing whether that is a paddle, or a spaceship, or a ball, or without knowing if it's a motivating touch or whatever it is. But if it's not null, then we adjust the y position of our object according to the touch's position in our window. We decide how long we want that to take to move the paddle. And then we go ahead and create an action which tells Sprite Kit to move it for us, and then we say, move it. And Sprite Kite takes care of managing the movement. And so that ends up here. Let's slow down our tracking a little bit. Let's make the paddles move half as fast. And we'll close with this, so in summary, Pong is the hello world of games. Doesn't always work smoothly, but you can see a little bit how I debugged the situation. Now if I click, it takes a little more time for the paddle to get to where it needs to go. Great, thanks for your attention. Let's dig in deeper and do a different case study with another game that might be kind of fun to see some physics work with. All right, thank you for your attention. [MUSIC]