Transcripts
1. Introduction: Hello everyone, Chris here. And this course I'm going to be introducing the ghetto game engine to all of you by helping you to create a working 2D platformer game prototype from scratch. One of the big focuses of the course is creating a platform, a controller that can handle many classic platformer actions like double jumping while jumping and bounce attacks. For enemies, we can set up simple reusable patterns like waypoint movement and projectile's attacks. Handling physics layers, collisions and area entered or left triggers is another major coding area so that the right objects triggers certain events to occur. For instance, RB enemy only fires at the player thanks to using physically for building levels out that tile map tools and Godot are quite helpful to us. You can use auto tiling to quickly build out levels for testing. All in all, I've tried to make the course cover most of what could DO has to offer out of the box, including signals, UI creation, handling animation trees, inheritance as a coding patent, and global data through singletons scripts. So if you want to get started with Game Development, want to learn a free But currently evolving game engine, need help building a classic 2D platformer game or you just want to have some fun, then I hope to see you in the first video is my course where we're going to start by setting up our project settings and then jumping into making tile maps.
2. Setup Godot and Import Pixel Adventure Art: So in this video, we're going to basically go through the steps of setting up Godot, grabbing our assets and importing them into our new project. So first off, if you don't already have Godot, can pick up Godot at Godot Engine.org slash download. And you can see there's versions for Windows, Mac, and Linux. So just go ahead and download and install the Virgin you need, like you would any other program. Also, if you have steam, that is another place that you can get it, like you would download a game on Steam. You can also install Godot from there. So just to point out in this course, we're going to be working with Godot 3.3.3. And I am personally using the universal 64 bit version of Godot on Apple silicon. So aside from that, we're going to need some art for the project. So a great option we can use for creating a simple platformer like we're gonna be doing is pixel adventure. So you can get this on each dot io if you search for pixel adventure, or if you go to a pixel frog dash Assets dot, dot slash, pixel dash, adventure dash one. In addition to that, there's also 20 enemy characters you can download with pixel adventure to, which is a second, and you can pick up both of those on each dot io. So I'm going to be importing both of those into the project. It's just so you know, where we're getting our assets from. But in the end, this is just what I'm using to demo for the course. You can use whatever our assets you want in the end, maybe you prototype with us and then put it on your own art later. So when you launch window for the first time, you may see some projects, but we're going to be creating a new project. So over here on the right you have a new project button. I'm going to click that and then I'm going to navigate where my computer I'd like to create that project. So hit this little Browse button over here and I'll be using, and I'll be using this path for my project, but you can basically store it wherever you want. Now note that here I have my reference project, pixel adventure projects. So I'm just going to be calling it the same thing and throwing a dash tutorial at the end, since this is going to be the follow along version of that same project. So let's go ahead and select the current folder. And now we need to give it a project name and create a folder inside of this directory for the project. So let's call it pixel adventure, project dash tutorial. And I'm going to do create folder. You can call it whatever you want. And I'm using OpenGL ES 3 is the renderer, haven't had any problems with it so far. So let's go ahead and hit create and edit. And here's what Qdot is going to look like the first time you boot up your project. And you'll notice that this is obviously a 3D view. At the top, we can actually switch to 2D, which is what we're going to be using for basically the rest of the project. So before we import all of the art into the game, we should set the default settings for any art that we do import into the game so that it displays correctly. So if I was to click on this icon dot PNG and every Godel project that's due a logo. We can go over to the import tab and we can see that this is importing as a texture. So we want to set the defaults for texture to be a pixel, our default setting. So if we click on preset here, you'll notice 2D pixels, one of the options. So if you click there, you'll see that certain options like filter going to turn off. So filter would normally make your images blur around the edges so that you wouldn't see the pixels as crisp and everything would kind of just blurred together. So we don't want that for the game in pixel that you want each of the pixels to be clearly recognizable as the color it was colored. And so we want 2D pixel as the default for all of the images we bring into the game. So we don't need to hit V important for this particular icon. Probably not going to be using it as a actual our asset here. But we do want to change pre-set up at the top and then set as default for texture. So this is going to mean that these settings we have right here just got copied to the defaults that are going to load for every image we bring into the game by default. And note that even in a pixel art game, there might be some images that you actually don't want to have these presets. So I would just set the preset as whatever is going to be the majority of your art. In this case, that's going to be 2D pixel for pixel art, characters and tile sets and all of that. So let's go ahead and bring our files. And now we might want to add a folder in this project to store all of the art assets. So we can create one in the bottom left file system by right-clicking on this resource folder, which is basically where we created our project and other path to that. So let's right-click there and do new folder. And I'm just going to call this art and hit OK. So now we can navigate to wherever we have our assets we want to use for the game. I've already gone ahead and extracted the pixel adventure 1 and pixel adventure Tupac's note that when you extract pixel adventure one, the folder might be called free. I renamed that to pixel adventure 1. And pixel adventure to is called this by default. So now we want to basically copy these into the project so that we can use them. One way would just be to drag and drop from your File Explorer into Godel. And you can just drag it onto that folder there, but it's possible to put it in the wrong place on accident. And whenever you move folders around and Godot, it's going to have to re-import. All of those are assets which can take a little while, so it's better to get it in the correct place and the first attempt, so I'm going to select these and I'm going to copy them. You can just drag a box and then right-click and copy, or you can select them and hit Control C If you need. And let's go over to the Godot project folder. So I have that stored and this Tutorials folder, and then we have the project here. So we can see the art folder we just created over. They're going to go into there and then I'm going to paste the new assets in here. So now, as soon as I click back into Godel, we can see that it's going to reimport. These are assets applying the defaults for how it should display and Godel for instance. So if we open up arch and pixel adventure now, we can go into main characters. I'm going to be using Ninja frog as the main character for this course. So if we drag one of these spreadsheets on to the screen now, we should be able to see it with proper settings for Pixar it. So let's drag this idle. I'm going to Control middle mouse wheel and zoom in a whole lot and makes sure that these pixels are displaying crisp. So when you're very zoomed in like this, you shouldn't see any blurriness. You should be able to clearly tell every color that these pixels are and where the placement of each pixel is. That's the look you generally want when you're doing pixel art style games. So I'll zoom out and we can also confirm that the settings are correct because if we click on idle and if you go to the import tab on the top left, you can see that this idol, 32 by 32 PNG is it being imported with filter off? Now, when you create the project and Godel, that's on by default. So that's one way we know that we have set the default for 2D pixel for importing images. So at this point we've created a project and we've brought in the pixel art with the correct import settings. So in the next video, we'll just be doing a couple more setup requirements for this project before we get started in creating our game levels.
3. Setup Project for Pixel Art (Window Size, Stretching): So before we start working on the levels of our game, we're going to need to change a couple settings about the game window so that when we're testing the game, it displays a little bit more appropriately. So first off, we're going to need to create a scene so that we can load that scene as the starting point for the game. So right now I have the sprite image that we just brought into this main window here. And you'll notice that in the scene top-left, that contains the sprite. So a scene is going to be any node and Godel plus any nodes nested below that. So a character can be a scene, a level can be a scene, and scenes can have instances of other scenes. So you could put a bunch of enemy scenes in a bunch of characters, scenes into a level scene to make it all come together. And once you start using, it gets pretty intuitive. So we're just going to take this bright and save it as a scene so that we can load that as the starting point for our game. So I'm going to hit Control S or Command S. And we're going to put this as level one, and I'm going to create it in a new folder. So let's say Create Folder in the top right. And this new folder is going to be maps or levels, whatever your head. Okay, and let's save this scene inside of there. So for right now, this doesn't really make sense as a level saying, don't worry about it. We'll change that later. And let's go up to the play button in the top right. So you can, so right up here and we can go ahead and hit Play the project. But if we haven't defined a scene, we can select a scene as the starting point for our game. So let's select the player one scene. So this is in the Maps directory and I'm just loading this n. You can also go up one level if you need to select the right folder. So let's just double-click that. Okay, and now the game should start with that scene. And our sprite sheet is displaying here pretty nicely. The sense that there's no blurriness of the pixels. So that's still what we want to see. But it's pretty small the sizes of this character. So we actually want to make it appear bigger on the screen. Now that we've tested it, we know the problem. Let's go to the project menu in the top left and project settings. And we can go ahead and find the settings for this. So as you can see, I'm already here and display window. But if you don't see it immediately, you can click on the Search box over here in the top-left and type in window that will filter the categories down so you have less to choose from. Alternatively, if you're up here at application, just scroll down to display window. And here we're going to have the settings we need to change. So for right now, going to be taking the width and height and setting that to 320 width by a 180 pixels wide. So that might seem really low because they think most people are going to have displays that are at least 1920 by 1080 pixels these days, maybe bigger than that. So that is a really low resolution. So what you do is you actually have the test width and height, a higher resolution. And then you take this width and height and scale it up to the test width and height. And because we have the 2D pixel settings for our imported sprites, although we're scaling it up, it shouldn't be blurry or distorted or anything like that. So let's take the test width and height and make it 12, 80, and then 720 pixels. So this should be a decent testing size, four hour window. Then one last setting we need to change down here at the bottom is stretch. Aspect is set to ignore. It is down here under stretch. So mode is set to disabled. We want to change that to 2D. So it's going to be doing default 2D stretching of our small size up to the big size. So if we close this now, hit Control S to save everything and let's go back to the Play button again. Click that. And when we load the game, this time, you'll see that characters are much bigger. I think we basically took the image and scaled it up four times on the screen. So this is a 1280 by 720 pixels window, but it's basically displaying the actual game at four times the size. So on a big monitor, this makes a lot more sense. So you can actually see the characters. So that should be the last of the basic setup for our project that we're going to need. In the next video, we can start working on building a background for the level.
4. Making a Repeating Tiled Background: So in this video, Let's start creating our level by starting with a repeating background texture. So when you're going to use a image as a repeating background texture, there is a flag that you need to turn on for that artwork. So if we go into the art directory and pixel adventure one or wherever you have that saved. And then we go into background, you'll see a few different textures we can use for background. I can bring one in here and you can kinda see that this tile is just going to repeat over and over again. So what we wanna do for this image and all of the different color versions of the image going down to yellow is go over to the import tab. And over here we can see read about filter. There is a checkbox for repeat. We want to turn that onto enabled. And when we do that, this flag is automatically checked so we can re-import these assets. So now these will work as repeatable textures. So in order to get a texture to repeat across the screen, you've got to click on the texture. Then you go to region, and then we're going to want to enable region here. So this is now basically going to take the texture tile and stretch it across a region. And because the repeat flag is turned on for these textures, it's going to tie it rather than just stretching. So now we just need to set a size for the background. So width and height here on the right, W and H. And let's just give that a size that should be good enough for our level. Really as big as you want, it is fine. We could just do it 1000 by 1000 pixels. And they're basically, you have a repeating background base that you can use for your level. So now we just drag this into whatever position we need and we'll pretty much be good to go. One thing to note about creating the background this way is that you do not want to use the scale tools if you need to expand the background further. If you grab on the scale, on the edge of this sprite and you stretch it, it's going to still stretch the image. So if you need a long career, you should come in here to region and add some extra pixels here. So 1200 with, you can see the expanded it without having any stretching. It just adds more tiles and which is what we want. So let's clean up the level a little bit more. So next I'm going to right-click on the initial sprite, which we'll be removing in a minute and adding a child node. And this child node is just going to be as simple node 2D. So this is basically a generic node and we can use that as the root of our scene. So everything that actually goes into the scene would just be nested below it. Let's create that. And now we can take this node and actually make it the root of this level scene. So I'm going to right-click here and I'm going to make scene root. So now this idol sprite image is nested below the node 2D and the blue background is nested below that. So I'm going to take the blue background. I'm going to left-click hold and drag it and put that above the node 2D. So now there's no children of this idol sprite sheet. And we can remove that by right-clicking on it and doing cut or delete nodes. So let's just go ahead and get rid of that. And now finally, we can take the node 2D and I'm just going to rename this to level 1 to match the name of the saved file. And maybe the background. I'll just rename this background so that pretty much gets us set up to the point where we can start adding in some actual ground for a character to stand on and platforms and all that stuff. So let's go ahead and hit control or command S, save the level, and that'll be it for this video. And in the next one will be building out the ground where characters can stand.
5. Tilemaps and Tilesets for Level Building: In this video, we're going to be working with tile maps and tail sets in order to create the ground where our character is going to stand on. So inside of our level one scene, up at the top left, I'm going to right-click here and add a new child node. This one is going to be called a tile map. So you can just type in tile map to find that and hit Create. So this tile map is, we can see on the right side, is going to need a tile set. So the tail set is going to be created from images in our project, and that's going to be specifically the tile size images. So there's the title file that exists here and Godel. And then it's the actual image where that tail set is pulling off it's tiles from. So let's click on the empty section for tile certain hit new Tulsa. So this we can click on, and when we do, there is a new window down here at the bottom called tile set. So we need to add a image here in order to start picking out the tiles from that tail. So image, so we can find the proper images for creating the tiles from the terrain category inside of our pixel adventure one pack. So we can see from the thumbnail there's actually a whole bunch of different terrains we can use here. And there are exist in one single image. Let's go ahead and left-click hold and drag this into the list for our tile set. When we do that, and we'll see the image kind of expands a little bit more down here. And you can hold Control and scroll on your middle mouse wheel to zoom in and out. Of course, it can also zoom in and out over there on the right. So we want this to be a big enough on the screen that we can kind of clearly identify the tiles that we're working with. So there's three types of tiles we can create for our tile set. There is the new single tile, which is going to basically define one region in here, which is a tile that you can left-click on the right here when you're painting your tiles and then just left-click and put it on the map. So that's the simplest option. There's also new art or tile will be working with that in this video. So the auto tile, you can basically define a set of tiles. And then you can create a bitmask for those tiles in the BitMask determines which tiles should border the other tiles. So in a sense, you can make it so that this one over here on the left, you can see that this is obviously a left end tile. So you can make it so that this will be the one that's always on the end by setting up bit masks, which is basically creating the rules for how those tiles should be next to each other. And then there's also a new Atlas, which you can define a whole bunch of tiles. And then you'll get a list over here on the right. You can just select the one you want from. Before we start doing that though, let's click on the tile map. So on the left here scene. And we want to go to sell and make sure that the cell size is set to 16 by 16, since that is the size of our tiles and the game. So we set the 16 by 16 here to match the designed tile size of the artwork so that everything matches up correctly. So we can click back on tile set and we can actually see that it kinda lost its reference to the terrain here since we didn't exactly save it. So a decent idea might actually be to click on tile map here. And then with this tile set over on the right, we can click on this little drop-down and save the tile set to a file. So this will make it so that you can reference it in any tile map. And the data will be basically hard saved inside of the project. So I'm gonna go ahead and save that here. And I guess I will put it in the maps category. And I'll go ahead and call this pixel adventure terrain. So we'll see that the name of this changed to the name of the file saved as a dot here, IaaS extension. So we can still open this up and edit it. And I think if you go into the maps folder, you can also just double-click on it here to open up the same thing. So basically the tail side is saved to its own location now and it's no longer embedded in the tile map directly. So we can add the terrain in here. I'm just going to drag that and again, and this time let's go ahead and hit new auto tile. So we're going to have to define a region for this are one of the really helpful features is this enable Snap here. So we can see that this will allow us to snap into the grid. So if we left-click in here once, that's going to define a region, and then we can change the settings so that we can actually get the desired sizes. So over on the right, we have snap options here. So This is the number of pixels that you want it to snap to in terms of steps that you can make this 16 by 16. I think I'm going to show you going with, let's say four-by-four this time. So you can see that the tail is basically broken up in this little pixel grid. And whenever we need to make adjustments, like, for instance, creating the collision shapes later on, it can snap to any of those intersections on this four-by-four pixel grid. So I think that'll work pretty nicely. And then we have selected tile. We want to change the subtitle size to 16 by 16 here. I also noticed out OTA or bitmask mode, so that I don't have a bitmask mode is going to be important when you're determining. Basically, when you break down your tile, how many corners are there that you can assign a bit mask on or off value two. So if you have two-by-two, then that means every tile is broken into four potential BitMask. And there's also three by 33 by three minimum, which you would imagine gives you nine bitmask subtitles per actual tile. So for these, we're going to be working with a two-by-two. These are simpler tiles over here. And I believe these are as well. But when we get over here to the right, these are going to need, I think three by three minimal, but I will double-check on that later. So now we need to redefine the region four, Our first. So now we need to redefine the region for our first auto tiles. So we can see here that we have four squares here, and they are the right size, 16 by 16, thanks to the subtitle size. But we're actually going to need to left-click up here at the top and then drag this over our entire stone block region. So I'm going to zoom in a little bit, make sure that all of the corners match up so you can see what's defined as the region because that's this green line that outlines everything. Your tiles are basically wherever these green lines intersect. And that should be how it looks for right now. So we're doing a two-by-two BitMask. So it's going to be really simple. So I'm going to go into bitmask mode and this will set up the auto tiling. So for this tile, we're going to need it to look like this. So you can just left-click and hold and drag the red box where you need it to be. So my understanding of the bitmask in Godel is that where you have a bitmask enabled with the red square is going to be determining where this tile blocks to other tiles to see if it matches the bitmask in order to determine if there should be the tile that gets chosen. So in this case being a top-left corner, it has one to the bottom right. So it's going to be looking to both the right and down to see if there are tiles there. So in that case, if it matches both down and to the right, then it can be a corner tile on this piece. So in this case, if it finds a tile down and to the right, then it can be registered as the correct tile to automatically be selected. But there's also the areas where the BitMask is off that needs to be taken into consideration. So in this case, it would only be selected if down and to the right half a tile. But also in this case that there is nothing to the left. As you see the bitmask in the top left and the bottom left are disabled and also nothing above. So if we have two bit masks enabled in one direction for a two-by-two bitmask, then that's going to mean is going to look directly down rather than to the right and down. And if you have all four bit masks enabled, then this square wave basically have a black background is only going to be selected if it's surrounded in all directions by other tiles from this specific auto title. So only tiles that are selected from this auto tile are going to account for selecting which tile gets selected. So if later you put, let's say one of these pieces next to it, which is a totally different auto tile. It's not going to have any influence on these tiles being selected. Only these tiles influenced the other tiles from this auto tile. So for these tiles to the right, you can see that three out of four of the BitMask points are marked on and only one is off. So in this case, you would be looking for there to be adjacent tiles from this auto tail on the left and above. And I think also the top left, if you're going corners diagonally like this, but there would not be one to the down and to the right in this case because this tile is off. So to put it simply, when you're adult Heil draws onto your game map, it's going to select the best fit from this auto tiles setup. So ideally when you're working with BitMask, so you would only have one bitmask setup for each possibility inside every bit mask. Notice that although four of these tiles have one out of four of the BitMask on that they're in all different directions so you'll never get any overlap with this simple auto tile. So lastly, if you go to the adult-child bit mask mode, you'll notice that there's three by three minimal and three by three as another option. So both of those are going to have nine bitmask points per tile, since it's three by three, we multiply that you get nine BitMask, so you can have one in the middle. And we'll be using those later on for these terrain pieces over here. And actually as well as these little platforms. So if we click on the tile map now, we'll see our terrain tile is here to be placed on the script. So we can just kinda go ahead and place some tiles. But what you'll notice is that unless you have at least a two-by-two, the two-by-two bitmask can't work. So if you're just going straight down and align like this, you're just gonna get one tile selected. So for the two-by-two bitmask to work, you actually need to have at least a two-by-two square. So we can see as I start building this out, it just came out works perfectly and the center gets filled in. So with other tiling, it becomes really easy to create different shapes without having to worry about exactly which tail goes where. So if you can manage to set it up for yourself, It's pretty handy to work with and to kinda show those. Other tiles, I'll just remove a couple from these inner points here and you can just see it. Just kind of works. So let's go back to the tile sat and create some extra tiles. So we basically need to repeat the same thing for down here, this one, this one, this one, and this one. So we can just copy and paste kinda six times. So back in the tile set, go to region mode in order to see the names of each of these auto tiles, I'm going to click on this little info button on the right side. So you can see this is terrain 16 by 16 tile. So what we need to do is create a new auto tile and we're going to be defining the same box as the region. So new auto, click on the top left, hold it down and drag a box around this area for our second auto tile. Now, we could go to bitmask mode and define everything. Once again, it wouldn't be hard for this one, but even quicker, we can just click over here on this auto tile and hit the Copy button for the BitMask, and then click over here for this one and just hit the paste button, okay, but it doesn't need to be 16 by 16 subtitles size first. So to find that over here on the right for each of the regions you create, Let's do a new auto tile. I'll have to zoom out a little bit so we can see it down here and drag a box around this one. Make sure the subtitle size is set to 16 by 16. Now we can go to BitMask and paste it in, since we already have the one from this one copied into the buffer. So that's three auto tiles created. Let's auto tile, keep repeating the process. So 16 by 16 bit Mask Mode, paste it in. New auto tile, 16-bit, 16 bitmask, paste it in and you pretty much get the idea. So let's finish up this last one down here. So I'm going to paste it in. And yes, sometimes 16 by 16, and that should be good for those. Now, the same bitmask is not going to work for these. You can see that these are a little bit different and these little bar platforms as well, I think this one actually does have the same ADL tiling. So let's create one more over here for that. Then we can kinda test that out and make sure it works still. So let's paste in the BitMask, and there we go. So now if we click on the tile map, we can see that we have seven different terrains. So select from. So let's just start drawing one. And you can see that each of these, because they're defined as their own ADL tail, they work independently of each other. So having one auto title next to another one is not going to affect anything. We have. We can just kinda put this brick out there. And so we can also draw some other terranes here. So let's just make a two-by-two. And there we have some dirt ground. Okay. So let's go ahead and set up a couple more bit masks. So back in the title set, we need to define the other tile regions for these areas. So let's drag a box around it called a bitmask mode. And this time we're actually going to be using a three by three bitmask, which will make sense when you actually look at it. So change the auto tire bitmask mode to three by three. And believe we want 16 by 16 as the subtitle sites for the BitMask. So if we zoom in a bit, we can start drawing this. So it's gonna look like for the top bit. So we can see that this first tile has a square in the center and then one to the right. And of course this gives us 9 bitmask squares total inside of a single tile. So if we call the center, one, basically means there, it's looking for itself to be a tile and the SAT, and then also the BitMask on the right means it's also going to be looking to the right four tiles. So if it's on the end, it's going to count itself for that middle one. And then if there's a tail to the right, it's going to match that. And then that can basically let you create a role of this type of tile by just having these pieces next to each other. And then this would be the end, and this will be the end and this would be the middle because it's looking to the left for a tile and to the right for a title as well. Then we have this one down here, just a single dot. So this will be the tile when there's no other tiles around, just like a single tile. And then we can drag 16 squares in the middle here, so the outside ones are not going to have anything. So you can basically use this shape for creating what you see here. Basically just creating a two-by-two title block. And then for a top-down platforms, we have this. So kind of the reverse direction for this one over here. Go to tile map. We can kinda see this in play. If I drag over here, we can create a little platform. We can also create a two-by-two to have that kind of block. Individual ones will just be these little squares. And then of course we can do top-down as well. So for these purposes basically you could see that in the tile set image, it will work just fine for that. But creating things like this, I don't think those tiles are actually designed for that, but if you know differently, feel free to put a comment and I can correct myself on that. But basically, this is how I was able to get it setup for that specific portion of the tile map. But that's basically how it was able to get it setup for that specific portion of the tile set. So let's go back into here for the tile set terrain and we can copy this bitmask down to the other tiles. So new auto tile. It's created down here, 16 by 16 in three by three bitmask mode. And we're going to go up here, copy this one and paste it into the one below it, and just repeat the process for the other two. Let's create that bitmask, paste it in, and make sure three by three and 16 by 16, the information should overlay correctly. New auto tile, drag the region, but Mask Mode, paste to them, changed the three-by-three 16 by 16 subtitle mode. And that basically sets of that up. So now there's these last three platform tiles. We're going to need to draw a region around them. So let's go ahead and do that. Make sure that although the height of the platform here is only about 45 pixels, that you actually do the full 16 pixels because it's still going to be tiled 16 pixels by 16 pixels with the rest of the game. Or at least that's how I'm gonna do it anyway. So then we take the auto tile bitmask mode and put it in 3 by 3 minimal. And the subtitle size 16 by 16. And then bitmask is going to look basically like this. I believe. So. Let's go ahead and test it on the tile map. We can click on the platform and its draw a row. So note that the ends say in their place, if I add another piece, the end moves over to the right. So that's what we want. And this will work as long as you don't put another platform that's like right below it, like this. As long as you're not doing that, it should work correctly. So I think that'll be sufficient for our purposes here. Now, let's go back to that tile map. I'm going to double-click it and the maps folder terrain. And let's just copy over that bitmask to two more new auto tiles. So new auto title and we select a box around here, go to three-by-three minimal 16 by 16. And then bitmask, we're going to copy it from here into here. So they're basically the same. And then lastly, the metal version. Let's create that three by 31616 bitmask paste. So that's going to be the auto tiling setup for all of these terrain tiles. Now you can get to the fun part where if you click on the tile map, you have all of these auto tiles that you can use for building your own game level with. So for instance, if I want some platforms and maybe this could be used for a platform you can kinda jumped down off of. If you wanted to, just thinking ahead. If you want to create some long blocks, you have that, some tall ones, you can do it that way. And then these other tiles can be used for setting up the base ground for your character. These just have to be at least a two by two tile to auto tile correctly, like so. And you should be good to go. So you can just kinda build up whatever you want to test out for right now. And then in the next few videos we'll start creating a simple platform or character that we can use for kinda testing this level out. So I'm going to say for now and until the next video, I'll see you then.
6. Setting Up Player Animations: So in this video, we're going to start creating a player character and a camera. So the first thing we're going to need to do here is to create a new scene and have it start with a kinematic body 2D. So I will add this to a new scene tab up here at the top. And I'm going to click other node because I want the root to be a kinematic body 2D. So if you don't already know, a kinematic body 2D is basically a physics character that will move based on the rules that you program into the script code. In other words, a lot of how your character moves around is going to be manual. The other option would be to create a rigid body 2D. And those work having forces act on the body rather than directly controlling the movement of the character inside of its script. So for games and physics-based puzzle games like, let's say Angry Birds, the rigid body would make a lot of sense there since you want forces to act on the character. But if you're trying to create a platformer, kinematic body 2D is usually what you're going to want. So let's go ahead and start by creating with this kinematic body 2D. The first thing I'm going to do is rename it to player. And then let's create a folder for characters to sit in. So that would include the main player character. Enemies may be NPCs, whatever you need. So I'm going to right-click down here in the file system and create a folder called characters. And now I'm going to hit Command or Control S in order to save the player seen inside of that character's folder. So let's go ahead and save that in there. Now, you'll notice that there is a exclamation mark over here and node configuration warning that this node has no shapes so it can't collide or interact with other objects. So we have to add a collision shape too deep to this player so that it can actually collide with, let's say, the ground or other enemies, so on and so forth within the game. So I'm going to right-click here and add a child node. So we want a collision shape 2D. So I'll add that in. And he also notice here that the collision shape actually requires us to create a shape type. For that to work. We'll do that in a minute. So the next thing we're going to want is a sprite. So I'm going to right-click here. I'm going to add a child node. And for this specific character, we'll go with a animated sprite. And the reason for that is how this packs sets up the sprite sheets. So I'll show you what I mean by that in a minute. But for now, let's just go with animated sprite. And depending on how your specific sprites are, the sprite node may work better than an animated sprite. So let's start adding the animations to this animated sprite. And you'll see a little bit of what I'm talking about. Over here on the right there is this section here called frames and empty. So we want to change empty to a new sprite frames. So that is something we can click on. And when we click on the sprite frames, window pops up here at the bottom and we can create individual animations. So if we look at the art for the ninja frog, which is going to be in the pixel adventure one pack, and then main character and then ninja frog. We can find, let's say our idle animation over here. So when you create an animation for a animated sprite, you just give it a name and you can create new animations up here. So we're going to do add frames from sprite sheet. So if we go into art, pixel adventure, one, main character, ninja frog, and then idle, we can grab that. And so you'll see that over here for horizontal will be up, just specify the number of columns and then vertical four rows. So 11 by one gives us 11 sprite frames. We can select or clear all frames here and add 11 frames. So that will work really nicely for this kind of setup where each of your different animations of broken into their own sprite sheet. So I mentioned, why would you want to use animated sprite over the sprite component? Well, let's just go add a sprite component and I'll kind of show you what I mean. So we'll add in the sprites and for right now I'll just hide the animated sprite by clicking on that little eyeball. We'll go to texture. And then you can see that we can put exactly one texture in here. So that could be a sprite sheet pack. So for instance, I can put idle in here and you can see the frames load just fine. So if we expand the animation section, you can see horizontal and vertical frames so we can set rows and columns like before. So I think we need 11 horizontal frames, okay? And that splits up the frames individual. So we can go through the frames here and just kind of play out our animation. So we'd be able to animate using this frame setting. But the problem is that you can only have one sprite texture. If we change this into, let's say this jump, you can see it's still using horizontal frames, 11 by one. This animation is completely different. It only has one frame, so I would need to change this value to one. And then whenever we're playing an animation, we would have to not only change the texture, but also the number of horizontal frames and vertical frames. And specifying individual frames on the animation by the animation basis. When we go ahead and create an animation player, which normally that would be okay if everything was condensed into one pack, just like one single texture file. And then you can just go through all the frames here and it would be no problem. But because they're separated, animated sprite just makes more sense here. Both will do the job, but if you have different animations that are separated, then it's much easier to just click Add animation. And let's just do run here and drag and drop it. You actually want to hit this button so you can split up the frames, then you click on Run. I think we have 12 by one here. Select Clear all frames and the top-right add frames and there's your animation. So we can check they're playing box on the right to see what our animation looks like. This is way slower than it's supposed to be. So in the sprite frames box, we actually want to change the speed to 20 FPS and there's the correct speed for playing back the animation. We've got to set that on our animation by animation basis. So click on idle and make sure that is also playing at 20 FPS. And you can see that runs much smoother there. So you basically just keep going down this list to create the rest of your animations. So I guess we can actually just add in everything right now. Why not? So let's add an, a jump animation single frame. So I'll just add that as jumped and then we'll have fault. So the difference between jump and fall as far as when your character is going down and then jump is going to be when your character is rising. So you use basically the vertical velocity in order to figure that out, but that's for later. So we can also have a double jump. So I'll add in a new animation. We'll change that to double underscore jump, I guess. And let's add n. That animation. I can see that that is six frames, so six horizontal, one vertical, select Clear all frames, add them, and then we have our double jump animation. So 20 FPS, and that is the correct playback speed. So let's see what else. 3.5 here, hit and wall jump. So hit, I believe is going to be when your character takes damage, Let's add that end. So new animation hit and then new animation while underscore jump. Let's grab the frames for that from their separate texture files. That looks like seven frames. So seven by one, select Clear, All, put it at 20 FPS. And we can test it by changing to that animation. Okay, well, this double jump and we want hit. So there's the Hit animation pretty slick there. So while Trump is the last one. So let's just fill that unreal quickly. Add animation while jump five frames, so 5 times 1, select Clear all frames, add them in and make sure that this FPS is 20 FPS. So we can check all the animations and just make sure that they're all 20 FPS. Okay, so that's basically our animations for the character set up nice and easy with an animated sprite.
7. Player Input and Left Right Movement: So now that we know where our character is in terms of this bright with reference to the kinematic character object. We can basically go to the Animation, put it in idle, and we can figure out where the killers and shape should be using the idle state as a reference point. So in collision shaped 2D, I'm going to click on shape on the right and we can do a capsule shape. So if you do a capsule shape, there is the ability for a character to kinda slip off edge if you're just approaching the edge. If you don't want your character to be able to slide accidentally off the edge. You want it to be either purely on the ground or slightly off the ground and therefore falling, then you could use a rectangular shape and instead, I'm going to go with capsule shape for now. We might change that later, so new capsule shape. And we want this to roughly fit where the character sits on the ground. So I'm going to shrink this. And actually I want to see the collision shape above the sprites. I'm going to reorganize the order. So animated sprite is going to be on top. You just drag and drop. And now we can see the collision shape. So let's change the transform. Move it a little bit down. I think I added a 9.5 pixels or so. And now we just need to adjust things a little bit further. Just get the shape you want for collisions with other objects such as the ceiling or the ground. Maybe we actually do want the character to have a relatively high hit box. So if you're bumping your head into the ceiling, that should happen up here, not way down here. So let's take the transform and move that up a little bit. So let's see five, okay, and that probably is pretty good right there. So currently the settings are five for the pixel position. And if we click on capsule shape, we have a radius of 7.1. I'll just round that to seven and the height I will make 10. And that should do for our initial capsule shapes. So our character should be able to collide once we set up the movement, which is going to require some scripting. So first off, let's take the level. So back on the level tab, I'm going to close the art and the file system go to characters, and let's just drag this player character onto the scene. I'll put them a little bit up here so that when we actually start running the game, gravity should make them fall to the ground. And then we can check if he's on the ground for things like being able to move left and right normally. So it's pretty easy to actually check that and get 0 as well. One of the cool things about 2D kinematic body and movement and Godel. So let's dive into the player scene. We can open an editor that's going to switch into the original scene on level one, this is actually an instantiated copy of the scene, so you can just put it in a whole bunch of players if you want. And these are all separate from each other, but they're all basing what you have, the different nodes here and the code based on this original player scene. And so anyway, we need to add a script to the player. So I'm just going to hit the New Script button while clicking on the player kinematic body 2D nailed, which is the root. You'll see that this will automatically give it the name player dot Gd for GD script. And it's going to put it in the Characters folder. So I think that works just fine for us in terms of organization. So I'm going to click Create. So what we're going to need to do in order to make sure our character can move. When we press keys, is to check the input when the game is running. So we're gonna do that in a function called Physics process. You will notice that function process is commented out here. But since movement is basically part of the physics of the game, we would want to run that in physics process. So anything that has to do with movement, collision, or physics, generally, it's recommended that you run that in the physics process function rather than the process function. So one of the differences with the physics process is that it will burn a set number of times every second of real life. Where's the function underscore process delta can run more or less times than that. So basically the physics process is consistent and in their normal process function runs at inconsistent number of times per second. So let's just delete all of that right here for now. So I'm going to write in here bunk for function and then underscore physics process. You'll notice that this gives us the auto-complete. So I'm just going to hit Enter there, completes it. There is a parameter here called delta, that is the time between frames. So we can use this as information for our physics process. So what we're going to want to do in this is to get the input. So I'm actually going to just create a variable here called input. And then we're going to create a function that will run here. And I'm going to call that gets player port. And then we just need to create that function. So function get player input, okay? No parameters. And then we add the two dots at the end, we hit Enter and now we can start writing with a function. So we can just kinda create a variable here. I'm going to call it var input. I'm going to put this colon and then I'm going to type in the type. Vector to just to kinda inform anyone reading the code that this is intended to be a vector two, which is basically to float numbers. You have an x value, which in this case it's going to be used for horizontal import or horizontal movement. And then you can have a y component for the vector, which would be up-down vertical. So if you're doing a 3D game, you might have a vector 3, which adds the third direction, which would be kinda like your depth into the background, your z axis. Okay, so we have the import and we need to start getting the values for the inputs. So we have extra set for horizontal input and y to set for vertical. And so input.txt. And we need to set that to import. Now the first letter here is capital. This is something you can access and Godot by default, you don't have to write anything before this will appear. And then there are functions you can run on this input. So the function we want to run is get action strength. So this takes a parameter and the parameter is the name of the action. So you see by default there are all of these UI actions that we can grab. So we could just become lazy and use UI underscore left. Another option would be that you could define a customer action and call it a left, right, up, down, or play a move up, down, left, right, whatever you wanna call it, that's totally separate from the UI left. So maybe you have different controls for the UI, and maybe you have different controls for the player, up to you how you want to do it. Ultimately, we're just figuring out the key we want the player to press in order to move the character left and right. So let's go up to the project menu. At the top left, we're going to go to Project Settings Input map, and here we can set the actions for our game. You can see the UI left, UI up and down are already set. So if we wanted to, we could just check for those values and then use up, down, left, right arrows on our keyboard in order to remove the character for the game. I generally prefer WASD movement. So I'm actually going to add a new action. So this will be separate from the UI, left, right, up, down. So I'm just going to call it left up here at the top. If you're creating a multiplayer game, you could call it P1 for player one underscore left. You know, it's really up to you. So let's add k. So we have the new action, but there's no keys for it. So we want to hit the plus button over here on the right. You can see that you can add in joystick, button controls, mouse button controls or keyboard. So let's do keyboard. And I'm going to hit W on the keyboard to set the key and hit Okay, so await, well that would actually be forward. So let's change that. Let's hit the edit button a for left. Okay, and then let's add the next action. So up. And then we can do down and right. So for each of these reset or key, so it up will be w, down will be S, and then write will be d. Okay, so WASD controllers, maybe we want to move this up there. So it actually says WASD makes a little more sense. Let's close this. So now in order to get the x input, we're actually going to need to do some math between two values. So if we're setting the horizontal movement, there's two keys that would control that. That would be the right movement and the left movement. So right on the screen is going to give you a positive value for the x. And then left on the screen is going to give you a negative value. So how we calculate it here is that for the XML, we're going to get the right value first here. So it's positive. I don't put a negative here. V is just positive. If we're going to the right. And then we can subtract the action strength from the left. So get action Strength. And now we do left. Make sure there's the quotation marks because it's a string. And this basically would mean with a key port. If we press on the right, then this is going to be one. And if we press Left the achy, then this is also going to be one. So if you press right and left at the same time, one minus one is going to cancel each other out and you're gonna get a 0. If you're not pressing right, but you are pressing left, you're gonna get a negative one. And if you're pressing right but not left, then you're gonna get a one. So we can use that in order to determine which direction that player should move. So for the y-direction, it can be very similar. So for this specific game, since it's got that classic platformer style, the up and down keys might not actually be used in the end, but we can still get the input values for it. There may be some kind of movement component later on which would depend on the input Y. So we might as well just get it since we've already started up. So let's do input y, and we're gonna do get action strength. And this time we're looking for down. So that might sound a little confusing, but down is actually positive when you are doing 2D games. So you go down on the screen, means that your y-value is increasing. So we want get action strength down minus get action strength up. So there we go. And now we have the The vector setup properly, so we want to return that so that it can be used in the main physics process function. So we turn to input, and we're pretty much done with that. So maybe I'll just write a comment here. So now in order to move the character, we're going to need to determine its velocity. So I'll go up here to the top and declare a variable up here. I'll call it far velocity. And I'll just say that this is a or two, just like we did in the function down here. So the advantage of declaring it up here is that this is basically attached to the player script directly. And we can use this value in any of the functions that this script is going to be using. So it's just kinda publicly accessible whether we're in physics process get player input or any other function. So that also means we can set the value and then the new value can be used in other functions as well. So we want to set the velocity and we're gonna do that based on the direction times the players movement speed. But we haven't set up how fast they are. Player should move, so we need another variable. So I'm going to this time type n export, and I'm gonna give it a type, either float or integer. So if you want to be able to use decimal points, you use a float. If you want it to be integers as an 1, 2, 3, 4, 5, 6, 7, no decimal point. Then you can write INT for Nt. But I think there's really no downside here to using floats. And it just allows you to be more specific with the exact speed. So I will make the variable a float, and we have to put export float var here. And after that we give it a name. So I'm going to call it move speed, move underscore speed more specifically in religious, given an arbitrary number like and 200 for now, we can always change it later. Now, the difference between doing an export float far and a var is that this variable is not going to show up on the inspector for the character. But when you do export float, the float determines the type, basically how that should be set in the Inspector. And then the export is going to make it publicly viewable. So if I click over here on the player, we can see the move speed variable is set here and we can change that to anything we want. It defaults to whatever we set in the code, but we can change this on a instance basis. So if I have three players over here in the main scene, I can click on those. I can change the values over here, so 300. But we can still save that. Go back over to the player scene. And you can see here it's 200. But then on the instance copy, it's 300. So different characters, even though they're based on the same code, the same nodes can have different settings. So you could also use that for things like color. If you want to take a, I don't know, green frog and turn it blue or something like that. So we have our Move Speed value. Now we need to multiply that by the direction. So let's go into the script and I'm going to take the x input. I'm going to multiply that by the move speed in order to get the x direction movement. So velocity, I'm just going to set that equal to the vector 2 here. Maybe I'll kinda break this up into multiple lines. So this will be our x line and this will be our wireline. I'll just set that to 0 for right now. Later we'll add gravity and jumping. But up here on the second line for x, we're gonna do and put that X. So that's the direction we're going to times that by moves speed. So because right is 1 O on the keyboard, left is 1 O on the keyboard, we're going to get either 0 or plus 200 or minus 200. And we can use that velocity for movement. So moving a kinematic body in 2D itself, once you have the speed and the direction, it's pretty easy. All you have to do is move and slide. And then here we're going to put in that philosophy variable, boom, done. There's actually another way to move to, which is moved and collide. And there you would also add n times delta. So really that would look like moving collide velocity times delta. So that's the time between frames are moving slide are medically accounts for that, but moving slide does not. I'm not sure why, but that's just our currently works. So the reason you would want to keep in mind the time between frames is if there's any inconsistencies between the time between your frames, you want to move the character the right amount based on the time since the last frame. So the character should move at a consistent speed. But if your frames aren't rendering at the same speed, then the amount of movement on each refresh should be different. Now, theoretically and physics process, it's always going to be the same. So generally, you wouldn't run into that problem. But just in case that is there, that's why delta exists. And move and slide just automatically factors that N. So you just need the velocity variable. You don't multiply it by delta in a nutshell. So now that we have that, I think we could just go ahead and hit Play and move the character left and right. Okay, first off, we should make sure that we're on the level seen. And let's zoom out a bit here. I guess we're gonna need to put a camera. And so let's add a child note here. And I'm going to add a camera, specifically a camera to D. And then if you zoom out a bit, you can see that blue border for the camera. So I'm going to click on camera, can click down here and we're going to move the camera 2D and just put it roughly on top of our player for right now. Now we can hit play. And the other problem is that we have to make it the current camera. If you don't make it the current camera, then the camera is going to put it somewhere around 000, I think. So if we check current on, then this is now the active camera and this is going to be where the game starts looking at. So play once again. And let's test that out. Okay, So our characters there, so now we can use a and D to move our character. So a, d, Okay, cool, it's working sort of. So obvious problems include being able to walk through the wall and not having any gravity to drop to the floor.
8. Gravity and Global Game Settings with Singletons: Let's solve the gravity problem first. In Canto. If you go up to a project, projects settings, there are technically default gravity values that you can set here, okay? And you search in the search bar, so gravity, and then you can see 2D, we have default gravity and default gravity factor. Default gravity is measured in pixels, and these are just kinda arbitrary numbers that you could apply with your 2D kinematic bodies. I think these might, I think actually it might have more of a direct impact when you are using rigid body 2D and that would automatically factor of a cent. But in kinematic bodies, you have to do everything manually. So you could either use these values and customize them up here. Or what I think I might prefer to do is create a singleton where we just have game settings which we can load up either on like upper-level basis or for the entire game. And anytime we need to change global game settings, we do that in a singleton which loads up one time per game. So I'm going to close here and then we can create a new scene and attach a script to it. So let's go to the menu in the top left, hit new scene. And here we're gonna do other node. This isn't really a 2D object, so to speak. It's just a node that is going to contain a script with a bunch of variables that we can set and reference and other scripts. So other node. And I'm just gonna do note here. So as basic as you can get, I'm going to hit Command or Control S. And let's save this and the root directory for now. We could actually create a single turn folder, might as well have more folders. So I'm going to right-click and do new folder. And I'll put it in Singleton here. Hit Okay. So this node is going to be called game settings. So during the camel casing, capital G, capital S, and hit Save. So I'm also going to rename this node to game settings, make it consistent. And now we just add a script to this. So we do that. It's going to automatically default to that singleton directory, which we saved the G, which we saved the scene file to. So now it's going to store the QDOT script file as well. So create that. Let's delete everything over here. And now we can just add in a couple of export variables. So let's do export, float, var. And I guess what we're going to want here is gravity. And we can set that to an arbitrary default value. But once again, we're going to save a instance of this game settings. So we can just click over here and customize it anytime we need. We don't actually have to use the script because we have the export float here. So that's really handy. And we can do export flow far. And I'm going to call this terminal velocity, as in basically the max falling speed that you can reach. So gravity gets added on every second. Character keeps speeding up, going downwards on the screen. And what do you want that cap speed to be at? So because it's a 2D, cartoony game, it's kind of arbitrary. Real-world physics not required. Just can play around with the numbers and figure out the feel that you want for your specific game. So I'll just fill port 300 four right now. And we'll mess with that a bit later, I'm sure. So we have these values and we just want to have it load this game settings node every time we launched the game. So I'm going to go to project, Project Settings. There is a tab here called auto load, and we want to add in that game setting scene. So let's go to single term and then do the game settings.js CAN double-click there at it. Okay, so now this game settings is going to load every time we boot up the game, It's a singleton. A single tone basically just means that can only be one in existence at any given time. So if you've referenced the game settings, you should be relatively assured that that is going to be the same game settings that you have across your game. So it shouldn't change. It should always be the specific scene that we have saved in this singleton folder. So let's go ahead and hit Close now. And now we can go over to the player script and we can reference that gravity and the terminal velocity. So we're going to set the velocity, the y velocity specifically to its current wave velocity. And then we are going to subtract, and then we're going to subtract the gravity. So minus game settings dot gravity. So this is all you need to do to reference it. Just game settings dot whatever variable we have setup and that singleton, and we can just reference that across. Okay? And we are going to also limit that. So as things are made now, the gravity value is going to change the velocity and it's going to keep going down faster and faster with no limit, basically infinite downwards on the screen speed. So I can kind of show that real quick. But let's also make a print statement here. So print and we'll just do velocity dot y so that in the console, we can see that the value just keeps going down. So let's try playing the game. So level one, okay, and we can see in the output we're going to get the value for the speed. So now we are approaching like negative 16 thousand as the downward speed. And actually I made a mistake. It should be plus gravity because down is positive when we are doing these 2D games. So we're going to want to cap the speed here. And the way that we kept the vertical movement speed is by using the Min function. It's a math function. So it's going to return the lower of the two values. So we have our a over here on the left, which is the new velocity we're trying to set. And then over here on the right, we're going to have games settings.py, terminal velocity. So now when we go ahead and hit Play, we're going to see, or we should see a cap on the value. And we did not. So I think we actually want plus game settings doc gravity. Let's go ahead and hit plus here and see. Okay, yeah, right, that's correct. So down, once again is a positive value on the screen. So this is positive. This is negative. If we hit Refresh over here, we can see, right when that starts, our character kinda falls to the floor, but the velocity is actually kept there. So that's, that's what we want to see. No matter how long it goes, it never goes faster than that terminal philosophy. Okay, so now we actually need to have some collisions between the player and the ground. So we can check our tile map for that. Let's go click on the tile map object, the pixel adventure to main.js file, which we saved to the project. And now we can open up our terrain. We can zoom in. And the problem is that we haven't set any collision tiles. So it's not too hard to do it, but it may be a little time-consuming. So let's click on our region over here. Once again, we already set up the BitMask so that we can draw it, but we have no collisions added. So the quickest, easiest way to just do collisions is to add in a new rectangle. You can see that this has hotkeys, so it's Shift R on the keyboard. So I found a good way to do this is to click on your tile, hit Shift R, click on the tile again, and then you have your collision square, which is basically the same shape and size of the tile itself. So we click on the second square for hit Shift R. We click on it again, and now we have a collision shape. So if the character bumps into this from any direction, it should stop it in its tracks. So let's just keep doing that. Click Shift, R, click, click shift, click. So you just keep going through and you run into an issue. You can just kinda manually click there, just make sure you get one collision on each one. If you see that after it was yellow, it becomes even more yellow. That might mean you made to collision shapes on top of it so you can just click them and delete them if that becomes a problem. So everything should have this same overlay of yellow. So let's just keep doing that. I'll just speed up the video. So if for some reason it's giving you a little issues, you can also manually click up here to create your next rectangle. So you can make it like click up there and then click down here. And then that'll give you the same results. But hopefully they're hotkeys will work for you as well. That is basically all of the collision shapes with exception of one. So if we zoom in here, we can see that these platform tiles we created only have a four pixel high platform. So it doesn't really make sense to have a character collide with it from underneath. Because that would mean it would bump it's head right around here where there's clearly nothing there. So when we add in the collision shape for these, you can see that I said the snapping to be four pixels by four pixels earlier. There is a reason for that and that is so that we can adjust these collision shapes to match these platforms. So when you're creating your collision shapes, you can check the snap options. Make sure step is four by four for these particular tiles. And now you can click on each of the corners and drag them up. So if we do that for each one there, now we have a collision shape that actually matches the artwork for this tile set. So we can basically just redo that for each of these. So just click on the four corners you need to adjust. And that's basically all there is to it. As long as you make this snapping four pixels by four pixels, it'll be really easy with this particular tire set, okay? And for right now, and that should be all the collisions we're going to need for our terrain tile set. So great. And now we can hit control S. And if we go back into the game, the collision should actually be working. So let's hit play our characters now going to be on the ground. So we can hit left and right for movement. And a character, it's just gonna kinda fall off the edge and then stops when he gets here. And once again, when he man's down here. Now, you can see a couple of issues. One is that it's a couple of pixels off the ground for the character. We just need to adjust the position of the collision shape in order for that to look correct. And then over here on the left you can see that they're y velocity keeps saying it is 300. I'm not technically correct. So let's hit stop here. Now we go into layer. We will open this up and what we need to do is that after we have the move and slide velocity, this actually returns a velocity after making collisions with the ground. So basically it, I'll take the y-value here and set it to 0 because there was a ground collisions. So basically it can't move anymore. So if we set the velocity values stored in this script to that velocity value returned by here. Then that will make it reset the y velocity to 0. And then that will set up here so that the next time it comes in here, we're going to be adding the gravity to 0. So that should be correct. And also, we really want to see the velocity after the movement, not before, before. When this is 0, it's going to add the gravity which will make it 50. But really after the actual movement is calculated, it's going to be moving at a speed of zeros so that it makes more sense to print it here. So let's go ahead and hit play and we can take a look at that. So you saw maybe that at the initial couple of frames, it was 50 was a 100 and then it was a 150 as it was accelerating towards the ground. But then after that it is 0 because we're on the ground. Keep an eye on the output and you might see it change again. So right there for a split second, it was accelerating towards the ground. And that is what we want to see. So let's go into the 2D view for our player. I can see that the collision shape is a little too low here, so we just need to adjust that. So I'm gonna go to collision 2D and then let's try making the position three. It does depend on the direction that you are facing, so it may be four here. And now let's go ahead and make sure that it is pixel perfect with the ground. So taking a look here, we can see that we have the ground pixels and then right above it is the character's outlined pixels. So that is what we're going to want to see here. And that's you want to actually cut off the outline here and just have the Greenberg being what's connecting with the ground. That's more of a stylistic choice, I think. So let's go ahead and hit stopped here. And actually when I take a look at it, we've basically covered everything for this video. So we have a camera set on top of our player. Our character can move left and right based on our input that we set up creating those custom actions. And gravity is working as well as the terminal velocities. So a decently functional platform, a character no jumping yet, but we will get to that. So if you've made it this far, you're already well on your way to having a functional platform or character. So that is really cool.
9. Jumping, Movement, and State Machines: So in this video we're gonna take our character and give him the ability to jump. So part of this is going to be setting up States. So for instance, if the characters on the ground, he should be able to jump. But once your character is jumping, the movement is going to work a little differently. So depending on where the character is and what buttons are pressed in each of those different modes that the character has for being able to interact with the game world is going to be called a state. So let's go ahead and dive into our player scene again. So here we can see we have the animated spray, the collision shape, but we don't actually have a way for us to change the animation yet. So, so currently, even though we can move around left and right when we go ahead and hit play. And we try to move left and right, we can see that the characters still just stays in the Idaho and he doesn't even face the correct way up. So we can correct that and then add in jumping us and other option. But first, before we dive into the scripting, let's add an animation players. So our animation player is one of the tools we can use for changing how the characters current animation is going to look like, which when we change the state and code, we can also update the animation player. So it's playing the right animation for the right state. So let's right-click on the player and add a child node. So we're looking for animation player, which is right down here conveniently, and let's go ahead and create that. And now when we click on Animation player, we can see there's this animation window down here at the bottom. So we want to create one animation for each of the animated sprite animations here. And so I think the way of doing this as a little bit cleaner when you use a sprite, not an animated sprite. But once again, because in our previous video we discovered that all of these different animations are separated into different image texture files. Animated sprite works better for this particular project. So how it works for animation player and an animation sprite is that we are going to go into this animation button and hit New. So we need to create one for each animation. Let's start with idle. Hit Enter, and now we need to add a track. So when we have these Animation Player Animation tracks, we can change different properties as the animation progresses. So I'm going to hit Add Track here, property. And now we can take any property from our scene and basically animate that. So let's change animated sprite. And we want to change the animation here. When we enter the idle animation on the animation player, we want to play the idle animation on the animated sprite. So I'm going to right-click here, insert a key. A key just being a moment in time when you change the value of something such as which animation is playing. And then over on the right with that key selected, we can change the value two. I don't, we're just kinda conveniently already on now because when it's in the animation state, we never want it to stop, although we may not technically needed now because when a character is idling, we wanted to keep continuing the animation. I think it makes sense to check animation looping here technically might not be required in this case, since this is only telling the animated sprite which animation to play. But the animators prays probably going to be looping either way. But if you were using a Sprite rather than an animated sprite, you would have to have that looping checked. So I think it's just better to have it there just in case. So let's also take the animation up here and create a new one. So let's also go up to the animation menu again and add and run animation. And let's add one for jump as well. And we'll work on the others later. But let's just do those for now. So r1 and we're going to add a track property, track animated sprite animation. And then on that first frame, we want to insert the key, make sure it's in the right position, all the way over here on the left. And we take the value and we change that to run. And of course this is going to be the jump animation. So in the bite, co-insurance that keyframe to jump. So we can make this stuff go a little bit faster if we actually duplicate our animations instead. So I will go to Animation duplicate, and then we can rename this to whatever we need. So let's see another animation. We probably are going to setup it. Let's just rename this to head. And now we don't need to check looping. We don't need to create a keyframe. We just need to change the value here to hit animation and we're good there. So that should be enough for right now. Let's go ahead and dive into the code. So we're going to need an e num variable up here at the top. So I'm going to type in enums and we can give it an optional name, so I will call it enum state. And then in, I believe it's the curly brackets here, we want to put in Idle, run and jump. So what the enol basically does is it translates a human-readable ward, such as Idle run or jump into a integer value that is going to be associated with that. So basically you can think of it like a position in an array. The EIDL is the first one here, so that is going to be represented as a 0. When the game is actually running and R1 is going to be a one and jump is going to be a two. But when we're typing out a code, we don't need to use that 012. We just can use state dot AIDL to reference that position within the states. So it makes it easier to understand what is trying to go where when you came to troubleshooting your code. So along with this, we're going to need a variable for the current state. So I will put var current underscores state, and we can just default this to state dot AIDL. So really this is just going to be a 0, but that 0 specifically is referencing the 0 position within this enough. So just keep that in mind. The next thing we're going to want to do is have a way for determining what the next state is going to be for our character as we press buttons or move off the edge or so on and so forth, we want to basically figure out where the character is in the game and what actions should be available to it. So we're going to create a new function after the move and slide runs. And we're going to call it pick next state. So we can just hit Enter a few lines and create this function, function pick next state. And so one of the first conditions for determining the story is going to be whether the characters on the floor or not. Some of the characters in the air than it should be in some kind of jump or falling state. You can even makes up receipts for that if you have a reason to. For this character, I believe we're just going to have one air state, which is going to be that Jumps state. But on the ground, our character can be idling, or it can also be running depending on if there's any horizontal movement and off. So let's check the main condition first, which is going to be, is it on the floor? So this is a kinematic body 2D script, which means we have access to a function that is called is on floor. So basically, this script already knows how to check if there is ground directly underneath. Basically if our kinematic body is colliding with another thing underneath it by checking our collision shape versus collision shapes if other things like the ground terrain tiles. So if that's the case, if there is in fact ground directly beneath our character, we want to end being in any kind of jumps state. And that's going to mean we're going to want to reset the jump so our character can jump again later on. So I'm going to set jumps equal to 0. So for our character will have the ability to jump one or more times. And this will represent the number of times that the character has jumped since hitting the ground last. So let's actually create that variable up here and advance so far jumps. And that's going to default to 0. Since presumably at the start of the game, we want to give our character the ability to jump. Jumps goes to 0. Anytime we're on the ground, we need to determine if we're going to enter a jump state, a run state, or an idle state. So we want to go into a jump state if we press the jump button while we're on the floor. So we can check if the jump and port this pressed. So if input dot is action just pressed, and then we're going to look for jump, which I don't think we've actually created as an action yet. So I will go ahead and do that right after this line. And then we also need to check if jumps is equal to 0. So if jump is pressed while the character is on the ground. So let's set up that jump actions. So project, Project Settings, Input map, come down here to the bottom. Let's add the action Jump. Keep in mind your capitalisation. It should be the same as the string that you're using inside of the script. So let's add a key. I'll just make the space bar licensable, hit Close. And now we have a jump action which can be checked with this input manager. So then we need to set the current state, or more specifically, state dot jump. So when we add this self bit to the current state, we can be sure that we're referencing the current state of this object up here. So when we add this self here, we can be certain that this is going to refer to the current state that is specifically attached to this kinematic body up here. So that is going to mean self dot current state, which is right here, which is what we want. So we're setting that to state dot jump and we have other states we need to work on. So we can also put an else if as an if the first condition isn't met, then this is our alternative. And we want to see if the character is moving horizontally. So that can be either positive or a negative x basically, as long as it's not 0, we could put in absolute velocity is greater than 0. Another way you can pretty much write the same thing would just be velocity does not equal 0. However you want to write it kinda the same thing. And let's add self dot current state is equal to state dot on. So if the character is not jumping, but he is moving, then he should be in the run state. The last one that we're going to have for right now, it's just going to be state DOT I also, if those other conditions aren't met but the characters on the ground, then it's going to be idling. So if you're not moving, you're idling. And we won't do this yet. But I am going to add a little message to write this later. So if it's not on the floor, then we may want to have a double jump down here. So in the air basically we can also do a Double Jump Cannon move. So I'm going to say to do double jump. And I'm just going to pass here passes and basically just continue with the program. And there's no code here, so we're just skipping over it. So next I want to create a set function for our current state. So when we change the state from, let's say idle to jump, we want certain actions to take place. Namely, we want to add some upwards movement for our character when it enters the Jumps state. To represent the jumping in the game, the character should move up. So we can have a set function mean that when we change the current state, we can have certain state interests actions occur. So up here at current state, I'm going to add onto the end set GET. And then we're going to call it current state, just standard naming convention. Another idea I had in mind, I'm not gonna do it, but you could also call it interstate. I think that also could make sense. But we'll go down here and write our setter function down here at the bottom. I'm actually just going to put a hashtag, setters can a header here in case we have other variables with setters later on, just kinda keep them contained in the same area. So let's do function set current state, and this is going to have a value, basically the new state where entering. So I'm going to write new underscore state, just keeping it as straightforward as possible. So if when we set the current state, the new state is a jump state, then we want to have the character jump moving upwards on the screen. So I'm going to use the match function on the new state value and check if that state coming in is the jump state. So we can use down here as the second line state dot jump. So this is the value we're matching. So if the value passed is state dot jump, then we're going to want to jump. So this is a function we haven't written here as well. And finally, we want to set the current state to the new value being passed in. So if you don't have a custom set of function created, basically if you change the value, it would just be exactly like this current state equals new state and nothing else but the setter allows you to add an extra code that will occur when that value is being changed. So now we need a jump function. So this will be really simple and straightforward. Going to go here, write another function, function jump and semicolon. Now, what we need to do is change the y velocity of this character and add in a jump impulse value. Basically the amount of movement we want to add upwards on the screen for the character to move. And this should be an immediate boost. So much in acceleration over time, or at least it'll be like that for this character. If it was an acceleration, that would be more like a jetpack. So let's do a velocity dot y. And this is referencing the same velocity up here, since there's no velocity variable specified in this function, it's going to default to the one of this script. So the velocity y. And we're going to set that immediately to a new value we're going to create. And I'm just going to call it jump impulse and restarting that to a negative value because we want it to move up on the screen. So this is just going to be the amount and this is going to be the direction. Negative. Value means move up on the screen and we jump. We're also going to want to increase the jump counter. So jump plus equals 1. So this is important in case we want to add double jumps, which we will be doing later. So let's create that jump impulse variable. And I'll put it up here at the top because this is something we might want to change. So it's going to be an export, float, var, and jump impulse. So different characters are going to jump different amounts. So we can set this to a nice and high value like 600. So keep in mind after the initial speed, this is going to be decreasing on every frame by this gravity until it reaches the terminal velocity or the character hits the floor. It's only going to move this fast initially, and then it's going to slow down and then eventually go back towards the earth. Okay, this should be jumps down here, not jump. And now if we hit Play, our characters should be able to jump on the screen. The animations won't change yet. So when we go into the game and we tried to hit space, nothing actually happens. Even if we fall off the edge, we can clearly see the character is on the ground, but it's actually not registering the characters on the ground. And the reason for that is there is an extra argument we can pass to this movement slide, which is the direction of up. So in a 2D game, we can just easily do that by doing comma and then a vector two. So this is going to mean that upwards on this screen is going to be our AP direction. And now that that's set, moving slide can set the values for is on floor, is on ceiling and is on walls because it knows what direction the walls, the ceiling and the floor is now. So let's go ahead and re-enter the game. And now we can hit space. The breakpoint hits for state jump. So let's continue that. And if we go back in there, we can see the jump is working nicely. We can also see that the characters jump is fast initially, but as it gets to that highest point, is slows down and then we accelerate back downwards. And that's what you want from a standard platform or jump.
10. Animation Tree and Switching Animations: Okay, the next thing we're going to want to take care of is setting parameters in an animation tree so that we can actually have this animation player switch to the correct animations depending on the values we set for that animation trees. So basically we need to tell the tree whether the character is moving left and right or jumping into the air. And then let that tree figure out what animation state to put the animation player n. So we have the actual code for controlling how the character can move. But we also need to have the animation player and animation tree side of things for controlling and how it represents those graphics to the player, but basically changing the animation. So let's add a animation tree. I'm going to right-click on the root node at a child animation tree. And this animation tree needs to Animation player. So let's assign our animation player to the animation tree. And now we also need a tree root. So there's different ways of setting this up. But I think for our project using a animation node blend tree as the root tree node is going to work out. Alright, so that's what I'm going to go with for now. So we can see in the blend tree that we have an output. So we need to determine how we're going to get to that output and which of the animations is going to be the current output for our animation player to use. So in our blend tree, the first node I'm going to add n is going to be any right-clicked, by the way, to add nodes, I'm going to go down to blend space 1D. So with that blend space 1D, we're basically working with one parameter as a input. And we're going to tell the animation tree about the parameter value and the player script. But we can see those parameters if we click on the animation tree again. And you come down here and the inspector, you can see perimeters blend space 1D. That's actually the name of our parameter right here. And the value. So this is the blend position. And you can set that with parameters slash name of the parameter and then slash blend possession. So in our case we're going to be setting it to negative 101. It pixel art game. You're not going to blend together animations like you would with a 3D model. So we only want those three values. And we can also give it a better name for this. So I could call this value x move or x sine, sine representing the direction either a one or 0 or a negative one for our character's movement. And by taking that into the editor here, we're able to determine whether it should show idle or Vaughn. So let's open the editor here and then we're going to add in points in here. So I'm going to hit Create points over here on the left and then left click in the middle, add animation idle. So if the value of x move is set to 0, That's going to make it idle. So let's click over here on the right ad animation run. So we can see looking at the graph that this is set with a value of one over here on the right. The EIDL is 0 and then negative 1. We also want to make Run animation. So it's still going to be running. It's just going to be doing it in reverse direction. So we want it to play the run animation. So we can come out here to the root. And I'm going to connect this to the output. Now, all we need to do is set this parameter in the code. And the animation tree will be able to tell the animation player whether to run or whether to idle for the animation. So let's click on the animation tree. The parameter we need to set once again is this x moves. So if we hover over blend position, we can see the full path to it is perimeter slash x underscore move slash blend underscore position. So if we go to the player script now, then after the velocity is set, removing slide, we're going to want to set some animation parameters. So I'll create an appropriately named function set n m parameters. And we can kind of come down here. I'll just actually enter a couple of lines and we'll write it right below this physics process. So function set and m parameters. So for this we're going to need to reference the velocity. But once again, we can see that the velocity is always being set up here at the top. So we don't really need to make it a parameter inside of this function, we can just reference that directly. But what we do need right now still is a reference to the animation tree. So if you want to take one of the nodes that is inside of your scene hierarchy and reference it really easily inside of your script. Then what you can do is come up here. Let's go above the velocity. So now up here we need to write in unready. And what this means is that when the script starts, we need to do something. But we are putting the on ready with a variable. So when the script starts, we're doing something with this variable. And the variable is going to be animation underscore tree. So that's the variable name. But what we actually want here is a reference to the animation tree node. And the way we do that is we hit equals and then we put dollar sign animation tree. So this is going to look in our scene hierarchy and then try to find the node called an animation tree. And then when the script starts, it's going to take that node and assign it here. And with the unready, this gets assigned once the script starts. So now that we have the animation tree, we can set parameters on the animation tree in our set and m parameters function. So I'm going to do animation underscore treat dot set because we're setting a parameter. And now we need the path to the parameter inside of that node. So we want parameters slash the name of the parameter, which I believe was called X move, and then slash blend position. And what we want to set there is going to be the sign of the velocity. So it's either going to be 10 or negative one and no other values. Since we're not trying to actually blend, That's the values we want to use. So it's 100%, either idle or 100% run and not trying to do anything weird. So let's get the sign of the x velocity and that's basically that value. And later we'll have more anime parameters, but that's all we need since we're just doing the x movement. So let's go ahead and hit play and we can move left and right. It's not quite working yet. And I think that's because the animation tree isn't actually activate. So free check active the animation tree. Now it's going to show the idle animation. Okay, we can also see it switches into the move animation, but only after a second has occurred. So what's going on there is that if we jump into the Animation player and look at these animations, that they are only updating once a second. So the foie animation needs to occur currently in order for it to switch between animations. So for us, that's a pretty easy fix. We can just take the time of each of the animations and set them to ¢0.05. All this is actually doing is making sure that it's in the right animation, playing on the animation sprite. So the duration doesn't really matter here, 0.05 for the idle animation, the jump animation. So print 05 and let's make sure that R1 is there two. So 0.05, let's go ahead and hit play. So now we can move around in our game. And when we move, instantly switches to that mood state. And when we start moving, it instantly moves back to the idle state almost instantly anyway, take 0.05 seconds at most, so that pretty much will work just fine. Now we also saw that the character can move left and right, but it doesn't adjust the direction it's facing based on if it's moving left and right. So we need one more function up here called adjust flip direction. And in that going to take the input variables. So this is that import from right down here. Okay, we can actually stop the game so it doesn't hit breakpoints. So we need to write the code for just flip direction. I will add another function down here. So function adjust flip direction. It's going to take one parameter and I'm going to specify that that should be a factor two. So a semicolon vector 2 and then finish up that line with another semicolon. So what we're going to be checking in here is basically the sign of the input. Now we could also check the sign of the characters current velocity. But I want the character to face the direction where the player is trying to move in, not necessarily that direction that the characters current velocity is headed. Now, for this character, if we're just moving instantly 200 to the left or to a 100 to the right, the move speed, and there's nothing else acting on it. There won't be any functional difference there, but some characters might have acceleration, whether it be accelerating towards the right because you're holding rate down. But it hasn't actually changed the velocity direction from left to right because it has an accelerated long enough Or it to actually change directions and which way it's heading on the screen. So anyway, we're going to use if sine of input X is equal to 1, basically meaning that the value is positive towards the right direction, then the animated sprite is not going to flip its direction. So animated sprite dot flip H for horizontal is false. Our default direction is going to be false and you can always change this. You could also have a default facing variable if you wanted to be a little bit more flexible. But we're just going to assume here that we're making our character's face right by default. So this looks correct. And our alternative is else, if this sign import that x is equal to negative one as the character is pressing to the left, then the animated sprite should look to face the left direction. No, no, I don't have a else. If the sine is 0 here because if there's 0, there's no input. And if there's no input, I don't want to change what direction it's facing. It should just face where it was facing. Before the last time we let go of the keyboard. And we'll actually missing this animated sprite variables. So we need another on ready var up here. So just like with the animation tree that animated sprite is nested in our hierarchy for the scene. So unready var, animated underscore, spray equals dollar sign, animated sprite. And that's all we need to do to get referenced to this. Note that when you do things this way, you should keep the name the same or else I think you can run into problems there. But if this is the name of the node, it's going to reference that just fine as long as that node is contained in this hierarchy. So now that should solve that problem. Let's go ahead and hit Play and our character will now face the correct direction. We can also jump. And while we're jumping, the character can face the right direction. But it's not playing the animation for that yet. So that'll be something we set up in the next video as we walk on our animation tree and adjust, our state's a little bit more.
11. Jump & Fall Animations Setup in Animation Tree: So next we need to set up the animation tree so that we can support changing into the jump animation. So let's dive back into the player sing. I'll click right up here. And let's click on the player tree. So we can see currently that we only have one linspace one-dimension, which is taking that x move parameter in order to go between idle and run. But we want to have a case where the character is in the air. And then if it's in the air, we should switch between rising and falling states depending on the direction of the y velocity. So we can take the output from this one-dimension, and then we can right-click over here and create a blend three. So the blend three allows you to have three inputs. So we can have a negative blend value. We can have the standard input default, which in this case it's going to be our x move. So I'll just disconnected there and connect it right in here. And then we have the positive blend value case. So I'll go ahead and call this something like y underscore sign. You could also call it y underscore velocity. But really we're going to have three values here at negative 101. So if we have the negative blend value, that means that the character is going up on the screen since negative is up on the y-axis. And that's going to mean we want the jump animation. So I can right-click over here at an animation. And we can just select jump from the list and feed that into the negative blend. Then the same thing. If we have a positive blend characters moving down on the screen. So we want to use the falling animation. So right-click animation, switch to fall, which apparently hasn't been created yet. So let's go ahead and switch into animation player here and create another animation. So I'll just take this idol and duplicate it. So now we have idle copy. I'm going to rename this to be fall as the animation. And we'll just take this animation thing, change the value from idle to the fall animation. So because we duplicated the animation, we already have the time of the animation set to 0.05 seconds and on repeat. So that may be all we need there. So back in animation tree, we can select the flower animation. Maybe we actually need to recreate the animation box. So I'm going to right-click Add animation. And hopefully this time it shows up here. So we have the fall animation and we want to connect this to positive blend value. So now I have three possibilities are a jump, allowing the blend space to pick our animation based on the x move or having fall as the other animation. So let's connect this to output here. And let's move this slider value around. So we can see at plus one, it's a falling animation, negative one, we have the jump animation. And at 0, it's going to default to whatever the output from linspace 1D is over here. So now we need to do one more thing which is to set this y sine value and code. So if we click on animation tree, we can expand the perimeters and we can see the path to this y sine. So it's going to be pretty much just like the x move and just parameters slash the name of the variable as he typed it in here. So y underscore sign and then finally slash blend amount. Note that for the blend space 1D, the final part of this parameter was blend position. But for this blend three, it's actually blend amount. So you do have to be careful there. Okay, so let's go back into the code and we have our animation parameters function here. Let's just add another bit here. So animation tree dot set parameters and we want y sine slash blend underscore amount. And the value we're going to do for that is just sine velocity dot y. I'll go ahead and save it. For the sake of consistency, I guess I'll just take the x move and I'll rename that to be x sine as well. And then in the animation tree, let's just make sure that this parameter is called x sine. So if you change it in one place, make sure you change it and the other as well. And now we can go ahead and relaunch the game and see if the animations play correctly. So let's go ahead and hit play. Okay, and that's it. Jump. Okay. So it switches to the jump animation and when it falls, it has the fall animation. So our character is moving left and right and jumping and falling just fine.
12. Signals and Player State Debugging Label: Okay, the next thing I want to set up is a label that we can have display above our character for debugging purposes in order to know kinda what state or animation the character is at any given time. So on our character object, I'm going to right-click and add a child node. And then this is going to be a label node, which is technically a control node, but you can put it control node on top of a 2D node like a kinematic body 2D if you want. Otherwise, generally controller nodes would go on the Canvas, which is kind of your UI. So I'm going to click on label here, and I'm going to position this label somewhere above our player. So let's just kind of move this up here. And because it's a child of the player, should move along with the player. So maybe for the label default, I can just write none here or something. And then we'll take the alignment for the text and center it just so it looks a little bit nicer there. So what we can do with this label in order to have it show the current state that the player is and is to create a signal. So in sight of the player script will create a signal here. So under set current state, whenever a new status set, we're going to create a way to tell it the label that the new state has been set. So one way would be to just directly access the label up here, like he did with this, and then just do label dot text equals whatever the new value is. But another way is to create a signal. So as signal basically sends out a message and anything that is attached to that signal will be able to respond to it in some way. So rather than the label or the kinematic body player needing to directly know about each other. The label just needs to have, the label just needs to have a response function to the signal being emitted from the player, but it doesn't need to know anything about the player directly. So in a sense that kind of decouples your code between your objects. And then the connection point is the signal itself, which you can connect to buy code. And you can also connect to pretty easily by clicking on the object going to node. And then you can see a bunch of signals here that you can respond to. So when we create a signal and the player script, it'll show up over here. And then we can double-click and the notes section and just tell any other object that we want to respond to the signals emission to have a function, to do something with the data when that signal is emitted. So let me go ahead and set it up and hopefully it'll make sense after that. So let me dive into the code here. So up here at the top, we'll create a signal for this player class to emit whenever we want to emit it inside of the script. So I'll add a couple of spaces here. I'll type in signal and I guess I'll call it changed state. And then this is going to have a value for any other scripts like the label script to respond to. So I'm going to call it a new state. And that's pretty much it for setting up this signal. Now we just need to emit this signal. So down here at the bottom, and we're going to emit a new signal whenever the state changes. So emit signal. And then we put the name of the signal. So changed state. We can see that up here. And then there are some other default signals, I guess for this class. But we're going to use the custom one we just created. And then we need the parameters. So I am going to put in the new state. And then we can save our script. That's pretty much it. Now if we click on our player and we go to the notes section in the top-right and extra inspector, we can see this player dot G, D has a new signal. And then we can double-click on this in order to connect to the signal. So clicking on the player, we can now go over to node and double-click on where it says changed state here, the new signal we just created. Now we pick a script to connect it to. And it's going to create a receiver methods. So the player emits the signal with some parameter values, and then the state label has a receiver method in order to respond to that. So let's click on state label connected. And now we have this function on player changed state. So whenever the player changes its state, we want to set the text of this label. So I could just do self dot text. And so with the text of the label, we can set the new state there. So I'm going to do string of the new state. So whatever value gets passed here, we just want to convert it to a string if it's not a string already, and set that as the text. So let's go back to our game and go ahead and hit play and see if that signal is working. Okay, we gotta get that S. So let's try that again. So if we go ahead and hit Play, we can see the enums being represented as the integer value. So 0 for idle 14 running around and then two for jumping. So technically it's working just fine. But here it might be more useful to show the name of the enums. So instead of saying 0 for idle, we just have idle represented at the top there. So if we go back over to the player class, when we emit the signal, rather than emitting this new state as an integer, we can have the string value get pushed as well. So in order to do that, we're going to go up here at the top. And for this changed state, I'm actually going to have two parameters being passed. So the first one is new states during and then the second one, which is the current one, could just be new state ID or a new state integer, something along those lines. So now down here at the bottom, we're still going to pass the new state, which is the integer value. But we're also going to access the string name of the state and pass that as well. So we can do that by accessing the name of this state. So this is a dictionary and we can just do state dot keys. And now we need to pass the array position, which is going to be wherever we find new state. So if we do that and we save, this should now pass with two arguments to the state label. So that's going there. And we could reconnect this function if we wanted. I think we might just be able to get away with retyping the parameters. So new state ID and then new state string. And we're just going to take this value and set that to be the new text. So now our signal is going to give us two parameters to work with. And we only care about the string because that's what we want to show above the player for debugging purposes. So let's go ahead and see if that actually works. I'm going to hit play. And now we get into the game. Okay, we have idle, idle run and jump. So that should be a lot more helpful than just having a 0 or one or two appear above the play.
13. Follow Camera: So now that our character can move for the most part, one of the things we're going to want to add is going to be a following camera. So currently, the camera we set up is just aimed at this one area and it's static. So if we hit play, it's not going to follow our character at all. So a character can run off the screen. And that could be a problem if we get to this part where we can't see our player anymore. Now, in some cases, you may want to have a static camera depending on the style of your game or this specific scene. So you can actually switch between different static cameras if you just wanted to move from screen to screen, kind of like as individual stages. But if you do want to have a follow camera, let me show you how to do it. So we have our level and then the player down here. And we need to add a remote transform to the player in order for the camera 2D to track. So if I right-click on player and add a child node, we can look for that remote transform node, just type in REM. And here we have remote transform 2D. So I'm going to add that in. And now this remote transform 2D note has a property called remote path. So basically, the remote path tells a different object to look at this transform for tracking it. In this case, that's going to be the cameras. So let's assign the camera 2D. And that will basically be all we have to do to make sure the camera follows this remote transform around. And by default the smoothing is an on. I'll toggle that off right now and hit play. So if you don't have Smoothing, then the camera is going to basically perfectly follow your character amount. And there won't be any lag between the characters movement and the camera. So in some circumstances might want there to be a little bit of a following lag. So you can check enabled here. And the less lag you want, the more speed you're going to increase. So if you want it to be very slow at following the player around, then you would want a lower speed. This defaults to five. So let's go ahead and test it with 10. So let's hit Play and move around. And you can see a lot of Jenkins, Yes, right? So one setting that we can use that will help correct that a lot is the GPU pixel snapping. So if we go into the project menu top-left and then project settings, we can search for pixel snapping and I believe it's under Rendering 2D. So we can just check this on. And that will fix a lot of our display problems. So I'll close that and let's go ahead and hit play again. And this time, when we move around the screen, it looks much, much better. So once again, if that following is too fast, you can try lowering the speed down. So five is the default. Let's show what that looks like. And here he basically out of that. So if I stop moving, you can definitely see the lag there. So it's kinda up to you what your personal preferences are going to be for your game style. Let's go ahead and close that out there. And I guess for right now I'm just going to put it back to 10. So that's basically all you need, just a remote transform and tell the camera to look at it. And you're basically be good to go for our follow camera and get o.
14. Double Jumping State Code: Hey, so currently our character can move around the screen, it can jump. But what we might want to do is add a little bit of extra functionality to our character. So in order to let them move around the level a little bit easier, Let's go ahead and add in double jumping. So I'm going to exit the play mode and let's go into the script for our character. So inside of this script, we can set up a new state and have it switched to that with pick next state just like before. So what we're basically going to do is if the input is pressed, we're going to jump. But in this case it's going to be a double jump because the character is already in the air. So that is going to, so for our pick next state, it's going to be similar to right here, where if jump is pressed, we entered jump, but we're going to be checking when the characters and the air, and if the character is in the air and repressed jump, then we're going to do a double jump only as long as the character hasn't hit its max jumps. So it is on floor is set to false means it's going to come down here. So we can just set up the if input is action just pressed. And then we look for jump. And now we're going to switch to the double jump state, which we haven't created yet. So state dot-dot-dot jump, double underscore jump. And I'll scroll up here to the top and we'll just add that to our list of states. So double jump. So what do we want to happen when the jump is pressed? Well, we want it to jump just like we did with the regular Jumps state. We also want it to jump when we do a double jump. Now this could be exactly like the first jump where we just do the negative jump impulse. Or you can have a separate function for a double jump. And maybe that has a different jump impulse value. For right now, I'll just set it up down here to just do a normal jump in terms of its movement. So how we can add double jump to this little match statement here is we just put a comma and then we do state dot double jump. And I think we can have a space there as well. Hit Save. So now if the state is jump or double jump, we're going to run the jump function. So you can just have like a list of different states do want to match certain actions to. Now of course, this only matches the movement of it. We'll still need to set up the animation tree for the switching to the double jump animation. But one other condition I want to add to this is action just pressed is to see if the jumps are above the maximum number of jumps. Because our character probably can jump two times, but usually not more than that. So we can have a max jumps variable, could set it to two or three however many you want. But if we don't have that set, the character will just be able to keep jumping forever. So we can actually just show that in play. I'll go ahead and hit the play button. And let's start jumping. So I can just keep spamming the jump button and just go way above the level. Generally speaking, that would be groundbreaking. So let's go ahead and close out of that and have a max jumps variable up here. So I'm gonna do export integer var max jumps, and I'm gonna default that to two. Then whenever we run into this situation where we could do it jump, we make sure that it hasn't already reached this amount of max jumps. So that's going to be down here. When we're considering doing a double jump. We want the end condition that jumps is less than or equal to max jumps. And as we know, whenever we run the jump function that's going to increment. So we hit Jump once to get into the air and it should go to one. We do the double jump and it should get to two. And you shouldn't be able to make any more jumps until we hit the ground and then is on floor is true, and jumps gets set to 0. So let's go ahead and hit play and while on the ground so I can jump once and I can hit spacebar twice to double jump. Okay, looks like we can still jump forever. So let's take a look at that. So I think I'll just debug it by printing the number of jumps to the console. Log down here, the output. And let's see what happens when we hit play and then we keep hitting the jump button. So 23. Okay, looks like we can go to three, but not higher than that. So, yeah, this should actually be less than the number of max jumps. And now the character should only be able to jump twice. So let's replay the game 12, okay, 123, nope, doesn't work. Okay, so we can only do two jumps. We have double jumping, but it doesn't go more than that.
15. Setup Double Jump Oneshot in Animation Tree and Code: So the next thing we need to do is to set up the double jump animation to work with the animation trick. So if we take a look at the animated sprite in the player scene, we can see taking a look at these animations that the double jumping animation here is a somersault. So I'm going to say that the character should only do one somersault whenever we hit the spacebar to do a double jump. So therefore, this is going to be kinda more what we would call a one-shot animation. And we can set that up quite easily in the animation tree as well. So at one shot is going to play once and then it's going to resume other animations depending on other parameters that we have set. So this one shot is going to take priority over the standard jump, fall, idle and run animations. So if we right-click on the node graph here, we can add a one-shot. So you'll see that it has two ports. One for the one shot in one four-year standard input. So I'm gonna take this connector between the blend three and our output. Then I'm going to redirect that into the input. And then the one shot is going to connect to the output. So this is going to mean that they're one-shot takes priority over anything else over here. If the one-shot is active and we know it's active because of this little Boolean parameter that we can set when this is on, we want it to play the double jump animation. So I'm going to right-click on the node graph, go to animation. And then here, Let's select the double jump animation, connect that into the one shot, and let's just rename the parameter that this one shot is going to use. So if you click on animation tree, we can see the one-shot perimeter here. And let's give it a name that is more specific. So I'll just call it double underscore jump. I think that's about as clear as it can make it. And if we hover over active, we can see that the full path to this parameter is perimeters slash double underscore jump slash active. So we're going to need to set that encode in a minute. But before we do that, when we have a one-shot node, there's two properties that we should change. So that's Baden time and fade out time. So for our pixel art animation, we don't want there to be a time delay between entering a animation and actually starting the play it. So we wanna take these and set it to 0 for both of them. So when the one-shot is active, switching over should be immediate. Okay, so now we can jump over to the code. So let's take a look at this. We are going to like before we need to use the animation tree and set a parameter. But this set and m parameters function is being run every physics Process Update. So that would be a set number of times per second. But the thing is, we only actually need to set that animation parameter to true, specifically when we are doing double jumps. So it would be very redundant to put it in here and do some kind of check and then set it to active or false on every single second. So let's actually come down here to the bottom. And a much better place would be to put it in the center. So when we enter a new state with set current state, we can have that parameter B sat when we enter the double jump state. So if you haven't already separated your state dot jump and state dot double jump matching. You can do that now. So I'm going to put a colon here. And we're gonna take state double jump. And I'm gonna move that down below. So this is now going to be its own separate thing. State dot-dot-dot jump colon. And of course we're still going to want it to do that jump, the function of the jump. But we're also going to want to take the animation tree and set the parameter. So the perimeters name was parameters slash double underscore jump slash active. And because we just enter double jump, want to set that to true. So this basically tells the animation tree K. Play the one shot. We're going to do the double jump somersault because we're now in the double jump state. So the last thing we need to do is to figure out how to exit this one shot. So the script is going to set this to true, but we also need to set it to off so it can go play the other animations after it's done. So we can do that in the animation player. And if you find the double jump animation, it should be set to 0.3 seconds. So it's playing six frames at 20 frames per seconds. So we make the animation 0.3 seconds long. And we also want to turn off animation looping if that's on over here on the right, because this is only supposed to play once and then Finish. Now we can zoom in a bit here and we're going to want to add another track. We're going to set the parameter on the animation tree for the one-shot to false when this animation is finished. And of course this multiple ways you could do that. You could do that in the code here as well. But this seems more convenient to me. So I'm going to add track, property, track, animation tree, choose the perimeter. Perimeter is double jump active. And now we need to set a keyframe for that. So over here at 0.3 seconds when this animation is done, right-click Insert key, and it's already going to default to off. So basically, at this point in time, it's taking the perimeter, the double jump active, and setting that to false, indicating that the animation is done. So after that, there's one shot will be false and it will resume going back to the blend three to pick what should be the output. So if all goes well, that should be all we actually need to do to set up this one shot. Let's hit Play and see where we're at. Okay, animations to working with jump and there's our double jump working really nicely. One thing to note, the way the current code is written, a player can jump up to two times before it touches the ground. So if you actually fall off here, that doesn't count as a jump. So if I fall off and do a double jump, we can actually do to double jumps in the air. Of course, it's only going to play once if the first double jump is still running. Let's see. Okay, But yeah, if the animation is finished and you do that second arrow jump, then it will do that second animation there. So just something to think about. You may want your character to be able to do that where regardless of how it gotten in the air, you jumped twice or you might want it to be limited that a character can only do one double jump in the air, period regardless of if it fell off the edge or jumped into the air. In which case you could set up a variable like has double jump occurred. And if that's false, then allow the double jump. And once you enter double jump, set it to true and only reset that when the, when the character hits the ground. Otherwise, you might actually like it when you character can jump twice regardless, it might make sense for some games. So just something to think about, but pretty much for this video, getting the animation to play as a one-shot seems to be working. So I guess we're good here.
16. Waypoint Pathing for Angry Pig Enemy: Next, let's create a enemy for our platformer game. So we're going to use the art for angry pig for this. And I'm going to open up art, pixel adventure to enemies. And there we have our different character sprites. So we can click on any of those and see basically a preview of the different animations over on the top right. So to create our new enemy, it's going to be kind of similar to creating our player objects. So we need to create a new scene. And the root of that scene is of course going to be a kinematic body 2D. Meaning that how it moves is going to be something we have to write in setup for ourselves in a script. So let's go to scene and new scene. And then for here, Let's other node and then kinematic body 2D. So for this kinematic body, Let's double-click it. And we can see it's basically centered at the scene view at position 0, x and 0 y. That's what we want. And let's add a animated sprite to it. So add child node and then animated sprite. And once again, the reason we're using animated sprites is because for the SART pack, all of the animations are broken into their own individual straight textures. So animated sprites allow us to use separate textures for different animations. Much easier than it would be with a sprite node. Let's take the animated sprite and I will create some animations for it. Let's go to the right side. So frames or hit on the empty button and click New sprite frames. Let's open that up. And then we have our animations window down here at the bottom, gonna default everything to 20 FPS. And let's rename the first animation to idle. So we'll click on this button over here that looks like a grid to I add frames from sprite sheet and we'll go into art, pixel adventure to enemies, angry pig, and an idle. So we can just kinda quickly count how many frames are in here. Got nine. So nine for horizontal, vertical, and then on the right side, select Clear all frames, add frames. And if we have playing, we should be able to see our little idle animation there. So now we just need to repeat that for the other animations. So let's add a run animation. And run will take, of course, the run frames. So let's see 3, 6, 9, 12. So 12 horizontal, one vertical. Select all add and make this bead 20 FPS. So let's add that from the character. This looks like about 16 by one, or select all add them. And we can just test that it's working by having an autoplay on that animation. Just making sure that everything seems centered correctly. So it should be pretty obvious. Okay, next, let's add hit one and hit 2 for when the enemy takes damage. And that looks like five frames. Select Clear all. And then we need to do 20 FPS. Okay, it looks like I messed up adding it. So let's delete all the frames and make sure it's hit one by a horizontal, one vertical, and add those in. Okay, that's what we should be seeing. Now let's add in two. So I'm going to add the same thing by frames. So five horizontal, one vertical, add them and it makes sure that FPS is 20. So we can go between our different animations and everything should be playing smoothly. So the next thing we're going to need to do is determine how this character is going to move. So my idea for this angry pig and what's actually rename it there and save it as a new scene. So angry pig, or save it into characters because we can create a enemies folder here just in case we end up with a lot. And then angry pig seen more, save it in there. So my concept for this pig character is going to be that by default it's going to walk between two different waypoints research, so it can only move left and right. No vertical movement, at least without gravity. And if a player is detected, then instead of walking, it's going to change to a angry runs. So we put that on run later on, increase the character's movement speed. And if the enemy here runs into the player, then the player will take some damage. And that'll basically be the habits for the angry pigs. So a really simple enemy here. So I'm going to put the default state back in idle. And we can add a script to this character. So I'll just right-click Attached script, and this will be called Angry pig dot h gd. So for right now, this will just extend kinematic body 2D. In the future, we might want to use inheritance to have a base enemy script, and then other enemies can inherit from that and basically gain some of the basic functionality. So we don't need to write it on every enemy. But for right now we'll just put everything in the angry pig. And then if we need to take it into a higher level enemy class later, then we'll do that separately in a different video. So right now for the movement I talked about, we're going to have to set up some kind of way point for our character. So if you haven't already, Let's go ahead and save the scene as a senior and Enemies folder. So I'm going to go up here, Save Scene As. And I'm putting it in characters, enemies, as you can see here. Also, make sure that you have your script saved to the same folder for organization reasons. And now let's go to level 1. And I'm just going to drop a copy of the enemy into here. So in order to have our character move, we're going to have to give it some waypoints in order to move towards. So there's a few ways we could do this. I think what might make sense is to set up some waypoints within this level that our enemies can use as a point to move towards and then assign it as a list. Whenever we create an instance of our object, we just be able to assign them over here in an array for what position should have moved towards. So in the level I'm going to right-click up here and I'm going to add a new node. So we'll start with the node 2D as apparent, because we do want this list of waypoints to move along with the level if we ever move to the levels position for any reason. So I'm going to call this waypoints. And then underway points, we're going to add some position two d's. So for these, I guess I can just rename them waypoint one and then duplicate them a few times and we'll just get waypoint 1, 2, 3, so on and so forth. And he had just make sure as you're dragging them around, but they aren't children of each other, so they should be their own thing. And then we can set up the location for these waypoints when we're looking at this stack of objects and we want to make sure that we're moving the one we have selected. You can hold Alt down. And then that'll make sure that waypoint one gets elected and moved because we have waypoint one up here. So if we hold Alt down, we grab the right one. Let's add a waypoint. Let's just say right about there. And then let's go waypoint 2. And we'll just drag this out of the stack two right there. So our character will be able to pace back and forth between there and there. And then let's get 0.3. No need for this yet, but maybe for the future there'll be more relevant and I'll just pop it over there. So now our angry pig is going to need a list of position today used to be it's waypoints. So let's open up the script and let's create a export far. So this is going to be a array of position 2D and we'll call it var waypoints. Let's try saving that. Okay, so it doesn't actually look like using an array of the position 2D node type is going to work for us. So another alternative and my head is to use node path here. So no paths is going to be the relative path is a node. And then when the game is actually running, we can get the node from that node path and then get the position of those nodes in the game world while the game's running. So at this time, we should be able to increase the size of our array over here on the right and then assign the different nodes. So we want waypoint 1 and then waypoint 2. And then that'll be it for this character. So now in the angry Pig script, do we need to make sure that when the game's running, that our character is moving back and forth between those two points. And it's going to start with the first waypoint. So we should have a variable here to keep track of which waypoint it's at. So let's do var waypoint index. And this is going to start at 0, which is going to mean the first waypoint in the list. And so in addition to that, we can have a waypoint position. So this will be the XY coordinates for where this waypoint is at. So we only need to get it once. And then every time the physics process function is running, it can just move towards this position until it gets to that position. So speaking of which, we're not going to use process dot-dot-dot More going to want function physics process dot delta. So let's pass that for right now. So when the game starts, Let's actually go ahead and get the position of the first waypoint. So we're gonna do on ready to specify that when the game starts, something's going to happen here, or more specifically, when the script starts, which is presumably when this character is loaded into the level. So the waypoint position, we're going to be doing a get node and we're going to have the waypoints array. So up there. And we're going to need to put in the index we're trying to get. So waypoint index at the start of this game, Assuming this waypoint index is 0, this you get the node at that location. So then after we get the node, we're just going to need the position of that node. So let's put that in here and we could go ahead and test that by doing a print on the waypoint position, then we can launch this level with that angry pig in it. So currently the angry pig has no collision shapes, but that should be fine for right now. So let's go ahead and hit play, okay, and we can see we're actually getting the position of that waypoint, which is good. And we can actually turn this into a function that we can use every time we need to get and set the new waypoint position, we could actually make it a set of function. So let's do set wave point, I guess I'll say index. And then we'll make that function down here. So function set, waypoint index. And of course we would be passing the value of the new index. So waypoint index is going to be equal to that value. But then we're going to also say that waypoint position. Well, basically just this line up here. So let's pop that in there and then replace the value with the waypoint index at this point, saying this or that would be the same here. But now we'll just use the value that was passed into this function just in case. So now whenever we said the waypoint index, we also set the waypoint position. So I guess we would actually be able to erase that, make this an honorary var. So when the game loads, it's going to set the value to 0. And we can get rid of this bit, since that's going to be assigned already. Theoretically, this should be a vector to, I believe, and let's go ahead and see if that works. So we'll see if we get to this point when the game launches. Now that this function is there, we can actually just have this bit gets removed and we don't need this to be an ion ready. But what we can actually do and don't actually remove that as well. We'll just have when the game starts here, and we'll just set the waypoint index to the starting value. So let's say starting waypoint. And we could actually make this a export far. So I'm gonna make this export and var starting waypoint. And we're going to default that to 0. So now in the script starts, it's going to start the waypoint index off at whatever the starting waypoint is. And as a result of selling that, It's also going to set the waypoint position. Okay, so we actually need to put self dot waypoint index here to make sure that runs correctly. Okay, and now it gets down here. So it's saying invalid get index, of course, because I set this to five for testing. And now we can control it with the starting waypoint. And that value can be set over here. So if you want the angry pig to not move to the first waypoint, but the second waypoint, you could just specify the array position here and decide from that. Basically anytime we change the waypoint index, we're also going to change the waypoint position as well. So now we just need to set up and move speed and make sure that the character is moving between those two points. So let's go up here and create a move speed variable. So I'll do export flow, bar moves speed, and I'll just arbitrarily set this to 200 for now for the future. Let's also, while we're at it, add a run speed. So this would be the fast speed when the angry pig is actually angry so as to run speed and 300. And now doing physics process, we want the character to move between those two points. So we're going to need to look at the direction between the character and the current waypoint. So of course, as with many things, There's a few different ways we could do this. So let's start by getting the direction between the current character, they angry pig, and the waypoint. So I'm going to make a bard direction. And then let's do the self.position. And then for that vector, we're gonna do direction two. And then we need to give it another vector. So of course, we need the waypoint position, okay? And now that we have a direction, we can also get the distance. So let's actually make it distance x because we only really care about the horizontal distance, not including how far it is vertically, because our character is never going to be jumping up. So let's use the absolute value of self position x and then minus the absolute value of not-self position x, but our waypoint position dot x. So this should be the distance between the two points, not counting for direction, and then this would be the direction. So what we're going to do is if the distance to the waypoint is above a certain threshold, then we're going to keep moving towards that waypoint. And if it's below that threshold, we're going to switch to the next waypoint and something to move towards. So if the distance x is greater, and we could say greater or equal then. And we could call this something like waypoint, threshold are actually waypoint arrived distance. I think it makes a little bit more sense in my head. So if the distance is greater than the waypoint arrived distance, then we're going to move towards waypoint. Else. We're going to switch waypoints. So let's put the waypoint to distance up here. So export flow, our waypoint arrived distance. And I'll just create that as 10 for right now. So to move towards the waypoint at first, we gotta get a velocity. And we could actually make this a variable up here, is we need to reference it in other functions. So the velocity is going to be equal to a vector two. And the x value is going to be the move speed times the sine of direction dot x. So regardless of what this exact direction value is, we only care about whether it's positive, negative, or 0. So basically sign or kinda convert that to either positive one. Negative one or 0, which means that the move speed is going to be consistently either positive 200, negative 200, or 0. And then let's add a comma in there. So the second value will be a gravity. But I guess for right now, we're just going to actually, we can just basically look into the player scripts. So we'll use this same kind of thing. Let's see. I'll just copy this whole line here. So the current velocity and we add the gravity, but we cap it at the terminal velocity. And this will just be consistent between the player and the other enemies in the game. So we just basically stop that right in there. And now our character has gravity based on the game settings. Okay, so let's move and slide our kinematic body. And we're going to move it with the velocity. And we do want to say vector two dot up. I probably won't be too relevant for an enemy like this. But if we ever need to check if the kinematic body is on the ground, then having the up direction set will be important. So better to have that than not to have it, I think. So otherwise, we want to switch waypoints. So we've got to figure out which way point we're switching to. And to know that we have to know the size of the array, basically how many waypoints are currently in it. So just in case this is something that would change during the game, I guess we'll get it once every time it gets to this point. So let's Find the size of that array. So numb waypoints, waypoints, dot size. And, and then we'll check the current index. So if waypoint index is less than the number of waypoints, then we're going to increase it. So waypoint index equals rather plus equals 1. Else, if the waypoint index is actually equal or above the number of waypoints, then we need to reset it back to 0. So waypoint index equals 0. And then this bit will allow us to loop through the waypoints. One thing we're gonna need us to initialize this velocity variable to a vector to 0. Okay, So that means this is going to start with the values that are 0. And also our character is actually going to need to have a collision shape in order for any of these physics functions like movements, like to work on it. So let's go ahead and add a collision shape to the angry pick. So collision shaped 2D. Ok, and let's give it a save. Let's do a rectangular shape. Keep it nice and simple. And then let's increase the size of this collision shape so that it can interact with the ground. And I'm going to hold it out, stretch it out a little bit. And I'm going to go into the transform and adjust its position down a few pixels. I'm going to be pretty important that this collision shape equals the ground feet position. So let's actually hit play here. And we can see are angry pig was able to move to this left position. So it's correctly moving and sliding along the ground. The collision sleep seems to be roughly good. It's got the right pixel, right above the ground there. So that's all good. And now we just have to figure out, why didn't it switch to the second position? This angry pig has two positions here. So I'm going to set a couple of breakpoints. Whenever the waypoint index changes. Let's hit Play and let's see what happened. Okay, So we do get here where the waypoint index increases by one. So let's dive into this next function. Okay, we're not using self.age waypoint index. So we need to do that or the setter function to actually trigger there. So now we can hit play and see if this is going to work. Okay, invalid get index 2 on array. So should not have gotten here with two if the waypoint index is less than the number of waypoints. Okay? So it should be number of waypoints minus 1, okay? Because this is a count and then this is an array position. And remember that eerie start from 0 and counting starts from one. So we need to put a minus one there to adjust for that. So now if we hit flowing, our character should be okay. So looking at the code are pig gets stuck over here. And then as we can see, it's constantly switching between the first and the second waypoint. Okay, so here we can see in the code that this bit right here isn't working. So we can see down here that when the first way point is reached, it switches to the second waypoint. And then this distance x is a negative 173. So we don't want this to ever be negative, so it goes a bit away of doing this would actually be to get two vectors and compare them with the distance to function. So let's do a vector two of the self.position dot x. And we'll say 0 for the y. We're going to do that for both of the vectors, source a distance two and then perimeter vector to waypoint position x and then 0. Okay, so we actually need waypoint underscore position dot x. So when we do it this way, basically we're creating two new vectors and the y-value is the same. So the only thing to compare on is going to be the x positions of those two vectors. And a distance two is going to be direction nonspecific. So when we do it this way, we should get a plus 173 value instead of a negative. And we could actually, well, we don't really need to, we can just kinda hit Play. And see if it works. So let's hit play, okay, and now we can see our character is actually moving between the two points. So that's basically what we want. I mean, that's moving pretty fast. So I might want to turn that down quite significantly. So let's go to the move speed, make it 100, that run speed 200. And also, uh, we do want to flip the direction of that angry pig. So when it's moving to the left, we flip to the left and one is moving to the right, we flip to the right so we can do that in the code pretty easily like we were doing that before. So I guess we could say down here, if we're going to make a move, then we can flip the direction. So let's get access to the sprite up here, and we'll do our animated sprite equals dollar sign animated sprite. So that's referencing this right here. It doesn't need the unready in front of it. So animated sprite dot h is going to be true in one condition. And that condition is going to be if the sign of the direction x. So we should make a variable for that. So var direction x sine equals sign Direction dot x. Now we can pop that in right here and right down here. If this is, if this is negative one, then we will flip it. So if it's negative one, then that means we're going left, which means we want to flip this bright horizontal. Else-if the sine is one, then that means we're moving to the right, which means we want to have it turned off the flipping. And we're assuming currently that the sprite faces right by default. Otherwise this would be in reverse. So if the character is moving to the left, then it's flipping to the left. And if it's moving to the right, then it's going back to the default, no flipping. And if it's not moving at all where the direction x sine would be 0, then we're not controlling the flipping because if it's not moving, then we shouldn't really be changing the direction. So now we can go ahead and restart the game. But C, Okay, so the flipping working except it's in reverse. So let me take a look there. I guess this is a left by default facing character. So what we could actually do is put our export Boolean just in case we were making a new character or the sprites changed, we would want to be able to set the default flip direction. So down here we can say faces, right? And, and the reverse of faces right down here. And let's stop again for money. So if the sprite faces right by default, then we want to turn off the flipping while it's facing to the right. And if it doesn't face the right by default, so if this is set to false, so faces loved by default, then that's going to be false and we don't want to flip it. So basically as long as we set this boolean to the right value, the character should face the right direction when it's moving. So we're turning off faces, right? Let's hit Play. We can see that our instance of the pig is able to go between the two waypoints. It's kind of working in general. There are obviously some problems like running into the player and being stuck there. We probably don't actually want there to be a hard collision with the player, but rather just maybe dealing damage to the player and then passing right through it. And also we need to add and the angry run state and also make sure that it's animating correctly. All of that we will do probably in the next video or two.
17. Angry State Animation, Physics Layers, and Area Entered Detection: So at this point there's a few adjustments I'd like to make to the angry pig. First off, it needs to have some kind of detection zone so that when the angry pig actually sees the player, that it can switch to its angry run mode and move faster. Secondly, as you can see, currently, none of that animations are playing. So we'll have to set up an animation tree for the angry pig. And we'll also need to store it, setting up physics layers so that when the angry pig runs into the player, it won't actually stop the physics body from moving so forth this game, we're going to make it so that the player and enemies can move through each other, of course, still be able to do damage to each other, but we'll need to set that up by starting to use physics layers. So We might not let the pig collide with the player layer, but there might be a damaged box on the pig, which will detect if it can do damage to the player and then do damage to the player when the player enters that specific zone. And so once we have the angry pig setup with the animation tree will also need to script out the states and code for that to correspond with. And that's pretty much what we're going to take care of in this video. So let's jump into the scene for our angry pig. And I am going to add a new area to it. So I'm going to add a child node and we're looking for an area to d. So we can just type that into the search editing. And this area 2D is going to need a collision shape of its own. So I'm going to right-click on it, add a coalition shaped 2D. So this can be whatever you want it to be. And this zone is going to basically detect when the player is nearby so that the angry pig can go into its angry, enraged state. So I'm going to rename the area 2D angry detection zone because I think that just makes a little bit more sense here. It will make it so that the character will enter that state even if the player is directly above the head. So I'm actually going to use an oval shape. So on the right where we have Inspector, let's change the shape to capsule shape. And then I'm going to rotate it 90 degrees because I want it to be more wide than tall. So let's go to the transform 90 for the rotation degrees. Okay, and then let's expand this to a reasonable amount so it can be basically as big or as small as you want it to be. And as you play test, of course, you'll want to adjust that. You can even have a custom zone sizes for different variations of the enemy, okay? And for this angry detections on the area of two D, I'm going to I'm going to turn monitor trouble off because I don't actually need this zone to be detected by anything else in the game. We only need monitoring on because this zone is going to check for the player, but nothing needs to check her care about this zone. So it seems pointless to actually have it on. And in fact, why use extra resources when we don't have to. So that's why I'm leaving that off. And now we can set up a node graph for a animation tree on this angry pig. So like the player, we're going to have to right-click and add some notes. So let's add a animation tree. And then let's also add in an animation layer. So this animation player is going to have all of the animation setup that correspond with our animations on the animated sprite. So let's create hit one. So let's create hit one, hit to Idle, run and walk. So in the animation setup, Let's do new. Hit one. And then we can add a property Trek. So the property is going to be animated, sprite animation. And on frame 0, we want it to play. Hit one is the animation. And we will default these animations to be 0.05 seconds long and on repeat. So now we can duplicate this. And of course next will be hit two. So let's change this animation to the hit to animation. Duplicate it again, rename it. So do Idle, run and walk animation. Okay, so that's the animation setup. Now we need to connect to the logic and a tree. So for the animation tree, let's create a animation node blend tree just like the player. So in order to make the angry detection zone work, we can set up a blend space one D, which will give us a variable that we can set to control whether the character should be walking or running. So let's change the variable here to play are detected, and this will kind of be like a Boolean, either set it to one or 0. And if we open the editor, we can add in the points. So at 0, we want it to be a walking animation, meaning the player isn't detected. And then at one, we want it to be run. And just in case let's also make negative one a run that as well. But I think we're just going to have two values, either 0 or one. So now that we have the simple blend space setup, we can connect that to the output. If we make it 1, we get the run animation, and if we have several, we get the walk animation. So now we just need to check if the player is detected in code and then set the parameter at the correct times. So one way that we can have the angry detection zone tell the angry Pig when there is the player inside of the zone is to use signals. So we can set up a receiver method by going to note over here on the right. And then we can use body shape entered and body shape. Excellent. So I'll double-click on each of them and we'll add a angry detection zone body shape entered to the angry Pig script. And let's do that for both of them. So double-click connected to the script. Okay, and that's basically all we're going to need from the zone. In order for things to work in here. So when a body shape has entered, it should be a player. And we're going to set that up with layers and a minute. And as a single-player game, there should be only one character in that layer at any given time, one or a 0. So we can just set animation parameters on the animation tree in order to take care of this. So if you don't already have the on ready for animation tree equals animation tree up here at the top. You can go ahead and set that up. And then down here we can do animation tree dot set the parameter. So we're going to do parameters slash, player detected slash blend position. Okay? And we're going to want to set that to one. And then when the player leaves that area, we want to set the parameter to 0. So select all this and paste it in here. And we set that to 0. Now if we were doing a multiplayer game, we might need a little bit more elaborate code because there might be multiple players. But in this case it will work perfectly fine because there's only one player in the game at any given time. So this just simplifies it for us. Now if we go to the angry detection zone and the inspector, we can set up its collision layers. But before we set up the collision layers, we should actually define what those are. So in project, project settings we can go down to, I think it's under physics. So 2D physics down here under layer names. Let's write some layer names. So layer one, Rican make world. And then for now let's go down here to, let's say layer 4 and layer and enemy. So we have a few layers setup. And for each of these layers we can have an object collide on a certain layer, and we can also allow it to be found by other objects looking to that layer. So let's close out the layers here. So we have the layer option under collision. So the layer is where other objects can detect this object in and collide with it or do whatever they need to. So for the angry detection zone, we actually aren't going to want a layer right here because it's nothing really needs to collide with it. We're just using this to trigger events, which is basically making the pig run. But the mask is going to be where we're checking for these events to happen. So for us that's not going to be the world layer, which would just set up as one, but it's actually going to be layer was at Fort, which is going to be the layer layer. If we click away and click back, it should update down here. So you have labor for is the player layer. So with this angry detection zone, we're only looking to the player layer and this should only be one player in the game. Therefore, that's going to be the only object that can trigger the receiver methods down here to set the animation treat 21 or 0 depending on if we need it to run or if we need it to walk. So if we save that, now we just need to define the player as a player layer object. And we should also just update the enemy to be an enemy layer object while we're at it. So under angry pig, the kinematic body go to collision, physics body collision. And then we're going to change the layer here to enemy. We're still going to use weld as the mask. So I guess what we're going to define the world layer as is all of the ground, the platforms, the tiles, things that the normal physics interactions should occur. And so the kinematic bodies are going to keep looking to the world so that those collisions can still happen as an enemy, player won't be able to directly collide with this kinematic body. And this kinematic body won't be able to directly collide with the player because we're not checking the player mask well, and they checking the world mask. So let's go dive into the player again. So the player scene, we click on the player kinematic body, physics, body 2D. And we change this from a world object to a player object. And it is going to be looking to the world layer in order for collisions to happen. So now when we run the game, if I've set everything up right, the pig should not collide with the player and the player should not collide with the pig. But the 2D detection zone should be able to detect the player so that it can tell the angry Pig script if it should be running or if it should be walking. So let's go ahead and hit play and see if all of that works. So currently the players in endosomes, so it's just walking. So at least our animation there is playing correctly. Let's move kinda right above it. And we can see that the animation is changing. So that is actually good for us. Now the last thing we need to do is to basically control the movement speed so that it does a little bit more than just change colors here. So let's stop the game from running there. And let's open up the angry Pig script. So in these properties get set up for the animation tree. We can also set something up for the angry pig. So just like the player, Let's create a enum representing the state that the pig isn't. So up here at the top, I'll do enums state, and currently we will just have walk and run. So up here at the top we can create another enum for our angry pig, just like we did for the player. So our states are going to be, I'll walk and for the run state, we could just call it run. And that would be more consistent with everything in the game. I guess I guess we can do that. I mean, I was also thinking we could call it like mad or angry, but maybe if we just call it R1, that'll make more sense when we actually look at the animation player in the animation tree as well. So let's set that state down here. And of course we need a variable to store the current state. So variable state or other variable current state. And we'll default that to state dot walk. Since the character is going to be walking as soon as the game starts. And that's also make these states capital, since they're constant throughout the game. And state dot walked down there. Okay, So now we can take the current state and set that to state run if it's getting that one value parameters. So it's going to be running down there and the animation tree. And then current state equals state doubt walk if it's set to 0. So now those are going to be consistent. And now we just need to kind of control the move speed based on what that state is. We can change the move speed actually up here to a walk speed, okay? And then this will still be moved speed. But the actual move speed that we're going to be updating on every frame. It's going to be a new variable that we create here. So this is going to be a factor two. And then we can run a match on the current state. So if we match the current state for state dot walk, then the move speed is going to be equal to the walk speed. And actually this, this should be a flow because we only care about the x movement and this should be an underscore. Then we just need state dot ruin down here. And of course we're going to set the move speed equals to the running speed. So now should be a lot more obvious if the character is walking in, you know, kinda casual about things or running and trying to chase the player down. So let's go ahead and hit play and see if that all works up to this point. So as we get closer to the enemy and we can see moves to ridiculously fast. And as we step away, then he just goes back to his green states. So there's this kind of arbitrary zone that as soon as the player enters, it triggers the pig to move really fast. So we might want to turn down the numbers on the movement, but as far as the detection goes, this is working correctly. So I'll go up here and make the character move a little bit slower. So it's a little bit more fair to the player.
18. Jump Attack ~ Hurtbox & Hitbox Setup: So in this part we're going to be creating the ability for the player to attack the enemy, in this case the angry pig. But really I think we're going to set it up so that we have a enemy based script that characters like the angry pig and other enemies can be based on so that we don't have to keep retyping the same code over and over again, basically inheritance. So the attacker just going to give this character is the ability to bounce on top of enemies, deal damage to them, and then bounce off at the most original. But it'll work for now. So let's dive into the angry pig character again, and we're going to be creating a new area to d. This area 2D is basically going to be a hurt box. An area where when the character lands on top of if it enters that zone, it can check to see if the player is on top and if that is the case, Deal Damage and do a little bounce animation. So in the process of setting that up, since we can see that there's already a few collision shapes on our character that might get in the way. It might be a good idea to lock them into place. So if we click on a layer, we can click on this little lock symbol to make it so that we can't accidentally move them. And I'm just going to do that with all three of these. The area to D, the collision shape to D and the angry pigs, kinematic body collision shaped 2D. So now let's add in a another area 2D. So I'm going to right-click on the angry pig at a child node area 2D. And then let's give this a shape as well. So collision shaped 2D. And to make this simple, we're going to use a rectangle shape. So this rectangle shape is going to be very small and it's going to be positioned right here at the top of the pigs had. So I might take the area to D and move that up. And which will also move the collision shapes location as well. Or you can just move the collision shape directly however you want to get it up there is fine. So let's see if we make that 12. Maybe we want negative 12 there. And let's just that negative 10 seems good. So now let's take the collision shape and adjust its extents so the Y extents and just going to want that to be one. So we can see that this is a very, very small collision shape. And this area to D, I will call a jump box. And it might rename this collision shape, jump collision shape. Just like when we hover over it, we can actually see a name that makes a little bit more sense. So I think that might be a little bit helpful. Okay, So now for this hurt box to work, we're going to need a collision layer for the hotbox and don't believe I have set those up. So let's go into the project Project Settings. And we will go down to where it says 2D physics. So we have layers for world player enemy, and to be more specific about enemy and player, these are the kinematic body layers. But we might also want at layer four areas where certain events can be triggered, but not necessarily for move and slide collision type mechanics. So maybe we can say over and about layer 11 will have enemy box, which we may or may not use, which would be the enemies trying to hit the player or another character. And then beyond that, I could create a jump hurt box layer. So you could also just create a generic enemy HIPAA. So you could also just create a generic enemy hurt box layer, which would work fine currently. The thing is if your character ends up having multiple attacks, you might only want surgeon and taps like a jump, bounce to actually be able to hit very specific areas and not all of the potential attack areas on the care. So for right now I'll just have jumped her box and this layer will be exclusively used for those jump attacks. So up here, I'm not sure if we use it or not, but just to be a little bit consistent with down, they're also create a layer hit box in case we need it later on. So let's close that. And this jump hurt box is going to be in, of course, the jump box layer. Of course it won't show the correct names until we switch out to a different tab and back. And now if we go over here, okay, I guess it's on the second row, we should be able to find and me hit box and then jump hurt box. So let's take it off all the other layers. And then this area 2D isn't going to be checking for anything. It's only going to be receiving information, so we just need to have it on the jump her box layer. We don't need to use a mask for, to check for any entering or leaving from other layers, at least for now. Okay, so now let's go into the layer character and let's create that jump hit box. So I'm going to right-click on the player and add a area 2D, okay, and we're going to rename this jump pit box. And of course we're going to need a collision shape. So the collision shape, we will make that a rectangle. And I'm going to make sure that the height of this is one. And then we're just going to pull it down here to the bottom of the character. And we can adjust the transform on the jump hit box area, I suppose. So let's bump that down with transform position. And I guess 15 is about what we're looking for it there. We probably also want to shrink the width of it because the character's feet only go to about here. So let's change the H2, maybe a six, okay, I guess I can look for now. And this jump hit box area 2D is going to be looking for the jump hurt box layer in order to see if it can hit the enemy at that point in deal damage to it. And currently, I don't need anything to check for the hip box, so I'm just taking it off of layer 1. So it won't be used in any collisions only to check for things entering it on this layer, the jump hurt box. Okay, so now what we need to do is connect this jump hit box inside of the player script. So we can do that using signals pretty easily. If you click on the jump pit box, we can go over to note. And then we're going to want to use area shape entered because we're checking for the hurt box, which is a area 2D. If we were checking for a kinematic body, he would use body shape entered in body shape accident. So let's do Area shape entered. And I think that's the only one we're going to need to know. So the receiver method default name on jump, hip box area shape entered works perfectly fine. Let's connect that into the player script. And now we're going to have this down at the bottom. I'll move it up here so it's not in the center section.
19. Jump Checking for Enemy Class Type: When something enters the hit box, theoretically it should only be the enemy jump hurt boxes. But I do want to make sure that the area that's entering is actually attached to a enemy. So what we could do is we can check this area and then we can see if it's owner is in fact of the enemy type. So I'm going to do var enemy and then Area dot owner and foreign instantiated seen that should give us the root node. So if I was to check what the owner would be four like this jump hit box. If I had a script attached here, it would go to the owner, which in this case is the player. So in the angry pig, the owner of this jump hotbox is the angry pig, which is going to be of type enemy. Actually, let's see, did I create the enemy type yet? No, I have not. So we'll do that in a minute. So back in the player script, we need to check, is the enemy actually an enemy. So I'm going to say is enemy, enemy, and we haven't created that yet. So that's not going to work and we just need to basically create the script for that. So end the Characters Folder, enemies. I'll just create a new script here. So I'm going to right-click here, do a new script and we're just going to call it enemy. And inside of enemy dot GD, this is going to extend kinematic body 2D. So the base type of this is the same as angry pig, which is going to mean that angry pig can just inherit from enemy dot g, which is going to inherit from Kinematic body 2D. So it gets all the functionality of both the kinematic body and also the enemy. So for GD script to declare this as a type which we can reference without a path. I think we need class name here and then enemy. So it's just basically giving a, if you were doing C plus plus kind of like a namespace to this script. And now in angry pig dot h gd, we can just write enemy, so it extends enemy. And that enemy is because we defined it for our project with this class name. Now anything we want all of the enemies to have can just go in here. So for instance, angry pig, I guess we haven't set of health variable, but this would be a perfect place to actually put that. So let's do export, because we'll make it a float var health and will default this to three. So now if we click on Angry pig, go to the Inspector, we can see the health variable is here. But this health variable, it's not coming from angry pig, it's coming from the nested enemy script. So now malloc and the receiver method for the jump hit box, if we've gotten to the point where we've figured out that the enemy is in fact an enemy. Then we also want to make sure that it can currently be hit because we don't accidentally want to double hit the enemy for any reason. So there might be an invulnerability time, such as like when the Hit animation is currently playing, maybe the enemy should be in vulnerable for a minute. So we can add another variable to the enemy, which could be something like can be shut. So enemy dot can be hit and this will be a Boolean. And we can just declare that over in our enemy script. So we could say export bool bar can be hit. And presumably this would generally default to true, since at the start of the game, you want to be able to hit the enemy, but you can customize this, of course, for each enemy, since that property would just show up here inside of each of the characters. So now at this point we want to check if the character is actually above the enemy. If we're jumping from down below and then the areas overlap, that's not really the same as falling down on top of it enemy. So we can check when the area shaped enters, if it's entering from above, wherever the enemy is. So basically for this, we can grab the jump hit box. And I might actually make more sense to have this as a variable up at the top to be more consistent. So we'll have on ready var, jumped hip box equals dollar sign. Don't fit box. So we make sure that's there at the start of this script running. So we check the jump hip box dot. Let's do global position dot Y. So in the game world, this is going to be, it's like absolute position, not relative to anything. So if we compare this to another global position, then we can be pretty sure that it is actually above the other position or not above the other position. So area dot global position dot y. So this is going to be that hurt box area and theory, since the jump pit box can only detect on the jumper box layer. So we can be reasonably sure that this area is in fact the jump hurt box. So if we get to down here, then we're going to do the jump attack. So for that, we're going to take this character is velocity, and we're going to increase it with a little enemy bounce. So I'm going to have a variable, enemy bounce, impulse, and then we're going to do damage to the enemy. So we'll have this function get hit with an amount of damage. So we need to create two variables up there at the top. So first-off, export, var, enemy jump. And I'm gonna make this less than the main jump, something like 400 sounds a little bit better than we can also have another loop variable. So this will be dama damage and I'm just going to default that to one. Nice and simple. Okay, so we start out at air down their enemy bounce impulse, enemy jump. I guess enemy bounce works better. Okay, That's what I called it in the original scripts. So that should clear up the problem there. We just gotta make sure that the enemy script we have that get hit method. So get hit. Let's make that function get hit. And this is going to take a amount of damage, presumably a float. And so when the enemy gets hit, we want to make it so that it can't be hit again until we have something else. Say that it can. In our case, it's going to be the end of the hit one or hit 20 animation being done. So while it's playing the Hit animation, basically in vulnerable in a sense. So we're going to take the health and we're going to minus equal the damage. And then we're going to set can be hit equals to false.
20. Get Hit Implementation and Hit Animations: Now in the angry Pig script, we want to create a function that we can run when our hit animations are done. So let's create a function that animation finished. Okay, So when it's finished, we want to set the hit equals true. And I'm also going to want to return the state of the character to run or walk. Since once it's done being hit, it should basically resume its normal functionality. So we're going to say current state equals slate dot run for now. Okay? And that's also move these functions up here, okay? And one thing about these, when we're in the HIT state, we don't want the character to be able to switch its state to run or walk. The only way we're going to let the character go back to urban state is if this function finishes. So in essence, we wanna kinda lock that up. So I'm going to put in here, if the current state is state dot walk, then it can go to a run state or down here. If it's running, it can go to a walk state. When this parameter gets set and the player isn't there anymore, it should start walking and when the player enters, it should start running. But only when it's not in another state like hit. And this needs to equals sign. So now let's go into our animation player, angry pig 2D. Let's click on the Animation player. And let's add in another track for HIT 1. So our track is going to be called method, and we want to call methods from the angry pig, okay, and we also need that to occur at the end of the animation. So we're going to need to extend this. I'm actually going to extend it to 0.5 seconds for now. And when we go to the animated sprite, I'm going to slow down the FPS and vz by half so that it takes nought 0.25 seconds, but 0.5 seconds for the whole animation to play. We'll see if that works for us. And now we can go back to the player. So it should take till here for the 10 FPS animation to finish. So this is where we want to put in the, forgot another equal sign there as well. Okay, so now for our functions track, we can insert the key. Hit animation finished. Okay, Now that should run the animation there. Now we also need to do the same thing with HIT 2. So let's make this 0.5, but the duration, and let's turn off looping as well because it shouldn't loop. It should only play once and then go back to running. So a call method on Angry pig, and then we right-click here at 0.5 seconds, insert the key, Hit animation finished. And now our function is going to run here. So this should return it to the state and allow it to be hit again. So that should be what we want. So now let's just check, hit one and turn off looping. And one more thing we need in the animation tree is to actually set up a one-shot variable so that we can into those hit states. So let's right-click on the node graph and do a one-shot. So this one shot is going to be, let's just call it hit. But why not just keep it simple? So this one shot is when the Hit animation is going to be played. So when this animation parameter hit gets set to active, it should show either hit one or hit too. And we can make that a random variable. But in order for that to actually work, we have to reconnect the outputs. So let's take this line here for the output and played detected. And now this blend space 1D should feed directly into the n as the default function. And then this goes to the output. And now we just need to create those. Hit one, hit two animations down here. So right-click Animation, right-click animation. Okay, So on the first one hit one, on the second one hit two. And now we can go over here, right-click and I think we want to blend two, okay? So, uh, basically going to have two values, 01, if it's 0, then we play hit one. And if it is one, then we play hit two. So we can call the property here, hit variation. If it comes pelvic hit very Asian. And let's connect this to shot. Okay, so now we have two variables to hit. This will determine whether we play hit one or hit too, just for some variety. And then this will determine if we are playing the Hit animation at all. So for the enemies in our game, after thinking about it, we might actually want each enemy to have its own implementation of get hit. So we can still pass the same amount of damage in to the function for each character. But maybe some characters don't actually take damage when they get hit. Maybe they just move a bit or maybe some characters aren't invulnerable after being hit. So in any case, I might actually make sense to allow the player to tell the enemy about running this function, but have a different implementation for each character. So I'm going to put an underscore here to make this a virtual function. And then we're just going to cut this for right now. So then what we're going to do is take this over to angry pig. And we'll put this down here as a implementation for that. So we'll come back to this in a second. So for right now if the function gets run and it isn't a custom implementation, I'm just going to push an error. Just say that get hit has not been implemented. So if in angry pig or another enemy, they get hit has been created, it should use this version of the get hit. But in case it doesn't, we'll just have this error message so that we basically now that we have to go ahead and implement it. So for this version of get hit or the angry pig, I'm going to make it so that when it gets hit, we enter the hits state. And as part of that, we can actually set these variables down here in the animation tree. So I'm going to get the animation tree and we're going to set the parameters. So the first one is going to be perimeters slash hit slash, active, and then the other one, Let's go ahead and check that. So player detected, so that's going to be parameters slash player underscore detected slash 08, not that one. Hit variation actually. Perimeters slash hit variation slash blend amount. Okay? So, so animation tree set or her amateurs slash hit underscore variation slash blend amount. So that's going to be either 0 or one. And we'll have to figure that out on a second. And then this is going to be a true. So we can generate a random number here. And in order to create a random number, you need to create a random number generator object, which has its own constructor. So we could create one inside of this class or we could create one every time we run this function. Or what we could do is we could put it on our singleton global script. And then anytime we need to run a random function, we just reference that game settings global. So I like that idea better. So in our game settings.js, we can create a variable and this will load at the start of the game. So this will be our random number generator. And what we just need to do is random number generator and create a new instance of that. So at the start of the game, whenever it loads, we're going to get this new random number generator and we only need one and we can use it everywhere. So in angry pig now we can add a new line. So let's do that. Far anime selection. And this is going to be equal to game settings. Our singleton reference Hubble anywhere dot, Let's see, we call it rant Jen. And then we need to generate a new number so we can do random int i for int underscore range between 01. So integers can only be non decimal numbers. So that's gonna give us specifically either a 0 or a one. And we can put that into the animation tree value. So let's put that enum selection in here. So that'll give us our randomly selected either hit one animation or hit to animation. So one more thing in games, settings.js, when we use the random number generator to generate random values, by default, it's actually going to use the same seed whenever the game loads. So it'll have the same sequence of, so to speak, random numbers. So if the random number generator was only used once to determine that the character got hit and which animation to play, then that character would, in theory, be playing the same animation whenever the game loads and that same event happens. So to make a truly random, what we could do is implement a ready function here. And then if should randomize a Boolean, then we'll randomize it. So Ran Gen, re-randomize. Okay, so if we have this R1, then this will create a new seed for the random number generator. And it should actually give us different variations every time we run the game. So let's make that a variable that we can set in the game settings. Seen that TSC and file so should randomize. And it will default this to true. So if we ever need to turn off the randomization because we want to test for the same seed for the random number generator, then we can just go into this scene and turn it off on the inspector or to the side. So let's just have that in there for right now. Okay, so let's go ahead and hit play here and see where we're actually at. So let's go ahead and hit play here and see where we are at. I'm going to jump into the character. So first off, it should not have got here because it was below the area for starters. But we can also see non-existent function get hit. That's because we have the underscore there. So we can take that away since this is the final implementation of get hit this character. So let's go ahead and hit Play. And now we can see the character is getting hit, but we haven't actually created the hit state. So up here at the top, Let's add that state, state hit, Okay, and let's give it another shot. Okay, so we actually had the bounce on top of the character. And you can see that after that first bounce hit, it's actually not possible to hit him again, or at least temporarily. It wasn't. Another problem seems to be that the character doesn't actually die when the health is below 0. So let's solve that real quick. If health is less than or equal to 0, we can just use Q free to remove the character. So of course, if you had like a death animation, you can play that unsaid first and then Q free. But this removes the scene from the hierarchy. In other words, removing the enemy from the game. So let's hit play and see that again. So that's one hit, two hits, three heads. Okay? So that does actually do damage to the enemy. Okay, So it seems like what we actually needed was the global position on the hip box should be higher than the global position on the area. And you can kinda debug that just by printing out the global position for each whenever you'd have a collision and see if the numbers actually line up. So now if we jump onto the character, it should actually bounce, but only if it's on top. So let's see, coming from underneath, nothing happens but if we jumped from up above, we get that bounce. Okay. And then there's that third hit. Okay, so that seems to be more or less working. Let's test that one more time. Seems like I missed the hit box. Okay. There's that. Okay. Jumping from underneath doesn't do anything but we can jump and hit him again. Okay, So we can quickly check the box for the character. Let's see. So we have that little line up here. Maybe we do want to make the jump collision hit box a little wider. I think that's not the only problem there, so we'll be kinda generous with that so that if the character kinda hits the edge of them, we can go a little further even maybe we make it 13, 14, even when not. Okay. So let's hit play. Test it one more time. Oh, okay. I guess and seems to be working overall. One other tool you can use to check collisions. If you go up to the Debug menu, you can turn on visible collision shapes. So now if we hit Play, we can see directly where his collision shapes is. So where we should be hitting in order for the jump to occur. Ok. And let's jump on him again. Okay. All right. And one more time. Okay, That pretty much seems to be working correctly for our angry pig. So in the next video, we'll be working on making a way so that the angry pig can actually damage the player if the angry pig runs into it. So that part should be hopefully a little bit more straightforward than having to set up these hit boxes for jumping and bouncing. And the different states.
21. Adding Hit State for Player: So now that we're able to bounce on an enemy in order to deal damage to it. Or at least with angry pig area, we should make a way for the enemies like the angry pig to be able to do damage to the player. So we can go ahead and set that up now. So previously we made an enemy class, which is a base script that the angry pig and haired. So I'm in this class, we create the ability for enemies to get hit. And also every enemy has health and the variable can be hit. So in order to make it so that our player can be hit by enemies, we're going to need to set up a few variables similar to how we did with the enemy script. The angry pig inherits from enemy, which means that the angry pig has health and should implement the get hit function. What we can do is pull everything up another level where any character and the game will have health and should implement a get hit function. So we can create a script for that. If we go to characters and then right-click on the folder, do a new script. So I'm going to call this character dot G, D. And in this script we're just going to pull that information from the enemy, such as the health variable. And let's give it up everything, put it here, and then make sure that this is a kinematic body 2D, since every character is going to be a kinematic body 2D type character. So now if we have enemy inherit from this, it'll get the health value again. Now what I do notice sometimes is that if you have too many class names in the game and you have a bunch of inheritance going on that sometimes it gets errors. So rather than putting className character here and then extends character, what we can do is just cut away this text and then drag and drop the path to the character script. So if they're just drag this up here, it's basically going to work the same as if we had used class name and character. Although doing it this way, we can avoid some errors that occur with using class names and Godot. One problem is that if you move your script files in the directory, it's going to obviously cause a lot of errors because this is a path to where it's stored. So if the character dot h gd script is no longer a in the Characters Folder, then it obviously when it tries to load it, it's going to give you some errors. So you can play around with it a bit and figure out which method works better for you. So our enemy is going to inherit from Character dot GD. And that means that it's going to have this health, but that's also take this function and put it in character as well. So that is character is going to be our base custom script written on top of kinematic body 2D. So that's what this is inheriting from. And then enemy is a type of character. And then angry pig is a type of enemy. So the angry pig class is going to inherit from everything beneath it. Have everything in enemy, and we'll have everything in character as well. So we can keep enemy as a separate script though, because as the game gets a little bit more complex, there may be certain things that we want all enemies to have, but not necessarily characters like the player. So let's now make our player a character. So I'll click on player and let's cut away the extensor and just drag and drop the character dot GD script. So extends the path to the script that's worked for us. So now the player is going to have a health and we're going to need to write this function. So let's go down here and write they get hit function. So function get hit and we're going to take a damaged value, which can be a float. And the things we're going to need to do with get hit is to obviously take the damage. So self dot health, it's going to be minus equals to the damage of value. And we should also change the state of the character. So we can do self dot, current state equals state dot hit, which we have not created yet. So let's just take that and pop it right up here, creating a fifth state. And then of course, we have a setter method for this current state value. So when that runs, the set current state is going to happen down here. So I think this would be a good place to set the parameters on the animation tree. Of course, we haven't set the parameter for the new one shot where the character takes damage and has a little bit of a staggered knock back. But we can just go ahead and type that out in advance. So the state we're matching for is of course state dot hit. And when that occurs, we're going to do animation tree parameters, slash, hit, slash active. So just like with the double jump, this is going to be a one-shot. So that's why it says active here. It's going to be a Boolean and we're making it active or true. So now let's dive into the player scene. Let's go to the animation tree, and let's set this up for HIT. So in our game, when the player takes damage, that's going to take priority over any other animation. So this one shot should be in front of double jump and the hierarchy. So I'm going to right-click here, do a one-shot. The variable name, just like we vote in the script, is hit some good about that. And now we can redirect this output to here. And the one-shot will go to here. And when this hit variables active, we're going to play the one-shot, so we want to get that Hit animation. So let's put that in here and connect that to shot. Now, we also need to make sure that our animation player has the Hit animation setup correctly and that the Hit animation in the animated sprite is also setup. So if we click on animated sprite, we can check hit. And we can see this as eight Frame Animation. We're running it at 20 frames per seconds. So that's important. We can figure out how long that the Hit animation should play, 4.05 seconds per frame. So that's going to be a total of 0.4 seconds before we jump into the Animation Player. One more thing on the one-shot, like with the double jump one shot, we want to make the fade in time and fade-out time 0. We've got to do that a second ago. And that's going to be pretty important so that the animation is actually look correct. Now let's go to Animation player. Let's look at our Hit animation. We can see it's looping and it is only 0.05 seconds. So we need to turn off looping and make it 0.4 seconds, because that is how long it takes to get through all of the frames of the animation. And now, when the character is done with the Hit animation, we're going to want some kinda call-back inside of our script where basically the animation is complete. So something should change in the player class. Namely, it should resume a normal state like idle or walk will probably use state dot AIDL. So let's go ahead and write that part of the script. And in fact, what we could probably do is just put that into character, since I imagine every character in the game, as long as you're not having NPCs of some kind that are totally immune to everything. I'm going to have a hit animation of some kind. So you can put this in player, or we could just write it here as something that should be implemented for every character in the game. So we'll do on, hit finished. And we can just push an error if it's not implemented, since we should have our own custom implementation of it. So in player, let's actually write that. So down here, we can do function on hit finished. And what we're going to do is take the self dot current state and we're going to set that to state dot idle. And if you recall, our script is already set up for going between idle and running states, depending on if the players input. So I'm putting it in idle should be just fine for right here. And now we just need to make sure that this gets called so that we can resume the idle state. So in the animation track for the animation player, make sure you have animation player selected. Do Add Track, call method, select the player script, and go to the end of the animation, which is 0.4 seconds. And let's right-click and insert a key, pick the method that you want it to run. And this case it's going to be void on hit finished. So let's just double-click that. Now when it gets to this point, this function is just going to run automatically. So the state will be switched to idle.
22. Enemy Collision Hitbox Detection: Now that our characters basically set up for entering the Hit animation state, we're going to need a way for the enemy to actually deal damage to the players, similar to how we have the jump hit box for this player, we can create a hit box for the enemy that's going to look for the player. And if it finds the player at all gone, this get hit function. So we can jump into our angry pigs scene. So now with the angry pick, we can set up a hit box. This is going to be very similar to setting up the hurt box down here. So I'm going to right-click on the angry pig, going to add a child note, and we will make it a area of 2D. I'm going to rename this enemy collision hit box, since this is its ability to do damage when it just bumps into the player or a collides with the player. And now we need a shaped 2D for the hip bucks. So I'm going to right-click on it, add a child node, and let's do collision shape 2D. All right? Just like with a bunch of other stuff, we can just keep it simple with a rectangle shape. Currently, I don't want to accidentally adjusted jump hurt box, so it would be good to lock that in place. Make sure we don't add it in any way. And now we can take the shape for our hip box and adjust it. So I'm going to say that this character can only really collide with the player fit bumps into it right when it's looking at it about Here. Okay, so let's take our collision shape and shrink it down a little bit. So the big collision shape that'll be for this pig colliding with other things, but we'll be kinda generous with the player and just say that the character kinda needs to be right around here overlapping with the player in order to actually deal damage to it. So I'll take the rectangle shape and let's make it something like 77, hit Enter. And maybe we can say 78, but then we take the collision hit box and move it down a little bit. So let's move that down there and we can temporarily hide the other hip boxes so that we can see everything clearly if we need to. I think that could be okay. Maybe I'll move it down just one more pixel and we'll call it good for there. We can always adjust it later. So now for this enemy collision hit box, we need to set the layers where it's going to be looking to, to deal damage to the player. So if we want, we could create a player hurt box layer if we want to define a custom shape for where the player can be hit. But I think that the main body collision shape will work just fine. We can see this here. Kind of fits the size of the character pretty good. So we'll just use this collision shape that we're going to look. For instance, this is the collision shape for the kinematic body. Then in the script we're going to be using the body check, not the area check. So we don't need to create a player her bucks, but if you want to do that, you can go to the project menu, go down to 2D physics, and then in Layer 8, can say player hurt box, maybe we'll need that later on. So I'll just write that in as a layer right now. But instead of that, I'm going to change the mask, which is what the area to-dos looking for. And just change that to the player mask. And I'm going to turn off the layer for collision, since this is only going to be looking for the player in order to deal damage to it. And in fact, we can just take monitor a tuple and just turn that off entirely. It might also want to rename the collision shaped 2D on the left. Just so we know which one's which. So I'm going to call this enemy collision shape. And I'll save that there. So now we need to take the signals of the hip hawks and add that to the angry Pig script. So with the enemy collision hit box, I can go in here to you body shape entered, and I'm going to connect that into the angry pig. So on, enemy collision hit box body shape entered, we're going to try to deal some damage to the player. But the thing is a lot of enemies are going to be able to deal damage in this way, if not all of them in the game. So I might actually want to take this out of the angry Pig script and we can put it in enemy GD and stat. So enemies are going to have the ability to do damage to the player whenever the player enters that area if the player is not in a vulnerable state. So in order for an enemy to deal damage, we're going to need another variable. So I'm gonna do export, let's say float collision, a collision shape, collision damage. And I'm gonna default that to one. So we're going to check if this body is a player type. So for our collision hit box, the body should be attached to a player. And we can be pretty sure that that's going to occur because in our hip box, the collision layer is only set up to have the player mask and players are going to be a type of character. So what we can do and our enemy script here, it's just assigned the damage to this body, assuming that it is a player type. So body dot get hit, collision damage should in theory be able to occur since the only bodies that are going to be on that layer in the game are going to be the player. And if it's not a player, then we probably messed something up and we do want to get an error message out. So I think it'll be fine to make that assumption here. Why they get an error or at all been successfully, maybe it hasn't been implemented in that specific character type. But let's give it a shot. Okay, so now get hits going to run. Players implementation of that is that it's gonna take damage and that it's going to set the current state to hit. Let's make one extra change here, which is that in the character class, let's add a set GET method here. So Set Health. And then we can say function set health, and we're going to say health equals value. But if the health is less than or equal to 0, then we can cue for me on this object. So basically this will just mean that any character that drops to 0 health is instantly removed from the game. Maybe we change that later on if we had some animations for removing it from the game, if we write it here, then it's basically setup for all of the characters. So if we go to angry pig, for instance, we don't actually need to have this Q free here. We can just do self dot Health minus equals damage. And then that should run the character set health setter method. I'm going to pull this up here so that it's close to that variable. So let's go ahead and hit play and see where we're at. If we run into the enemy, the animation plays for 0.4 seconds. And I believe we would be taking damage, that's two heads. And then after three hits, health drops to 0. So the player is Q freed from the game.
23. Timer and Adding Damage Knockback: So that's all technically working, but a couple of things we probably want to add to the character. First off, if all of our enemies are colliding with our character in this way, using the hit box studio damage to it. Each enemy can just keep doing it over and over again every time the shape gets entered the body shape. So we want to make sure that the character can't just be overwhelmed. So there should be some kind of invulnerability timer for the player to protect itself. Basically, it can only be hit once every second. And that will make the game a little bit more fair for the player as we add extra enemies. So if we go to the player, we can right-click here at the top at a child node. And let's make a timer. So this timer, we can just have it be 1 second wait time by default. So that will be the duration of the invulnerability. And let's check one shot so that when that timer drops to 0, it doesn't restart, it just stops. So we could call this the invincible timer or invulnerability timer, whatever you prefer. Let's go open the script and we will reference it with a fever. So I'm ready if our invincible equals dollar sign and Vince full-time. So with this timer, we're going to want to start it whenever we get hit. So if you find that get hit method, then we can start the timer when we take the damage. So invincible timer, dot start. I'll put that in here. So now we want to prevent the character from taking damage while the timer is running. So we can put it up here. So if invincible timer, and there's a way to get if it's currently running or not, but I forgot it for a second. So let's actually searched the help. And you can use this in the top right. If you need to look up details about any of the nodes and the game. So if we just type timer here, we can find timer and we can see all of the properties and methods about that. So we want to check if it's stopped. If it stopped, then it should be able to take damage, but otherwise not so. And player dot GD and we wanna do is stopped. This is a method, so we need the parenthesis and only if it stopped are we going to do all this stuff. So otherwise, the invincibility timer means it doesn't matter that the character technically got it by the enemy is not going to enter that state. That character is just going to keep operating as normal. Okay, so now if we hit play, we should be able to kind of limit the amount of times we take damage. So I'm going to run into it a bunch and see how long it takes to actually have the player die. So as you can see, I went through the Enemy many times, but the player didn't die for at least three seconds there. I can hit play and just show that one more time. Okay, So going back and forth through the enemy, and it takes a while to die because the invincibility timers limiting the amount of damage to the player. Now one last thing is that the character can just move around, however wants when it takes damage. So I don't think that feels that good in terms of emphasizing that the character should take damage and kinda be knocked back a little bit. So we should set up some custom movement when the character takes damage so that it staggers a little bit. So how we can do that is up here in our physics process, this is our normal way of moving, but we want to have a different way of moving if the character is in the hidden state. So we can take this code, move it into its own separate function. Down here, I'll call this function normal move. It's going to require an input. As you can see, this flip direction needs the input. And in that, we're going to run this code. And actually we're not going to set the velocity here. Let's just return it. Let's do a match up here. So basically in any other state then the state we're going to move normally. So let's do match current state, and let's get all of those other state names. So state dot AIDL, comma, state dot, state dot jump, comma state dot double jump. And in all of those cases, the velocity is going to be equal to whatever we get back from normal Move, which takes the player input up here. And now, in the last case, or at least the last current case, which is state dot hit. We want a special move function, so velocity equals hit Move. And this isn't gonna need any input because the player is going to have no control over how the character moves in this case. So let's create that function down here, function fit, move to write a little comment here. Okay, so in hit move, we're going to be returning a vector. Of course, the velocity. So we're going to need an amount and a direction. So for the direction, I want to check which way the sprite is currently flipped. And then I want to go in the reverse direction. So if the character is facing to the right, I want the knock back to be in the left direction. So let's make a variable for that variable, knock back direction. And this would be an ant, either positive or a negative one. And if animated sprite dot flip h. So this is going to mean that the character is facing left. So in that case, we want the knock back to be to the right. So the knock back direction, it's just going to be one. And the other cases the character is facing the right, so that's going to be not flip h. And that means that we want to knock back to the left. So knock back direction. It's going to be equal to negative one. And now we can take this value of one and negative one and multiply it by its speed. So our speed for the NAACP back is going to be knocked back speed, not that collision skied. I don't know whatever you wanna call it, times knock back direction. And then for the y, we could have gravity still work during the collision. That would be one option. Or we could just set it to 0, which means that if the character gets hit in midair, it's going to stop having gravity. So for the y part of this velocity vector, we could just have the standard gravity apply here. Or what we could do is set the y speed. Or what we could do is set the y velocity to 0, which means that for that 0.4 seconds for the character is doing the hit move, it's just going to kind of flow in the air and move backwards a little bit. That's how I want to do it for now. It's totally up to you on how you want to set up the character's movement. But yeah, if you don't want the character to move vertically during this hip move, then you can just set it to 0. So let's now create the variable up at the top for the knock back collision speed. So export slope far this and could set it to something like 50. I don't want it to be too fast. Don't want the character to just easily fall off edges that it happens to be nearby, that would be pretty annoying. So we're just keep it kinda small for right now. Okay, let's go ahead and hit play and see where we are at. Okay, so let's go down here to the enemy, get hit. So before we test the player, first, I'm going to go to level 1, click on the player and I'm gonna give him, let's say like 20 health so that we can test without having to restart the game. So let's go ahead and hit play and see where we're at. Okay, so here's the enemy. You're gonna get attacked. Doesn't really have any movement. But if we're facing the enemy, then we do get that knock back and it is in the opposite direction that we were facing. So that is basically what I want. Okay, So I do see one bug at the moment, which is that the characters and tearing the idle state and a little bit too fast. So let's check the player and the animation tree. Okay, and let's make sure everything's working here. So the one shot seems to be working right? The animation hit goes here. So maybe in the animation player, we can check this zero-point four seconds and animation and looping. Okay, so here's what it is. The picnics state function is running even though it's in state dot hit. I believe that the pig next state function does run after everything else. So we might be able to cut this down here and then just take the next state and have that run here as well. Let's see if that works. So pick next state is only going to be running normally if it is basically doing these kinda normal moves. So let's hit play and see if that will work. All right? Okay, So a character can still move around. And when we do get hit, it is properly being knocked back. So that's what we're looking for. We don't want any way for the player to accidentally leave the hit state other than the animation being completely done. So it looks pretty nice there. It can just get rid of the print debug here just to check for the velocity. One final thing we might wanna do is make the knock back direction vector 2 rather than an integer. Technically, this works fine, but what we can do to make it a little bit more clear is due equals vector to right. And then instead of negative one on the x direction, we can say vector two dot left. There may be cases where you want the player to be knocked up and a little bit. And in that case, vector two's would work better here, since you'd be able to kinda define a y component for the direction as well. So for this, what we can do instead is take this out here and then just multiply this by the knock back direction. So this will be our magnitude and then this will be the direction. Theoretically, we'd want to normalize that. So I guess this one technically do anything here, but we would want to make sure that the directions don't go above one because then it would have kind of a magnitude over here. So let's have it normalize. And then we'll set the knock back direction to that. So the normalized vector only having direction multiplied by the speed. And it should work effectively exactly the same as before. But I think this makes it a little bit easier to understand exactly what's going on so our character can still move and everything. Let's get hit by the enemy, gets knocked back in the correct direction. And yeah, it's working exactly like before in terms of final functionality. So that is how we can have enemies like the angry pig damage our player. And that's pretty much going to be it for this section on setting up the angry pick.
24. Coding Wall Sliding State: So in this next part we're going to be adding the wall sliding state for our character. So when we're bordering the wall, we should be able to slide up and down it. And it's also going to give a different field to the movement. So one thing I'm going to add is reducing the rate you slide down the wall as opposed to when he just fall due to gravity. And we'll also add the ability to do a little jump off of the wall, which is different from a normal jump because it's gonna kinda propel us away from the wall automatically. So let's go ahead and dive into our player scene. And I guess one place we could start with would be the animation tree. So if we expand this, we can see that there is nothing here for a while sliding animation. And I think what we're going to put it is between the one-shot hit and the double jump. We do want the well slaying be a high priority animation for getting her and taking damage basically is token and proceed everything. So we'll have it right in here. And instead of a one-shot will make this a blend because being on the wall can be turned on and off. So let's right-click here and I'm going to add a blend T2. And this blend two is going to be, is on wall. So as we connect the output from our one shot double jump to be the input on is on wall and disconnect is on what? The one-shot to finish the trend. And before we add in the animation, we actually need to correct it. So in the animated sprite, we can see that we have a wall jump animation here. But actually that's not accurate. This really is a wall sliding animation. The jump is going to just look like a standard jump animation. So let's rename this animation to be wall slide. And now let's go into our animation tree so I can right-click at a animation and let's choose that wall slide. Well, we haven't actually created that animation in the animation player for it either. So in the animation player, Let's go to idle animation and duplicate it. Okay, so we can rename this to be, I think I need to change here is going to be the value or the animation. And we're of course going change that to be while slide. So now we can go into the Animation tree, delete that animation node, and add a new one so that it's updated with the wall slight animation. And now we connect that into the blend. So if our blend value is set to one, we're going to be well sleeping. And if it's set to 0, we're going to be playing one of these other animations. So now let's dive into the code. So with the kinematic body 2D, there is a function that is, is on wall with parentheses. So you can run that on any kinematic body 2D to check if the character is on the wall or not. But in my practice, I'm not a 100 percent sure why, but I find that you get more consistent results in checking if there is a bordering wall, if you just do a re-cast. So rather than use is on wall and using that to check if we should go into the sliding state, we will use array cast to see if we're right up next against a wall. And then that wall objects supposedly is also going to have to match for being on the world layer because we only want things like the bricks and the platforms to actually be able to count as a wife, we bumped into an enemy that shouldn't count. Luckily, though, if you remember, our player has the collision mask where we're only checking for the world. So basically anything we can collide with poor a 2D physics operation is what we're going to use for the masks or we'll just use this mask. So let's go ahead and create our function for testing if we're bordering up next against the wall. So I'm going to call this funk is on wall re-cast test. I want to make sure that it's clear that we're not just using the standard is unwell function, but doing our own thing here. And then we're going to need a variable. So this is going to be the space state. So in a ghetto game, we can get this space state object, which has the ability to do re-cast tests by using Git world 2D and then checking that direct space state property. So with that we can do a ray cast, which is basically taking a starting point, going out towards another point in our 2D world and seeing if there's any collisions between the starting and ending point. So we're going to have a result variable, which is going to be a dictionary of the collisions that occur. And this is going to be equal to our space state object doing the re-cast and we're gonna do it as a intersected ray. We're starting from the position of our player objects. So that's the global position. And we're going to put the end position on this ray. Basically our starting position plus a certain number of pixels towards the direction our character is facing. Where our character is facing is going to be the wall that we care about. So we can start with our global position here. And an arbitrary number of pixels. I found that 10 works really good. And you can put a property up at the top if you want to set it there and stuff. And we're going to times this phi and u function will write facing direction. So let's go ahead and write that function now. So function get facing direction. So this is going to be pretty straightforward. We're just gonna take a look at. Uh, which direction the sprite of the character is facing towards. And then that's going to be our facing direction. So we can just check if the animated sprite blip H is false. So if that's false, then our character is facing the right. So we want to return a vector two dot, right? So in terms of values, this would just be one comma 0, 0 for y, one for x, meaning we're facing the right. Otherwise, basically it's facing the left. So we can just return vector two dot left. So super easy. Okay, So now we can go back to our re-cast test functions. So there is a couple more parameters here. So you can see the third parameter right there is exclude and it takes an array, so we want to exclude the current object from that. It's not really required here, but just in case for any reason, we don't want the player to show up as a wall for the results. So might as well just do self here as the array. So note the square brackets. That's how he defined it as an array. And this has to be an array because that's the type for the perimeter. So next we can put a collision mask here to make it so that there's intersectoral you when it's going out and checking for collisions, It's only doing it on the world layer. So the easiest way to do that is just going to be to take the collision mask here. And we can just pull that right from the kinematic body 2D by doing self dot collision mask. So this is going to do the re-cast check for the wall for us. And now we can just do some very simple checks. So if there's a result and the dictionary, that means that there was a collision. And presumably that collision happens in the world layer, meaning that it is a block or some other object that would count as a wall. And we just want to see if there's any of those. So we can do that quite easily with if result dot size is greater than 0, then obviously there's something there. So we return true. Otherwise there's no collisions. So there shouldn't be a wall right in front of us, so we can return false. So depending on how we code, it would probably going to need the result of this several times for each loop of our physics process, this is going to be a useful variable for determining what status should be in and what actions and movements we should take. So if we run this up here and our physics process function could just kinda put it right here next to set animation parameters. So we'll run this function and then we'll save the result of it to a Boolean variable. So we can just come up here and do var is bordering wall. Once again, just changing the name a little bit so that it's distinct from the kinematic body is on Wolf function. So is bordering wall. That's just the result of this, is on wall re-cast tests. And now we can just use this whenever we need to see if it left the wall or we jumped off the war, whatever. So this will be very useful. Okay, so let's take this value and go down there to picking the next state. So after this, else will add another one. So here we're going to do something with this and a second here. But for right now, we're going to have another else if down here below. So we need to change this else and to an else if, since there's only this one condition here anyway, we might as well just pull this up here. And I paste it in like that. And now in that case we'd enter the double jump state should work exactly like it did before. And now we need another else. If going further down, if all those other conditions haven't been met, then here's where we're going to use. This is bordering the wall. So if we're on the wall basically, then we want to enter the wall slide state. So let's do self dot current state equals state dot wall slide. And then of course, let's go up to the top and add this into our state's list. We can also modify this a little bit as well. So if the character is in the air and does the jump button, then usually we do want the double jump to occur, but if we're on the wall, we want the jumps to reset. So basically it's going to be jumping from jumps are also should do a normal jumps. So what we can do here is put that IF is bordering wall, and then if that's the case, then instead of entering double jump will just entered jump. So self dark current state equals state dot jumped. And then the else down here, double jump. So while we're on the wall slide, we are going to want the movement to be a little bit different, but we're still going to run the PEC next state function. So we'll set up another match for the current state. So if we get the wall slide, we're still going to pick the next state. Since we basically already setup the other conditions we need for that in the picnic state function. But for the movement itself, we're going to change how that works when we're on the wall. So I'm going to create a new function for law slide roof. And this is not gonna take any input from the player because basically we're not going to be using x input to determine x movement. It's going to be stuck on the wall until the character jumps away from the wall. So let's go ahead and create that function down here. Hip. So function while slight move. Okay? And just like the other functions for moving, we're going to be returning a vector. And for the x, we're going to take the current velocity and we're going to just keep that as it is. So if there's no x movement, we're not changing the x movement. And then in addition to that, we're going to still do men taking the lower of the two values. So velocity, why the current y velocity and kinda similar to before, we're going to add the game settings gravity, but we're going to multiply this by a friction value. So I'm going to call this wall slide friction. And then just like the normal function, we still want that terminal velocity being kind of our absolute fastest speed. We're going to follow them. So obviously we need this wall slide friction value. So I'll just go up here to the top and make an another flow variable. And I'm going to want this to be below one because the character should slide slower when it's on the wall, kind of grappling the wall, then it would normally just free-falling. So I can multiply this by 0.5 and then it will slide down the wall quite slowly. And so that will basically give us our wall slide move while we're in the wall slide states so we can't change our x velocity. And the sliding down the wall is going to be slower than it would be falling. So in our code when we're in the wall slide state, in most states, we can press jump in order to jump. So if we're bordering the wall, we're going to get that state.com, otherwise, state dot-dot-dot. And if we remember, because of the satyr function for this current state, if we come down here, that means it's going to run the jump function, which is going to add a Upwards Jump impulse and increase the jump value. So that generally is okay, but we want it to work it a little bit differently when we are doing it. From the wall.
25. Wall Jump Movement: So if we enter this Jumps state from the wall, and we can check for that by checking the current state before we actually change it. So current state double equals state dot loss slide. And then just in case we switch to the Jumps state in any way without pressing jump, that we don't jump from the wall. So for instance, if the character kinda slides off the wall, but not under the ground, and we enter the jump state for the animation. We don't actually want it to jump immediately. So input dot is action, just crest. And we're checking for jump. Okay, That's one extra set of parenthesis. Okay? And then if that's the case, then we can do a wall jump. So this would be similar to jump, but not exactly the same. Else. We can do, the normal jump and other circumstances. So let's go up here to the basic jump and let's create a wall jump. So things that are going to be the same about the wall jump. So for the wall jump, we're going to be doing this same thing. The y velocity is going to be the same when we enter that wall jump. And because we entered from the wall, the jumps should always start at one. Since we're considering the wall kind of like the ground in the sense that it resets our jumps. The other thing that we're going to want to have here, basically locking up our base movement so that we can jump away from the wall with some x velocity in addition to the y velocity. But we don't want this to be something that player can control for just a second. So up here, for our standard normal move, we can actually check here if the water jump timer, which we're about to create has started, and if it hasn't started, then we'll do is a normal move. But if it is running, then we're going to forego this normal move. Even though we're in the Jumps state in order to do a special wall jump move temporarily. So let's create a wall jump timer and our player. So I'm going to create the timer, gonna make a wall jump timer here. And we're going to take away the normal movement from the player for bough, let's say 0.15 seconds. So if you change the wait time to 0.15, make sure one shot is checked because once the timer is done, we don't want it to run again until we restart a new wall jump at some point in the game. So now we need to reference that timer in the script, just like the invincible timer. So unready var log jump timer equals dollar sign wall jump timer. So we can check down here if the wall jump timer is stopped. And that's a function. So if it is stopped, then we'll do the normal move here. Otherwise we're going to do a, another special moves. So that special movement, Let's make another function for that we can call it while jumping movement. And once again, we don't need the input because this is kind of forced control for the x-axis. And let's come down here. So function while jumping movement. And the reason we need this function is because unlike the jump, which is kind of just a standard quick impulse, this is actually going to be over a few frames. So we want it to keep doing this until the timer on the wall jump is done. So that's why we need to run this each frame until that timer is up. So we can just return a vector to here. And this is going to do move speed. And other variable will need to set which is while jumped direction, which is going to be in that wall jump function. So basically the direction that the character jumps away from the wall at is going to be the direction and keeps moving in until the timer is done. And then down here, the movement is going to be the same as a standard movement. Just pull away the wall, slight friction. So it's just velocity y plus gravity. And now we need to create the wall jump direction. So let's go down to the wall jump function. Again. One thing we're going to need to do is to start the timer while Jam timer does start. And we also need to get the wall jump direction. And this is going to be equal to the opposite current facing direction at the frame where we start the wall jump. So negative gate facing direction. And that's a function. So that's also declare this variable up here at the top. In this should be a vector two. So this was a lot of code. Let's go to set current state. And we need to set up a little bit here for when we enter the wall state. So Let's do state dot wall slide 11 on the wall. One thing we definitely want to set is the jumps equal to 0. Since we're resetting the jumps for the player. And we also want the animation tree is going to set the parameter is this ON wall slash blend amount. And this is going to be set to one. And so that needs to be a one in order for the wall slide animation to play. Okay, and it looks like I wrote the name for that variable wrong up here. So let's just paste that in while Jam direction is what we want. Now lastly, we also want the is unwanted to update on each frame. So we're just checking if the character is still on the wall or not and then updating that. In fact, maybe we don't even need this here because we're just going to be setting at every frame. So I'll just cut that. And we'll go up here to set anime parameters. And that's what we're gonna do it instead. So we're going to take that is bordering wall and convert it into a one or 0 depending on if it's true or false. So let's write in is on law and I guess I can declare that that's going to be an ENT obviously. And we can do if is bordering wall and if it's bordering the wall, we're saying it's on the wall. So the variable should be a one. So is on, while nT equals 1, otherwise is on wall, is going to be equal to 0. And now that it's an integer, we can set the parameter. So animation tree dot set parameters is on wall slash blend amount. And that's going to be whatever hour is on law integer is set to. So now our animation tree should be updated every frame to know whether we should be playing the wall sliding animation or not. Let's just make sure in the animation tree we have that parameter here. So we can see parameters is on wall, blend them out. And we can see that setup with the wall slide.
26. Testing Wall Jump and Finalizing Character Movement: Okay, so after all that code, let's go ahead and actually see where we're at. Let's hit play. Okay. Let's see. We do have the wall sliding, okay, and you can see when we jump off the wall, the animation parameters sets correctly. So this is one of the reasons I'm not using his own wall check because when you use the webcast, I just get much better results. So as soon as we get up here, it's checking over here for the re-cast. It doesn't find a wall. So we immediately switch to the jumper fall animation, which just looks a lot better. So one thing we can note here is that our character moves pretty fast currently, with the ability to double jump and do wall slides. This is quite over the top, so we're probably going to need to tone that down. Another thing I noticed is that it doesn't always feel good going up to the edge of one of these blocks and then sliding off with this capsule 2D shapes. So actually changed the shape of the character to a rectangle as well. I believe I said towards the start of this course, it's kinda up to you what you prefer. And I think by this point, I prefer it to be a rectangle. So one thing that's not currently working super well is when we do that wall jump, we get stuck in it. So I'm not sure if we are checking properly to see if the timer has stopped. Because once the timer is stopped, you should be able to regain control of your character. Okay, so let's do the low-hanging fruit first in the player, we can change the collision shape. So we'll change this to a rectangle shape. And I believe the sizes I wanted to put for this work, 10707 and 10, I guess it was. So roughly the shape of our character, but, but now our collision shape will make it so that we shouldn't have any sliding off the edge and why the B clearly on are clearly off. I think another way to potentially get around that could be using Moving collide function instead of move and slide. Since the movements like function is going to kind of move you along the ground. But the moving collide function, if there is something in the way, it's just going to stop your movement entirely, roughly speaking. But I think this will work pretty good for right now. Next, I want to kind of limit some of the movement in the game so we can turn down the jump impulse. I'm going to pull this down to 500 by default. And then in the game settings, I'm going to lower the gravity to 40. Let's hit Play and see how that affects things. Maybe we even want to lower the characters speed down by a little bit. So let's see in the player, okay, It's still using 200. So I guess we could set it to 180. Okay, so it's still pretty fast. But I think with this amount of gravity, it's a little bit less ridiculous. Distill would be a pretty fast-paced platform a bit, maybe for a ninja frog, that kinda makes some sense. So we can leave it at the settings for right now. Okay, so we have the problem with a wall jumping movement is going on for way too long. So I'm actually going to take the wall jump timer and print the time remaining. So let's print the time remaining to the console log and let's see how long this actually goes on for should be 0.15 seconds, which is pretty fast. Okay? So it took one frame, they're essentially and then after that, it's still going. Okay. So you see what's going on here? When we leave the wall, It's still on the wall. Slide states, so that's why we can't control the movement. So what we could do down here is just add another way to enter the Jumps state, but make it so that we do that without actually jumping. So we already know at this point that is bordering wall is false. So we don't really need to check. So we can just do self dot current state here is equal to state dot-dot-dot. So when we enter the state like this, since this is going to be basically when something causes the character to leave the wall that isn't pressing the jump button. Then we wanna make sure down here that we enter it without jumping. And that is why I wrote this bit here. Okay? So this is basically just to distinguish that there's different ways to enter the Jumps state. And we're not always trying to actually do a jump function, even if we're playing that jump animation. So let's go ahead and hit play now. And hopefully the character should be able to, oh God. Okay, so let's go ahead and take a look. And clearly, that is not what we intended. So I do think we need a condition here actually. So we're gonna do else-if not bordering wall, I guess. So let's put in the else-if and we're going to be checking that the current state is equal to state dot wa slide. So we should only be able to arbitrarily and to the jump state from the wall slide state like this. And just so it's a little bit more readable, understandable also important. And not is bordering wall. So if this bit has already run, then this should already be true. So it's not really going to be necessary. But I guess it gives a hint about what's going on right here. So let's go ahead and hit play. And we shouldn't be able to enter that jump from the start because we weren't on the wall, but now we're on the wall slide. Let's jump from the wall. And you can see it gives a way for us to enter the jump, but without actually adding another jump animation. So we only have that one jump away from the wall. And this is what we've been looking for. So we can see although the wall jump is forced, we can press towards the wall and it does go back pretty quickly. Technically, that is working as intended. Maybe it moves a little bit too fast and the air, so we could slow down the characters default, air movement or air horizontal acceleration if we wanted to. But if you like the feel of the character now, then it should be pretty much good to go for all of the animations recording, set this character up with maybe a little bit to sliding around the map. But a lot of that is just going to be tweaking the variables. So let's cut out that little bit that is printing to the console log a bunch. Just going to hit Control F and check Footprints. This one's okay I guess. But let's get rid of this wall jump Timer Text. Now, one more thing to show. Earlier, I said that when we're doing our webcast, we want to make sure that this only occurs when our characters on the wall like this. And maybe we don't even want to have the wall hugging if we're on the ground and the wall like this. So that is another thing we can turn off. Maybe we like, I don't know. But we wanted to make sure that the pig can't count as the wall. And you can see that clearly the pig does not count as the wall because it's on a separate layer, it's on its enemy layer, which makes physics layers really helpful. So we can still bounce on them. We can still, let's see if we can get attack and then a double John. Okay, Nice. And then after that we can go for some nice wall slides into a jump or while slides into a double, dumps, whatever we want to do. So our character is pretty much fully working here. So there'll be a couple more things we want to add to the game still like a second enemy and actually building out some levels. It's been awhile since we've touched the tile set, but it might be fun to transition between a few levels. When you beat level one, you can move to level two, so on and so forth. So that'll be kind of what we're looking at in the final videos.
27. Cleanup and Bug Fixes: Okay everyone, So as we get close to the end of this course, I want to have one quick video here for cleaning up some of the things that were a little bit messy earlier on. So starting with that is increasing the double jump animation to 0.35 seconds. So if we take a short look at the double jump, I think it ends in a little bit abruptly there. And I was finding that if we increase the animation duration a little bit, that it transitions back into its fall or jump animations a little bit smoother. So let's go into the player, the animation player. And if we find the double jump animation, we can increase the duration here to 0.35 seconds. Change this snap to 0.05 seconds. And let's zoom in and just move this animation finished over to the 0.352 mark. So now when we go back into the game, I think the animation just goes a little bit better there. The next thing I wanna do is add a second pig to the game. So we're not really building our levels quite yet. But I figure this third waypoints been sitting here for a long time. And since our angry pig is completely made, it kinda of a shame if we don't reuse some of the code, let's just select our Pig in the hierarchy and do a Command or Control D to duplicate it. If you hold Alt down where you're hovering over the pigs, we'll select and move the currently selected one. So let's move this angry pig over here to the right. And now let's duplicate the waypoint 3. So I'm going to Alt. So I'm going to Command D on Mac. And then I'm going to go over here to where it is in the game world. Hold Alt D to move that specific waypoint and as pour over here. So since we have the code set up pretty nicely, we've already created the pathing for the angry pick. Now we just need to define that the angry pig is going to use waypoints 3 and 4. So let's click on Angry picked to go to the waypoints array. And let's select waypoint three instead of one in waypoint four instead of three. Another small issue is that if we look at the collision shape for our angry pig and hitting the game world, we can see that it's actually bouncing a little bit above where the ground is. So that doesn't look quite right. So if we go into the angry pig, we can just take our collision shape, the main one for the actual world collisions. And then let's just take the position here and change it to a two from a three for the y position. So this just moves it up a little bit. And now it will collide with the ground a lot better and it will look more correct. So let's just go ahead and preview where we're at so far. So our pigs are kind of a little bit more up against the ground and we have this second angry pig. Know how it's paddling distances a lot further, but I still works just the same as the first angry pig. And that's really cool. It was so much easier to create the second enemy. And then when we have to actually code everything from scratch, reusability, yeah. So one other issue, and this one's kind of a major thing is that with our jump mechanics, sometimes if we jump at an angle like this, we actually damage the pig even though we're ascending, which doesn't really make sense. So what we can do is add not only a, was the players jump hit box colliding from above, but was the velocity as ascending or descending. So we should only damage the pigs. We're dropping down onto it. Not when we're sending out an angle like that. It's kind of weird. So it's a quick fix. Let's go into the player script and then let's find where we're checking to deal damage to an enemy. So I think that might have been on Jump Box entered. And here we can see the line for if we deal damage to the enemy. Okay, So this line is just to check if we're hitting the enemy in the right way. So the position should be above. So we're going to go down here and add an extra condition, which is that the velocity dot y. I think we want that to be less than 0. We want to make sure that it's going downwards on the screen. So let's just hit play and take a look. There'll be immediately obvious. So if we jump onto the enemy, okay, what's, it's actually the other way. And so it's a little confusing since the y-direction is sort of inverted. So if we are going down, that's actually positive and negative would be going upwards on the screen and our character is going down to land on the enemy. So let's hit play, test that again on what time, just make sure we can bounce. That's what we want. But now we can't do this weird inclined damage move. In fact, what happens is we get damaged, which is kinda how it should be. I think. The other thing with the angry pig, and if we go into it's seen and take a look at that, Let's disable the main collision shaped 2D. We can see that when I made the enemy collision shape is actually really small. And that does pay that the player a lot. But I think to the point where it doesn't make sense. So the player can be here and still not take any damage from the enemy. So I'm going to bump that up just a bit. So let's take the enemy collision shape under the enemy collision hit box, and let's take the extents and make that 10. So now you can see that this still isn't really matching the sprite frame. So you can see that this still is smaller than the sprite itself. And if we turn on the main collision shape, the one for if the pig collides with the world, you can see that still larger. So there's still flight. So this still favors the player, but maybe it makes a little bit more sense now. Okay, So with those fixes, come out with the angry pigs should be a little bit more clean. So let's hit play and just test everything. So first off, making sure we can still do a bounce attack on the enemy. That's all good. And let's just try to be kind of sneaky and try to avoid damage. Well, obviously we can see that the collision shapes are going to favor us, but
28. Game Over Screen & Camera Bounds: One of the next things I'd like to add is for the ability for the character to fall off the edge and lose the game. But right now, we have a follow camera with no limits. So I can kinda show what will happen right now, if we go off the edge, you can see, no matter where the player goes, it's just going to keep following. So would be kinda weird to just have a game over right here. So the next thing we're going to want to do is to take this camera and set some limits to it. So with any camera, you can manually set limits using the limit category down here. So you can see left, top, right, and bottom. But I think a better way of doing that is using position 2D nodes in order to set where the top left limit is and the bottom right limit is just like we set waypoint targets. And then to apply that to the camera 2D and a script whenever the script loads. So let's go ahead and take this camera 2D. I'm going to rename it something like follow camera to be a little bit more specific. When we do that, it gives us a warning on our remote transform. So you've gotta reset the path to the follow camera on this remote path thing over here. So now let's take this follow camera, right-click on it and turn it into a reusable scene. I might be a little overkill, but I guess I'll create a category in here, a photo rather. So if I click New Folder and I'll just call this camera. So if you have any other cameras, so might be a bit redundant. But I created a folder here called camera. Just right-click new folder. And we go in here and we can save this scene as a reusable objects, but they're so now let's dive into the cameras scene. And this scene. First off, we're going to want to reset the transform to 000 by default. And secondly, we need to add in some position Tuesdays, but we don't want the position to these to move with the camera if the camera changes its position. But rather we wanted them to be more of a global position in our game. So we can make sure, even if it's a child that it's not going to inherit the position by right-click, Add a child node and then using node as the base. So I could call this bounds. And then inside of this bounds node will create the position Tuesdays. What you're now going to have a totally separate position from the follow camera. So with the position 2D here, I'm going to call this top left. I'm going to Command D, duplicate it, and we'll call this bottom. Right. Now let's just set some default position so that we know it's not sitting there at the origin. I'm going to select top-left hold outbound, and move the top left to right around here. And I'll do the same thing with bottom-right. Select it, hold Alt down, and move it to right about here. Now in script, when the script loads will set the top, let set the left and top physician over here, and the bottom and right positions for the camera by using this position. So let's take the photo camera, right-click on it, add a script. Of course, we'll call this follow camera, save it in the camera folder. Now, we're going to need on already var or top left, bound, or just top left or other. And let's set that equal to dollar sign top-left. Now note, when you have nested children, you need the full path. So we're going to need bounds slash top-left, but Godot kind of already know is what we're going for there. So it's pretty easy to have autocomplete. So let's do var bottom right equals dollar sign bounds, bottom right. So now in funk ready we can take the limits. Let's do self.view limits. Okay, I guess you have to set each one individually, not as a whole category. So we'll do self limits. Let's start with top. And this is going to be a value. So get the position, the absolute global world position of the top left. So that's going to be a top left, top underscore left dot global position. And since we're dealing top, we're looking at the y-value. So global position dot y. Now we need limit left equals top left, global position dot x k. And saving it should have no errors currently. And now we do the same thing with the bottom right. So that's going to be equals bottom, right? Dot global position dot x, because right is going left and right, which is x. So self bottom dot right equals bottom right, local position dot y, and that's not bottom right here, that's Limits bottom. And up here it should be limited, right? So now that we have the set only need to do is make sure that the camera is on level one and then we can set the bounds. So right now there's follow camera isn't properly getting the scene, so I'll just add a new follow camera and I just put it right around here. Let's delete the old one that doesn't have the bounce. And then this one, we can rename follow camera, since it has the same path as the remote transforms path that kind of fixes itself. And now we have a camera with these bounds. So what we need to do is right-click on follow camera, choose editable children. And now we can edit the top left and bottom right bounds. So the top left bounds, that's put it. I don't know somewhere over here for right now. So that'll be the top and a leftmost limits for our camera. And then down here, first, let's hide the game over screen. But we'll take the bottom right and let's move it to or just have it set to right around there. It might be helpful to turn on a pixel grid for right now if we'd like to. Now to show that these limits are separate from the camera in terms of its position, Let's select the photo camera, hold Alt down and move it. So you see even though we move that follow camera, the limits do not move their position, which is, we set up that bounds node. So now to get our limits perfect, we might want to set up a pixel grid. Maybe we want the bottom cutoff of the screen to be right here so that we can't see anything below that. So let's turn on grid snap and smart snap ligase. And now let's pull this to where it lines up here on the grid. So I'm going to pull this right around there. And we can check the transform here. We can see that this is kind of a multiple of twos. So I think that's not being as going to work out pretty well. We can always adjust it later. So now let's make sure I follow camera is actually working or hip plane. Okay, Now note, no matter how far out character moves to the left, we can't actually go further than this left limit and the top limit as well. So you can see we're getting to the top of the screen there. So having constraints like this means we don't have to just identify them. So having constraints like this means we don't have to design an endless level. So let's see when we fall off the edge here, well, our character is gone. Technically, he's still able to move. You can see we haven't game over it or anything. That'll be next. We have to create kind of a dead zone where we end the game for our character. Also re-enable the visibility of the game over screen if you want it to still be able to work.
29. Death Zone & More on Signals: So next we need to create a zone which basically when the player enters, we get a game over the player die is quote unquote, whatever you wanna call it. So that area will be right below our bounds. So the character goes off screen, dropping below the screen. And while you get the GameOver, pretty standard platform of stuff. So let's start by creating such an area. I will right-click on our level. Let's add a child note. There'll be an area 2D. And we can call our area 2D whatever we want. And maybe dead zone. I think I'll just take it and call it bottom of the screen. And now we need to define the area for that. So I'm going to right-click Add a child node, and let's add a rectangle shape, I think would work perfect for this. So we need collision shaped 2D. And then I'm going to take shape, do a rectangle shape, and let's just kinda stretched the size of it so we can say something like this. Now we just kinda need to move it into a position where it's at the right edge of the screen. So let's drag it right there. I think it's about what we need it to be. We're just kinda precision. It doesn't really matter where it is left and right, since we're just going to have it be at least as big as the level size. So having it like this, okay, it just needs to be right there below the bottom of what we can visibly see. So now I can add a script to that. So let's actually make it a separate scene for right now. So I'll right-click it and let's save branches is seen. So we could put this in maps or maybe another folder for something like Zones are special areas that we use across the game could be okay. So let's save it and they're going to right-click it and attach a script. So we can leave this as bottom of screenshot, GED. Or you might want to call it game over areas because it might be different areas in the game other than the bottom of the screen where you'd want to trigger an immediate game over. For right now, we can just call it this just so it matches our scene name. I think that's the most straightforward. So let's create that. And now let's just get rid of this extra code we don't need. So as we have done a few times before, if we take an area to D go to the Inspector, then we have the ability to choose if it is monitoring and monitor terrible and to set what layers we're going to be colliding or checking on. So we can just turn off monitor bowl because nothing is really going to be needing to check on this. So unless you wanna do it the other way around with the player checks for the zone. But I think kind of separating it out with the zones, tell the player when it enters and something should happen, but the player figures that out rather than the player constantly checking for different zones. I think breaking it up this way, it just makes it a little bit more sense to me. So I'm going to turn off monitor trouble. And as such, we don't need a layer down here for the collision, but we do need to check for the player layer. So let's take the mask and set that to the fourth bit for player or wherever you have it set up and your physics 2D settings. So this bottom of the screen we'll be able to pick up when a player enters the bottom of the screen. So we can go to note, we can do body shape entered, and we can just create a receiver method for that inside of the bottom of screen script. So let's add that in. So let's select bottom of the screen down here, connecting from the object to itself. So for our body when it enters, it should be a player. So it should have all the functionality that a player has. And if not, we would want to have an error thrown so that we can figure out how something entered it and was picked up without actually being a player. So we can just take our body and basically run whatever function we expect the body to have on that object. Some. So maybe we can just call it body dot die or something like that. And now we go into the player and we just need to create that function. So let's go down here towards the bottom. I would do, I'll put it right here, function dy. And for this, we'll definitely want to trigger the game overstate. So we'll want to emit the signal just like we would if our health dropped to 0. So let's emit the signal, lay your died, and pass ourself as the player object to that game manager. Or rather we're not directly passing it to the game manager. But if you recall, in the game manager, we had the connection here made between the game manager whenever a player loads in the game to that player signal. So it's not directly telling the game manager, but rather it's emitting the signal so that anything connected to that signal can respond to the player dying. Which means that that could definitely be other objects. Or depending on how our codes threaten, the game manager might not necessarily actually respond to that connect, but it does as red. So the other thing of course, is to Q3. Now, if you had a animation for the character dying, this would be a great place to switch into that state, create a totally separate state for it. Run the animation. When the animation is done, then you q3. And so to queuing for you immediately. But we don't have that animation, so we're just going to do with simple Q3 and move things along. So I think these are actually just going to be basically the two things we really need there. So as long as we don't have any errors, we might actually have everything good now. So let's actually test the game and see if that works. So we can still follow, can move to the edge, but we can't see down past the bottom of the screen anymore. So let's just jump down there and see what happens. Well, looks like we get an immediate game over. Now obviously, it's a little bit more fun if you do have an animation, make a big deal out of, uh, maybe some music, that kind of thing. But that is at least as simple way to do it. Now, do you notice one other thing which is that with our game over screen here, it's not 0% transparent. You can actually see a little bit of the background there, which isn't actually too bad. I mean, I maybe I actually don't want this background to be a 100 percent transparent, but as retina, it's not supposed to do that. So let's just quickly take a look at that game over screen. And you know what the reason is. It's the in that final frame where the timer is stopped, then I think the reason for that is in that final frame, whether the time was actually stopped. It's not going to do the final update here. So let's see if there's a way that we can actually update that. So if we jump into the game over screen, we can probably create a receiver method with the timer. So let's go into node. Let's see timeout emitted when the timer reaches 0. Yeah, Perfect. Okay, So let's connect that into the game over script. And now we have this little bit here. So all we need to do is set screen modulate color and turn this final value to one. So there you go. More free practice with signal connections and you can see how they get pretty useful and pretty easy to use when they become kind of intuitive.
30. Drop Down Platforms and Player Jump Attack Fix: So one of the things that's been sitting around the game since the start, but we haven't really done anything with are these platforms. So I really standard platform and mechanic is the ability to drop down. So a really standard platform and mechanic is to be above a platform that's then like this. And to be able to drop down below it, also, to be able to revise through it from jumping from down below. So as things are right now, if we jump at this platform from down below, we're just going to bump our hat on the platform, pretty much like cell. So that's not what we're looking for. Also, we saw that we got to game over really quick. Let's change that health back to three, just so we don't accidentally get a game over from really simple tests like that. And now we need to set up the tile map so that when we create these tiles, that they have a one-way collision so that we can pass through the bottom. So if we click on tile map and we go to our tile set over here, we can click on our terrain tiles. Let's zoom in a bit. And let's look for those tiles which should have the one-way collision, which are over here on the right. So if we look at the inspector now we can see selected collision one way. So we just need to check that for all of these nine tiles and any other tiles that we'd like to be able to pass through from underneath. So let's just do those all. Now let's go ahead and hit play. And we can try and jumping through that. We can see that we're able to jump through the ground, but when we are on the top side, we do not pass back through it. So let's just test that a little bit more and seems to basically be working through. So in order for our character to pass back through down, we need to set up some kind of drop function. So in this game, how I'm going to set it up is that when you press down twice, whatever you're down key is for us right now that's S. Then it will drop the character down below the platform. We wouldn't want to just automatically dropped down through the platform because then it would basically be like a no collision tile. But we do want to be able to sit on top of it as well as dropped down through it. So how we can set up a drop function would be with a drop timer. So let's go into the player and create another timer. The reason for this timer is that we want to check if down was pressed twice in a short period of time. And if so, then you've under drop function. So I will right-click on the player at a child node and we will add in the timer. So let's call this timer, interrupt timer. And I'm going to set the wait time to 0.2 seconds. This should be at least the duration of one or two frames of animation. So I think point to is working pretty well for me earlier. Let's go into the player script now. So you can kinda choose where you want to put it. I was thinking about putting it in player input, but this is more specifically just to get the left-right, up-down movement. So I guess I'll put it right beneath it. So what we're going to be doing is checking if the down button is pressed. So input.txt, and then we will see action just pressed. So that's the one we want. Then we need to choose the action down. And if this was just pressed, then we need to see if the timer is running or not. So if the timer is running already, that means we just pressed down previously, so we should drop. Otherwise we should start the timer. So if, let's say drop timer is stopped. So as basically just like any other timer, but we need to declare it up here on ready var Schwab timer equals dollar sign drop timer. So if it's stopped, then we want to start the timer. So drop timer. Otherwise the timer is running. So we want to run a drop function on the player that will create an a second here. Now note that we don't want this timer to loop. We only want it to be running when we specifically start it up till the duration of that dropped down period. Click on the drop timer and then make sure one shot is checked. That's important. So now we just need to create a drop function. So I will put it kinda down here with the other movement functions, jump, ball, jump. And then next we'll do function drop. Okay, So in order for our character to drop down through the platform when there's a collider, there is to just adjust the position of our character and we can just do that a single pixel. So if we take physician dot y and add one to it, then that will move through the collider on those platforms and our character will fall through the platform. So it's really as simple as that. So let's go ahead and hit play and test where we're at. We come over here, we can press S twice. We fall through the platform and over there as well, should fall through that one. And this one over here. So any platform that we've set up with that one-way collision should work from for us. And we should also be able to jump straight through it. If you find it a little bit hard to pass through, sometimes you could consider bumping up the wait time or 2s or 0.25 seconds. And if for some reason you find you're not able to pass through one of the platforms. Just go check the tile set and make sure that that one-way collision is checked. So this is just for a bug fix. But one thing I've noticed is that for our character trying to do jumped damage to an enemy, sometimes this global position isn't always consistent. So I think we might be able to just actually get rid of the collision check and then just check if the velocity is falling velocity and leave it as that. So let's go ahead and hit play and see if this will work for us so our character can bounce. Let's test from a higher position. We can do the following while jump. Okay, and then there as well. And then let's just retest shouldn't be able to deal damage from below. And yeah, that's still the case. So I guess in this case simpler is better. So I'm just going to leave that position, check out of it. Since sometimes the position of the hit box can be a little bit below the hurt box. You could also have a bigger adjustment in favor of the player. But even if you do that, there may still be extreme examples where the characters hit boxes. For some reason, ten pixels below the enemies hurt box. So this just seems to be a much more straightforward solution. Okay? And now we can just go do one final test, making sure all of our platforms work and that we can damage the enemies correctly. So that seems to be much, much more fluid and just better in general. So that's pretty much going to be it for this quick video.
31. Level Transitions and Creating Levels 1 & 2: In this next video, I'd like to actually create a level one, create a Level 2, and then create a way for us to go between the two. So how you design your level is pretty much up to you. We already created all the tools for it. So if you want to add some extra tiles and platforms, we can go into the tile map. And of course, creating additional angry pigs is just going to be a matter of duplicating them or a dragging the scene from our file system and creating new waypoints for them to go between. So first off, as a trick that you can use, you can use the select function when you have the tile map selected. And we can just select of these tiles. I'm gonna control X them away or Command X on Mac. And you can see that you can paste it in. But really I'm just gonna get rid of all of this. So let's switch back to the pencil tool. I'm just going to go ahead and draw what I need. Okay, so now I'm going to go ahead and create Level 2. I think the quickest way to get it started off, It's going to be to duplicate level one. So I'm going to go into my maps folder, Right-click level one, duplicate that, and just kinda call it level 2. Now we can open it up and obviously I'm going to rename the root node to level 2. So to make it obvious that it is a different level, the first thing I will change, it will be the background. So let's change this to, I suppose let's see the purple colored background. So now level one and level two are distinct from each other. Let me go ahead and create a level 2 scenarios, basically going to add and created a lab, a one, a level 2, and we have a level 3, but that's really just said that level too, you can transition into level 3. So now let's go ahead and create our way for the character to move from level one to level two. So I'm going to use the area to D for the switch will trigger that event where we jumped levels. So I'm going to right-click on level 1, add a child node. We want to area 2D at the bottom. I'm going to rename this and we can call it move. We might not necessarily be calling them levels, so we want to be a little generic here, plus the folder is called maps. So with Matt move, I'm going to save this as a new scene. Right-click Save branches scene. And let's put it in zones. Since this is an area which triggers some kind of event, kinda like the bottom of screen GameOver oven. So let's save this here and then let's dive into the scene. So for our map move area, we're going to need a triggering a collision shape. So let's do a collision shaped 2D. I'm going to make the default for this a rectangle shape. And then we can see it in our level one. So I'm going to select the mat move and let's hold Alt and move it up around here. So clearly this won't be a big enough collision shape to really justify being the end of the level. So we'll probably make this bigger. But another thing we want to do is actually give the players a way to indicate that it is the end of the level so that they know what goal they're shooting for. So inside of the art for this game, we can check our pixel adventure one and go down to items and check point. And we can find a pretty cool flag that we can use for the end of this level. So I'm going to go into the map move scene, and let's add a sprite here. And so if I drag this checkpoint onto the screen, we can see there's a bunch of frames of animation for this. So I'm going to hit Control Z to undo adding that spray. And a perfect node for us would be a animated sprite nodes. So I'm going to search for that. And then we're going to take this flag idle and pop it into frames. Well, first we got to create a new sprite frames. So click on frames, empty new sprite frames. And now let's add in that flag idle animation. So I'll rename the animation ad and I'll click here, add frames from sprite sheet. So it's going to items, checkpoints, checkpoint black, idle. Ok, and let's get all of those frames. It looks like there's 10 of them. So we want ten horizontal, one vertical. And then select Clear all frames, add them in. And then make sure that this animation is playing and put the FPS at 20. Now we are also going to want to move this animated sprite object up. So I'm going to hold Alt down and move it up. Having snapping may help here. Then let's also take the collision shape and move it up as well. And if you need to at any point you can also turn Snapping off. It's not a requirement. And we want to resize the collision shape to be a little bit bigger than our flag. So this'll be a good end of the level point for our character to reach. Now we can look at Level 1 and we can position this map move goal. I guess I'll put it right around there. Now if we go back into our map move, we can define the collision layers we need, which is basically going to be to pick up when the player enters it. So open collision on the right, like we did for every other area. Turn off world mask and world layer and then put player as the mask. And you can also turn off mono terrible because this is going to be, because this is going to be a one-way event. So we're only going to check for the player. Okay, so now we just need to add in a simple script to our map move. So I'm going to attach a script that's created. And in this script we're going to need one, receive a method which is going to come from the area 2D. You probably know where I'm going with this body shape entered on the node section on the right. Body shape entered connect to the mat move script. And here it should only be players that enters. When the player enters this area, we want to switch levels. So we can do get seen dot change Scene 2. And we're going to need a packed scene here. So how we can define our packed scene for the script is we create an export variable. So we're going to export a pack seen variable. And we can say destination scene. And now of course we need to use that variable as our parameter. So paste that down there. Now if we click on our map move, we should be able to see that we can set a destination seen here. So on level one, I'm going to take our mat move and we're going to set the destination seen as level two. So you can click here a lotus seeing. And of course we're gonna go into Maps level two. You can see a little preview for our scene there. Let's go into level 2 and let's add a map move scene. We'll put it right over here for the end of this level. Make sure it's not on the tile map, of course. But in terms of hierarchy, you may want it above the player so that it shows behind the play rather than in front of it. So let's move that. Okay, I'm going to shut off snapping here so we can get it just right. That looks about right. Let's take the destination seen here and make it level three, maps level 3. Okay, Now we can kind of play test our game here a little bit. I'm going to hit play. Then I'll just run through this level real quick. Okay, gotta get past this pig without taking too much damage. Just kind of ignore him and do the drop-down function to get down here, I have required that intentionally and just a little bit of a precise jump there. Let's get to the second level. Okay, and it did run into this issue earlier. So it turns out that checking if a object is not null is not good enough here. So what you actually want to use here, and this is back in that game manager script we set up. Is, is instance valid? And of course this is going to be active player. So if you've created an object in your game and you want to make sure that it is still there before you run something. This is the right code. If you check, if it does not equal null, then this can end up running instead, which obviously isn't going to work when the active players already been removed from the scene. So now we can go ahead and rerun the level and it should run this time. So let's bounce on that guy. Note the damage attack. This is a little tricky here in terms of game design. That might be a little unfair, but we're still just testing amount. So let's get to that second level and then boom, we enter level 2. Of course, we might want a transition of some kind, kinda like we did with the game over screen. Here we gotta jump down, okay, we gotta angry pig to deal with going to jump up here. And here it's a little bit tricky because we have to stay away from the bottom of the screen. So that's going to require kinda doing a double jump. And then we gotta keep jumping around k out. It seems to be a little bit of a bug there with that one-way collision. I think it's setup for the wrong direction. So I'll have to check that one out because as you can see, it can fall through there but I can't go back up. And then for the rest of the level 0, why do I gotta fix the camera bounce? But you can see I went to level three there and once again, the one-way collision is the wrong direction there. So let's fix the camera bands and level 2, I'm going to lock the tile map so that I accidentally don't mess around with that. Let's grab the top left and move it to around here. Actually, it should be lined up with the left side. So that's our bound. And then down here. And then down here at the bottom right bound would set that up to be right there, I think. Okay, so here is an issue when you are building your tile maps. You gotta make sure that you don't accidentally rotate your tiles. So you can see here that these platforms are obviously going down below. So if you press a S and possibly some other keys like Z and X on your keyboard, you can actually rotate the tiles that you're placing. So if you want a one-way tile that is going to go way basically from down below, you can jump up, then you want to make sure that that is facing the top like this. But if you accidentally hit the Z key, you're going to be flipping the why to the bottom. And then that's going to reverse the direction for your one-way collisions. So likewise, they'll come up here and fix this one because it shouldn't be on the top, but flipped to the bottom with z, but it should rather be just top facing. So this should prevent the character from accidentally falling through the floor here without actually doing the drop move. That would be pretty annoying. So let's just move this flag down a little bit. And now that platform should work as expected. And likewise, on level three, it's kinda silly if we drop the player right into the ocean here. So let's fix that one as well. So let's see auto title. Let's put this platform and remove the one that is on top. So there we go. That should fix that issue and we even learn something in the process. So now we can just go ahead and play test the game one more time. Now that we've fixed the camera bounds and we fixed to the platform directions. Okay. So we got our up there, didn't take any damage getting this way. And we get to our level 2. Okay, took some damage, they're going to do the tricky jump. And okay, there we go. Now that's working correctly. And it's just finish up the game and bone. Okay. Everything's working well.
32. Health UI: Okay, next let's create a simple health UI so that we can show the health of the player at any given time. So I'll go down to the canvas layer. So if we want to keep things simple, we can just add in a simple control and then this control is going to be the Health Bar. So then below the Health Bar, we're going to need to add in a texture rect. So I'm going to right-click here on the Health Bar at a child node and then choose texture, correct. And then for the texture inside of this texture, I'm going to use the kiwi health indicator. And so I basically took that image right out of this kiwi fruit from the pixel adventure one. You can see this image right here. Just extracted the first frame and it is 18 by 18 pixels now. So I bring this into the texture and it's going to appear there. And if we change stretch mode to tile, we can keep repeating this as much as we need. So if we control the size of our texture vect, kinda like so. But in code, then we can show how many health points the player has left at any given point. Let's get rid of that texture and then let's hit Play and kinda make sure it does appear there in the top-left. Maybe we want a bit of a margin as well. So I can take the Health Bar and we can give it a top and left margin of five. Okay, that seems positioned a little bit better now. So now the Health Bar is going to need to know how many health points the player has at any given time. So it knows how many keywords to show. One equals one kiwi. So I'm going to add a script to our Health Bar. Right-click on the Health Bar attached script. And let's see, It's not going to be on the maps. This should go under the UI folder. So health bar, that's open and create. So in our health bar when the script loads, we can try to find the player which should be in the game manager. So I'm going to put it in a funk reading. And we're going to basically set the active player equal to the active player from the game manager. So let's create a var active player. And it's due flare equals game manager dot active player. And that's not, let's create a signal for our player, but instead of putting it in player, let's actually put it in character dot g, d. So any character can emit this signal, but we don't necessarily need to connect to it for every object like the angry pigs. So let's create a signal in character. And this is going to be changed. And we're going to pass new health here. So before we assign the value, the new health to the health variable, we can see if they are the same. And if not, then we emit health changed because the number is different now. So if else does not equal value, then we'll emit the signal health changed and will pass the value as the new health total that we're going to be sending out to anything connected to this script. So now with our Health Bar, we can connect to that active layer doc and enact. And we want to connect to the health changed. The receiving object is ourself that health bark. And we're going to create a on health changed message. This way by using a signal rather than checking the health on every single frame, It's just a little bit more efficient. So we're going to write func on health changed here. And this is actually going to take the new health. And so let's get reference to our texture rect. So up here I'll do on ready our extra wrecked equals dollar sign texture erect. And we'll multiply the width of that texture racked equal to the new Health times 18 pixels because that is the width of the sprite image. So make sure that you're a texture vector is equal to the number of healthy I've multiplied by the width of your image size. So let's do texture wrecked. Dots. Let's see, would be with, or we can actually click on it and just check. So, so I guess that's wrecked dot size dot x. So let's find that wrecked dot size dot x. And we'll make that equal to Sprite width times the new health. And we can make a variable up here so that we can set the sprite with in the inspector. So let's see, exploit ENT are right, width equals 18, since that's just the default I'm using. And we can see if that actually works. So I'm gonna go ahead and hit play. Okay. We saw that there. Let's see what happens when he took damage. Nothing yet because I forgot the underscore up here. So that's a method that doesn't exist. Now they have the same name. So let's go out and hit play and see if we can get this to work. Okay, we take the damage. Let's continue. Invalid, index wrecked on texture. So it looks like what you actually want to underscore size. And then we can set the x value of that. So vector size is a vector two and we only care about the x. So we're setting that there. Let's go ahead and hit play and see if that fixes it up. And yeah. Okay. That seemed to basically work. Yeah. Okay. We have one health left and then of course, after that, we lose the game, but it's not updating with that last health. So it seems like with the default settings, it can't actually go less than that one texture image. So there's probably a handful of ways we could solve this. But I think the quickest way that comes to mind would just be to disable the texture racked if the health is 0. So if new health is, let's say less than or equal to 0, then we'll just take the texture erect, visible and we'll set that to false. Else. I guess if we ever hit 0, but then for some reason or one higher, or just say that it's visibility is equal to true. So now we can hit Play. And let's see what happens. Okay, well first off, we set the health to 2, so it expanded, it goes down, and then now it gets disabled entirely because the health is set to 0. And now seeing that at the start of the game, it actually only showed one. We need a little bit more code. So when this is set up, we should actually set the Health Bar to be equal to the starting health of the player. So we'll run this once as well. We're going to want the health of the player, so do active player dot health. And theoretically we don't actually need to keep a reference to this anymore since we're really using the signal to respond to it. So x2 bar active player, the player connect. Actually just one var active player connected. So we get the active player, we connect to the active layer. We set the bar up for the current player's health and whenever the player takes damage, we respond to that. Okay, now everything should be working good. So at the start of the game, we have three health, so no, it expanded to that and we take one damage. Let's take another damage. And then now, well, if we lose our third health and it's the end. So that's basically how we set up the Health Bar. Just make sure that you save it as a scene so that you can reuse it across your game. So I'm going to hit up, I'm going to put it in UI health Bardot scene and we can make sure that it is on the future levels. But to go one step beyond that, I think a good way to do this would be to set up a base canvas layer that we use for every game. So I will just call this game UI. And let's create a scene from this so safe branch as it seen, and this will be our parent object of the game UI. So we can go to level 2 now. And I'm going to cut this away. And we'll cut it from level 3 as well. And then we're just going to put in the game UI seen. If we need to add something to every level of our game now, it'll all be in one single UI. And if you do need to see any of the children at any point in time, you can right-click on your game UI and UX editable children, and you can still see the Health Bar and the game over screen. So make sure your levels are saved. And if you hit play, hopefully it still works and everything. So let's hit. Okay, and let's actually just jump to the next level. Level VSA, our health reset because it's a new player. And well, that's basically it there. Now when the level ends and we don't take damage to actually cause the defeat. We might also want to add in just removing of that health bar as well. So I think what we can do with our Health Bar is just respond to the game over event from our game manager. Since we have to reference the game manager at the unready of our Health Bar. Anyway, we might as well just reference this signal and have a on player died or on GameOver. So let's go to our helper. And when we get the Game Manager, we can also connect to that. So Let's see a game manager dot connect game over, self on game over. And put the underscore there for a receiver method and we'll create that receiver methods. So function underscore on game over. And we just need to take the visibility of the texture vector and set that to false. So let's copy this code, paste it in there. And now if we get a game over for any other reason, then the player taking damage, like for instance, is falling off the edge here. Then that is going to show it invisible, which is kind of what we would expect.
33. Setting Up Bee Enemy: So in this part, which may be the last for the course, we're going to build out a second enemy, kind of more of a fun activity. And the enemy we're going to create is a B that flies around with a projectile, will be able to reuse some of the same code from angry pig, possibly moving some of it into the enemy script so that it's reusable. And then we'll be adding extra stuff to it. Obviously projectile's or something we haven't done yet for this game prototypes, so we need to add that. And so just like the angry pig, the bees are also going to move between waypoints, but there'll be able to move vertically as well. They won't just be going left and right, and they also won't respond to the position of the player in the same way that the angry pig would where the player enters this area and then the angry peg moves faster. So we can move the waypoint code into the enemy class for enemies that are going to use the waypoint. And then we can have them each have their own move method where they figure out how fast they're moving and in what direction. So let's go ahead and open up the angry Pig script. So basically we're going to take everything here and move it into the enemy script As a function called waypoint blue. So let's go ahead and write that here and we'll pass delta into it. So now in our enemy script, let's go up here and we can write function waypoint move, which is going to take delta and paste that in there. So when we do that, we can see that we don't have the waypoint position, so we need to take that out of angry pig as well. So the b or other enemies are going to have all of this stuff over here. Waypoint arrived distance for switching waypoints, an array of waypoints to go between the starting waypoint position, index of that, and probably also faces right as well. So let's just cut that into the enemy script. And we can kind of position that up here. So as long as enemy has it, that'll clear up any of the problems that we have for the angry pig as well. So obviously we have an error where we don't have this set waypoint index method, so we need to take that out of angry pig as well. So let's just cut and paste that into the enemy script. Another error we have is for our pigs specific moving. So rather than all of this and the enemy script, we will create a function that we can implement on each specific enemy for their own customer. And then we can call it get move velocity. And that's going to take the delta and also the direction which we're moving towards. So we calculate that by figuring out where the waypoint is going to. So if we're doing a waypoint move, we're moving towards those were moving towards those waypoints. So now we just need to make sure we have a virtual function down here. So get move velocity. So this'll take delta n direction. And if we run this, we're going to want to print an error because it hasn't been implemented. So you can just write an error message like that. So the idea is if when the script is actually running, it runs this enemy version of the method, we get an error. We should implement it in the top-level character, that angry pig or the B. So this is just telling us, Hey, we need to write more code so that this function can run properly on the final enemy. And this over here is going to return the velocity so that we can use it for our move and slide. So let's just put our velocity equals get moved velocity. Okay, So now for everything we cut out that should go here. We just take that into angry pig. So let's go into the angry pig and implement that function. So underscored, good. Move for velocity, delta direction. And then just paste that n. And instead of setting the velocity, we're going to be returning that. We may also want to take the var velocity out of here because we don't really need it in the script anymore at the moment. And just make sure those are a tab over to the left. So for the other bit of code, we were using this before to determine if it should move left and right. Since we're passing in the forward direction into this function, we will put this in two different places. So back and sit back and the enemy script, I'm going to paste this in so that we can use it for checking if it should face right or face left. Then just lastly, we need to get that returned velocity, store it to a variable here. So barred velocity equals get moved velocity. We pass that down here. Animated sprite. We'll move that up from the angry pig into our enemy class, as well as the animation tree as well. Pretty much every enemy is going to need both of those. So let's just paste those in there. Okay, So next we should go back into the angry pig and make sure of the errors are taken care of here. Here we can see one of velocity y is getting added to the game gravity. So the character basically still has its gravity. So for that reason, what we should really do here is set the new velocity equal to this MOOC velocity. And then have a variable up here which all of the enemy types will be able to access. So if our velocity and this will be a vector to, we could even initialize it to a vector to 0 by default. And then the movements slide, I believe that returns the velocity. So if we have any collisions. Should update the velocity for us as well. So now the velocity is declared here. And if we go check at the angry pig and here, then this velocity y is going to be using the velocity y from the enemy. Another way we could do it, if you think it's a little less messy, is we could pass the current velocity and as a variable and then use that in the script and return it back outwards. This should work for now, so I'm not too concerned about it. So now what we should really do is make sure that the angry peg works the same as it did before. Even though all we did is move stuff out of the angry pig into the enemy script. So let's go ahead and hit play and test that out. Yeah, it looks like our enemy is still moving. So now what we can do is take our angry pigs scene and duplicate it and the file system and use that as the base for our B. So I'm gonna come down here where we have angry pig scene. I'm gonna do a Alt D and duplicate that and we'll call this B dot t SCN. So that's our be seen. Now we can open up that scene. And first I'm going to rename the character to be up here at the top. So next we can go down each of these and remove and add what we need. So first off, we don't need a angry detection zone in the script. So I'm going to just completely get rid of that. And if you see errors pop up down here, It's not letting you see the inspector just switch to another scene and come back. And now that should that up so we can remove the angry detection scene. For the animated sprite. We're going to want to redefine that to the sprites for our B character. So I know that the baby has a hit animation and idle animation in an attack it and delete the ones that aren't relevant to us here. So let's just make that one. And now we can add N and attack. And making sure that's 20 FPS. The Hit animation will keep at 10 FPS at the men and do the same thing for a hit and attack. So let's delete all the current frames, go to hit five horizontal, one vertical, select all, add attack animation each frame. So eight horizontal, one vertical, select all at, Okay, and there's our little attack animation playing their next in the animation tree. We can set this up for our new character as well. So first off, there's no hit variations. There's just gonna be one Hit animation for this character, so we can get rid of all that. Next is not going to be any player detection zone. There's only one idle animation which we're going to be using for the bee flying around. So we don't need that either. But we are going to need one more one-shot for an attack. So this will go before the hit one shot, taking damage being hit takes priority over doing an attack. So one shot, and then this is the attack, thanks to the output feeds into the input for that. And we need the Hit animation to go into here. I'll actually delete that for a second. We need to update our animation player. So in the animation player, going to rename hit one to just hit. And then for the animation, make sure this is selected as HIT. We can leave Hit animation finished because we'll be creating a version of that for our B as well. Hit two, we're just going to delete that. And then idol, I think we can leave that one as is. Just make sure I'd always the right animation playing on the animation sprite and then run, we delete that and then walk. We can either delete that or you can just rename it to attack. So I'm going to rename this to attack. And I know that later on this is going to be a one-shot. So I'm going to change the duration to 0.4 and not looping 0.4 because it has eight frames at 20 frames per second. And then down here, we can add a track called method track on the B. But we haven't created the method, so we can't really add it in there yet. So our idle looks like that. Our HIT will have the animation finished going on there, and then attack is over here. Okay, So now back in the animation tree for the one shots, make sure that they're fade in and fade out time is 0. We want them to play immediately after entering those animations. That's important. And then for the First off, I'm going to change the default animation to idle kids. Flashlight on the screen all the time is pretty annoying. So down here, Let's right-click, add an animation and let's do hit, connect that to the one shot. And then for the one shot over here, the attack, we want the attack animation. So animation attack, connect that into the one shot. And then for all other cases we just want it to do the idle animation. So connect that in here. So this is basically our simplest animation blend tree yet. Just make sure you have 21 shots. Hit goes before attack and that both of them have the fade in, fade out time set to 0. I then connect the animations as you need. Okay, So this character still going to have a jump hurt box since we're not checking for the position anymore on the hurt boxes, I think just making a bigger shape might actually help a little bit for the player hitting the character. I don't know, I'm just going to make it a little bit bigger there so that there's more area for the player to hit. So I'm just taking the y-value and setting it to three. It's not really necessary, but, but I don't think it hurts either. The enemy collision hit box will still use that for our enemy. All of the enemies are going to be able to run into the player to deal damage to it. This character will also be able to launch a projectile. Okay, so now we need to detach the angry Pig script from this b. So if I click detach and I'm going to right-click attach a script. So we're creating a new script in the characters enemies folder. It's going to be called BDD. And this is actually going to inherit from enemy. So let's just change up here and we'll type in enemy, hit Create. So now when we create the script at the top, it extends enemy. That's what we want to see at. Let's cut that away. And now we can start working on this B script. So like other characters in the game, we're still going to have states in a sense. So I'm going to put enum state and the three states for this character are going to be idle. Hit when it takes damage and attack when it's playing the attack animation, we're going to make sure that the enemy can't move while it's attacking. For this script, I think will make it so that the enemy doesn't move while it's attacking only wilds and the idle state, though you could have it attacking move at the same time. It depends what you want. We're also going to need a speed for the character to move. So export, float, var, Lightspeed, and I'll set that to 50 by default. So later we're going to set up a projectile, of course. So we can include that as something we can spawn an instance of for our B by having an export packed scene variable. So export packed scene. And then we just tell the B with this variable what seen from our project. That's a TSC and file that we want to create a copy of, and this would just be a var projectile. We're also going to need a current state variable and then a set current state function. So I think we can actually put that in enemy as well. So, so this character is also going to need a current state variable and a set get for the set current state. So this character is also going to need a current state variable and a set current state setter function. So we might consider pulling that line of code from angry pig into enemy so that basically every character has a current state to set. And then we can define a custom set current state method for each one. So an angry pig, I'm just going to pull this out. So like the player walls are going to need a current state, your variable. So a variable current state, and we're gonna set that equal to state dot AIDL. By default, we're going to write a set of function for its set current state. So when we enter a state, we want certain things to happen for this character. And we're also going to need an attack direction and an attack target for launching projectile's. So the, so the direction is going to be the direction to launch the projectile n. And then down here we're going to have the attack target. And then down here we're going to have the attack target. When a player enters the radius of the B for attacking, it's going to be locking on to that player. And it's going to keep launching projectiles at that player until the player leaves the attacks zone. And we're going to want the projectile's to launch periodically, not on every single frame, but more like once every second or you could even slow down further than that. So we're going to want a timer, so I'm going to right-click on our enemy at a child note, let's create a timer. And this can be attacked timer. Make sure that it is a one-shot on the right. And you can make the wait time however long you want between projectile launches. So a wait time of 1 second means it launches one attack per second. Now we can get reference to that attack timer. So unready var, attack timer equals dollar sign attack timer. And there's a couple other nodes and our hierarchy that we need to get access to, like the enemy collision hit box so that we can turn it on and off depending on the state. So unready var, enemy collision, hit box equals dollar sign, enemy collision hit bucks. Okay, so next we can write our physics process functions. So underscore physics process, we only want to have the character move in one state, so let's match the current state. And if the state is idle, then we're going to move, so state dot idle, and then we're going to do waypoint move delta. So remember that requires us to set up how the character moves if we go back to enemy and we can see Waypoint move has this function, we need to implement. What do that in a second, but everything else about moving between waypoints is taken care of for us. So half of that is already written. And it's just kind of a time-saver as the frames are running. If we're in the idle state, then we can start attacking the player if it is there. So I'll just put a comment here to let us know to add it later. So we'll set that up in a minute. Now let's work on our character's movement. It's going to be super central for the b. So we're implementing get moved velocity, which takes Delta and, and direction. All we need to do is return the new velocity, which is going to be Fly speed times direction. So the direction is basically the same, but the direction is going to be pointing towards the waypoint. So I kicked it just moves towards the waypoint 1 its end the idle state at the speed of the flight speed. And that's really all we need for that. We should also implement a function get hit. This will take damage and float. So every enemy needs to have some version of this. So self.age minus equals damage and will change the current state to state dot hit. We need to implement set current state, new state. Now we need to write this function down here. So function set current state and this would be new state 3 can make sure that the current state is equal to the new state. And of course, we'll add more into here for when our characters enter a certain state, we want stuff to happen. But let's see where we're at. But let's see where we're at right now. So let's go to level 1, and let's add a copy of the B into here. So our B, we need new waypoints for, so duplicate the waypoints with command or control D. And let's just move these waypoints. I don't know. We'll put it over here for testing purposes, I guess. Okay. And then waypoints six, B will move here, and then it will transition over to moving this way. But that's only if we actually set up for those as the waypoints. So click on B and create a. Set the waypoints array to size of two and knowledge choose waypoints five and waypoints six. Okay, now we can hit play and see how it's working so far. Okay? It looks like we got the error where the waypoint position hasn't been set yet. So let's close that. Let's go to the angry pig where I think we need this bit and the enemy. So the waypoint index needs to be set to the starting waypoint at the start of the script. Or really rather than having this, we could just make it a rowdy bar. So the waypoint index will be the starting waypoint. Let's delete that. Go to enemy. Waypoint index is going to default to the starting waypoint. And we have to make this on ready var. So that way we can have this setup without having a ready function and possibly overriding an old. So that way we can solve that problem without having to create a ready function inside of here for that. So let's go ahead and hit play and see where we're at again. Okay, so up here, we also need to set the waypoint position by default. So I think we can do that with a, with a waypoint position and we'll get the waypoints at the starting waypoint. And then so in order to get this out to already bar, Let's get the node at the, let's get the node at the 0 position of this node path, that starting waypoint. So we want waypoints at the array position starting waypoint, which is 0. And then we can get the position of that. And that. And then we can get the position of that, which should be a vector 2D. Let's go ahead and hit play and see if that helps. Okay, Yeah, that seems to work. So IB is going between the waypoints, are angry pig goes between the waypoints. Let's see if we can damage the beak currently. Yes. Okay. Currently you can, but it's not playing the Hit animation. So everything so far, so good.
34. Bee Enemy States & Projectile Attack: Okay, Next in our set current state for the B, let's match the new state. And let's set up some things to happen depending on which state gets entered. So if we enter a state dot AIDL, we want to take the collision hit box of the enemy and turn that on, meaning that this enemy can run into the player and deal damage to the player when it's in the idle state. So that's going to be enemy collision, pit box, dot, dot set deferred. Since that, when you are setting these properties on the area 2D is it has to be done with a set deferred method. And what's turning off? And we're turning on monitoring. And we're turning on monitoring. Which means we make that true. Okay, so that's going to mean that our character can deal damage to players again. And we also want to take the variable can be hit and set that to true as well. So this is what the player is currently checking for any enemy to see if it can do a jump attack on it and deal damage to it. Next we want state dot attack. So we'll just set this up in advance. So in state attack, just in case, for some reason it's not. We do want the monitoring to be true here, so it can still collide with the player when it's doing a projectile attack. And we also want it to be able to hit the player style. So I'm going to say I'm going to copy paste that. The only difference here that we want to turn on the animation tree perimeter for attack active. So take the animation tree and let's set the parameters attack active. And we're setting that to true. So as long as it's not currently playing the Hit animation, it'll play the attack animation as a priority over idle, which is what we would want and the attack state. And then lastly, or state dot head, we want to take the monitoring and turn that off. So what disabling the enemy's ability to deal damage to the player. We may also want to turn off, can be hit so that the enemy can't be hurt. Watts and the hit state. Otherwise, the character can just keep bouncing on top of it and kill it very quickly. And then we also want to set the animation tree parameter here. I'm just going to copy paste. Except now we're changing it to the hit parameter instead of the attack parameter. So when the enemy gets hit, we don't want it to suddenly launch a projectile at the player. I think that would be a little bit unfair. So we can actually start our attack timer here as well. So I'm gonna do attack timer dot start. Our timer set to 1 second. So while that timer is running, no attacks will be made. Which means this is saying that when the enemy gets hit, there'll be at least a 1 second delay before it starts attacking again. Now so that we can clean up the animations. But let's also create a couple functions. When our one shots are done, we want to return to the idle state. So let's create function, Hit animation, finished. So at this point, we just want to go back to idle state. So self.contents state equals state dot idle. And then we'll also set up attack animation finished. So like Hit animation finished or do self dot current state equals state dot AIDL. But if we take a look at the attack animation, we can see that this is the buildup for the character launching its attacks. So the timing we actually want to launch the projectile is going to be at the end of our animation. So this is a perfect place to put launched projectile, which we will setup in a bit. So launched projectile. And then let's go ahead and create that launched projectile function. For now, we'll just pass. Now let's go to the Animation player and it's set up those callback functions. So I'm going to insert a key here. Okay, let's see, that's the attack. So we want to do on a tack finished wherever we have the attack animation finished, and just make sure that that's the right one being called here. Now let's go to hit. And then we want on hit finished. So I'm going to click there. It looks like it's already set up from the angry pig. So hopefully we should be able to go between hit and idle correctly now. So I'm going to hit play, I jumping on the B, okay? It looked like hit the, hit animation and it does return to idle. After that, 0.5 seconds is done. Just to test one more time. Okay, seems to be working good. Okay, Next we need to create a projectile for our B2B able to lunch. So let's go create a new scene. I'm going to create this as a kinematic body 2D, since it is going to move. And we're going to add, of course, a collision shape to it, this collision shape. So I'll rename the attack here, bee sting or the projectile of other. And let's save this in a new folder. I'm going to call this projectiles. And we will save that in there. So our collision. Now we also need this bright for our bee sting. So I'm going to add in a sprite. And then let's go into our art and find that attack, so b, and then we have the bullet here. So I'm gonna put that in the texture. So continuing on our bee sting projectile, the main collision shape for the kinematic body 2D. Well, I'm only going to have a collide with the world for basically deleting the projectile. But then to deal damage to the player, we're going to have a separate area that checks basically by using collision layers. If it's a player and then dealing damage to that player before deleting the projectile. So let's take the B string object and set the default collision. Layers to basically just be world and weld. So for our bee sting kinematic body today we're going to turn off layer world. This object is only going to try to collide on the world layer. So I think that's all we need there. And then let's define the collision shape for that. So we'll just use a capsule shape. I think that fits this little be stinger, which kinda looks like a tooth to me. That's adjust the size and shape of it. And also I'm going to position this right above here so that we can see the collision shape. Layer it on top of the sprite. And that looks pretty good to me right there. I might even just tone it down just a little bit more favorite player when it comes to collisions with this object. So now we need another area to D for dealing damage to the player. So let's add a area to D. And then I'm just going to duplicate this collision shape 2D. And we're just going to put it down here for that too, is basically the same shape is for world collisions and for player collisions. But on the area to D, we check for players and on the kinematic body we check for enemies. So here we're going to turn off monitor bubble. We're going to turn off the layer and the mask for world. And we're going to turn on mask for player, which I have set to the fourth option over here, the fourth. But, so now we can rename that something like attack area, I suppose. And we can put in a script for our bee sting. So for right now we're just going to have this inherit from Kinematic body 2D. And we'll go ahead and hit Create. Okay, so our bee sting script is going to be relatively straightforward. Let's delete all of that up there for right now. So our projectile is going to need to know how much damage it deals. So export float or VD damage equals one by default. For export of float for the move speed of this projectile as well, we'll make it a little faster than the B itself, move speed of a 100 by default. And now we're going to need a variable for the target direction. And we'll default this to vector two dot 0. Now we're going to need to update this object for every frame it's existing in the world. So we'll run physics process. And here we'll get the collision that occurs when we move. And we'll do a move and collide up to this point in the game we've been doing move and slide, but we don't actually want the projectile to slide along the edge of anything. So we're just doing moving collide. And then if it collides with anything which is currently only going to be on the world layer for the kinematic body 2D itself, then we're just going to delete it. So we're using moving collide instead of move and slide. So there won't be any slide functionality. And we need the move speed, which we declared up there at the top, times the target direction, which we will get from the launching object when we go ahead and create this. And then we'll multiply that by Delta. Remember that moving collide does not automatically account for Delta, which is the time between frames. So you need to multiply by delta when you are using moving collide. You don't need to do that for move and slide, which we've been using for the rest of this course. Let's just keep that in mind. And if we have a collision, so I'll do if is instance valid on this collision, then we're going to queue three, which just removes this projectile from the game. So now we need to set up when we hit a player. So we'll use this attack area, go over to a node and do body shape entered and connect that to our bee sting. So now we have an attack area body shape entered. They should always be a player. And when it's not a player, We probably want it to send an error of some kind, surges, do body dot get hit damage. Any players should be able to do that. And I think we actually set it up for character, but that should work for right now. And then after dealing damage to the player, we q3 because we're removing the projectile from the game, and that is it for our bee stings script. So now let's go to the be seen. Let's click on B inspector. And let's load the projectile n for our projectile packed scene. So over here, load, Let's go to projectiles and choose bee sting asean. Okay, so we should be able to see a little preview of our B there. We can see resources projectile's slash bee sting, dot-dot-dot asean. So that should be able to create that.
35. Launching Projectiles: Now we actually need to create the method for launching the projectile from the beam. So he created launched projectile, but we haven't done anything with it. And we're actually going to need to pass a parameter into here, which is going to be the target direction, which will be passing along to the bee sting as well. So a direction vector 2D, and then that direction will come from an attack direction. And we'll be setting that up in a minute. So when we launch the projectile first, we have to create an instance of it. So I'll do var launched projectile over here, and that's going to be equal to projectile dot instance. So that packed scene, we're creating a copy of it inside of our level, seeing when we, whenever we run this method. So with the new projectile, we need to set the position of it. So launched projectile dot global position. And we want that to be equal to the position of our B object. So creating the projectile at the B's location, and then it moves from there. So equals global position of this object. And then we need to set the rotation of the launch a projectile to match our attack direction. Otherwise, it'll look a little funny. This will just make the animation look better. So launched projectile, and I'm going to do plus equals on the angle because we might have to adjust that in the projectile scene itself to set up the default direction for the projectile. And then this changes. It, rotates it to where it should be facing based on its trajectory. So let's do target direction angle. So this basically converts this 2D vector to an angle that the rotation can actually understand. So once projectile dot rotation should be on the left and then plus equals target direction angle. Next, let's add the launched projectile to our current scene. So get tree and then get current scene. And we add a child to that. So we're adding the child of this launched projectile. So this bit line basically means that when we're in our level 1, it's going to find this level one route object and we're going to add it as a child down here to exist inside of our sink. And then the last line we need here is to set the target direction of the launch, the projectile. So launched projectile dot target direction equals target direction. Now, what is this target direction and how do we actually set up the launching of the projectile's up here? So in order to attack the player first, we have to identify that the player has entered an attack zone. We haven't set up an attack zone. So let's create another area to D on our B. So I'm going to right-click up here at a child node area 2D, we can call it the projectile attack or area might make it a little bit more sense that projectile attack areas, but I'll go with, Let's right-click add a collision shaped 2D. It's just like every other time, and let's make it a circle shape. So this circle shape, I'll take the radius, the expanding up there, and I'm gonna make it a 100. So it's a pretty big radius for where we will say that we're attacking the player if it happens to be inside of here. So if we click on projectile attack area and go to node, you can see that there's not a signal for the player existing in there, but there is one for body shape entered in body shape accident, so on entered, we'll set the target player to be the player that just entered. And on exit, we will remove the target player from the currently referenced target. So if there's no target, it won't launch a projectile. And if there is and other conditions are met, then we will launch projectiles after every attack timer is done running. So let's connect body shape entered into the B script and also body shape exited into the script. I will take these little bit up here, yes, right around here. And now let's set up the attack target. So this is really simple. We just need to do attack target equals the body. So this is the thing that kinematic body or the player in this case, the entered our attack area and we're registering it as the target to try attacking. Now, when that object leaves, we're just going to say the attack target is equal to null. Now up here on our physics process, which is going to keep running as the game progresses. We want to see in our idle state if we should transition into a attack state. So first we're going to see if the attack target is valid. So if instance valid, and we'll do attack target here. But also that the attack time or is currently stopped, then we'll do an egg timer is stopped. So the cool down from the last attack is over. We have a target to attack, so therefore, we are going to attack it. So let's do self dot current state equals state dot attack. And now let's set the attack direction to be equal to the direction to the top, to be equal to the direction to the attack target. So a tech direction equals self.position dot direction to the attack target dot position. And then let's start the timer. Because we only want this to occur once every 1 second or however long you set the attack time or to be. So attack timer dot start. And this needs to be direction too. So this puts us in the attack state. When we're down in the attack state, our attack active animation is going to run thanks to this parameter. So the attack animation charges up the attack. And then we have attack animation finished, which is going to launch the projectile towards the player based on that attack direction. And we're going to return to the idle state until our script tells us otherwise. So let's go ahead and hit Save and see where we are at. Okay, so the projectile is getting launched. You can see that while it's in the attack state, the B does not move. Which I might actually not like maybe I do want it to be able to move water attacks because this just looks a little bit clunky, doesn't it? So let's set up another match state and will allow it to do waypoint move down into. So now only in the HIT state it won't be able to move. Let's hit Play, Okay? And now our b as attacking while moves. And we do have to rotate the base projectile so that this is actually pointing towards our player. So if I recall, if we go to the bee sting, the correct way to have it faces straight up. So if I remember correctly, taking the bee sting and then setting the base rotation to either 270 or negative 90 to make it face to the right is going to be the correct way to make it face when you add in the angle from that projectile's launch. Okay, so if we go ahead and hit Play, we can see that it's actually not attacking our player. Currently one it's attacking is the world itself. So if we check our projectile attack area, you can see monitoring is still turned on monitor a boy is still turned on. What we want to use as the masker is player, turn off mask as the world and layers the world. And we're also going to turn off Mano terrible. So now it should pick up on the right target to attack what should only be the player. So when the player is not in this area, it's not attacking anything. But we can go in this area for it to attack. And it looks like the direction of the projectile is more accurate. So that it looks mostly correct. Except one problem is that it's not actually entering the attack animation currently. So let's go ahead and take a look at our B scene and kinda debug why the animation is not running. Check on here. You can see that the attack animation is not running. We can check hit for on, and that works. So why isn't attack running? So let's check the animated sprite. Let's make sure everything is good here. And it seems to be. So we can go into animation player. And one thing we could do here is just recreate the attack animation that might resolve the bugs. So let's go ahead and remove the attack animation, and then let's add in a new one called attack. So once again, resetting up that we're going to take the animated sprite animation on frame 0. We insert the key to set the animation to attack that we also need the call method track on the B. So at, I think it's 0.4 seconds. And we want to right-click and insert on attack animation finished. And also we want to make the total duration of the texts that are 0.4 seconds. Snap down here 0.05 seconds as well. So now let's go to the animation tree and let's add in the animation one more time. Attack. Connect it to the one shot, and let's check the one shot. So now it's actually going I can't exactly explain why that occurred. Now. It seems to be working so we can go ahead and hit play. And let's see if it actually plays the animation. So it does, okay. So did play the animation, but I guess it didn't return it to any other state. So we've got to make sure this on animation attack finished actually occurs. And the problem here, if we zoom in is that it's at 0.5 seconds, where you want it at 0.4 seconds. So that's important. Let's go ahead and hit play. And we can see now it's going to work. We're going to get those projectile's to launch. And it's gonna be kinda tracking the player around for launching those projectile's. So we can still jump to hit the B. And note that when we hit the B, that there is definitely a delay for it starts to attack again since we restart the timer when we hit the B. So now our b is basically working. We just need to create a few clones of it in the game and set waypoints for them to move between. So let's click on the B and maybe I will have him start a little bit up here. Let me have him attack the player when he's kinda on that platform and its move we 0.56, where we want it to be. This part is totally up to you just position things where you want them to go between and where you want the starting location to be. And maybe let's duplicate the B again and put a B up here. And maybe for testing purposes, let's actually not give this be any waypoints. So I'm going to reset the waypoints array here to 0. And let's go ahead and hit play and see if that gives us a bug. So it does. So basically, this can only really run if there's actually a waypoint in the array. So at this point we could make a very function. So funk, underscore ready. And then we'll just put this down here. So waypoint position equals this. Instead of making it on very viruses, this might not always be able to actually be set up. So only set this up if waypoints dot size is greater than 0, greater than 0. There we go. Let's go ahead and hit play and see if that clears up all the areas. So here we have another one, which is that basically if there's no waypoints, there's no waypoint position. And if there's no waypoint position, then we basically can't actually do a waypoint mover. So we can put a check-in here. If the waypoints dot size is greater than 0, if it's not, then basically waypoint move shouldn't do anything. So let's just tab everything over. And if there's no waypoints are just going to skip over all of this. There may be cases where we actually don't want the enemy to move. So now that seems to basically be resolved. Okay, for some reason the B is launching projectile's from a weird position. We can work on that in a minute. But let's go up here and see about this b. Also launching projectile's from a weird position, but at least it works without the B actually having a waypoint. So maybe using the position instead of the global position for lunch projectile would work a little better and let's go ahead and hit play and take a look at that. Okay, so now it's launching from the actual b. So I guess that works. And let's see up here, launching from the actual b. We could also add a specific point, such as a position to D where it's going to launch the projectile from. I actually like that better because since it's a B stinger, it shouldn't come from the center of the BA, should come down here. Let's add that in. So let's dive into the B saying go into 2D view. Let's add a position 2D add child node, physician 2D, going to call this launch position. I'm going to hold Alt down and we're going to drag this down here to the stingers bottom, roughly right about there. Now we can reference that in our script. So we will do on ready Bar, Launch position equals dollar sign launch position. And then we'll get the position of this position 2D. And that is where we will create the launched projectile at. So let's go ahead and hit play now. Okay, that didn't quite work. Maybe we need global position for the launched position. Okay, Let's say play note that causes that issue again. Okay, So we can see that the launch position of this object is not actually a conforming with the world very well right there. So as I found, I accidentally moved to the position of the world away from 000. So we could add the position of the world to the global position of the launched projectile. Or we could just make sure that the level is always at 000. So if we position in a 000 way it should be, then let's take the level and let's lock it. So now we can't edit its position. We can only edit the children. So if we hit play now, that should solve that issue. And now our stingers or launching from the target position we set down there. And this looks much nicer. So we can kinda progress through our level. Okay, that pig still kind of a pain. And here we have to be careful because that be it's just gonna keep shooting at us. So let's set up some bees in level 2 as well. So I'm going to search for level 2. We're going to open up level 2 scene. So let's set up a couple of B here, B, k we got the B scene, could just drop it in.
36. Finalizing Bee with Vertical Waypoint Movement: We can position it there and then let's duplicate a couple of waypoints. We print five or 8.6, and let's move them into the position we need them. And then make sure that our B position m up here with the other enemies is going to be using waypoints of two. And we're going to assign waypoints six and waypoint five. Now we can add this just had two extra bees. Why not? Okay, So I'm going to drop in a b right here and a B right there. Let's actually make a kind of difficult. We'll have three Bs. And each of these bees don't parent them under the other bees. Let's see. They should have no waypoints. They're not going to move the just going to be kind of a pain for us. Now if you want to test the current scene rather than the starting scene for the game, you can use this option over here, play scene on Mac, that's Command are imagined, that is Control R on Windows. So we can just start from this scene and Skip Level 1. So let's just come up here. We can see that our B is going to try to attack us when we're within the sphere. If you wanted to go a step further, Use the re-cast to see if there is a line of sight between here and the player. And then when that rate cast collides with this world, it would stop it from doing the launching. But we're going to just set it up like that. I do also see another bug, which is that we're not moving in the y, so I need to, okay, and let's just continue. So we're going to do some wall jumping. And now we come over here to R be enemy. Yeah, that's a little bit of a rough platform, so we have to be kind of careful. Okay. I can't double jump off of taking damage, which is working as intended, but we can't go a little bit above the enemy. This is actually pretty tricky. Okay? So jump and jump. Okay, got that jump. And there we can beat the game as it is. And then we get to our stage three. So I think I'll take this b over here and maybe get rid of the B3 or the demo of this game, because that is a little bit rough. But let's quickly find out why that B wasn't moving on this level. So I'm going to actually move the player over here. And just so that we can get to that test a little bit faster, I'm going to Command R to enter the scene at that area. And let's see, it doesn't look like it's actually running the move method at all. The next thing we can test is the current state. Let's print that out. It should be running the physics process case at the state promising command R. And it looks like it's in state 0, so it isn't the idle state. I can switch to the attack state, that's too. Let's click on the B. It does have waypoints, it does have a fly speed. So I guess the next thing to check is what's the direction? So let's print the direction here. Okay, Well, in that scene they have a direction, but let's see right here, it does not print the direction. Okay, here is the problem. We're only checking for the distance x. We're not checking for the total distance to the waypoints. So maybe what we should be doing instead of here, we can still have this specifically for the pig. But we'll make another method for doing default distance two waypoints because right now the distance for x is 0 on that B, there's only up and down. So it makes perfect sense why it's not moving. So let's create a var and we'll call it distance. And this will be equal to get distance, to get distance to waypoint. I think that just needs the waypoint position. So maybe we pass the waypoint position and okay, and instead of distance x, we'll just say distance here of some value. Okay? So we're gonna need to write the function here. That distance to waypoint. Put an underscore here for a virtual waypoint position. Okay, so I'm going to pass that. And the angry pig, I'm going to paste in the angry pig version. So let's write a function that underscored get distance two waypoints, waypoint position, vector 2. And then we're going to paste this and we're going to return this, since that is the angry pig x only distance. Now for a standard enemy will have a default implementation for it. And how we're gonna do is we're going to just do self.position dot distance two, a waypoint position. Okay? And we need to return that of course. But the underscore there. Okay, and that should clear up the errors. So let's go ahead back to our level to sing, going to hit Command R. And we can run the scene as it is. And our b should be moving because the distance is now checking on both the x and the y for characters like this. But note that our pigs are still moving with their own version of the function. To prove that, Let's go to level 1. And let's actually move the waypoint one above the pigs had, and the waypoint two above the pigs had as well. And although the distance is definitely greater than 10 pixels, I'll make that weigh more than 10 pixels there. The character is not going to move because it's only checking distance on the x-axis. So we can see we don't have a moving pig, even though the distance to these waypoints is way up ahead, it doesn't switch between the waypoints. So let's undo those positions. And that should clean up our problems for the baby not moving. So let's go back to level 2. I'm going to lock this level two so we don't move the position. Make sure that transform servicer. And let's move the player over here. And let's command R or control R. And we will run the current scene. So let's just test this one more time. And of course I'll get rid of that debugging information. So let's just do a quick run through this level and you can adjust the difficulty of it however you need to. Obviously, if the wall jumping is too tricky, that could be a little much for some people, a man that's pretty tough. You might actually want to make the platform so little bigger than 1 square, at least some of them. Okay, But anyway, everything seems to be working. So just, let's go back into the script one last time. Let's just clean up the printing. So I'm going to search for rent wherever we have it. I'm just going to cut it out. We don't need it anymore. And that's pretty much going to be it for our platform game. So we have setup, movement scripts for our player. Or player can jump on enemies, do damage to them. We've set up two types of enemies. We have set up a tile map. With auto tiling, we can transition between levels. We have a game over DeathZone, a game over screen, and a health UI. So notice most of the basic components you would need for creating a full platformer game. I hope this course has helped you guys to get started in Godot in understanding how to set up a platformer game. So, so thank you all very much for watching and hopefully I'll see some of you guys in some of my future content as well.
37. Bee Animation Player Bug Fix: So we have one last bug fix video for the course. If you set up the B exactly how I did, You may run into the problem where, especially after you add a second beat, that it just doesn't seem to play the animations consistently. So I found that a solution to this is to just recreate the animation player. So I'm going to cut this away and then re-add it. So let's right-click on the bee and add a Animation player. We just need to recreate those same animations again. So in here, we're going to do new animation idle, going to add the track animated sprite animation. And then at frame 0, this needs to play the idle animation. Make sure that loops. Snap set to 0.05. And let's add n the other animations. So attack ad track animated sprite animation. And then this is going to be attack. And I believe had a zero-point 35 seconds time with 0.05 snap. And the idols should be looping. Add this set to 0.25. Now let's just go ahead and create the animation. So hit property and made it sprite animation. Okay, and so the key here at frame 0, and let's get that Hit animation there. So this was 0.05 for the snap and 0.45 for the animation, I believe. Now we just need to add in those call methods where our B was basically saying hit finished, so on hit finished. Now let's make sure that it snaps to 0 45. And now we go to attack ad track call method b. Insert key. Attack animation finished. And we can zoom in just make sure that it snaps to the correct time. Thanks. So now we have hit idle attack. So now we just need to take our animation tree and reset up our animations here. So right-click animation, idle goes to the first n. Then we need attack to go into this first shot. And then for the second one we have hit. So let's connect that in here. And now we can check active for our animation tree. We can test our animations by checking the on for the one-shot and for the second one shot. Now let's go ahead and hit play and see if it actually works in game. So here we have our animation working magically. So I'm guessing what actually happened was just miss timing something by 0.05 seconds. Maybe it was the timing of the animation calls. But this seems to fix what we have going on. And let's just jump into level 2 and just make sure that that's still the case. So we're gonna do a Command R on this level, and we'll just test it very quickly. Okay, so that B is working just fine. And now let's go up here, or the less three B's. I guess I dropped it down to two temporary IP. So that's the kind of issue UN into. You can of course check the settings for your animations as they are. But recreating everything could be slightly more time-intensive way to fix your problem. So if you're having any trouble with animations for your b, your player or the angry pig. I hope that helps solve some of your issues.