[MUSIC] Okay, let's follow up with our introduction to SKActions and do a code check, where we walk through some code and look and see how it gets implemented within the body of an actual app. It's pretty easy, but I want to show you some of the flexibility and some of the different things that you can do with it. So let's go ahead and switch to code. Now, the code base that we're looking at is one that I created just for this example, and so, it's not based on our breakout code base that we've been working on. So let's cut to our code and what we can see here is that we have the basic framework of the game. In this game, it's not really a game, it's more of a demo, let me show you what it looks like for starters, and then we can walk through where all the different things are happening. So I'm just going to run it so we get a sense of what's happening before we get going. So I'm going to run it on my iPad, which is attached, and here is a reflection of it. And what you can see is that there's some balls that are bouncing around in a physics simulation, and there's a man that I've drawn and constructed that is also moving around. Now there's a vortex field in the center that's causing the balls to spin around and the man to spin around as well. But the man is affected by gravity, and the balls aren't, so occasionally the balls will lift him up, and he will move. Now, you might notice that some of his limbs are moving independently, and that's because I constructed his body of several different sprites, which are affected by the gravity independently but are hinged with a pin joint. So you can see they kind of move as he walks around. Okay, so let's go back and see how we're doing that. Here's our code, and let's start with our entry function down here, did move to view. So now to show you these different actions, what I'm going to do is I'm going to go through a sequence of states. And so, in order to keep track of those states, I've established a state variable here that's going to start at 0. And we're going to increment it as we explore each of the different actions that we can do. I've named our outer wall fence as we've seen before, and here, I attach a physics body to that outer fence so that the balls don't leave the screen and so that the person hits the screen and reacts. Here what I've done is I've added a vortex field and I put that vortex field in the center of the screen to keep the balls moving and to just give us something that we can actually look at. In this bit right here, what I do is I go through a loop 20 times, creating 20 different sprites. And those sprites are all the bouncy balls that are going around the screen. I give them a name and then I call it helper function that I've created that looks a lot like the ones from our previous lecture, in which I create the sprite and place it on the screen. Once I place all those balls on the screen, then I call my own function which is going to build the man. And I call that function makeBody or that method makeBody. So let's just take a look at addSprite first, the function that adds the balls to the screen. It takes a category mask, a contact mask, and a collision mask. This is kind of built on the code that we had before where we were learning about the masks. I created a round physics body that's dynamic, not affected by gravity and is placed randomly on the screen. It has some physics properties that give it a little bit of damping. Since it's a ball, I don't have it rotate. I set its contacts appropriately in a massive one. Finally I give it a random velocity, and I add it to our node hierarchy. All right, so that's straightforward for this sprite. The man, it takes a little bit more complexity. The man consists of a lot of sprites. So also notice that I have this property that is the sprite that's going to end up being the man, so that's local. But as I'm building it up, here's what I do. I create six different sprites which correspond to the head, the body, the right arm, the left arm, the right leg, and the left leg. And I go through and sequence and I build this body out. So the first thing that I do in this section here is I create all of the sprites for the different parts of the body. And you can see what I'm doing is I'm pulling graphics that I've built and that I've drawn and that I've imported into the project. I give them a name and then I layer them so that they that they look like they're layered appropriately on the screen. You don't want the arm that's behind the body to be showing up in front. I give the head an absolute position, this is a position relative to the scene's coordinates, and the head is actually going to be the root node of the hierarchy of this body. All the other pieces, I get a position which is relative to the body part, which is its appearance. So, all of these pieces are all going to be relative to the head, so I give it a point that's not relative to the scene space but relative to where the head, relative to the head's coordinate system. And the head gets centered, 00 is in the center of the head. Okay, so I do that, I create the legs and I create the arms. And here's the piece where I build the node hierarchy. I first add an arm to the body, an arm to the body, a leg to the body, a leg to the body, and then I add the body to the head. So actually it's two level hierarchy, head, body, and then from there, it branches out into four different items. So that's the nodes, that's good, we haven't added any physics to them yet. So, the next thing that I do is I create six different physics bodies that are going to correspond to each of those different body parts. The basic physics body looks like this, they are dynamic so they are part of the physics simulation. The body is affected by gravity, unlike the balls. I gave it a little bit of damping here. All the other pieces can rotate, but I don't allow the head to rotate because there's actually a bug in the physics engine for if you pan a rotation and limit how far it can rotate and the parent object rotates 360 degrees, it messes up the calculations. And that's sort of a known bug within SpriteKit. So I'm just not allowing the head to rotate, that's why the guy always kind of looks upright as he moves around the screen. Otherwise I use precision collision detection for the head, so that's the head. And then the body and the other pieces all kind of look the same. They're affected by gravity, they can rotate, they use precise collision detection. So I do that with the body, I do that with the right leg, I do that with the left leg, I do that with the right arm, I do that with the left arm. And then in this bit of code, I attach the physics bodies to each of the sprites that I created earlier. Here, I set my property to be the root sprite nodes so that I can access it from other pieces of the code so that whole hierarchy is rooted on head. And this is where I add the body which I've created to the rest of the node hierarchy. We keep track of it locally and then I add it to the hierarchy. Once I've placed all of the sprites into the scene, now I can add physics constraints. And so what I do is I create a bunch of pins that make the different body parts rotate around each other. So the first one I do is I anchor the head and the body together, and I do that by making an anchor located on the bottom of the head position and I limit how much it can rotate. This is to keep the head in one place and so the body can only go a certain distance left and right. I create that joint, I give it a little bit of friction, and then I add that joint to the physics simulation. I did a similar thing with each of the other joints. So I create a joint between the right arm in the body so that it looks like the arm is hinged at the shoulder, and then I add that to the physics simulation. Same thing with the left arm, I create a joint between on the left arm in the body, so it looks like the left arm is anchored to the body, give it some rotation specifications. And these rotations are really governed by the graphics, because the left arm and the right arm don't look the same. And then finally, I'd do the same thing with the left leg and the right leg. I create an anchor for them on the hip of the body so it looks like the legs of the rotator on the hip and it limit how far they can rotate. So at the end of that what I've done is I've created this hierarchical object I've added it to the scene, I've created physic bodies for the character. And I've created a reference to it, self.man, that I can access later. So that explains what you say moving around the screen. What you haven't seen yet is the use of SKActions which is of course the whole point of this lecture. The way that I'm going to demonstrate this is each time I touch the screen I'm going to create a different SKAction. Hopefully I'm going to be able to go back and forth between the code in the demo to show you that. So let's go down to where the touches begin, and I'm actually going trade it off when the touch ends. And you can see here, that as the touch ends, each time I'm going to beep. I'm going to play, do an SKAction, every time a touch ends. I'm going to play a sound file named beep, and so that's an example of an SKAction you can play. You can play a sound. And that's going to play as soon as I let go of the touch. This field, wait for completion, indicates whether or not this action should be considered to be ended immediately even though the sound continues to play. Or whether the action should be considered to last as long as the duration of the sound. It doesn't matter a whole lot if this action is being run independently, but if you put it in a sequence that matters, for how the following actions will play. So then what we're going to do is if in our first state, the first time we touch we're going to do an action that moves a sprite, and then rotates a sprite the second time we touch. Third time we touch we're going to scale the sprite. Totally, then just the x we're going to scale, and then the y we're going to scale. We're going to show a sprite fading out and fading in, we're going to show a sprite resizing, and we're going to capture that action. And we're going to reverse it, and so the next time what we're going to do is we're going to run the undo action on it. Then we're going to change the physics property of the man. We're going to change it to be very heavy, and then very light, and then back to where it was. Finally, in this simple set of actions, we're going to play a different sound. And then on the last two we're going to do a combination action. So, in this case we're going to do a completion block effect where we create an action. The action is to wait a certain amount of time. And then when we run it, we're going to run it with a completion block. And so when this action is done, it will execute this code that we place here. And in this code, we make the man's dynamic property in the physics engine to end. So it'll lock in place and then we'll have another action which is wait for duration. That gets triggered at the same time. We'll run that action and when that second duration is complete then we'll set that man's movement back. And finally in the 14th state we'll run this really complicated sequence of actions where we wait, and we play sounds, and we move the character, and we allow the head to rotate after all. And then we stop the rotation, and then we move the rotation back, and they put it all on sequence and then we run it. But let's take them one at a time. So I'm going to run it, and the first time I hit the button we're going to see this move to action. And of course this is executed on a sprite. So we're going to see that after we create this action to move the sprite to the center, not quite the center of the screen, the middle of the screen, and just off the top. We're going to allow it to take five seconds. And so that movement, it's going to move the sprite across the screen for five seconds. We're going to run it, and then we're just going to sit and wait and watch it. So let's go ahead and run our application. And run it on the iPad, and it's locked, let me unlock it, Okay, let's try, it is running, I think. Yep, there we go. So it's running, we see this animation operating and now when I tap the screen, what's going to happen is we're going to execute that first action which is going to move the man to that location that we've specified. I'm going to wait til he's on the right because it moves it to the left. And I'm going to tap it now. And you can see that the man is dragged up and left, and then once he gets to that location after five seconds, he's released back into the physics engine. All right, now our next state is to rotate the man. So to rotate the man a full 360 degrees or two pi. You will see that his head rotates, focus on his head. And as his head rotates, his body in the physics engine will react to that. So here we go. I'm going to tap the screen, you see his head start rotating and it rotated all the way around. The physics engine has bug if you rotate a root 360 degrees. You can see the body flip around like you would expect. All right, the next thing that I'm going to do is I'm going to do an SKAction scaleBy. And what this is going to do is it's going to scale the node and all of the children by 200%, or two times their current size. And you'll see kind of what happens when I do that. All right, here I go. And I am tapping the screen. You can see that the guy blows up. Maintains the same physics properties and notably, all those hinge locations remain at the same location relative to the sprite. All right, the next action that I'm going to do located there at the top of your self.state equals three. Is I'm just going to scale the x factor down to 1.0, now this is not a relative factor, this is an absolute factor. And so the x scaling is going to go to what it was originally when I tap. Here I go, I'm tapping and you see that the y remains blown up at where it was. You get kind of a distorted sprite. My next action then is going to return my y scaling back to 1.0. So back to the original sprite that we had. There we go and I'm tapping now. And you can see that the man goes back to the proportions that we originally started him with. Again, physics engine working on him the whole time. So in the next state, what I'm going to do is I'm going to do a fade out with duration action. I'm going to create that action and then I'm going to tell the SKNode man to run it and we're going to see that the graphics for the man disappear but the physics body is still operating. So even though you can't see the sprite, the physics body is still affecting the other objects on the scene. So here we go, I'm tapping now. Over the course of two seconds he fades out still reacting to the balls even though you can't see him. So, now for my next action I'm going to fade him in and I'm going to tap the button now. Let's see he was operating and moving the whole time but just faded out. For state seven I'm going to resize the head node to a width and height of 200. And you'll see that this one affects only the root node not the whole body. So I'm going to tap now, and his head gets really big. And one thing to notice here is I'm going to do an undo action, but I'm going to do it in a particular way. So if you notice in the code in the background you can see that I create, I do action reversed action. What that does is it creates a new SKAction based on an action you already have, that reverses the effects of the previous one. And I keep track of that in a property variable called self.undo so that next time I touch I can access it and undo it. Now not all actions can be reversed. You have to look at the documentation to see which ones can. But this one can. And so the first action was to blow his head up, by 200. And in this state you can see that I'm not actually creating a new action. What I'm doing is I'm running the action self.undo. Which I created in the previous step. All right so now I'm going to tap it and we'll do state 8, you'll see that his head returns back to the normal size. You know when his head was twice as big. You saw that it went off the screen. That's because although the sprite got twice as big the physics body didn't increase in size. And so the graphic was twice as big, but the physics body that was representing it didn't grow as well. I would have to also change the physics body's property if I wanted that effect. Alright, in state nine I'm going to show an example of changing the physics body. And in this case I'm gong to change the mass of the guys head to fifty. And I'm going to do that But I'm going to see if I can wait til he's up in the air so that we can see the effect. All right, I'm going to tap it now. See that his head got really heavy there and he's squishing down on his body. Oops, I got ahead of myself. So now. Let's see where are we now? We just changed the mass back. So now we made his head very light, I think. And we actually played the audio too fast, all right. So the audio didn’t show up because of the way I'm doing the screen recording, actually we doubled tapped there. But we've already seen the example of playing the sound, so that should be okay. All right so for our next state we're going to use this completion block. And this is a little bit more complicated. But this speaks to the way in which you can trigger sequences of actions. And so in this case what we're doing is we're creating an action which is simply to wait for a given amount of duration but the way that we're running it is that we're going to run the action. And then we're going to provide a completion block so that when the action is done we can do something else. What's that something else that we're going to do when the action is done? Well, we're going to make the body not dynamic. So the head is going to get fixed and not updated by the physics simulation. So it's going to be two seconds and then the head is going to get fixed. After we fix the head we're then going to create another action nested within this one, where we're going to wait for two seconds, and we're going to execute that, and when that two seconds is done on completion we're going to make the physics body active again. So the effect should be tap the button, wait two seconds, and now get stuck, wait two seconds, and the man will be freed again. So let's go ahead and do that, I'm tapping, now. 1, 1,000, 2, 1,000. Stuck. 1, 1,000, 2,1,000. Free, okay. So you can see that that worked, pretty well. Also you can see that, changing the mass of the head has create change, the physics properties such that, now his head bounces around on the spring. Maybe not the best simulation of a man ever seen. All right, the last one is a very complicated sequence of actions. And let's see if I can position this correctly. All right, so what we're going to do, here let's see, there we go. So what we're going to do in this sequence of actions is a whole long sequence. This is just to demonstrate that you can chain these together in quite a sophisticated way. So first start down here where we specify the sequence. And you can see we're giving a sequence of actions. a, b, a, b, a, c, a, d, a, a, e, a, f, c, b, and if those are all indicated up here where a is wait for five seconds, b is to play a sound, c is to move to a point, d is to run a block. So this is an action that does arbitrary code which is going to allow that man's head to rotate and then we're going to stop the man's head from rotating and then we're going to rotate the man's head to zero. And then we're going to wait at the very end. All right, so let's go ahead and do that. And just show you how that operates, all right? So here we go I'm tapping right now and so we're waiting. One, two, three, four, five, sound should be played but we can't hear it. One, two, three, four, five sound should be played again. One, two, three, four, five. He should be moved to a specific location over the course of five seconds. There he goes, and then one, two, three, four, five. Now d, we're going to allow that man's head to rotate. One, two, three, four five, six, seven, eight, nine, ten, we're going to stop allowing the man's head to rotate, and then we're going to rotate it back to zero manually. Now we're rotating it back to zero, that's action f, and then finally we're going to move him to specific location, that's action c, there he goes, and then the final b is to play the sound that we're not going to hear. And then he will continue with his execution. Oops. All right, and then if I hit the button again we'll go back to zero. All right, now his head's off the screen. Okay, so that was our SKActions Code Check. What I wanted to show you in that example is how you create an SKAction. And hopefully you saw that in the code. It's really straightforward. You just instantiate it. But you have to look at the documentation in order to figure out the whole range of different things that you can do. And once you instantiate it, you just ask the node to run it. And so the real challenge with working with SKActions is really the design, figuring out when you want different effects to happen and which effects you want at a given moment. All right, thank you for attention. [MUSIC]