UE4 Beginners - Making a 2D Platformer With Unreal Engine 4 | Dev Enabled | Skillshare

Playback Speed


  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

UE4 Beginners - Making a 2D Platformer With Unreal Engine 4

teacher avatar Dev Enabled

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

20 Lessons (3h 50m)
    • 1. 01 - Course Intro

      2:22
    • 2. 02 - Project Setup

      9:39
    • 3. 03 - Player Input

      18:05
    • 4. 04 - Textures

      7:08
    • 5. 05 - Flipbooks

      13:27
    • 6. 06 - TileSets

      6:22
    • 7. 07 - TileMaps

      10:06
    • 8. 08 - Player Animation Setup

      14:37
    • 9. 09 - Player Animation Improvements

      11:10
    • 10. 10 - Player Health

      10:39
    • 11. 11 - Player Health Widget

      16:30
    • 12. 12 - Enemy Base

      8:28
    • 13. 13 - Enemy Bat

      9:01
    • 14. 14 - Enemy Bat Movement

      8:43
    • 15. 15 - Enemy Bat Direction Change

      17:14
    • 16. 16 - Damage

      24:57
    • 17. 17 - Player Death

      12:53
    • 18. 18 - Interactive Base

      10:35
    • 19. 19 - Interactive Health

      9:07
    • 20. 20 - Interactive Spring

      9:00
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

402

Students

1

Projects

About This Class

Get started with UE4 by learning to make a game from one of the classic genres, the 2D platformer. 

- Learn how to use the built-in Paper2D system 

- See some of the benefits of leveraging UE4 for 2D games

- Cover the basics of programming a player character, enemies, pickups and more. 

Meet Your Teacher

Teacher Profile Image

Dev Enabled

Teacher

Class Ratings

Expectations Met?
  • Exceeded!
    0%
  • Yes
    0%
  • Somewhat
    0%
  • Not really
    0%
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. 01 - Course Intro: Everyone, and welcome to this brief overview of the section of videos. What we're going to be looking at making a 2D platformer game inside of the Unreal Engine. Unreal is known as being a very kind of powerful, heavy, 3D based engine, but it does have some unique features and very powerful tools that also allows us to make these 2D projects inside of Unreal. Have an example here of some in what projects on even some complete projects that have been made using the Unreal Engine, it using the pre-built animation system and some of the level design tools that come pre-packaged with Unreal. Some of the reasons that you might want to use this kind of 3D focused engine to make a game like these that you can see in the background. Unreal comes with some powerful lighting towards you can definitely implement the lighting effects, as you can see in some of the games have building off of things like normals and getting that normal reflective surface quality that you'd be expecting to see in other 3D games. You've also got things like the APIpath traveler, which was made again inside of Unreal. And this is leveraging a little bit of kind of the best of both worlds and creating a somewhat unique game that haven't really been seen before, where it's a kind of 2.5 D game where the world is 3D, but everything's working off of 2D animations to get up rarely original feeling JPEG, but bringing it to a kind of modern and revitalized audience here. Other games are using very similar 2.5, the 3D world, but 2D animations as well. All we've got games as you've seen, which a purely 2D and we'll be looking in this course how we can start getting an understanding of how to leverage some of these systems to make similar games. To do this, we'll be working from an empty project and will be leading up to this kind of complete approach type style vertical slice of a 2D platformer, full width, a player, player animations some basic enemy AI, automated as well. We'll have some different intractable classes such as the springs and health pickup. So we have a full health system and then all of this will be done with a focus on clean, structured, maintainable blueprint code. And just creating this very simple prototype game is going to allow us to look at all of the features that go into the 2D systems, such as the flip book animation system, the towel sets and tile maps, which will be an overview of the inbuilt level design painting system that comes in with the Unreal Engine by default. So hopefully these topics and interesting to you, and I look forward to seeing you in the rest of these videos. 2. 02 - Project Setup: To try and save everybody a little bit of time, I'm just gonna go over a brief overview of what I have here. So I've created a brand new project. I'm not gonna go through our steps. I'm assuming that you have some experience with the Unreal Engine. I've got things installed and launch your project. So the project I have here though, if you want to follow along exactly, is a blueprint base, completely empty project, so no stars content will be needed here. The quality settings have been set for desktop, set to the highest quality. So there should be looking pretty good even though we're working with the 2D assets. And I before jumping in and getting things moving around and getting our class setup and bring in textures and all of those good things for the game. I just wanted to go through a few housekeeping steps that I tend to take in any new projects that I create. So there's gonna be a few things that I wanted to set my project to do just for convenience and I didn't want to self screening case, you're following along. I wanted the same results. So the first thing I tend to do is we can see how if we open a new blueprint or asset by default, this will open in a kind of floating window which can get a little bit annoying. I prefer everything to be docked up here at the top of my screen. So it's got this result. I'll show you what we get at the moment. We have a blueprint we can use here, which is the skyscraper. And you can see actually that hasn't opened a tool. This is on my second windows on extract this idea of a. And like I said, we've got this floating screen. If we want that, hey, we have to drag that to the top and we'll have to do it for every new blueprints or asset that we wanted to open. So ideally, I'd like them all to stock up here by default. So I'm going to go to the Edit, Edit Preferences. And then just here we can see the asset editor open location change that from default. And they'll change this to main window. You've got a lot of different options here as well if you wanted to. But I prefer this to just be the main window by default. So this means that if we don't have anything open a tool, we can click this again and we can see that the skies fed blueprint is now open exactly where I wanted that. So that's going to be the first thing that I tend to change. Then next, there's just a few other small issues that I find with the default project. So this is a little bit hard to see in the recording. I know I've tried this before, but you can see as I zoom in here, the floor seems to be going from a kind of darker gray to a lighter gray. And the same thing happens if we press Start and look around. We can see some adaptation happening with the lighting here. Now this is the auto exposure is trying to recreate what the eyes generally do when you're going from a light to a dark environment or vice versa. And it's a very useful thing to have on, but generally as something that you're going to want to control in a post-process effect or 30 camera directly. And what this can lead to is that you can start creating something in the Odessa that you think looks pretty cool. And then when you press play, the colors will look saturated and wash night. So to avoid this happening, we're going to have basically what we see in the editor be exactly what we see when we press Play as well, unless we override that manually in some of that post-process system. So it's picks this, we can go to Project Settings, we'll go to auto or just search for all time exposure. So Auto III, we'll bring this up. There's no other results here. So auto exposure is what we're looking to turn off. And that means if we go back in there, even if you get pretty close, we can see that we're not getting that darker colored floor as that's not what we're going to see in the game. So if we press Play, that will now also be exactly the same as it is in the editor. So we now know that if we want our world to Dhaka when he touch you, update that in our viewport just here. Next, we just want some of our folder structure setup. So this is going to allow us if we do this now, we can jump in and just start adding blueprints, bringing in assets, setting up materials, and all of those good things as and when we need them. And we don't need to worry about our project structure. Because generally we know that we're going to have a very similar structure for pretty much any project that we work them. So what I'll be doing is in the content folder, which is our root folder, I will create a new folder named assets. So this will be where all of our external things, textures, modals, anything like that, that we might bring in, side-effects will go inside of this folder. Now for this set of videos, I know that we're going to need a few different file types. We'll be working with textures, sprites, flip books, and different tile assets. So I'm going to create a folder for each of these. The shortcut, by the way, if you wanted to grab new folder is Control Shift and Enter when you're selected inside of the folder, you want this to be a child of. And that should do it for assets for now. If we do end up adding anything else, we can always come back and add a new folders later. Then back inside of the content folder will also have a Blueprints folder. And again inside of the content folder, we could also do with a maps folder. Now that we have I'm maps folder, we can also go ahead and save this on that tight would map we can see has untitled and we can press Control ns, place this inside of the maps folder, and we'll just call this Main. And this will be our main map that we'll be working from for the rest of the project. That also allows us to do something else, which is to set some project defaults. And we'll go into that in just a moment. Basically, we want this to be the map that we load up as soon as we close and reopen the project. Before doing that, we can also set some of the other defaults such as the character that will be controlling and Game, and also the Game Mode which is controlling the different controllers, the characters, and things like that, which will be spawned in, and the in-game at logic that will be kind of tracked if we have things like pickups, scoring, or any kind of objective system. If you wanted to flesh this project I and take it further by yourself. So to do this, I'm gonna go to the Blueprints folder. We'll create a new blueprint and how this is done by right-clicking going to Blueprint Class, finding the government mode base, which is going to be the Game Mode class. We want to use a name, this one, BP underscore gain might base. So something else to note in these selections of videos that I'll be following the standard unreal naming convention. So you can be confident that if you wanted to put anything on the marketplace or just work with other people familiar with the unreal ecosystem, this naming convention, that should be a pretty good way to get you started. So BP for blueprint, underscore the name of the class. And just in case we wanted to make any child classes of this game mode, we're going to specify that this is the base or parent version of the classes. And that'll make it a little bit more sense when we get into the rest of the videos, as we'll be using that kind of hierarchical structure a little bit later. For now though, we can open this. And what we want to do in here is set to the default class head that will be controlling when we have a character created. Of course we don't have that character yet. So I'm just gonna go back into the Blueprints folder, Right-click again, create a new blueprint class. And we wanted to find that the type of character we can control. So we have a couple of the base controllable ones. We have the pull or the character. Now neither of these are really created specifically for 2D characters and we actually have a class ready for that inside of Unreal. So if we type paper, basically everything will be using is part of the paper 2D system. So we've got flip books, which will be our animations, sprites. If you want something which doesn't animate, we've got things like Tom apps, trained editors. And we can see down here we have a child of the porn is the character, which is just a controllable porn with a few extra things such as the capsule collider on it expects a skeletal mesh and things like that. And then we have the alternative, which is the paper character, which is the child of the character class. But instead of having a 3D Skeletal Mesh, it predefined some properties, such as a 2D paper flip book, which is exactly what we want. So we're going to select this one, we'll call this one BP underscore player base. So again, if we ever have any kind of alternate versions of the player that we want to potentially spawn in, then we can make those a child of our base class. All of the basic logic that I will be in our player base class, such as the and movement health variables and things like that we can put in here. So with that we can have a quick look and head, but there's not very much we can see at the moment. We don't have any sprites or flip books that we can assign. Like I said, this is going to be controlling with the animation like I. But what we have is a capsule collider and a character movement component, which is going to allow us to very easily set up the movement for our character class. So what's not ready? We can now go back to our game mode. We're gonna go to the default porn class, and we'll change this to the BP underscore player base. So this won't do anything at the moment. If we press Play and see over here was still getting the government might base. So this is not using I was at the moment, which means we're also getting the default Pune, which if you've never seen this before, is the gray sphere. So if you ever see this, this is the default Pune, which means if you're not expecting this to be used, it means you've probably missed a step somewhere and you haven't selected your custom class to be selected. And this gives us that kind of flying around spectator mode type movement. So what we want to do is go to the project settings. We want to set the Game Mode be the default, the one that we've created to be the default for the project to use. We do that through the maps and mode section. We're gonna go to the game mode base here. We change this from a game mode base to BP unskilled game modes base, which is ours. We can see that automatically knows to use our player as the default player. And now if we go in and press Play, the difference here is that we don't have any movement because to the right-hand side, we can see we're using the BP unskilled game might base. And because we have a player starts in the world, it's created the BP underscore player base at that location. So I'm just pressing F8 had to eject from the player, which allows me to fly around. We can see his change to possess here. And we can see that we have the player base at the start of the level. And the reason we can't move this around us because we haven't put any code in our class to give it any understanding of what movement is. Can see it has things like gravity already processed hair though. So if we possess, we're always going to be on the floor at the moment, but that's a good start. That now means that when we do so adding that code to our play a class, the project knows to select that as the default class to try and possess and run the logic through. 3. 03 - Player Input: With all of that setup and out of the way, we can now go in and start providing some kind of visual reference for our class. So inside of the player base, as we don't have the flip books, so the animations ready yes, are imported from our textures. I'm just going to add a simple cube components begin with. So if we go to add components, go to cube. This is just going to be a static mesh to at least kind of visually represent where the player is going to be. And this means that we can start looking at the camera setup as well. So i, for the camera, I'm going to use something festival called a spring on component. This is going to be like a camera. Boom is a long stick, essentially a virtual stick plans our camera, it will rest on, we can see that's represented here. So the current is going to be at the end of our stick. And this just gives us a little bit of flexibility with how far away the camera is going to be kept. It has some built-in functionality for us to animate it or different types of camera lagged to get a slightly more dynamic feeling camera system. Now I've just noticed that I still have my cube selected. I actually want this to be a child of the capsule components. I'll drag and drop that in the capital components just so that we follow the rotation of the capsule and not the static match. If we do anything to that, then with the spring I'm still selected. I'll go to Add Component, find the camera, and then we'll place the camera component on, the spring on. So now whenever we take the spring on, the camera will follow. We were tight this or move it around as the camera is attached to the arm. This just means that we have to do a lot less with the camera as well. We're not going to be rotating it or accidentally doing things with the camera that we didn't want. And I, because we have this, we can see that's inside of Unreal. X is always forward. X's left and rights. Why is food and buy? So we actually want to be moving left and right half as obviously in a 2D platform over going from left to right, zed, up and down. And as I said, Y4 to back. So that means the camera is currently looking in the wrong direction at the moment, would be looking from the back of the character if the facing towards that arrow when we bring in the animated flip book. So what we're going to do we can get I was spring on and this is one of the first things we'll see is quite useful. We can rotate the spring arm at 90 degrees. The camera's going to follow that. I'm I looking at the, what would be our Player Animation frontal. Now, this is also going to be a little bit clefs. I imagine if we press Play, it will default to using that camera image. And we're going to be looking at very, very close out our cube. So what we can do is we can come have grabbed the spring. I'm going to up this target spring. I'm length to around about 600. And that means that when we press Play now we can see a little bit more of the level as well as just the player we're going to ignore for the time being that the capsule components little bit off. We won't be using this Static Mesh for very long because purely for demonstration purposes when we get into the base part of the camera setup. But I think that's going to be good for me. Next, we're going to want to set up our project inputs so the bindings tie keyboards and gamepads so that we can actually get our character moving around. To do that, we're going to go to our project settings. We will navigate to the input section. And just here we have two options. We have the action mapping and the axis mapping. So as a quick overview for those of you new to the engine, the difference head we have actual mappings would be things like single press inputs, such as jumping wolf, CMake, you jump once, or interaction keys like press E to pick up would be an actual mapping is something that you press and release. And generally as a kind of on-off switch. You then have access mappings, which will provide a value returned based on whether the input is pressed or not pressed. So if nothing is pressed, it's constantly returning 0. If you have it fully pressed, such as a key is either on, a keyboard is either pressed on and never perhaps if you have the key Daniel returning one or minus one. And then we can also work things in like unload sticks which have a range. So it'd be between minus 11. So if you're only pushing the envelope stick kind of halfway forward, then you'd be returning a value of like a rounded by 0.5. So again, this is a little, make it a little bit more sense. When we go into this in a moment, we're going to have just a very few different inputs for this game. We're going to want our character to jump. So we're going to have it jump input mapping. I'm going to want them to move forward and backwards or left and right. So we're going to have a move right axis mapping. So if we do the action mapping, first of all, we'll add a new action mapping here by pressing the plus icon will drop this time. I will name this one jump night for this, we're going to say jump is going to be, we can add a lot of different buttons, have to manage just a single input. So this is going to be useful if you wanted to make your own possessing a little bit more flexible. So as an example, we could say for people who use Ws and D, We could have w as a one option for jumping. For those who still like to use the Irish selection, we could use up the up arrow on the keyboard. Also for jumping. For people familiar with the space bar, we could use space for jump. And we could also say we'll use a will account for gamepads as well. So we'll use the gamepad and these are going to be the face Watson, left, right, bottom and top be x, y, a and B, or triangle, square cyclin x for example. So if you just visualize where they are on the gamepad, I'm going to go with the Xbox controller scheme. So we're going to use a and I want a to be jump, which will be button bottom. So that will be the gamepad. So we can now use a as the gamepad jump as well. So that's how a jump input. So if we press any of these and we assign this to the jump functionality in the character class. We'll get our character jumping around Next. Then we want to allow our character to move. So we're going to add an axis mapping. So the axis mapping, as I said, is going to return a value. So we can see the difference here is these are just single presses. We can add combinations, but it doesn't return a value, whereas for the Access we're returning an axis value. But this one, I'm just going to call this move right? And will actually only be creating the move right function. And you'll see why in just a moment. So what we're going to do is for the moving left and right of the character, we have a positive value. So let's say we were moving in a, we want the character to move right across the screen, which will be our positive value. We'll assign this to D for the WASD input. So we'll find D on the keyboard. That's how a basic rights movement here. Now we also want them to be able to move left. So we're going to add another input binding, and we'll find this one as a. And once we've defined the a input, we want to change that scale to minus 1. Now the reason being is that we're going to be moving in a positive value across the screen to move right. And we want to move in the negative value across the screen to move left. And that's why we don't need to move right. And I move left, we can just create and move right, which will be the positive assignment. And then it's kind of taken or intuited that move left is the negative value. And then we can do the same thing as we had for the jump. So we can create a number of these, afford the arrow keys I right arrow. When we've got the right arrow, we can again make sure it's positive. And then left. Is going to be our minus one and we can assign some underlooked movement as well for the gamepad. So would drop this time. And we've got the gamepad left. Thumbstick is when we want to use in the gamepad world, x is left and right, y is up and down. So we want the left thumbstick x-axis to be controlled hip. Now remember what I said, that the axis value is returning a value of either minus 10 or one or between that range. Now when the analog stick is unmoved in the middle, and that's going to be 0 if the user pushes it to the right and that's going to be up to a value of one. And if they move it left, and that's going to be done to a value of minus one. So this guy here, actually a kindness for all of that depending on the way that the client is moving the envelope. So that is everything ready for the move right functionality. So if we move them back over to our player base, will move into the Event Graph and we can do a little bit of tidying has, so we might need this a little bit lighter for the Begin Play. We can get rid of everything else for neither we went Neat the overlap or the event tick at the moment. And rather than dumping all of our input bindings into the general Event Graph, what I'll do is in these sexually, but yeah, I'll create a brand new graph. I'll name this one input. And we'll put all of our input related things in here. Now remember the names that you've just cooled, you're emphasizing his hands. So we've got jump and move right? Because we're going to be cooling and those in just a second. So to get up move right function, we'll just type move right? And you can see we have two options. We have the axis or the event. So if we start with the events and such again for me of rights, and then get the axis just something that can confuse new people, hire a little bit. Basically, the axis is the value returned when you're pressing some things like I've mentioned, minus 10 or one or in between that. And then the event is the option which gives us the execution pin. So we can run some functionality off of this. So let's do a quick print string. So what this is doing, and we can print the axis value. So if I come on component, press Play, when I'm pressing nothing at all, we can see this is running constantly, so it's kind of like an update function or an event tick. When I press D, which is my right movement, then I get one. When I press a, I get minus one. Same for the right arrow on the left and right, we can says, Well updating, I'm not in the most simplistic form is high. The axis binding works. So I'm just connect to the gamepad here. And I'm now moving to the left on lipstick slightly to the right. And we can see we've got some value between 01. And then if I move it left, we've got that value between 0 and minus one. So this is how we're going to be driving the movement of our character in a moment. What I wanted to demonstrate, the only difference here, the x's value is exactly the same as the return value from the getMethod rights value here, the only difference between the two is whether you need just the value for a calculation like so, whether you need the events for the execution pin to call another function. So we can see I'll use this again and we get exactly the same options or responses. We get one when I press D minus one when I press a. And I've got the control panel again, and we can see we've got that value depending on which way I'm moving the unrealistic. So exactly the same thing. This is just nice and handy if you're using a calculation and you are trying to get the velocity multiplied by the direction of something and you don't want to have to cool the events. You can just check the value being returned from the input mapping. So with that done, kind of have a better understanding of what this is doing. What we can do now is from this, we will cool our add movement input. And this is really as difficult as it is. A character moving. This is taking some inbuilt functionality from the player class on the Character Movement Component. And it's basically just going to add movement in a direction that we give it based on a scale. So if we say the scale is set to a permanent one, that means we're going to be even a sentence that direction opposed to value constantly. So we know we want to move left to right and we're going to say one on the x because remember, we've already seen that's the x-axis is this red one, and that's the way we want to be moving. So just here, y would be forward and backwards. We don't want to go in and out of the background and said would be up and down. We don't want to go up and down unless we're jumping. So if we press Play now, that's going to move one unit and a positive value x, because we've hard coded this to be based on our direction multiplied by the scale, is going to be moving constantly in that direction if we don't change that. So the way we're going to alter that you may have guessed already is based on the axis value. Which means if we are suppressing anything, we're actually multiplying that by 0, which is going to stop our movement. If we press, D will move right. If we press a will move left. Same for the Arabs, and again, same for the unlock stick. So it really is as difficult as it is to get movement going on a character. Now this is a little bit magic because there's a few things going on in the background here. So you may be wondering why such a low value like one is making us move relatively fast based on the direction we want to move it. Now the reason that is, is we're not actually moving one units in the Character Movement Component here, we're actually moving 600 units. So what this is doing in a very simplified form does a lot more going on in the parent C plus plus class. But to get the basics across, what's happening is we're multiplying the world direction by I will walk speed. So we're actually moving 600 units multiplied by the scalar value. So we're taking our value of 600 and we're saying that if you're not pressing anything, then multiply that by 0, which is again comes to that movement. If you're pressing D or whatever it was assigned to, move right on the positive value, then we're multiplying 600 by one. So we're moving 600 units in that direction. And if we're holding a negative value, so a or left, then we're multiplying 600 by minus 1. And that will get us moving in a negative value or left across the screen. So just to let you know that there's a lot to look through here if you wanted to play about with different things and to confirm that that is what is being controlled here. If we lower this to something really slow, like 50, then we can see that the movement is completely hampered by that change in speed. So there's a lot that you can play around with her. I won't go through all of this. I think a lot the naming is fairly kind of common sense. And if you look through it, you can see what it's responsible for. And that would definitely be something to play around with between videos and just get a better feeling of what the Character Movement Component it's doing. You do have a lot of flexibility using this, you can do things like changing the acceleration so you can make it take longer if you wanted to, to have like a build up to that speed, 2048 is pretty much 0 to full speed. If we load this to something extreme like 512, then again, you're gonna see a big change in how long it takes us to reach that maximum momentum. So you can have like a, I suppose that would be your old kind of Sonic game way. You'd have the jogging animation leading up to the running, leading up to the sprinting when you reach that full 2014. So that is the max acceleration. Again, I'll leave that the same tonight, but you can tweak all of these different values and really changed the way that your character feels to me for right? Now, the final thing for the input then is we're going to add our jumping inputs. So again, very simple. We want to cool the name of that. Action mapping that we made earlier, quite simply jump. You can see it's actually a lot of different returns here for jump. And that's because there's quite a lot built in to our character class that will allow us to alter how we jump and how that reacts. But we want our action event jump to begin with, with the one that we've created in the input bindings. And you can see again, this is slightly different to the mapping of the axis map. The main difference is that we're not returning a value. So like I've said, this is either pressed or not pressed. So when you press W or the up arrow or a on the gamepad, this will be cooled and when you release it, this will be cool to see you've already got these two states. Now again, quite simply, there's all of this function on that's already built-in. I'm going to pull from here. I'm going to call the jump function. We have a function heck would jump. This is through the character class and has again, some magic kind of going on under the hood, but it's just applying force in the z axis for us. So if I come in and press W, then we jump up. And same for a on the gamepad night because this has some stuff ready for us to kind of manipulate and play around with. We can come here to the player base, search for it, jump in the Details panel here. And we've got a couple of different things we can change. So we can actually change the jump. We can set this to a maximum of five. And we can get this doing a sync tuplet jump. Of course, if you just wanted a double jump, we have to, you've got a double jump, so super easy. So already get a double jump implemented. And then we've got the max HoldTime here as well. Now this is going to be relevant to the next spot, something that we want to do if we're going to use the base built in jumping system. Whenever we release this, we also want to call the stop jumping. So this will update that parent class was checking all of this and it will update the system to let it know that the jump button has been released, which then comes into this jump hold tight. So if you've played games like the old Sonic games, Mario games, or modern platform and games as well. They'll have something that a lot of designers will cool, variable jump height. So if you hold the button diagonal four, or if you just tap the button once you've reached that minimum at jump height. Whereas if you hold it for a certain period of time, you'll reach slightly higher peak in your jump like site. So again, very flexible system ready to go inside of Unreal. We have this already accounted for. The moment we don't have that variable jump height. We're going to get the same thing regardless of how long a help desk, because we've got the max jump old-time set to 0. Now if I put this to something extreme, like 55 is way too high for this. But if I put it for as long as a whole to up to five seconds, jump force is being applied here. And the way that we would use this, so the player has a little bit more control is that as soon as we press this release and stop the jumping function, this will be triggered and we're going to break out early and not reach that peak. So I've got up to five seconds to hold it. But you can see if I only hold it for like a second, we'll then start jumping up, falling back down. If I hold it for longer than until I release it, we're going to get that variable jump height. So always remember for reasons like this, because things are being done under the hood that you may not see. You want to remember to always call your stop jumping when you're calling a jump function, if you're using the built-in functionality, now turn this down to something a little bit lower. Like, I think something like 0.25 usually works quite well for the variable jump. It's not going to be a huge difference. But it does give that player a little bit of that feeling of a little bit more control over the way that they jump and analyze them to tackle different kind of obstacles in different ways. And I think for this game, I'll make it a little bit more difficult. We'll turn the maximum jump down to one. Don't really think we need a double jump for this one. So again, just come and test this. This is working with all of the inputs and I have the movement for the gamepad jumping with a. And again, we've got that VAB, we jump height if I hold it done. So I sent my systems. Let's get started with, it's pretty clear what these are doing, but just get into that kind of good programming practice. We can throw a few comments, right, nice. So if I select the nodes, press C, Then we get to a comment. This one would just say is controlling the directional movement. And we'll do the same again. So we'll select these press C and we'll say this one is controlling the jump. Now it may seem obvious, but the way that the comments what is very handy. So even for things which are very obvious, when you've panned out a lot, you're not going to be able to see the name of the events, but the comments do scale based on the Zoom. So it can be useful just to put comments in like this even if the very simple. So if you ever wanted to dive straight into the jump section, you've got loads of nights everywhere. And just Herman, I'm finding that the jump very, very quickly. So with that done that we can compile and save that. That's pretty much the basics of the plan movement. 4. 04 - Textures: With some of the fun stuff already implemented, we can I get to working on the visual so we can stop bringing in the assets, specifically the textures to start changing up the class so that we can actually see a little bit more and scale how it's going to look and how it's going to be represented in game night. For this, I'll be using a free asset pack that you can get from each dot io. It's called pixel adventure. There's also a pixel adventure to, it's made by pixel frog, and it is completely free to download. Of course, if you enjoyed the package and you wanted to support that work, I'm sure that more than appreciates some small, larger donations, if you're able to do that when you're done writing them. Now, I'll also provide some dihalides which you can get from below, which have all of these assets or some of the assets, the ones that we'll be using specifically for these videos, which have been repurposed on, altered based on the scaling and things. And I'll explain that in just a moment why I've made those changes. But if you wanted to highlight these, they do come in a very small size, which is part of one of the classes. A little bit of the problem when working in an engine like Unreal. But again, hopefully you understand the process of downloading something from each, if you wanted to get the entire path as it comes here. Otherwise look like it's got the download for the project files to follow along with the videos in the same exact way. So what I'll be providing these, we're going to get the bat, the heights, two forms of play, or they will only be setting up the frog, the spring, and the level pieces. These I have set up in a particular way so that I can show certain different approaches to extracting these, animating them and getting them set up in a project. And also these have been resized. So this is the way that you will find things or downloaded if you get it from the web page. So these are the ones which haven't been touched. We can see that they are 32 by 32 pixels. If we look at the jump animation or the double jump animation, we can see that a little bit small. And if you start trying to increase this, then we're going to get that blurry effect. Now, I've increased the size of assets that I'll be using. I recommend following along with in a way that doesn't do this, which is basically running it through a 2D package like Photoshop or Krita. I've chosen to increase the scale by 400 percent and making sure that we set the algorithm to nearest neighbor, which means you'll get the scaling crease based on the pixel percentage and you don't get any of that kind of smoothing around the edges, so you still get a pixel perfect kind of image. Now the reason for this, a couple of things I wanted to mention. Well, this isn't a very optimized way to bring things into an engine like Unreal. Because Unreal will try to compress things. It will compress the image sizes for performance later only if you provide it in a power of two. So that is something like this. Why I've put them all together in one big style sheet. You can see as 1024 by 1024 dimension, which is the power of two. So 512 by 512, 256 by 256, and so on. And I, because of that, it's able to take these assets that I've done that with, and it will try to compress them if they're in that power of two. So probably went do it with these. But like I said, this is more of a demonstration. I wanted to show a few different ways in case you do get, get given us as like this is not the end of the world. It's not going to break your project. And it will be useful to know how to extract things in this way as well. So that's the first thing I've changed is web or school. I've made them a power of two sprite sheet. Now the other thing is obviously the size and the reason I've chosen to go for the biggest size. So rather than getting the 32 pixel by 32 pixel, we're working more with a 128 by 128 per grid space, so per image. And the reason being is that this will avoid as needing to override some of the project defaults, such as the AI navigation, search volume. If you consider that nowadays, we're working with things like, okay, resolutions. You'll have images which each individual image could be lifestyle of law, and 24 even 2048 by itself to get those high res images. So working with something which is only a 128 pixels image is still going to be relatively small, definitely not going to be groundbreaking. We can see this entire sprite sheet is only 31 kilobytes in size. And this means it's going to be much easier to work with. We won't need to change the world sizes. We can still work with a centimeter by centimeter weld size. We went need to override any of the AI systems as well. So I think in this case, working with a slightly bigger image set is gonna make things a lot more convenient. So as I've mentioned, if you count, I would definitely recommend following along with the assets that I provide here. Let these, once you have these extracted, go back into the engine and we're looking at getting some of these textures into the engine and working. So we can do this a number of ways. The thing that we're going to be importing is a texture. So I'm gonna go to the texture folder. You could navigate to where you find or stored them on your system. Go to Import game assets, textures, which is going to be the location, and you just find them and select them all and choose Open. And that will bring them in. Another way is to just have the window open here. We can drag, select all of these and just drop them into our project. So they're looking at a little bit off at the moment, but that's fine. We'll be fixing this in just a second. I'm what we want to do. In fact, first of all, if we open one of these, we can have a look at some of assessing. So for the most part these look okay, maybe a little bit fuzzy around the edges. It's hard to tell, but we can do something to improve this in a moment. So we've got the Alpha that we're ready, you need to. So the first thing is that this is a texture which means we can't drag it into the world who can't see this in the world at the moment, we need something called a sprite to be able to do that. So I'm going to go back to the main, that Textures folder. And what I want to do is we can grab all of these. And basically we want to change the details here and get it to automatically update this to better suit our project. And we can do that by selecting all of these. So shift and select, right-click on our assets and go to Sprite actions and apply it paper 2D texture settings. And what that will do, you can see all of the alphas been accounted for. It's gotten rid of that black background. And just here we can see what's changed is that that used to be the default dx t one hand, it's decided that user interface would be Claire and I think that does look a little bit sharper. And then down here, the important thing is it's changed this to be 2D pixels. And this works perfectly fine because we're not going for that smooth hand painted or contacts should kind of look. The perfect pixel image is pretty much what we want here. And again, I think that started off his world by default. So doing that on all of our assets saves us a lot of time from setting this up manually. Now the next thing we want to do is turn these into sprites so that we can actually start to extracting things from them. Before we jump into that, I just wanted to give you a quick example of what I meant by these scaling. So if I start with the huts, you don't need to follow along here. And we're gonna do this in a particular way that moment, but I'm just going to extract the sprites, let it choose whichever option at once. We're going to go more into the options in the moment. And it's the sprites, not the textures, as I mentioned, that we can drag into the world. So you can see this is actually roughly the same size as this plant stopped if we press Play is not too far away from the size of our cube. So this, like I said, it's already kind of lining up with the centimeter based world scaling options. So I'm just gonna get rid of those for NIH. And in a similar way, I'm going to get rid of the ninja frog assets. We're not going to need the smaller versions, the ones which haven't come with the updates ready included. We're just going to keep for NIH our textures here. Now at the moment, I'm just gonna get rid of the hots will probably do the same process in just a moment. But I wanted to go through a little bit more detail on how we can extract these into our game. 5. 05 - Flipbooks: So the reason that this gets us and topic when it comes to extracting things from these textures, is that there's a few different ways that you can do it. And depending on how the assets have been provided for you, which depending on your team or the project you're working on, may not always be given to you in the ideal way or the same way. You may have some issues with highly pivot point is working which can affect your animation. Not perfect example for this. If we go to the player frog, when we want to extract all of the individual images, we go to, right-click on the texture sprite actions and extract sprites. Now this is why I did very quickly just a moment ago on the hot texture over here. And I just let it choose the auto extraction. So you can see the way that this is working. We have the outline color, which is the outliner and every image that it finds based on the transparency around it. So it's going to find every ending pixel and class that is the button. This will extract all of these. So we can do this again. If you wanted to change the naming template, you can change this hair and then each one will be named something like t underscore player frog, underscore, sprites, etc. So we can do that. We can see that here naming conventions quite useful because it adds the numbers. So we know that we've got 25 of these images have based on a zero-based array of images. And what I wanted to show is basically, we've got the idle animation, which is these first €2. Then we've got the running animation. We have the jumping animation and the falling animation or the other way around. So the first 11, so 0 to 10, the idle animation. So the way that we then make our animation from the sprites is to right-click on a selection of sprites that we want to build the animation, making sure the numbering is notice I, this is going to be the start of the animation to the end. So this will automatically put it in the right order for us and then create a flip book from this. So nice and simple. Remember the flip book is our animation. The sprites are the image that we can bring into the world and the textures build all of that information. Now if we bring in this animation, we can see immediately there's a little bit of a problem. So I'm going to drag this up, I'm going to press end. So the end key will drop this down to the floor. And we can see that the feet are kind of jumping up and the head is moving down. And that is because it's based on this central pivot point. So it looks like he's kinda floating a little bit. Ideally, the way that this animation was meant to work is the feet stay perfectly still and everything is moving up and down around that pivot point. So if we go and here we can see again, that's not quite ideal, it's not quite high. The animation was meant to run. So we can manually fix this if we wanted to, by selecting all of these assets. So again, 0 to 10, we can right-click on these and we can go to Assets actions and then bulk edit via Property Matrix. What this will let us do is we can drag and select all of these, shift and select all of these, go to the sprite options. And remember I said it's because the pivot point is I've placed that that's broken because this is going from the center and because each image wasn't the same size, it was based on the weather, the pixels and didn't post-its going to change from image to image is kind of confused whether is, so what we want to do is change this from the center, center to bottom center. Now if we do that, we can see the pivots jump down here and that is more of high the animation was meant to look. So that's an easy fix if you do get us that's like this and that's the way you have to work with things, then that's perfectly fine. We've got ways that we can fix this. Just to join another example, we can change this to something like top-left and that will completely break it. Animations and I playing from the top-left of the sprites. So everything's moving up to that pivot point again. So that's one way that we can fix it. No, I'm not going to keep these because I've actually set this up in a specific way. So I will delete these finite. If you have to do that type of process as well, make sure that you remove the thing from the world. We still have what is an icon of a null reference to an asset that doesn't exist any longer. So we'll get rid of t for all t from the world. And what I'll do next isn't pretty much same process, but I'll show you the way that I intended this to work. So I'm going to right-click on the player frog again. We'll go to sprites actions, extract sprites again. But this time, the reason I've put this in a grid is I've made sure to set up everything that she dragged everything a 128 units away from each last image. So we can change this from auto to grid, and we can see that finds the entire grid. It's not quite website where the images are. And we can change the cell width from 1024, which is the full size to 12 eight. So we can see we've separated those off and then the height to 128. And that when I extract everything, that's exactly the same size. So we've got a little bit of headroom on these, but we can see that all of the feet being cuts at the same place. The animations where the current is meant to be in. Yeah, Again, that's accounted for with that same size grid space. The problem with this does come that you get these extra cells, these will become sites and classed as a sprite. We can fix some of that by the number of cells that we want to cut down to, which I'm going to set to six, because we only have these six that we really want. But you'll see that there's also helps us with the naming convention. And we can very easily create our animations by using this. So what I'll do is I'll extract this. So we now have, like I said, this is separated quite nicely. We know that all of these are the idle up to the first empty space. All of these are run up to the next empty space. Then we've got full and we have jump. So what we're going to do, recreate that flip book. I'll right-click on this great flip book. Now I'm going to keep this one, so I'm going to name just want FB, full flip book underscore idle or player idle. So again, the naming convention for flip books is FB underscore name of the flip book, textures, a t underscore name of the texture, and so on. Because there are so many sprites so much you're gonna get a little bit lazy and not renamed these. I'm just going to Shift select all of these and drag that into the sprites folder just to get them right the way we now know that we can delete these empty sprites as well. And we can just kind of go along in this order and it makes the process fairly painless for us. Now you can see that because that has the exact size that it knows that each images that has actually worked for us correctly to begin with, we're not getting that unwanted falling animation. So next we can do the same thing with our running. So it will shift, select all of these right-click, create, flip book, lameness. Want to FBI underscore player run. And we have our running animation. Now I think this speed works quite well. The first thing that comes to mind here is the idle looks a little bit intense because it's animating so quickly. And it's really just meant to be when the player is doing nothing. I'm gonna change the frames per second from 15 down to something like eight. And that looks a little bit better to me. You can change that to whatever you want it to be, but this is just basically changing the playback rate. So if you want them to be very energetic, then we've got something higher. Or like I said, something a little bit more detail, we can go a little bit lower. Again, we'll drag all of these into the sprites folder that we won't be using these again, but of course that referenced in the flip books, so we do need those to still exist. Likewise with the textures, it goes without saying I would hope. And that leaves these two. So we've got the falling animation. Now this is quite interesting when you're working with something like this, even as a single frame, we still need to make this a flip book because that's what our components in the 2D character class is expecting. So we'll call this one FB underscore full and we'll call this one, create this one, sorry, and call this one f be underscored jump. Now if we open both of these, so I'm just shifts selecting and pressing Enter. We can see that this is still playing. We can save a little bit memory, I guess. Yeah, bye. It's time to 0. So that's not going to loop. It's not been actually play the animation, but this is not the asset type that we need for these two animations, as they are technically animations. So that is all of our player flip books ready to go. Again, we can grab these sprites and we'll drop that into the sprites folder. And then we can remove all of these empty cells. That leaves us with, I will flip books so we can move our player flip books into the flip book folder. And that is basically the project setup that we're going for with the structure. Now the next thing is our mask player. The reason I have this, I just want to show another example of West certain things went. What can you need to kind of jump in-between? So these have been set up exactly the same way, a 128 units apart from each other. But because of the size of this player and the head piece that it has, if we come into the extract sprites option, again, the automatic one wouldn't work here at school because these two, the feats are actually touching the head piece. So these would always be extracted together and completely break that first setup. So again, although for the frog that was kind of a work around, for this one, that wouldn't be a workaround. And you would have to know the grids scaling. And again, separate this by a 128 on each. And you can see that cuts through just whether foot on the head piece kind of touching each other. So I've just something that I realized what's going to be a useful example. Like I said, I'm not going to use the mask. I'm actually going to get rid of this NIH, but I just wanted to show that quick example. Likewise, the same thing actually happens with the bot. Will do this one together. We'll go to the bot sprites extractions and extract this. So again, because these wingspans are touching at classes, these two as a single bat and then the rest of these are working perfectly fine. So what we're gonna do is we'll change this to a grid. This is a complete width of 1288 and we have Southern bats images, so I divide it by seven and we'd have a cell with a 184. Good to be, yes. So that would be exactly the amount that we need to cut off. So we can now see that they're not the same size, but that's perfectly fine. Remember we have those pivot overrides if we need them, but that's my cutting of rights in-between those two wings going right up to that links us the size that we need. It's perfectly fine. A 120 is picked up what the maximum is, all of those. So again, we'll extract these. We will create a flip book and for this one FB undisclosed box. And we'll just check that that has worked. And in fact, we didn't need to do any pivot offsets. How that looks perfect. So again, move these into the sprites. We can weave that into the flip book. And we're just basically going to do this for the rest of them. So for the huts, as we've seen previously, this actually works if we just do the sprites extraction guide to extract sprites. And this one will actually work with the auto extract. So we can right-click on this Create flip book called FB undergo hots. And just double-check that is. Posting from the middle, which is what we want to anyway. So that has been set to perfectly fine. And the final one, I'm going to choose the option here that we're going to the spring, we're going to right-click again. We'll go to the extract option and that she can't remember if I set this up to be grid-based, so we'll have a look into this I think I might have done. And yet we can see that all of these on the ground. If you do a 128 by 128 grid, it means we just need to get rid of the empty cells. And then we can select all of our spring animation points. Grant flip book called this one FB undisclosed spring. And that works perfectly so it stays grounded and it does a small pushing animation. So just to tidy up, again, flip books in a flip book folder and sprites in the sprites folder. And you can Control click to deselect the things you don't want. Weave those in and we're done so well, that means we can close all of these windows. We've kind of finished with those unless you wanted to change the playback speeds. We can now go to our player base class. Inside of this, we want to go to our sprite. And in fact, first of all, he wanted to get rid of this cube. So delete the cube, we'll go to the sprite. And in here, we can now change our default source flip book to our FB underscore, let's say player idle, which gives us an idea of the size of the player. Now I know that we're going to need to move this up a little bit because of the pivot point isn't quite in the middle of the capsule, so we're going to move the up just a little bit. And then we can grab our capsule and we'll drag the capsule size dine. And we want this to be probably just inside of the feats. We don't want it to look like the plan is hovering and we're gonna make the capsule a little bit smaller than the player is. So it looks as though it's resting quite nicely on the floor. And if we try this, this should drop into the world. And then we go, we can see that we're moving around. It doesn't look so hovering. And as we get to the edge, that looks about right? So we obviously want to start playing different animations when we move around. But this is definitely a good spot to why we need to be. We have the 2D animation system now in, and we can start getting an idea of what it's like being in the world. So this is kind of like what I was talking about in the trailer to these videos. We've got the game up to path traveler, which is a 2D flip book, essentially moving around in the 3D world. So we could, if we add new dimensions to deaths, have a very similar game using these 2D animations, but having this kind of 2.5 D or 3D world to interact with. So again, another benefit of doing all of this, although it's not an engine which people really consider being kind of 2D 3D or 2D optimized. We do have some pretty cool features that we can make with the Unreal Engine, with the kind of 2D hybrid. So again, at this stage we're getting quite far and make sure that you're saving your project as you go along to keep all of those updates we're making. I mean, another thing I've just remembered, if you closing and opening the project, you are probably being greeted with a new map each time. So what we can do to bypass that for my go to the maps and mode section, because we have our main map saved, we can change the editor Startup Map. You're getting the template default, which is just the empty map similar to what we have, but not the one that we've been working him. Then what we can do is we'll change this to main. So now every time that we close and open the project, that will default to be the map to open. And likewise, if you ever want to give this to somebody else to play, we can change the game at default map to Maine as well. So again, there'll be greeted with this map that we're working on and we're going to start making changes to this soon. To make this more 2D base will be using our painted tile map and seeing hold of that works. 6. 06 - TileSets: Before we can get to painting things inside of our tile maps though, we need something called a tile set. And to get those, we're going to once again re-purpose our textures. So from the assets and the textures folder, the final thing we haven't used, you may have noticed is the T undisclosed terrain. What we want to do this is something a little bit more unique. So we're going to right-click again. Previously we've been extracting things as individual sprites. What we want to do if this one is, we will change this to create a tile set. This means you can say it looks pretty much exactly the same at the moment. This allows us to specifically set things like the size of each individual cell and then give these different cells things like collisions from this option up here. So at the moment the default tile size is 32 by 32. And for those of you paying attention based on the size of the texture, if you've looked at this, this isn't going to work. So each of these four, basically I meant to be what we select. So we can see that 32 by 32 is a little bit too smooth when we're painting things, it's being expected that we're going to be painting things in blocks this size. So what we want to do to achieve that is just up this to 64 by 64. And this is very important that we make this change nine as this will kind of carry across to our tile map when we create that a little bit lighter. So it's going to save us time and automate the process a little bit. So with that, that means that we now have the correct selection size, what we'll have our different pieces like so, so that's the first important step. Now the next thing to note is that I'm only going to be working with this selection up here if you wanted to make different levels and use these different assets that I've provided, then you can use one of these, just follow the same process that I'll be making on this selection up here for the different pots down below. And then you can come up with your own creations for the levels with these buttons. Now the next thing is we want to consider them hire these will be used in the world. So things like this, I'm going to class this as a bit of background information. So things like the back grind won't need any collision is not going to interact with the player or anything else. In a similar way, we have bits in the middle just here. So these again, that likely never going to come in contact with the players. So we probably won't need to add collision tiny thing like this, the bits around the outside. Thanks. So these walls and the floors and things, these will have potential to be interacted with. So we want to add collision to these tiles. Now the way that we do this is a little bit of a repetitive process, but we're going to select each individual tile and we'd see that this appears up here. Now unfortunately, if we select multiple things that disappears and there's no kind of copy paste that I've seen. So what we want to do is select each bit that we want to have a collision, go to add books. And you can see over here a white box is just a pad around our collision tile, which shows us where the collision is being set. If we wanted to update that a little bit. So maybe that's a little bit too, going up a little bit too far, in a little bit too high, we can move the arrow around and that would change the size of a colliding box. Or we can extend that if we wanted, pass the visible image. And I've heard of these, these actually work quite well if we just leave it very snug around the grid size we have here. So I'm just gonna go through and basically select every bit and hit the Add box. So that's the first one done. Basically all of the outsides there. I want all of the sides. So these tops and science and then all of these individually can have that collision as well. So I'll put that in a kind of sped up montage in the background here. So I don't have to watch it in real time and you can follow along and pulls it if it gets ahead. Okay, So everything done, I've given these colliders as well because these can not some nice detail around the edge of the levels that you can still jump up on it just to break up the monotony of just seeing this 1-bit of Lund and the border. So the final thing is once you have all of your collision, you think you have it set up in the correct way. We can go to the colliding tiles option here. And it will actually change everything to be a blue grid based on what has collision and then what doesn't have collision. So we can see that everything that I said would need collision has an F. I don't think the players ever going to reach this. So probably not worth doing. They definitely won't be able to reach this unless they've gone a little bit buggy. And likewise, this is just kind of filler visual for that to go in between the different grids when the painting to make things a little bit more interesting, these will all need collision there any really going to be used as like platforms or bricks to jump up them. So that is pretty much perfect. Now, I probably won't use these. But just to show you a final example, we do have these dynamics. So if you wanted to use floating platforms or something, these probably won't be ideal to use in a tile map anyway, because if you want to plot when we normally want to be able to jump up through them. And you cannot do that very easily with a tile map. You probably want to make that blueprint of its iron on your setup collision in a different way. But if for some reason you did want to use this, if you just want them to be like a solid bridge that you can't jump through. Then again, very similar way, we're just going to add collision here. So all of these, and then this is where this comes in handy though. Obviously the hello MOOC with this abridge is definitely too big from the bottom here. So we're going to select this and we can just drag this up and maybe drag it up just a little bit more so there's no great way to overlap this. We can change the grid snapping dynasty, something like 1. So we get less of a snob and I would go, we can go around the outline perfectly and we did that. But all of these, so I thought this used to update. It seems to only have information about the whole grid sizes. I was hoping it would visually represent this here, but I can't confirm from previous experiments that in-game it will take the collision from this book size here. I'm not necessarily what you see here. So that means if you do out these in, the character won't be colliding until they reach the absolute bottom of this rather than D, the dead pixel space around it. That is really all you need to do to get a towel set setup that's ready to go the collisions as we need those. And like I said, if you wanted to take that same approach, you can do that for all of the different assets. You can probably already see why I'm not gonna do that for all of the assets here, for the sake of the tutorials is that would be a little bit repetitive. And this will be more than enough to show the main techniques and principles that go into creating our tile map. So we can now close the Taus that we've pretty much finished with this for the rest of the course, I will drop this into the tile assets. So we're only going to have one tile sets on one tile map. So it's probably not worth having separate folders for them. So I've just created one kind of encompassing a tile asset folder. 7. 07 - TileMaps: With our tunnel set in place and ready to go, we now have the asset that we need to base a towel map on. So similar to with our textures, if we right-click on this, we have a context sensitive option. So we can now create a tile map from our tile sets. So we can choose this option. Again, this will create a new asset down here. I'm gonna go into this and we can see how this works. The first thing is the active tile set has been automatically picked from the one that we've created a bit earlier. If you had more than one, you could change that here and it is taking in some information. Again, the important thing to the right-hand side, we can see we've got these undo arrows and the tunnel width and height has been set to 64 by 64. If we had this by default, it would've been 32 by 32. And like I said, that would then mean that was selecting incorrect sizes from head when we're trying to paint things. So if we were to come in and select this, we're gonna be getting the wrong chunk as we can see. So that's why it was important that we were using the correct tile width and height to begin with for when we select things from hedge paint into the world. So now as I select these, you can see how it's changing the paintbrush and we've got the option here, paint Asia and fill. So very simple, but you're probably familiar with what these do. And then this white grid is kind of like how Canvas it will be the world that we're painting onto. So the next thing would likely be to change how big we want this to be at the moment, if we were to, for example, grab all of deaths, place this in, that would essentially be the size of our world. So let's see how this works. We can drag in our tile map with us into the world, and that's probably a little bit too small for the planets will correct them. So I've got some collision out of the camera, was taught that a little bit later what we want to do those make this bigger so we can change that with the map width and the height. So every grid unit head is going to be 64 by 64 as you would expect. And if we drag that along, we can make this much bigger. But you probably wouldn't want this to be huge, otherwise you have a very big space to fill. In fact, I think something like 60 by 40 might be quite nice here. Maybe a little bit smaller in my tests, I think I went over 80 by 20. So something wider done is tool. We're just going to make a very kind of horizontal level. And then we can start at least kind of working out how the system works. So the first thing is I'm going to get the eraser tool and get rid of these. And we want to focus kind of like if you're familiar with Krita or again, Photoshop, we have a very flexible last system here. So layer one is the one we haven't moment. We can add new layers to this because something quite simple. So I'm going to create a background and a foreground level. So the one on top is actually going to be the foreground. This is the front most layer, and then we have eight background layer. I'm just pressing F2 to rename these and given those are quick name. Now as a quick example to show what this will look like, I'm going to get this black color here. So by selecting that, select the fill tool and on the background, just fill that will in black. And then to test, we have the right one in front. Let's grab a little bit of hill changes to paint. And of course, anything that you select is going to be painted here. And we'll just make sure that this paints over the background. So that's pretty much how we're going to be using this. We now have our background is pretty much set and ready to go. So everything behind us is going to be lots. Black painted color. And then we can start drawing onto the foreground, which would be the bit that the character with the pie is going to be interacting with, with our colliding pieces. So a few things festival, these have been given a collision for a reason. So I'm going to add these as a kind of outline to the level. So ideally what I was thinking is we would have a kind of quota around all of these. And this is to contain the camera as well. So the camera's only ever going to see this kind of black outline, which level it needs to be wider because the camera can see quite far horizontally, so we need a good thing. And something like 16 units was roughly when the camera would start seeing that that was empty space around it. So we'll have like a corner around about here. I'm just pressing zed to rotate this and x will flip it horizontally. So I'm going to rotate that right one, the right one roughly there. And we can just erase that one and then grab one of these side pieces. Remember, we want the players be colliding with this stone looking piece here. So again, I'm just going to flip that and we can just paint that diner around here. You can use different pieces if you want. They're all pretty much the same way. So I'm just going to flip that to reuse it. And this is basically how we're going to set the level up. So this is going to be a lot of flipping things, dragging it. If you make a mistake, then we're going to arrays that. You can also come in select and width paint tool. As long as you got the paint tool selected, shift select, we'll copy that. And again, we can flip that and just paste these him. Again, making sure you've got roughly a 16 points distance from the edge here. And you should be fine with the camera not seeing the empty space that we're going to have in the background. Because remember, we're still going to have all of this around it in the background. We can simplify this a little bit for the artistic style. But the main thing is that you still don't want to see that kind of 200 obviously that this isn't the entire world. The next thing, so that's kind of the borders done. We can select this as well. And I'm just going to flip that again using zed. That isn't a bit dumb. The next thing is we want our hill. So this is pretty much just going to bes and this up a little bit too short many to add it a little bit extra height to this. We'll see how this goes. So paste this down here. Then we're gonna want these to go down to the floor and you can see it does have a little bit of an outline. So keep that in mind that these should be going along the floor as long as you want them to go. And then this will be joining up with the other pieces, making sure that the middle piece there because of the outline. And then like I said, this is the bit, this is just filler that the player went to see him early the autistic. So I'll have gone floor is when we want a new ledge just using a similar kind of setup that we can then paste these along. And another tip is if we drag, select these two to the right and then just drag that along. That. And peace will always be dragged to the very end. And so you can see, it just saves a little bit of time there from selecting different pieces over and over. We have lacked flexibility, so I can just paste that in. It doesn't mean that we need that to go down a bit further corner piece. And then we can do something like select the fill tool and fill that in there. So again, you're probably going to want to do something a little bit more creative than I have. So I will not keep this running and do the whole thing with commentary. So you've got the base idea that we can drag and select different things to have some Interesting looks here, like said, rather than just having one constant grass level piece, that's how you can kind of fake some foreground and background looks with the different connections there. And then the final thing I'm going to do as well is the area within this kind of binding that I've made. I'm gonna go back to the background area, grab the eraser, and just make sure that we take this. Because I find that that color does clash a little bit too much with the character outline. And they can look a little bit messy, a little bit confusing. And it's nice to get that nice, solid black outline from the character. So I'm just going to erase everything he had osteo, any other thing you'll see me do? For the next thing you're going to see is a fade to the final results. If you're in the UK, a kind of blue pizza, here's one I made earlier. And here's one I made earlier. So like I said, it is very, very simple. I've cleaned the background up. If I did a few different layers of platforms had some overlapping thing heads sure that you can make them look so the intersecting that would have that it's kinda accounted for in the way that the outlines being done here. I did a platform for us to jump up on. I haven't made use of the wooden platform, but you can add that in if you wanted to. And then just a brick down here for us to play around on as well. So it thus the final result, you can get something very, very similar to that if you wanted. The main thing like I've said is that when we drag this into the world, this is going to account for the, what the camera can we see any point and when it wouldn't be able to get higher or lower on the camera kind of viewpoint or field of view for the vertical side isn't quite as high as the horizontal plane. So if we come back into the map now, we can start seeing high, this is going to work. So we're going to drag this into the world. We can see it's much bigger. I'll 0 this site we can go 000. And because the pivot point is top-left, would just want to drag this over. And we really want this to line up with the plastic points. I'm just going to drag this below the planets dot and we can start getting rid of things like we didn't want need this floor any longer. We also went need the reflection sphere or the folk, so we can get rid of a few of the things from the world outline over here. Now if we press Play, as long as that's in line with the plastic to the player should fall onto those grids and collide. So we have something that we can look random. We can see that the plasma is kind of hovering, which is why we wanted to get this in nice and early. We can hop back to the plan quickly, bring that capture component up a little bit more. And like I said, we can make that kind of fake in size and kind of have that side of the foot a little bit there so that when we are resting, it looks that we're resting on the floor. And I'm not a huge fan of those realistic clients in a pixel art game. So what I'm gonna do is for the sky sphere, small tip here, I'm going to make the colors determined by sun, not based on the skylight that we have. So we've got our light source. We also went need the re-cast enough mesh. Back to the skyscraper. I'm going to set the brightness Lightspeed and Clyde opacity down to 0 and the star brightness. What all of those won't be relevant, which now gives us a class guy. I think that's not a little bit blinding and a little bit bright. So it looks as I went actually in heaven or something. So what we want to do is I'm going to change the zenith color to a darker, maybe a darker bluish gray. I'm going to copy that because we'll reuse this hex value in a moment. I'm going to change the horizon color to the same color. And this just gives us a nice kind of flat skyscrapers. If you've ever wanted the skies veggies just be a very kind of minimal flat color. I think that works a bit better. It doesn't conflict with the outlines. So we can still clearly see the outlines that have been added to all of the assets, but is also not too bright. It doesn't have the Clyde's. It looks a little bit more fitting with the style. And just a test we can see the camera, can't see anymore background over here. I will not seeing anything above us. And we're not gonna see anything to the right-hand side hopefully. So that's looking pretty good. I'm a colliding with everything that we'd expect us to collide with. 8. 08 - Player Animation Setup: With our tile map sets and ready to go. We now have something full at the player to run around. So we have our place-based, essentially, what we want to do now is returned to the player class and we're gonna go through the movement and the animation setup. So we're going to flesh that system might be a little bit more. So back inside of the BP undisclosed player base, we want the event tick again. So a possible, obviously we want to try and avoid the event tick cooling a lot of functions constantly, some things like the animation and checking certain states, we will want to be pretty much updated constantly so we get that immediate feedback. So we will be driving this off of the event tick. This is the kind of thing which is going to be subtle, lightweight to this Rooney not going to add any kind of performance bearing here. Now really what we want to do, there's going to be two different things that we want to be constantly checking and updating on the event tick. We're going to want to control the animation based on the current movement status in whether they're in the air, in the ground, idle, moving and so on. We're also going to want to update the players animation based on the direction, the moving or the input the planet is pressing. So to do this, because we know we have those two main things we wanted to check. I run this festival off of a sequence. So I basically we're going to have our movement sequence and our rotation sequence. We can have a reroute night half we wanted. Sometimes it's nice to kind of self document as you go along. So we know that when we come back, we'll leave a comment and we'll say that this will be our rotation. So my simple comment just to remind us what we're doing is we go through for the movement lie, this is going to be the animation based on the movement. This will be the slightly more complex thing I'm going to run through this in two stages, will be fleshing out at this stage, the very basic rudimentary implementation that we can get into the event ticks so that we can very quickly visualize what's happening. I'm going to go back a little bit later and we will refine this with a slightly better approach. But I wanted to show both approaches so that we can see Y1 will kind of automate the task force a little bit. That's a. So to begin with, what we wanted to do is start checking all of the possible states that we can be in, in regards to hire the playa is moving erect so fast we can run this off of an initial branch. And this will be checking whether or not we are grounded. So the Character Movement Component has, again, all of this kind of tract flora. And rather than, than grinded right, you're going to check whether we are fooling, same sort of thing, but kind of reverse logic. So it has a variable being tracked, whether the character is currently in a state of falling. So whether we're in the air at any given time, if we are, what we wanted to do is grab our sprite to so our animation that we have going and we're going to set the flip book. But we want to set the flip book to a certain states, of course, when we're fooling. So moving in the end anyway, we'll start by assuming that we are jumping. So we change this to FB underscored jump, and we will plug that in here. Now this is really going to cause a little bit of an issue because we've essentially got two states we want to account for. Whether we're moving in a positive vesicle value or a negative. So whether we are kind of reaching the apex of the jump or falling back from it. Basically anything when you're not on the ground is classed as fooling. So this isn't fully what we need moment, but this is a good start. Now, because we will be reusing this quite a lot, I'm going to grab it from the flip book and promote this to a variable. I'm going to name this one FB undisclosed jump. And we will need all of these as variables as we go through this as a nice, easy way to set this up. Because now that we have that set in our slot, you'll see that it automatically assigns the FB undisclosed jump value to the jump animation. So we'll go through this step-by-step and this will kind of flesh out some of the variables that we need as well. Or when we return in tidy up this logic, I'm gonna do another branch check here. And we want to find out if we're on the ground. So now assuming that we're not falling or rising, and again, we will return to that a little bit later in flesh, the site will do the ground stuff. First of all though, we wouldn't I wanted to know whether we're on the ground and we are moving side to side or if we're completely stationary. So quite simply, we can use the get velocity cool here. So we can find the velocity that the character is moving. And we wanted to check whether or not this isn't equal to. So we got this as a length to make sure we account for any of the directions. So this will return the vector essentially as a float. I'm basically this will know that if we're moving left, right forward, a backup, if there's returns 0, then we'll know that we're not moving in any direction whatsoever. So we can say isn't equal to. So if this isn't equal to 0, then we know that we're moving, so this will be moving or not moving. So again, what we want to do from here, we're going to have to grab our sprites and flip book. So I'll Control W to copy this line here. And I'll do this again. So Control W as we need to do this the third time. And hopefully you can start seeing why this isn't going to be the most ideal setup we need to keep cooling this one function over and over. It's kind of replicating logic. And again, you'll see how we can fix that quite easily in just a moment. But first of all, we'll get things going visually. We can actually start testing this as we go along. So at the moment, because we've got this set to nothing, we need to do a few more steps before we can test. But if we were to jump, we can see that we get the jump animation. Anything else is going to set this to be invisible. So what we're saying is that if the velocity isn't equal to 0, so if we are moving, then we're going to want to set our flip book here to be run. So we'll set this to be the running flip book or promote this to a variable again called this one FB and the school run. And we're gonna do something very similar down here. So this one is of course if we're not moving, so we're going to set this to FB underscore idle, or that is a player idle just night just a bit when naming issue not have that. So I can go back and fix that a bit lighter. I'm going to promote this again to a variable and that will be FB underscore idle. So now we've got something which is filling in those slots so we can now test this. So we have our idle animation, it, we're not doing anything jumping animation if we're in the air and running animation when we are not stationary. So of course we've kinda truth rotation. We haven't accounted for the jumping and falling, but they will be coming up very shortly. Slope for the jumping and falling. I'm now going to introduce you to the select note if you haven't seen this before. Basically what we want to do, if we know that we're in some form of being in the, we don't know whether that is a positive or negative speed that we're moving yet on the z-axis, what we're going to do is we're going to unhook our FB underscore jump, and we will select a flip book depending on a certain result. So we're gonna get our utilities select. Taking in a wildcard, we can change this to a few different variables by default. And we want this to be the return of a Boolean again. So we're gonna do a quick Boolean check. We can copy, I will get velocity down here. We're going to check on this in a moment. We can split this, weren't interested this time in one of the axes, that velocity. So we'll split the structure pin. We want to know whether we're moving in a positive or a negative value in the z axis. So up and down basically, and what we'll do is we'll say that if this is less than or equal to certain flights. So we're going to account for the exact data point we hit the apex, then we will pass that into our wildcard. I'll change that to a Boolean and we now have a check to find out whether or not we're moving vertically in a positive or a negative value. Good, because we know that this is a Boolean, we get this changed to true or false. So if this is true, so if we are less than equal to 0, that's true. Then we know that this is going to be our falling animation. And that one's named terribly. I'm going to go back and fix these nine because that is worse than I expected. So FB underscore fool should be playful and FB plaid jump. Okay, So that's gonna make it much easier not to find in a good order ahead. So well, I was saying is that if this is less than or equal to 0, if that is correct, then we know that we're fooling. If it's false, then we know that we have a positive value and we are still jumping, but we haven't yet reached a flat apex. So we can press Play. We'll double-check that this works. So we've got jumping and falling. And that seems pretty perfect. So it just gives us that kind of ideal of which way the players moving. It gives us a little bit more of that visual feedback and it fills a bit more polished immediately that we know in which direction we're moving vertically. So I'm just gonna plug this back into Jump, promote this one to a new variable. And I'm happy short handing these names because we're in the class. This is kind of obvious what this is going to be. The naming convention here is more so that it lines up in a nice, accurate way in the Content Browser and it's easy to find as you saw from the list options then that is the movement sets up. This is the quick, kind of dirty approach to getting the movement going. We've now kind of just for pretty much everything we haven't animation flow. So jumping, bowling, moving. And I do that. I will then have ready to go. To finish this off. We want to address this rotation comment down here. So I'm going to move these up just a little bit, just to give us a little bit of space and move this down a bit more. For the rotation, what we want is our sprite basically does a few different ways that we can do that. We can input the size of our sprites. So facing rights would be positive on the scale x here and minus one would essentially make us flip. Now if we have anything that which is attached to our character, if anything has like a projectile point or a PowerApp that we wanted to throw, this can get confusing because the power-ups still going to be here. I would also need to account for that. And it could also change the scale of things which are being split. And so generally, I'm going to avoid doing this kind of the more simple approach I suppose instead that we wanted to do is we're actually just going to completely rotate them around. And we can see with this that we want to do that on the z-axis, we're affecting the view of our character rotation. So I'll set this back to 0 by default just so that we have like an idea now of what we're aiming for and what we can do. We can do this driven by either our input. So we already know that we have. Move rights axis. And we can check whether this is more than or less than 0. If it's more than 0, pressing right, because less than with pressing the left. The issue of that is that if we change this whenever the player presses a button, it could get a little bit twitchy if the plant is pressing constantly. So instead I'm going to drive this off of the velocity again. So we're going to willingly change this to match where the character is moving in the world. Something like what's the vertical velocity? We can split this as we're only interested in the movement speed that we have here. I'm going to pull from this and we will use a compare. So we can get the compare floats operates and this will be executed. We can run this move rewritten node to keep this tidy anyway, so we get a nice line had, in fact, I'll do the same up here. Hello, I'm taking up a bit of space. So I'm just double-clicking that if you're not familiar with that double-clicking on a wire will give you a reroute night. And what we want to do is basically we can check if this is more than a certain value. So if it's a positive value, we're moving, right? So we want this to face food. If it's a negative value, then when moving left. So if is more than 0 or less than 0, which is our compound with value here, then we're either moving in a positive rights or negative left direction. So we can set the rotation of the character neither safest way to do this because the plant controller is tracking a lot of our rotation updates. We want to get, I will play a controller. And we want to set the control rotation of this. So this means that we, because we already have a class which is kind of overviewing and watching the rotation setup of the class, rather than having any kind of afflicting logic against that, we can just use the information which is already being tracked in our player controller and update that. They're going to split that and plug this in here. Now, remember we wanted to affect the EU, the zed rotation, the defaults are moving right is correct as it is. So I'm going to leave that at 0. We can copy this down here, and we can set this to 180 if the character is moving in a leftward direction. So we can test this again. So let me write that is happening as we'd expect. And left. That is flipping absolutely everything. And that's a problem with the camera, but that doesn't mean our logic is working. So I'm gonna go back to the spring on. Basically this is happening because like I've just mentioned all of this as being checks and updated in the controller. I'm not going to also include some of the camera and spring, um, setup. So basically what's happening if you're not sure what the moment is as we press Left, the entire actor is being turned around. The cameras still facing in the same direction. But when I'm looking at this from behind the tile map rather than in front. So to stop this happening, we're going to grab our spring on. We would change this to use the control rotation. So again, this is another benefit of using this playa and fro rotation because some things within our own class will be able to reference this. So we now want I was spring on to inherit the same rotation is the controller is tracking. And that means that we don't need to worry about inheriting any of the pitch. You'll end row. So basically what this meant is if we have these tip whenever the component that this is placed on is being moved around, rotate it or anything. So as a quick example, if we bring this into the world and I'll press F8 head. So using Backpack to the, we can see how the camera is inheriting the rotation if we move this around. So we don't necessarily. And this would also be if you were rolling a character. If you play an animation at some point, you of course don't want that spring on. Follow the same rotation that the character is taking in all of these potential different directions. We always want this to be facing straight on. So what we're going to do is we will undertake all of these and make sure that it follows that the Puna control irritation. So that means if we press Play, you can see that we can turn and move left and right. And the camera is still facing forward because it's updating correctly through the player controller. We have all of our animation is going. We would desire. So the font of thing just to tidy up the code, is I'm going to come in, get rid of that comment. And what I think we can do is we could do with putting these nine functions. So this is taking up a bit of room and we can potentially save a little bit performance by dropping these into functions as well. So we're going to make use of that. What I would do is grab all of these notes. So regarding the movement and the animation will right-click on one of these nodes, will collapse this to a function. And we will call this update flip book as that's really what this is responsible for. Okay, So this is what will allow a flip book logics going and we can say it's not saved us a lot of space and the event graph. Likewise, we can do the same and we change this to update play irritation by collapsing that into a function and naming that one update cavitation. And again, just a little bit of tidying so that this is nice and easy to read. We probably won't need to reroute notes, so I'll just get rid of those. And with that done, we can see we've saved a fair amount of space here. And I was going to be very easy to jump back through our code if we want to update the animation is we're gonna do in a moment, we know that we need to look in the flip book function. And if we ever want to change the way the rotation is working, we can jump straight into our rotation section. 9. 09 - Player Animation Improvements: As I mentioned, the flip book animation updates hasn't been done in the most ideal way. This is very kind of manual on a per share basis situation. We have to keep cooling this same function. And again, that's not really ideal either. So what we're gonna do is try and automate some of this process with something called an enum or a numerator. If you've not heard that term before, it basically it means that we can create a different value which can be tracked it represented by integer values. It's very easy to iterate through and we'll have one enumeration states for each of the different states the player can be in. This means that we can store a state for the player based on what's happening and set the flip book animation just once, based on the state we're currently in. Again, as with anything, if you haven't seen this before, it will make a lot more sense as we go and create this nice. So let's go back into our blueprints photo. This is essentially a type of blueprint. We find this by right-clicking, going to blueprints and enumeration. I'm going to call this one e, apply a movement. Notice here that there's no underscore. The naming convention for enums is E with no underscore here. And then the name of what they're representing, you could call it something like E movement states, states, whatever you wanted. I think this kind of gets the idea across. And like I said, we basically wanted to come in here and we're going to create a new enumeration state. So you can see it's quite Berlin empty. Lastly, we have to, we can press the New button a few times and get a few different enumerators. So that's just going to automatically named themselves. These are just kind of a named representation and we're simply going to create one for each of the different states. So I'm going to rename, needs to Idle, run, jump to full. Okay? So you'll notice that these are not associated with anything. They're not providing a certain flip book. We're not assigning anything to these. These are purely a representation to allow us to easily update the current state and conveniently track them as we go through our logic. We kind of give them descriptions if we wanted to, but that's not needed. And something that's usually a good practice to do as well is providing a kind of null or default state. So I'm gonna add one more state and name this one that default. Generally if we have a hit the state, so that means something's gone wrong. So this can be like a check that something has not been updated correctly. For some reason this would be a, for instance, all of our movement checks of felt and we haven't returned that were in any state at all. So that would mean we're like somewhere between Idle run, jump and full, which is something we've not accounted for. So we're going to set this to default, and I'm just going to click this arrow to move this up, because generally this will be the first, um, state that we provide. So if that done, we can close this. We now have our new variable, and that's what we're going to use this as a variable type in our player class. So if we come down to the variables option, we'll click this name, this movement state. And for the variable type, we want to use the drop-down, find our E movements or E plan movement. So the thing that we've just created a named ourself, and we can see now, if we drag this in, we get our variable pin. And if we do something like use our select note that we've seen a few times 9, we can see that we can select things between default, Idle, run, jump, and full. We could also set this as a variable. So again, ideally what you want to do. We're going to come in. I've drank this next to the event. Begin play, move this around a little bit, and we're just going to ensure that when the game starts, we're going to set this to the default state is kinda sets defaults anyway. But again, if we have a testing anything, say we wanted to just test the jump, then we might forget to reset this at some point. So it's good to set this to a default to begin with. Then when we're updating our flip book, we will keep track of this and be updating this based on what the player is doing. So back inside of the flip book updates, I'm gonna get rid of this finite, we can move this aside. We're going to reuse some of this as we go through. But mice to deaths will be gutted and removed in just a moment from the update flip book, we can set the movement state again. Again, if you're not familiar with this, if we just set a variable here, it's going to create the execution pens between bites of these. And we basically want this to be the return of a set of checks. So we're going to be very familiar by the end of this with our select note as this can provide some really useful, easy to read automated code in different ways. So what we want to do is we're going to set this to be the return of a set of logic using our select node. Now the first thing we can check, again, we've got much of this ready to go. We can start by checking if the plaza on the ground. So this is how a grinded logic. So I'm just going to Control X and Control V. So we went need this again, so we can just reuse it. So this is nice thing is if we're on the ground, this is false, of course that means we are idle. So we're going to set this to false. So we're going to assume that we're not moving. That does leave us with some more logic that we need here. So this is going to be, this true variable will be based on the return of the next select note that we use. So we use another select note here. We can see it's passing through the movement states to all of these. So these pins are all expecting the movement states. And what we want to do now is check whether or not we're falling. So if this hasn't been the case, which means we're going to pull through and check the next select note. We now want to know whether or not we're fooling. So again, we can control X and Control V so that we know what we're reusing and accounting for all of the movements States we've already looked into overhead. Again, if this is true, we are fooling. We're ready, know that we want to know in which direction we're folding. So we can't set this to jump or full because this could be two options. So that lets us know this is another select option here or another scenario where the select and I'm just going to work and that's going to be the return of this jackass. Remember that was our positive or negative check affords the vertical movement. So again, Control X, Control V. So we now have all of our checks. So we know that if this returns, we won't need any selects half. This means that if this returns true, then we are fooling because we're getting an, a negative value just here. So we'll say full for true and jump for false. So that accounts for our jumping movement. The different options that can come from that, that leaves us with just one option here. So for this select, we know that this is not moving. So we've got idol, that means this would be moving but on the ground, which means this is going to be our running logic. So we're gonna go into the movement state of R1. And then this is I were falling logic. So we're going to be in the movement state of either jump or full. So we can leave some comments just so that we can easily come back to this a bit later. So I'm going to say that this one is checking for the movement specifically. I guess that would be the velocity in which we're moving failing that we know that we're not in the air, so we're going to check for the ground movement. So leave a common half of that. And this one, if we're not moving in the air or the ground and then we're going to return idle. So some nice comments come back. So you just kind of remind us what these are doing and the best way to think about these, if this is again completely new to you, is these are kind of fooling through. So as this is being updated, the first and this is going to do, is going to select what movements like to set this to. So if the velocity isn't equal to 0, then we not just going to return false head, we're going to go and check the next select note because that would mean it's true. Then we're going to check this logic. Again. If that isn't the case, that if that's true, then we're going to go back and see what our final checks and aria could be. And that's gonna give us some type of movement. So this is actually already be working if we had the final stage, which is going to be assessing our flip book, and hopefully this is going to be the bit which kind of solidifies why this can be so useful. So we can unhook all of this selected, just one of these set to flip book notes here. So Control X, Control V, ideally able to grow the sprite with that as well. So we'll hook this sprite up into this. We'll plug this in here and we're going to use that useful select node one more time. So what we're gonna do is we're going to select the flip book that we want to display based on our enum that we have tract. So it will pull from here again and select. Quite simply. This is going to be really, again, quite interesting, I think for those of you who might not have seen this before, but we can control drag in the movement states into the index. So we're going to get the state, and we'll see that that will automatically read how many different states this has and to provide a select node for each of those states. So that means that we can live set this flip book just once based on what's being returned here. This is going to be a good tell sign again, so we're going to leave default empty, purposely leaving this empty. So again, if we ever see that our sprite isn't playing anything that we know that something's gone wrong and we haven't updated the state. Otherwise, we can take all of these values that we start over here. We're going to plug the idle into idle, the jump into Jump, run into r1 and full interval pretty much as you would expect. And then just make sure we can see them. And that is really our state machine kind of setup and ready to go. You had to check for what to do with the Player Animation. It means we don't need all of this branching logic. We can get rid of all of these night. We'll be calling the set flip book function just once and passing in the result of whatever happens to our movement States and how that's tracked. So we can also see this in a little bit how I'm going to add one sequence down here, and you'll see that this is updating constantly so we can print string, just that we can kind of visualize as well. Hi, This is operating. We can convert the enum state to a string and this will, when we play this, keep track of this for us. So we're not passing anything, which means we're in the idle state. If I jump, then we're jumping and then fooling, Jumping, folding and running. So all of this is being tracked based exactly on Highlight movements. State is being updated and based on pretty much the same checks that we had previously. But rather than having branching checks going everywhere, we've now just got this one kind of logical flow of full three states based on what's being selected and the calculation being abstinent to select node. Then all of this has being finalized by setting the flip book based on the current movement state. Again, very easy to read, very easy to manage. And this also means that if we ever wanted to add something else, if we added things like a double jump or a wolf slide, all we need to do, we don't need to add extra branch statements. Usually you would need to interrupt another check somewhere else. Ready? Break the kind of flow of the logic that we had going overhead. All we need to do is return to our movements. They would add two new things. I would say whoo, slide and double jump. That would immediately add two new books just here. And then we can just run some other logic off of here. So again, if we're in the air and we're also will sliding, then we'd have another select nodes check for that and would return either jump full, almost like or if we're jumping and it's the second time we've pressed it with written another slight note here that we've just momentarily onto double jump, change that movement state. And again, this will be updated pretty much automatically for us. And there was no real like automated system for this. But I think this is kind of getting to that state where it sounds kind of reusable and flexible as we can make it for this kind of project. So just before wrapping this up, make sure that we go back. We don't want to sprint constantly. If you ever had another sequence, another execution Ben from the sequence, we can right-click on this and remove execution pin seven, I just doing the flip book and the rotation update. And there's always make sure that we compile and save this. We won't need the player movement to be open any longer. And I think that puts us in a pretty good states where the player is pretty much flashlight. We have them doing everything that we want in the most robust way that I can think of doing it for a small project like this. I think what we can do now is we can move on to the interaction with other things for the house, pickups and things to have any use or the enemies to really provide any kind of danger or hazard to us. We're going to need to start implementing a health feature. 10. 10 - Player Health: So with the movement pretty much fully implemented at the stage, I think it's a good time to start looking at how we can interact with other things in the game that we have planned. So the enemies, the pickups, they will kind of neat us to have this concept of health and damage. So we can start by adding a health system to our player, which is what we'll be doing now. And then we'll look into how we can visualize this and get that to update based on what is being interacted with in the world. So let's begin with the health is very simple concept. We're going to track this in floats just because I know that will be easier for us to implement that with the widget system a bit later, we could represent this as an integer value, especially if you've had a health system where it's just like hearts or something, you'd be taking one-hot way at a time that would be perfect as an int. But for now, I'm going to create two new variables of type float, one named default health, and one named Health. Next we can compile this so that we have access to these two new variables. And what we want to do is I'm going to set default health to a nice round value of 100. So we'll start with a 100 health, and the health itself will leave to 0 to begin with. Now on the construction script, you could do is on the event begin play as well. But generally things like this, people like to put in the construction script so that we know even before we begin playing, we're going to reset our current health to the maximum health that we can have or the default health. So we're going to get the default by control dragging and set the health by dragging and will quite simply set Health to be default health. So now we know that again, we can do some tests if we want to unhook this. But in the main game, in the full game, if wherever playing around with things here and we wanted to quickly test something between the widgets and set that to a different value. We know that when we stop playing or when this is updated and the constructor that we will be setting our main health value back to the maximum we want that to have. To demonstrate this again, if we just press on the Begin Play, we'll start debugging a lot, I think with print strings, just to make sure that things are making sense as we go through. So we can just say our health will be printed to the screen and we're starting with the 100 health. So that's my son simple, that is our update to having health. We now have that concept. Of course we next want to have the concept of damage. So damage is very simple, and in fact, we'll be using an event that comes pre-built with any actor class in the game. And that is a function named any damage. So we've got the event any damage, we can see that the target is an actor. And the great thing about this is we can kinda bypass a little bit of casting and knowing exactly what we are communicating with when it comes to damage systems. We can actually just say if something has a function on it which is expecting to have damage handled, cool The any damage function, passing some information, usually the damage amounts and let that class workout and a handle, that logic that it's meant to be controlling. It's a very kind of object oriented approach to programming. It decouples a lot of references, can keep your projects at IDEO and easier to maintain and also saves, in some cases on performance as well. So what we're going to be doing whenever a damage amount is passed in, we're going to set the current house to a new value. So we're going to be assessing this and we want this to be the current health. So we're going to get the current health minus a float, which will be the damage being passed in. So if we've got a 100 health 20 is passed in. We're going to pass that into our health value here, and we would have 80 health. Now, again, we can do some debugging here. It's always nice to debug things as we go through. So I'm gonna create a temporary and puts, generally I wouldn't create and puts in the Event Graph or even outside of the project settings. But because this is going to be temporary, I'll just remember to remove this later. And let's say we're going to press H. So we're going to find the key binding for h, H for outs. And whenever we press this, we're going to call the ply any damage or apply damage. And the reason this is called any damage if you're not familiar, is we do have different types. So we could bind this to the event point damage, radial damage. So if we use any damage, it means regardless of the type of damage being passed to us, this will be fired off and take health away. So we're just going to call the default apply damage function, the actor that we want to damage. It is a bit strange, but this is going to be our self. So remember this is just a debug function here so that we can check our health system is working and the damage that we want to pass in, let's say that 20 units of damage that I mentioned a moment ago. And if we wanted to if we wanted to check different things like who the damage was caused by or instigated by as well. These would be for things like if you had different offsets, four types of damage. So ballistic damage versus explosive damage and things like that. You could find out what the initial. So it wasn't whether you should apply the full amount of damage or like a modified version based on that. Again, we're just gonna be going for a very simple type of damage. Yeah, Twenty Flight units of damage. And what we want to do is whenever this is cooled, I'm going to do another print string. And we will print the value of our current health. And this is going to have a few issues I'm going to fix on a moment and you'll see what those are as we're debugging. So we compress H and we can see that the damage is being cooled down to 0. So the plan shouldn't I be dead? If we press hate you again a few more times, we're going into minus values. So what we wanted to do to stop any weirdness like that happening where we could potentially kill the player after they've already been killed, were going to clump this to a certain value. So we'll pull from here, will clamp this to a flight, will make sure that the minimum is 0. So we can now never go past that 0 threshold. And the maximum I'm going to set to be default health. So if we have a used this in a way where we, a very common thing you'll see is that health systems can basically be passing in negative damage. So you could pass in minus 20 damage. Obviously, a minus, minus and minus will be a positive, so you start adding on that way health to your player. We probably won't get into anything that confusing in this playlist. We're just going to add a very simple AddHealth function. There are issues that come with trying to use the damage system as a healing system as well. Some of the logic, especially if you start adding modifiers and trying to change things up like and get a little bit confusing. But to account for that, we could make sure that we don't allow anything to pass a value to satis, essentially cheating, I suppose past our maximum at default health Valley. And the final step we want to add in the concept again of actually dying. So when we do get to this 0 health value, we're going to check a few things for whether the players died and create a new function ready for that. So we'll create a new boolean value here, and I'll call this one B is dead. So it can be useful to track the states of the players seems a bit obvious, but we want to again avoid things like if the plant is killed and then picks up, how do we allow them to revive? And if so, and the damage again, can they die a second time? So to avoid anything weird like that, will make sure that this defaults to obviously false. We don't want them to start to dead, but then. We gets to a certain value, then we're gonna want to set this to be true. So what we'll do is we'll do a branch check here. And we're going to say if the current health, rather than pulling from this pin, you could, if you wanted to. I quite like having the extra variable, how we can control drag this in my more expensive or anything, and then we can do a comparison. So if this is less than or equal to, and again, some people will find this a bit weird program. This is you want, you can say less than or equal to if you wanted to, because we have this clumping value have we should never get below 0. But again, this can change at any point and other programming might come in, find that they don't want this to be clumped. But of course you still probably want anything less than 0 to be dead. So accounting for things like that, I'm just going to say less than or equal to 0 for the health is going to be classed as dead. So that isn't a programming oversights. It's just something I like to do because you never know how the project is going to go in the future. Like I said, you could work with someone else. They could come in and decide this clump is irrelevant, not useful, or they want to use the clamp in a different way, in which case you could start going into negative numbers and still not have your plaid die. So if that's true, then we're gonna say that this is a dead player. And again, just for this added security, probably not something we need in such a simple project, but I'm going to say that we can only do this if the health is less than or equal to 0. And with her in an AND Boolean check. And we're not already dead. So we can say, is that isn't equal to true. And an easy way to say that, sorry, is to just say is not true, so NOT Boolean. So if we're not dead already and the health is less than or equal to 0. So again, this is the kind of checks you want to throw in just to make sure that you can have weird things. And I've seen it in some games where they haven't done these types of checks. The way that I'm planning on doing this, I think we'll have like a Mario or sonic death animation. So when you die, you'll be launched into the air. You will have the input removed from the player. And you'll kind of animate the screen of what I've seen in some games because they haven't done a simple check like this, another projectile will hit them. I'm guessing that they also didn't do unequal to check or clumping check. And what happens is that death automation keeps playing and essentially keep reentering the death loop until they stop getting hit by something, even though they're technically already died that once. So it may seem a bit overkill, but these are just kinda nice, simple checks on the ad that safety. They're not going to have a bogey looking game where you can die multiple times in a single lifetime and that's the worst thing as well. Especially if you have a life based game, then that could start taking away most people lives, even though you haven't even respond to that stage. So if that's false, we don't need to do anything a tool. Of course, if that's false, we just still going to be running around the level of doing fine. You could, if you wanted, this might be where, if that is false, you've taken some damage. You might want to play a knock back effect or a flashing animation. So in some kind of invincibility time, that kind of thing that can be done here. What we do want to consider though, if that's true, we're going to play a new function. So we'll add a new function here and we'll just call this one player died. And now the moment we don't have anything to really place in hair, so I'm going to add another print string. This will be as I'm topic a little bit later. But again, just so that we can test this is going to be working. We'll do the iodide function. Cool off of this and we'll just play buttons, print string. So coming in again, compress h until the health has gone all the way down and we can see another player has died, and that's been tracked correctly. So we know that all of this is working as we wanted. And the important thing again, to make sure that those I have been worthwhile, we can keep pressing H and we're not getting multiple iodide function calls. So we know that isn't licensed safe. We're not able to keep entering some kind of infinite deathly. So that's pretty much as complex as our health system needs to be. We can come back and make some improvements later. I think the next thing is going to be adding some kind of visualization to the health system through the use of widgets. So this is probably all we need to do in half. And now we can close the player class. I again, make sure you compile and save some point. I seem to have had a leftover tile map for justice. I'm just going to delete the old one and make sure that we have is the correct one here. That's perfect. And that means that when I good to go ahead and create our widgets for the player health. 11. 11 - Player Health Widget: To get started with this process, we're just going to create a new folder, which I will cool UI will be placing this in the base of Blueprints folder. And then inside of here would just be creating a brand new widget class. Find these, we're going to right-click. We'll go to the user interface options, so not under Blueprints this time, I'm gonna go to the Widget Blueprint option here, the naming convention for these classes will be WPP underscore. So Widget Blueprint underscore, and then the name of the class, I'm just going to call this one that player health. Inside of the class. If you're not familiar, we're gonna take a very kind of brief overview here. But what we have in the middle here is a Canvas. So this is kind of like the workspace in which we can add our different elements to make up the interface. In this case, that's just going to be a health bot. But this could also make up things like menus. We could add in buttons, text, and many other things. So this canvas here, and we can see that it's represented to the left-hand side. We have our canvas. And if we were to drag things onto the canvas, we'll see that does appear within this screen space just here. Drawing the health bother. What we're going to need is a progress bar. So this is pretty much set up perfectly. We have control over filling this. So we can fill this with a value which in this case is going to represent our health. I'm just going to drag this out to make this a little bit longer. And I think that should be a pretty decent size. Now the way that this works is we have at this percentage value just IN here on the right-hand side when we have this selected. And basically as we drag this up and down, we have control over how full this is. Now we can see this is a normalized value between 01. So we'll need to do a quick calculation a bit later to take into account our health value and get this to display between a value of 01 based on how much health the player has left. Now another thing is if you've seen any of my other content or tutorials, you may be familiar with my disdain to this gradient vote kind of umbrella texture here. So the most important and first thing we're going to do is we're going to drop down to the parents, will go to the style option over here. And we want to change the background image and the federal image. So we didn't get this weird gradient thing going on at the top here, and it will zoom in it as well. This is a nice way to jump hint and find out how to update and change the style of your health bar. If you had something custom that you wanted to bring into the engine to use her. So I don't have anything made for this one. I'm generally do with these just to make them look a little bit more Modern and go for that minimal approach is we're going to drop down the background festival. Ideally, we'd have a texture that we've brought in, especially for something like this and I kinda pixel texture, would it be pretty good as we don't have that? And of course, using the images that we have isn't really going to wet cap. What I'm gonna do instead is go to these View Options down here. I'm going to toggle them to show the engine content. I'm just going to search for a white square. And we can see here, we have the white square texture and that's going to be perfectly fine. It doesn't really matter how big it is because that's all scaled based on these options just here, we can see them. I just got a plain white texture in the background that's still leaves this wedge. So a gradient thing for the fill. So again, in the style, I'm just going to copy this, we can right-click. Copy this and then paste this into the federal image here. And we can see that's being replaced as well. Now in this case, for whatever reason that hasn't actually worked properly. So if that does happen, then we can just select one of the others and maybe select back just so we're using the same texture on both. So we have to pull it less in from the engine content that way. So we're going use the same white squares extra in both slots. So we can nicely, that does look immediately a lot better than it did and still works and exactly the same way because that scaling is happening automated based on the images being passed in. So we still get the full option to change this percentage bar and that will either fail or completely deplete our health by now once you've taken this step, the next thing we want to do is make sure that we go back down to the View Options and then Show engine content. Otherwise, we're gonna get a lot more information in this search bar. Then we want, generally, I think things like health have a fairly uniform color, which I think most people would agree as green as I'm going to change this from blue and change this to some kind of green to yellow tint here. And again, I think that's going to be pretty good for our health system. Now another thing you can change if you've never used the progress bar before, you can also change. This is going to update the color of the health as we change that percentage lighter. If you wanted to also change the background color, we can give our style the color as well. So we're going to change the tint of the background and we can make this something darker or lighter or something completely different work depending on how you wanted this to look. And I'm just gonna go for a nice simple gray background. Slide this to slightly darker gray just here. Maybe not full black, but a dark gray with a nice bright green health bot should look pretty good. So for the percentage we can leave that because we'll be doing all of this in code. But this gives us a nice way to visualize what's happening before we get the code going. Now what I wanted to do at the moment, of course, if we just go ahead with this, we don't have this being cooled. We will not be seeing this in game. So before we add any logic in here, and let's go ahead back over to our player class. And inside of the player class, we can start creating our health budget and making sure that we display this. So it's quite simple. If you haven't worked with widgets before, what we want to do is on the Begin Play, we want to create a widget. So we're just going to call the create widget function. And from this we want to pass in the widget to create, which is going to be our WPP underscore player health. And a lot of people may think this would be working now if you press play just to double-check that it's not. And this is because we've created the object, but we haven't done anything with it. So this does exist, but we just haven't told it to display or how to behave. So what we want to do is from the return value now that we have that, we're going to promote this to a variable festival because we will be using this a little bit later. We're gonna want to cool various functions and update values on our budget system later. So it's going to be useful to have a reference to this. So we're going to call this one health widgets, ref. So we have a reference and I2, the health budget Whenever we need to do anything with this again. And then from here, we'll be calling a widget specific function, which is Add to Viewport. So we've got the viewport option and that quite simply takes this object and we'll tell the system to display it on the player's current screen. So that means now for coming, we can see that we have our widget. Of course, something just happened a little bit strange there. But we can see at the top left-hand side we have our health, which is showing as expected. It seems somewhere along the line, the update flip book function has somewhat broken with the jump animation. So it seems as I've just not got anything filled in the jumps lot, just in case you have that same issue. I'll keep this in the video. That should have been assigned. Oh, yeah, I think that was working previously, but that would just double checks. Now we can jump before androgen and all of that's perfectly fine just in case you are getting the same issue there. The main thing was the focus of the health Bahasa, but not have the health part displaying. Of course we can take damage. We still have our function to cool our damage, our kind of debug. So we can see that I've pressed H several times that we have at debugging to that the player has died. But of course that isn't sinking up with our health widgets. That's going to be the next step. So back in the widget class, we just need to add some functionality to register when a health value has been updated. And I wanted to show you first of all, the way that I still see a lot of people doing this in such tutorials online. And it's a habit that I kinda want to help people get out of and it's kind of bad practice. And I'll show you why as we go through. So we're gonna do it the bad way festival just so that, you know, to avoid this in the ways around this, if you say it in the future, and what you might see is people will come down to the percentage value here and we have a binding option, and we combined this to a new function. So if we press that button, this is just taking us from the design a few here to the graph if you. So the design of years where we add all of our visualization, all of our elements, and flesh out that widget. And then the graph is kind of like our event graph essentially in any other blueprints. So this is where we put all of our logic and basically adding that binding is just automatically creating a function for binding the return value of that function to our widgets elements. So in this case it's a value, float value because this is bind to the flunked percentage value. Now the reason that this is bad, what you'll find people do is they'll get the player poem. So we use the default functionality. And let's say they'll just do something simple like casting to make sure that it's the player base. We know that inside of the player base we have our health values. So they can then get to the Health value. And then they'll plug that in, potentially plug this in. Now this isn't gonna work because that calculation I mentioned we need to, to normalize this value. But again, we're not going to keep this. This is pretty bad. This is just kind of an example of how not to do it so you know what to avoid and then we'll see why. So what this is doing now we're winding this to the black class with casting and then checking what the current health value is. So if we press Play, we can see that is now updating. And I'm going to need to press this quite a lot and then the Health is gonna go down to 0. So we know at least have the updating. But let's see why this isn't such a good idea. So what's actually happening here is this is working somewhat like a tick event. So if we throw out print string in here, and we'll just print element doesn't match what this is saying. And then press play. Even when the health isn't being updated, even when we just completely idle and not doing anything a tool. We have our bound functionality here, just checking constantly running. And in this case, not just constantly running but constantly casting to another class, constantly refreshing this kind of memory location and all of the variables that might be within this class of being passed to him from just to double-check that the health value hasn't changed. So that was really the entire point of that side tangent here is whenever you see people if you are falling out of the content and they recommend using a binding, kinda skip that bit, Brady, no very good practice. And what we want to do is we're going to unbind this, so we'll remove this binding. Really just never use this button. I think it was a legacy kind of carry over four. Testing which just never got removed as really not meant to be part of the development pipeline. And whilst casting and event ticks are not completely sacrilege, they can be used in games perfectly fine if you imagine that you had an entire widget and I just want to Health Bot button and tie which Amanda, you all play a text. The icons and everything around a more fully flashlight kind of widget. Stage, not just doing this binding and casting once you could be doing it five, 10, 15 times per widget just to check that nothing's happened. So hopefully that kinda makes sense why we're not gonna do that. So what we need to do to tidy this up, we're going to just completely delete this, will get rid of that percentage function. We can go back as well, and we'll rename our health bot from progress bar to play a health bot. Just because when we come back over to the graph section that no shows the name and a more kind of logical way we know exactly what we're looking at. So we do want another functionally, what we're gonna do is we're going to drop this down into a function. We're going to name this one update health. And this is a little bit more of a manual approach that does take a little bit longer to do it this way. But again, we're saving that performance and we already kind of in full control within the oval when this gets cooled. So instead what we'll do is drag in the player health by reference the assets which is being used in the designer. We're going to pull from him. I'm going to cool with these set percentage function, right? So the percentage, remember is the thing that we can drag up and down normalized between 01 and we just want to hook this up. So whenever this function is cooled, which should only be done when the health is actually changing. So when we're picking up a health bonus or when we're taking damage, we're then going to pass this pin into the health function and we can call that across. Now again, remember this is expecting a number between 01 and our health is currently between 0100. So as we've seen previously, what this does is it at the moment if we keep cooling, this is only going to change when it's either over one or less than one, which is in our case going to be when it hits 0. So we're not going to see the, the Health Bot moving up and down. Instead, what we want to do to normalize the value is quite simple. We're going to drag this in is because we're not have a flight value called in percent and we're just going to change this one to be called Health. And then quite simply we want another value, which is the default or maximum health. So I'm going to add another value here and change this to a float and name this one max health. Basically a normalized value is just going to be our current value divided by the maximum value. So we'll pull this from here. And we're going to divide our health by our maximum health and plug-in that normalized value. So that's always going to return a value between 01. If that doesn't fully make sense, just throw a print string on the end of this and do some tests and see what happens when we go through and call this function in a moment. But basically if we have a health of 50 and we divide that by a 100, of course we're going to get 0.5. So this is how we are getting that value from 0 to one when never gonna go past that range. Then the way that we use this, so this is actually the health function ready to go for us. Remember we've got that reference on the player class, so we'll return here. And what we want to do is when we begin play, let's create a function that we're going to call on the Begin Play Festival named update health. Okay, and inside of update health, we're gonna get our widget reference. We're going to call that function here, which was again update health. And we just want to pass in what our current health is. And then remember that's going to be divided by maximum health, which in this case is our default health. Because remember in the construction script with setting the health to be default Health. And we're also in the health system, we're making sure that we never go past the maximum is never going to be more than default health. So this is why we've set up this way. And so we'll kind of coming together nine. And the reason I'm doing this on Begin Play is remember the way that we can kind of play around with the widget here. So, like I said, is really nice that we can come in, checks the different styles if we ever want to check the color of the background of our Health Bar, we can always play around with this percentage by here. We can then come in and play with different colors out some different images. And we may forget to reset this to either full or minimum. So what we want to do in our player class is make sure we have full control over this. So I will only begin play once we've created the widgets. We're also just going to cool our update, our function, and we'll let that do its. Now. The next thing is when we take damage, we can also do this down here. So in-between our brunch to check whether or not we've died. Again, whenever we have the health being updated, we're going to want to cool that update health functions. So we'll just pull from him, cool the update function here. And remember if you're doing that between two execution pins, it will always fill that funnel execution envoy. So now what should happen is although we haven't updated or changed our widget here. In the other kind of visual element of this, we're going to call that functional begin play that will find out that we have full health for the health works. And then if we play around without debug health system, so the Debug button that we have had the applied damage, then we should see our widget to being updated. So here we have full health press H, and this is going down a small percent based on what I have here. So 20%, which is looking at byte rights for that normalized value. If I make this 50 damage, so half of our health, then we're going to lose half of a bar, and then the next half We have died. So again, we can just double-check that our mouth is definitely doing the right thing. And let's say 1909, we should have like the tiniest sliver of Health. And we can see that we've got pretty much one house left and again, one more time and we've died. So we know that this is working correctly. This is the main thing. This is why we want these handy kind of debug functions in just to check when we're doing new systems, that they are being implemented correctly before we even have enemies and things like that, we can easily test things with this night. What I'll do is I'll also, this is a little bit hard to find. I'm just going to call this debug in a comment and I'll make this red. So I will never forget that at some point we probably want to remove this. We don't want this to be shipped because of course we don't want the plants be playing around with the keyboard and then suddenly taking health. So we'll come back and remember to remove this when we've completely finished with the health system. So back in the widgets, that is pretty much everything. So we just double-check. We have all of this, tidy it up and have really need to come in here. We can see Let's just normalizing a value, making sure that we don't have our binding hopefully again, that makes sense why we don't bind anything to a widget function, whether that's a button, ACEF text, progress bought and nothing really needs to be bind is nicer to have this full control. And you can see now that this function is only being cooled at these specific times that we think something might need to be updated on the plans health, so on the begin play. And at the moment in the damage system should be what we need to do in the widget class and the player for a little while. So what we'll do, in fact, we're going to use the player in just a moment for the enemy damage. So we can just close the widget classify, make sure that we've compiled and saved all of our updates. 12. 12 - Enemy Base: So before jumping into the player health and damage system when interacting with the enemies, trying to flesh that out before we even have anything to really test it against. Again, I think the best thing to do is actually take a break away from the player class to this stage. And we'll implement the basic anatomy class to begin with. And then I went back to class and we can check that against the player when they interact with each other. So for the time being, we will in fact close the player class if you still have the open and inside all of the blueprints photo OCR add another folder again, this we're going to have a few classes nested in here. Oh cool, this one enemies. And although we'll only be creating one enemy in this set of videos, I did want to introduce the idea of inheritance and show how we can create a kind of hierarchy, all of the different entity types where the base class accounting for a lot of the more generic functionality and variables. So we will be taken the approach and then you can easily extend this to your own other enemies such as mushroom characters or stationary kind of art, enemies or anything that you've really wanted to add in. So from a base class, we're going to right-click and now we'll create a new blueprint class. And I'm actually going to reuse the paper 2D character class again. So if we find that with paper character, reason being is that if we ever did one to add detailed kind of AI implementations into this and this will have everything ready to go in that character movement system, which will automatically be set up to account for navigation volumes and high to interact with them. Not only that, this will also have our flip books and everything else like that, that we need to go for animating and setting things up and including the gravity the capsule client is and everything that we've been using. So for this one, this is going to be our base class. This will be the parent class that all other enemies inherit from. So we're going to call this one BP underscore enemy base. Now what we do inside of the base class, we tried to keep the logic in here as generic as possible. So we account for everything that every child of this class might need to do. So that would be things like intentionally movement, but maybe even that's a bit too specific because like I've already mentioned, one of the first two ideas that came to my mind was the enemy mushrooms which would need some kind of movement quite likely. And then the second one was the tarts enemy. So I've already come up with the idea of a character that might want to put in that doesn't move a tool that could be too specific, but they will only things such as health values, a win, lose kind of death state when the plant and traps with them, maybe a damaged causing state and things like that. So that's slightly more generic that child classes will probably need. But the other good thing about using this paper character, we also have all of the other things that child classes we need as well. So we have our capsule collider. So again, we already have the collision properties of all child class is set up and ready to go. And we also have the sprites components. So again, all of our child classes are going to need to be visually represented somehow, probably with the paper 2D sprite because we're using a 2D platformer have, so again, this has a few of the components already in here that we're going to need in the future. And I'm not actually going to fill this. The reason being is that this is going to make sure that if we have a forgets to provide a visual representation for our child or inherited classes. Then by leaving this empty, that's going to be a very clear indicator that in the child class we've made a mistake and forgotten to do something. What we will need inhaling is a couple of variables. So these are going to be our health trackers. This is going to be very similar to our play a character class. We'll have a float value. The first one, I will name a default Health. And I'll copy this. So control and w to copy this and we'll just call this one health. And in the same way, we want this to always set the health at the start to be the default Health. And let's set the default will give these a default of 100 as well. We can change this into child classes, as you'll see a bit later. But we just assume that they all start with a flat to 100, like the player does. The next thing we're going to want to do is add in a damaged systems again, all of our child classes, anything that inherits from this is likely going to need to take damage at some point. We can go back into the Event Graph here. We can remove the functions that we're not going to need, which should be pretty much everything from naturally and come in and add the on any damage. So that function that we've used before, the event any damage, we basically wanted to do the same calculations, take the health away from what's being passed in. And in fact, saying that we can just jump back to our player and inside of here because we've, if you've done the same thing as I have named everything the same way, we can actually just pinch this, so we'll copy this from one class. It will realize that the names match up and we can just pass this in half. So I daily at this stage, again, we're going for a very kind of basic minimum, MVP, minimum viable products for this project. But this is where you might want to start looking into things like components, reasonable components like a health component, because we already kind of copying logic between classes. So this means that this could be used as a kind of component or interface. So we don't need to keep readings. But for this again, we just wanna get things working. And this isn't necessarily bad coding practice, but we also don't want to take hundreds of videos just to get a simple platform are working. So this is going to update the enemy health whenever we take damage. And we already have the next part of the logic ready as well here. So we're not going to show any visual health representation. We can skip this bit, but we might as well go ahead and check the health again to make sure we are tracking whether or not with that, we can also copy this and we'll make sure we didn't copy the player died function, but we will be implementing something very similar in our enemy class. So we'd copy all of this will come back over here. We'll paste this into the Event Graph. We can have one small issue. And that is that we haven't made this Boolean yet. But if you ever get that, you can see we've got a slightly white line above this, which means this value doesn't exist. If we press compile, we have now nice and easy to fix this. We can right-click somewhere near that white line and we can tell it to create the variable. Is that. So we don't have that tracts in there as well at no extra cost to us. So we're not doing the same thing so that we don't have the ability like we didn't want, but the player where we don't want to die more than once, we could have something where the player continuously jumps on an enemy and puts it at a constant kind of Death Loop. Which could be quite funny now that I say that, but it could also look a little bit buggy. Not quite be the mechanics or the results that you want, but we're doing the same check half. So if the health is less than or equal to 0, then we're dead. Again, I'm fully aware that with clumping this, but just to future-proof our code, we're also going to make sure that nothing slips through this use case and we don't have a, an enemy at some point with minus 50 health which is still alive. And also if it's not dead, so we can't kill it multiple times, then that we will kill our enemy. Make sure that we set, is that to be true. And then we're going to make that function again. And we'll call this one enemy died. This one is going to be a little bit different. I'm not gonna put any logic in here whatsoever. What I will do, I'll just add a rewritten white, just so we've got something visual and a comment around the reroute night. Okay, so a nice simple comment, just kind of tell us what this function is doing. So we've made this function which is going to be left completely empty in the parent class. And this expected to be used in completely overwritten just in the child classes. Now we could do something here like cooling the destroy function. But in the child class is we may want to do something such as putting the common hair, playing animations, particles signed, and things like that. So we don't want to destroy the class before that's happened. And we can't change the way that functions are called. So we could Kuhn our child function first and then inherit the parent function afterwards and destroy. But again, there may be some use cases where we don't even want it to be destroyed. Maybe we're going to have corpses littered around the the arena. Maybe that's going to be part of the mechanic where they need to keep existing. So to avoid any issues like that, I generally don't cool. Destroy functions in the parent function calls a tool when the parent classes. But I will have set up the function are ready for that to be cooled so that the health is trapped and we know that the enemy has died. It saves us implementing the same functionality over and over in all of our child classes. But we get that freedom and flexibility to add in to the functions the unique logic and functionality based on the class which is calling that function. So what we're going to do, we will call this. We still want this to be cooled even though nothing is happening. Because in any child of this class and I when the health as being tracked and it's being classed as a dead enemy. And this is still going to be cooled. We'll be seeing shortly high. This can still be utilized in the child class is if you're not familiar with that, but that's pretty much it. So that is our base enemy class ready to go. That's the project, at least the variables and functionality that I think are going to be the most generic. The things that any class that I could envision nodding would need. And they're definitely the only things that I went back to class is going to need to avoid us manually implementing this in that class as well. 13. 13 - Enemy Bat: So just take that next look into the inheritance system, how we can get different classes to inherit functionality and variables and properties from their parent classes, we can now start creating our enemy bats. And we can do that by going back to our enemies folder. And in here from the enemy base, we're going to right-click on this. And we've got an option here to create a Child Blueprint class. So this class now inherits everything that we've just implemented in our base class. I'm just going to name this one BP underscore enemy bat. And we can even see here. So if again, you're not familiar with the unreal class inheritance structure, we can see that the parent class is the enemy base. We can navigate to this, which will be just here. We can see that the enemy base parent classes, the paper character, which is the one we chose originally, we click on this. This will take us to a C plus plus class, which we'll define all of these things. So we're basically just inheriting the capture component, sprite component and everything like that from our C Plus Plus parent class in this case. So I'll just get rid of the planet class. We won't need that again inside of the enemy. But what we want to do, we can start adding some of the visuals here, so we can add our sprites in this one. So remember, we're going to get rid of this, my parent version. This has been left empty on purpose. So we can fill this in with the animated, but we'll also want to change the Capsule Component size so we can just make this more of a perfect circle. So 34 and 34 seems about fine. It means we're not going to get hit from the wingspan. But I think that's going to be accepted was wanting to look too old in this type of game. And then just to check a few things as again, just in case you're not familiar. Inside of the construction script festival, we can see that we have a cool to have normal construction script, which is then cooling the parent construction script. So what this is doing, if we double-click into this, that will take us to the parent class. And we can see that basically the order of execution is we're going to cool our own function festival we could do is add something like a print string here, which means that we would in the construction script prints whatever is going to be on the print string. And then we would cool hour parent version, which is going to just set the health. Yeah, If we which does the different ways. In fact, I'll show this just to get this point across. So we'll say print string. We'll say this is ROM child. And then in the base class we'll do a print string here as well. And they're just realize this is going to be a bit confusing because the way it scrolls down the screen, but hopefully this should make sense. We'll say apparent. So this is going to make it clear whether these schools are coming from no change this one to be orange. Just so it's a little bit more obvious. And we can see that already. We've got a lot of different things that construction scripts run pretty much constantly whenever you are changing something, compiling something in the editor. So if we bring in just the parents would just getting that parent function code. I'm moving this because again, the construction script is cooled whenever we move something in the other set. So what that's doing is it's setting in the health and then cooling that print string. In comparison, if we bring in the bat, we can see this is cooling the child. It scrolls down so we can see if I leave it for a while. The first one should be blue, child-parent child. So that's calling the child function first, then the parents. And kind of looping that every time you buy a certain number of units. So this is the Oda, him, My, we can change this if I hook this up fast and then hook this this way, this one I fall into the parents Construction Script vest. It shouldn't I read a parent and then child because we're going to cool our construction script on the parent Fest and cool this print string. And then we're going to cool our print string in the class that we're actually calling it from directly. So again, I'll just bring the enemy bats in and it's a little bit hard to see against nothingness. I've felt the page, but I'm not doing it any other audit. So we've got parent and child and parent and child. So we can see is going in the right order there. So that kind of makes sense how we have the structure of the order in which things are cooled when you're inheriting things from other classes. Because we will be making use of this as we go through with the button class. And that's exactly what I meant with we can override things in the enemy died events. We could have done something like placing the destroy function here. I'm just making sure that when we overwrite this function, we do the child's version fest, which will be playing the effects. And then calling the parent function, which would handle the destruction of the class. But like I've mentioned, even with that kind of override, there may be situations where we don't want everything to be destroyed immediately, having things like that kind of permanent and the game can be quite nice with the bodies and having different interactable is when the enemies died. So for that reason again, I'm just going to skip doing that and make sure that we do all of the functionality that we want inside of the child class. So the way this is going to work, we can get that one function I have the way to begin with, so we can actually look into overriding another function which will be our enemy died override. So here in the functions, rather than recreating that, we can see that we have a few things that have already been defined in the enemy base. So we can override the, any damage function in the enemy base and we can override the he died function from the enemy base. We also have a bunch of functions we can override from the actor class. All of these again, are already being done in the General Act to class sets up. But the one we're interested in is the enemy died. So like I said, we're going to keep this cool to the parent just in case we ever do anything a generic that we want to happen in the base class in this simple example, it's not going to happen, but just in case we did, then we'll keep that hip. And you've already seen how that works with the construction script had this will be called first, that's essentially going to come in, do nothing history root, node, and then we'll call our own logic here. Now against everything that I've just been saying, what we're gonna do inside of the enemy back class is destroyed the class. So in this case, we're not gonna go into effect, says plenty of tutorials on particle effects and side effects and things like that. I'm just going to visualize the character being removed. So it will be cooling the Destroy Actor function whenever the player jumps on top of the enemy. But again, if you wanted to do something like adding a animation fast, then you can add that here, have a go off screen and then after a second to, to destroy it that way. But again, this is going to be a nice visual representation, will see that we jump on the back and then it will disappear. Well, this looks like at the moment, if we come in, we can bring them into the world. If we try and drag it somewhere on the tile map here, we can see it just rest just above it. But close enough, we want to set this to 0 and on the y-axis. And to avoid that as advising, we're just gonna make sure it doesn't go into the ground and we can leave it somewhere like that. So it become impress plane I. We have a bit of a streaming issue here that will take a second and then that should fix itself. And we can already see it's going to be a couple of issues I was expecting here. And that is that we can jump on this and we're going to be moved around, potentially be pushed backwards, which is what I was hoping would happen there. So because we've got to spec light is interacting with each other, it basically doesn't know which way to resolve the collision. And we can't have that issue where we're moved forward and backwards on the y-axis. So once we have that kind of issue in mind, I'm just gonna go back into the player class and we can solve this might sound the player class on the character movements. We've got the option here. If we search for constrain or just start typing constraint, we have the constraint to play an option. We basically want this to have a positive value on the y-axis, which means we're not going to allow it to move any direction on the y-axis. We still have movement in the X and the XIJ, which is left to right and up and down. But what this should do is if we come back in and jump on the bats again, we can see that we just pushed only left and right eye. So it's gonna take enough velocity. And we shouldn't, which helps this as many times as we want without worrying about being pushed forward or backward. So that's the first issue. Now the next thing you may have noticed is the Bernstein thing, slightly higher up, but is always ending up on the floor. So of course we won't. I'm about to be able to fly. And again, we can easily do that inside of the enemy. Back to class this time, going back to the character movement. And we've got a bunch of different kind of movement mites. We can set the default land movement strangely enough to be flying. So basically, when this is initialized, it will set the defaults movement type to Lund. And when we're kind of defaults in this land, we want this to be classed as a flying movement. So it's kind of contradicting itself that, but just be aware. The main thing is that this is the default movement mode, which is Lund. And we will not to be flying then the way that that will work, because if we come in and simulate this, we can see that that take the gravity away. And this is my class as a flying character, so it can move side to side. We can move up and down. And it's going to completely ignore gravity unless we override it to have some kind of bubbling animation with some gravity, a kind of form. But otherwise this is going stay completely on the app. Even if we possess it, then we can come up and start jumping on the bed. So at this point we have a fairly stationary, but the next thing we're gonna want to do is add some kind of movement logic to this. I'm just gonna make this very simple. It's going to fly left to right. It will pick at random whether it wants to move in a certain direction. And then it's going to be one of those enemies that when it hits a wall or something, collides with it, whereas in its path it will just change direction and fly the other way. 14. 14 - Enemy Bat Movement: The actual movement for this class should be fairly simple to implement because again, we're using the character movement component here. That means, as with our player class, just to kind of recap what we were doing, we can really leverage some of the movement logic already available within the character movement provide a direction that it needs to move. And that will be pretty much the logic that we need to do that. So that was on the input movement, and we can see we've got the movement inputs. So we're gonna do something very, very similar. In fact, if you have the player class ready open, we can copy this note. We're going to use exactly the same thing, will move back over to the enemy baton to class. And the only difference, of course, is that because we didn't have an input drive this room. We're going to paste this in next to the event tick, OK, this backup. And then all we really need to do is work out how we're going to get this scale value. So at the moment we have the x, well, the direction to move in. So again, we're moving left and right. We don't need any forward or backwards or vertical movement for our buttons. So if we actually go and play this right now, this would be doing at least the very basic movement that we need. We can simulate that hair. We can see a couple of things are probably a little bit. The first one is that the bat is flowing backwards. The second I'd say he's moving a little bit too fast. And the final issue is the main kind of point of this, that he's always going to be moving in that forward or right direction. So what we're gonna do is work out these different steps as we go through this class. So the first thing is going to be the easiest thing to approach, which we'll be changing the speed of the movement. We've seen again in the past that this is on the Character Movement Component. So with this selected D, Remember that we're using the default movements to be flying, which means we won't be changing with the walk speed like we did with the player. Instead, we need to go down to the flying section and lower this. So I'm gonna make this roundabout half at the speeds of the players moving. I think the players defaulting to 600, so we'll make the maximum wind speed at 300. This just means that it should be a little bit easier for the player or ourselves to kind of catch up and play around with the enemies for testing and also for games. You normally want the player to feel a little bit more controllable and powerful than the enemies. So we can see and that's fixed, the movement speed, which is the first and kind of simple step to do here. Select from the movement direction. What we can do is we can pull from here and we use another of those slept notes that we've been getting used to. Again, I'm going to go for the utilities select because I like the way that this will print out the true or false. When we turn this to a boolean. From here, I'm just going to drag and creates or promote this to a variable. And I'll name this one that B move, right? So again, we're defaulting to the positive naming of this, that move rights will be the kind of expected default. And what we can do is we're going to set this. So if this is true, we're going to set this to be one. And if this is false, we'll set this to be minus one. So very similar to what we're doing with the input axis. One is going to be positive moving right minus one would be negative moving left. Very similar logic, just a different way to drive this from a Boolean. Now to test this, we can very simply take the eye. So we'll make this public it compile. And we'll see that this will default to be false because the index here was false. And this means if we grab our bat in the editor, we should have full control over the movement direction here by finding that Boolean, we've got the move right Boolean here. So we would expect if we leave this unchecked when I move left. Okay, so first test done. And if we take this, we should be moving rights. And we can see we now have control over the bat as expected. So that's going to be the next part of the movement direction controlled. So we now have a variable to control. This works. Now nice simple way that we can update this on the begin place so we can kind of randomized the way that the bats will be moving. I'm just going to remove the access overlap. We won't be needing that. What we can do is we can drag in our variable, hook this up, and we can just pull from here and use a random Boolean function. So quite simply, this will have a 5050 chance of picking true or false when we begin play, we wouldn't have any control over this. We'll just use this completely random assignments of the Boolean value. And then when it gets to the event tick, that will be taken into account and our bat will be moving in different directions. Okay, So I've tried a few times and you can actually see some high, we did get an exactly 5050 split of the randomization that I wasn't expecting that. So though, that for what it is and what we can do here is make sure we went need to be testing this anymore so we can make this private again of C. We just don't want too much to be exposed if it doesn't need to be. And the final thing for the kind of basic movement implementation I'd say is to get it facing the correct way. So of course we do want this to collide with the surface at the moment. If we get this moving left, then what's going to happen is will collide with that wall and just fly indefinitely into that wall. So we will be fleshing this out a little bit later to get the bat to change direction as soon as it hits a wall like this. But for now I think we can just get the character facing the correct way. So as soon as we do at change a direction, we can take in this move right variable that we're tracking. And we can make it look either left or right depending on the way that it's moving. So again, to do this, It's very simple, I think in this case, rather than trying to work out control irritations and things like that. This is one of those things where you can do it either way. There's no real right or wrong way. Especially if something like an enemy, I know that we're not gonna have anything like a bat. Spitting fibers are some things that we don't need to be concerned with the rotation direction. We're not adding in sub-components. So I wanted to show you the other way that I've mentioned to do this, which is using the sprite scaling. So I completely optional, but I would like to show you as many different ways to do things as possible so that you have those options in your arsenal ready to go. So what we're gonna do is depending on the direction that we're moving, we're going to get our sprite component. You can also do this to the entire actor completely up to you how you manage this so you can set the scale of the actor. But quite simply, remember that one I said one option that we could have done with our play a character, rather than changing the rotation, is to simply get our X gal, set this to minus one and we're facing the other direction. So that's what we're gonna do. A nice simple approach here. And like I said, just another option I wanted to show you. So to manage this, what we'll do is we'll first of all get the current scale as we'll need this recalculation in just a moment. And we can do this with the GET world scale, the sprite. We can split the structure pin. So we have the x, y, and zed. And then in the similar way, we're going to then set the scale based on this. Again, we can set the world scale 3D for our sprite. And again, we're going to want to split the structure pin just because if you think about it, we don't want it to be flipping the y or the zed. So we can just automatically hook these up so that these never change. You could hardcode them to one. You may forget way of doing that. The main thing is we wanted to work out the calculation based on our x value. Then the final thing is we're gonna pull from here, and we're going to multiply this by a floats. Floats multiplied by a float. Return value will be what we wanted to set the scale of this to be. And as ever, we're going to pull from this final pin and we'll use a select note. Again, we're gonna go for the utilities option. Just to recap, we don't want that a or B. That's a little bit ambiguous. And of course, as soon as we turn this to use the Boolean value, we get the true or false. So that again, is very human-readable. We now know that if we're moving right, if that is true, then we want this to be scaled in one way. If it's false, then we want it to be scaled the other. And as we've just seen, this is actually a little bit different because of the way that the assets are drawn. It's right, kind of common that the assets, the player will be drawn facing right, the enemies withdrawn facing left is just something I've noticed at 2D artists dig, which means by default moving right? So we actually need to inverse this. By default is soon as the enemy starts moving right across the level. So if that's true, we actually want this to be a negative value. So we'll set this to minus one. And if this is false, so if we're moving left, then we'll set this to positive one. With that done, we can plug that in here, tidy this up a little bit, and that will be as good to go to test this ite. Ok, and there we go. So the bat isn't, I'm facing in the correct direction depending on which way that random Boolean is selected at the beginning play, if we're moving left, then he's flying fluid to the left. And if we're moving right, it turns around and is moving or wood to the right. 15. 15 - Enemy Bat Direction Change: To get the buttons reacting to the wolves, as we kind of expect, there's going to be a few different kind of grind rules and expectations that I'm going to put it into the logic just so that we know that we have full control over how the butt's could potentially interact with the different parts of the levels, such as the floor of the player, different items intractable as wolves and so on, so back inside of the enemy. But to class inside of the event graph, the first thing we want to do is the way that we're going to kind of handle this is going to be from the collision events, as I've already mentioned, the basic outline of this is when the bat hits something, we want it to decide whether or not it should be turning around. So we already have the main component that we'll need for this, which of course is going to be the Capsule Component. On the capture component, we can scroll down and we can find the component hits events and we can add this in. Now I'm just going to go through the way that I have this pond die. So you may want to have your enemy character interacting differently with the world. Generally though, there's a few kind of rules when it comes to the way the, I kind of look at game design on a more concept and theory based premise than just the rural kinda mechanics behind it. So the first thing that always stands out to me the most is that one of the things that this enemy could potentially collide with will be the planter class. One thing I always find very wed when this happens is when the enemy hits the playa and then has this automatic kind of logic triggered to make it turn around and move in the other direction. Especially when you break it down and think that the enemy is kind of early in the level just to either hunt, dine, find, or interact with the player class in some way to provide damage. Especially as I'm approaching this like a very old school ionic or Mario game, not some of the more recent ones where the enemies may pass through and the hub specific kind of montage is where they throw a punch the character, as an example, these are the ones which are going to purely provide contact damage. So I tend to think it feels a little bit strange if the one thing the enemy is intended to do is to walk into the play and cause damage and then turns round. So what I'm gonna do is the first thing we will drive from this is we'll pull from the other act up and find out what we've hit. And we only want to do our collision check if not isn't equal to the Player Pawn. So we don't need to do any casting or anything. How we can literally check whether the one thing, the only player in the game is going to be controlling if the thing that we've hit isn't equal to that. So the other porn or the plasma will run a brunch check from here. And if that's true, then we can go ahead and do our direction flipping logic. That's the first step done for this type of logic. The next thing is going to be finding. So if we have passed this one criteria, that way we want to completely be liked and ignore any future logic. The next thing we can look at doing is checking the surface that we've hit or interactive against. And we can do that by dropping the hit Pin just here. This provides a lot more information about the thing we've hit, such as the type of material it might have its name if it has a bone socket, the distance and you can see all of the extra pens we've got here. Now the one that we're going to be interested in is the normal. And this can give us an idea of the direction in which the hit was taken. The next thing I wanted to to account for it as if something comes from above or below. So ceiling or a floor, or even another type of enemy or an interactive class. All of these things should also be ignored. So we can see how this looks. If we drag from here, I'm going to print string. And inside of the print string, we can just plug in the hit. Normal is going to be the one that we want here. So let's just have a quick compile of this one and we can see what is going to be returns depending on whether that is being hit. Okay, So if we're hitting a surface like this one straight on, we can see that we're getting a lot of hit returns from this single collision. Basically for as long as this is colliding, kind of like a terrible mess, we're going to be returning this hit function. Now the important thing we can see here is that this is being hit on a positive one on the x-axis. So this isn't actually the hits position of the butt of SES is going to be minus one on the outside left, as we're already aware of, what we're actually getting is the positive location of the thing that we're hitting, which is at one on the x-axis of this rule. So flipping this around, I'm just going to pause this as soon as we hit that little bit of a corner that, and in fact, what I'll do is go back in. I will stop this because that's not going to be long enough and we can increase this to something pretty high. So the first thing I wanted to show is the hits of this corner because that's not quite straight on, but it's not below. We can see when we getting these values like 0.25.9 or between 0.8, we can see that this gives us an idea. And also no, sorry, minus 0.2, because this is coming from the left-hand side of this little hill just here. But this also kind of on the corner which is the top of the hills have got a positive on the zed, mostly positive on the zed giving us an idea that this is a corner and a clipping the side, it just hair as well. So in this case, what I would do is I'm going to kind of take these values and we can clump certain ranges that we're going to ignore based on what's being returned. So if we let this go a little bit further, we can see a similar thing as we've hit this from, what we've been hit from above is the way that we wanted to look at this. We can see when I'm getting a negative value on the Zed because it's the bottom of the platform rather than the top of this hill. And again, on the x we're getting a negative value because it's from the left-hand side of that platform. And we're going to expect pretty much the same sort of thing from that brick and the wall. And this is how we can use our hit Normal to get some information about the direction in which we've been hit from. So the first thing we want to do is rather than making our one-component hit anode much, much bigger by splitting the structure pen. Because remember wherever you actually interested in one of these, which is going to be the x-axis. So I'm just going to recombine this just to show you that if we keep doing this, it's going to get quite big. Another way of writing this as we can pull from here. And if you're not familiar, we can break this in a separate night. So they do the same thing. We can break this vector. It just means that we're going to have this in a slightly more separated location. We've already made this pretty long, so we can probably save a little bit of space by just separating this might in a different light. Now from the X, I'm just going to be quite strict with this. So if this isn't equal to 0, so anything not 0 on the x-axis is going to be classed as a hit result that I want to respond to. So again, we're ignoring the wind is add slight flaw and that kind of full grind background collisions potentially will be ignored. And anything which is higher or lower than Xerox, you can see where returning a point values. So even if it's just like flipping a corner, then I'm gonna class that as a reason to turn around. So as an example here, if we were to hit that corner again, even though it is like point to is something we would still flip around and change directions. Now you could add in ranges over is between minus 0.4 or 0.4, then that could be the bottom of a hit result on the zed. And you may not want to respond to that type of thing that's completely up to you if you wanted to add that level of complexity and hopefully it's making sense how we can use this slide. But just to get the bulk of the logic and we're gonna keep this nice and simple for now. So what we want to do now, now that we've got this condition checking and we're going to set our moving right direction. And just no trick here is we're going to get the current leaving right direction. And we'll set this to be whatever the currents moving right condition is not. So we'll say move right equals to not move right? And we can use the NOT Boolean check here, pass that in, and it's essentially just inverting it. So this is going to say if you're moving left and move right, if you're moving right, move left, next moving over, we're going to want to flip the direction of the bats and we already have some logic above to do this. So of course we don't want to copy this code. Instead, what we're going to do is we can grab this like we've done before, right-click on any of these nodes and collapse it to a function. For the name of this, we're not technically changing the rotation. Rather than calling it change rotation or update rotation or something. I'm going to name this one that Togo facing direction. I just think that's the most accurate descriptive for what we're doing here. And then now we have this as a function. We can grab this in and we can plug this off of our function here. I already know that there's gonna be some issues here because of the way that collisions are working. This kind of gives you an idea of what might be happening because we get more than one of these function calls per collision essentially before we even have chance to rotate, because we're getting more of these returns per lesion than we may want to. We may get some clashing or flipping happening too quickly. So we can just check what's happening to begin. You can kind of see it that tried turning and then didn't quiet. And then we've got some backward facing here so it can look a little bit twitchy. So we want to make sure we have a little bit more control, especially on these kind of tight locations here. And to make sure that we don't have too many updates happening at once. So to manage this, I'm going to use something called a do once known as the name would indicate this is going to only allow us to do something at that one time until we reset something. This is known as a flow control gate. So we're going to pass this in het. We're gonna do this functionality just once after this, and I've put this in the wrong place. We want all of this to be after I would do once. And we, for this branch comes back as true, then we only want to toggle all of this once and change the direction once again, this is going to cause a problem because this will not automatically reset itself. So if we hit something now, this is going to be a long way to check it, but we're going to hit this wall. And then if we hit this corner, we should hope to see you this flip or do something. But because we have that do once in place, it means we're only going to keep moving forward and that functionality will never be checked again. So what we want to do next is once this has happened, we want to make a delay. Don't want this to reset immediately. Remember the pump, the problem is that we're having too many hits colliding with the wall immediately until we kind of flip, right? So we're gonna add a delay node here. And the delay can be something very, very small. Something like 0.1 should be perfectly fine. And then when you see other people using this a lot, the time they'll just throw in a rewritten node over here while it pass into y hat and thrown to revert note. Try and make this a little bit more readable. Show you a way that we can get around this in just a moment. Quite a simple thing to do and just keep the code more readable, but this will work. So we can now see that as we come in, we're going to hit this one. So we will have that code. And then we've got another problem that we can see has said we're going to fix a little bit these as we go through. But the main thing is that when I flipping around again and that functionality is being cooled and checked more than once, as long as we've had that 0.1-second delay. And we should see it happening again when we have something here. And that is a welcome Perfect. Well, apart from the fact that the bat is flowing backwards as a working Perfect. Okay, So before finalizing and fixing that last problem, one thing again, we're looking quite a lot in this series of videos at a kind of clean away to code hopefully. So whilst we have some nice things nested into functions, everything here is very kind of blocked out to do its own thing. I'm one of the things you have quite a lot as a detracted from blueprints is high. You get spaghetti code and it can be hard to read and maintain your codebase. And that's true at definitely come be if nothing is put into a function, if everything is placed in the Event Graph, if you have looping y's here, which can make it much harder to work out what schooling, what when you saw adding different things on different branches and sequences coming off of this and everything is looping round back into the ones that some point is going to get very hard to work out which direction your logic is flowing. So instead, what we're gonna do is we're going to remove this and that's not a great way to get ahead. We're going to create a custom event down here. So I'm nice, simple fix, cool this one. Reset, direction, change check. So throwing it resets into the naming convention appropriately helps just hit. We know that this is going to be cooling some kind of built-in reset functionality quite a lot of the time and Unreal, In this case it's going to be this flow gate and that do once night. Then of course from here we're just going to pull from the delay and will be cooling and that resets direction change check. So nothing too wild. Most of you probably jumped to that as the first kind of fix for that kind of looping function. Now let's see. I'm not just reads much, much more clearly. The best thing is while here, as you're reading through this, if you starting to add code later, you kinda flashing lights and expanding that logic. And this is getting a lot longer going into different functions. The main thing now is we don't have to check whether this random Ys going from one part of your blueprint to another, double-click on the node, and it will take you here and you can see what this is going to cool. Trying to keep the code as clean, readable, and reusable as possible. So that's gonna do the same thing. We know that there's still one bug to fix it. And I'll be honest, I'm not too sure why what we have happening is the bat is still kinda flying backwards at some point. So happened that, so I'm wondering if we throw in a print string here, making sure that we're only doing this once. It may still be some high falling through this, maybe this one isn't quite long enough. And it could be that we're toggling this most CPU times out, but maybe not totally in the direction of something. I'm not sure what's happening, so we'll print this, see what's happening. As Ernie guest seeing one hello returns there. That seems to be happening a lot more on this corner. They're only getting one as well. Okay, so that isn't happening, which means I would do once is working correctly. So that is one good thing at least. And I'm going to keep this bit and as a kind of debugging tutorial, this wasn't intended that sometimes, I mean, this is the way that programming goes. Development is usually not too straight forward. So this could be quite useful hopefully as a learning example. So the only other thing we're doing, we are flipping our Boolean check, hey, we didn't not once have I delay, which we know is working. So it means that this Going to have to be something to do with the logic in our toggle facing direction. So we'll just double-click into here and we'll have a look at what's going on. So if coming in, we are taking the current direction and I can already see the problem, okay? So because we have this kind of oddity that I mentioned earlier, at least I think that's what this would be because we have the enemy potentially facing the opposite direction. And when we move as soon as we begin play, we are potentially flipping this. It's that would also make sense why any happens when we're moving in the rightward direction. Because we've already applied the most application based on the current scale of the sprite. So because we're taking that into context and flipping it that way, well, I think we're doing is we are multiplying a negative by negative in some cases, which isn't changing the direction that we need to go. So if we throw in an absolute nightmare, so we still want to get the value, but we'll make sure that we guessing the absolute value returned. So that would mean that in the cases where that's happening, we should be getting a negative multiplied by a positive and then still flip not in the correct direction. So yet let me go. We could see that was the problem direction before. And then we go again. So just double-check a few more times. We'll let this hit all of the different moves. Okay, so the delay time that was maybe a little bit too low because we were able to quickly change plumbing that made it look as I was interacting with the level quite organically in a way where it flipped that I'm flip straight back grind and carried on. So I think I'm going to keep playing. That smaller delay seemed to work quite well, that a little bit of a toggle, we could have possibly had it, so it's a little bit longer. But the main thing was the absolute value just a problem now. So it wasn't an issue to begin with because rarely have a hissing one rule. But once we've flipped a few times, we want to make sure that we're taking into account the correct multiplication here for the sum of the cases where we may be taking this already moving right? Because we've had to flip this at the beginning because technically the sprite is facing the wrong way to be moving forward to begin with, we just want to make sure that this is updated to account for that. And with that, that seems to be working. So we'll just double check how this works when we hit the far womb. And then we'll go with left in a kind of infinite loop. I think this is more of something for us to fix in the level design here or the placement of the bat. I think that looks better. So point to delay. I think at least making it go between this point and this point looks better than having it flip and then go up and over. Ideally, what we're going to do anyway is we're not going to place it somewhere where it can get into that issue. I would place it directly in line with this and I even if it hits that, we're going to go between these two walls. And in fact, we could also, we could keep 1.5 and thus put one down here. So we've now got multiple enemies and the level. And again, this way you can see I'm not really having that issue. They are going to be hitting things pretty much face on. So that I think is going to be a pretty good fix with that done that we're pretty much ready to jump into the combat situations between the player and the enemy, The causing and taking damage between the two different classes. The only thing that sticks out is we've already done our overrides for the enemy class. We have our enemy died functionality. And in the back class from the base class, you just want to double-check that the enemy bats has helped as well. So again, we've set this to a 100 default in the base class. If you want to change that, hey, you could change that to be overridden in each custom class, each customer child class by overriding the default health. And remember we leave the health alone as that will be guessing set in the construction of script through the cool to the parent class before we actually end up play. So if you wanted to bats have very low health or something, then you could change that. But with that done, I think we're ready to go now and start looking at how we can get the player and the enemy to interact with each other. 16. 16 - Damage: Before jumping back into the player class to get some of the damage between the enemy on the player itself kind of hooked up and working. I realize I kind of brushed over one thing which may have left some of you wondering why we were doing a certain thing in our facing direction toggle. So inside of this function, we've just seen that we needed this absolute value to multiply the current scale, the scale that we want the target scale to be. You may have just thought that this was slightly over complicating things. And it is, you've probably seen that the very easiest thing we could have done is simply plug this in. So for moving right, we're going to set the scale to be one thing. And if we move in the left, we're going to set the scale to be another. What I kind of forgot to mention a moment ago is the reason I would do this. Well, the reason I've set up this way is if you imagine a game like Mario, what you might have kind of a super power which will scale you or the way that the health system works. Even you've got mini Mario and I'm bigger Mario. We may do this by simply changing the scaling of the sprite. We can also do things like animation. If you didn't have the frames drone in to add squash and stretch, you may be doing something where you're animating the scale to compress it when you're jumping and kind of squash it when you're landing. So the reason I'm doing this is we can account for those updates if the sprite is ever being changed during an animation, during a power, we're not forcing this to be one because we may have doubled the scale of our sprite. What we're going to do instead is we're going to find out what the current scale is. So if we've doubled in size, then we're going to multiply this by the 1, 1 negative one. So we're still getting that increased or decreased scale of our sprites. We're taking that into account and multiplying it together to flip the scale over. So of course, if you know that that's something you'd never going to do. If you're certain that you're not going to be playing around with the scale of the sprite or whatever it is you're using this logic on, you can very safely then just plug the return of your select note into the skull and work it that way. Just something I wanted to mention, as I just realized, that could be a little bit confusing and left people wondering why we're not just doing it that kind of manual and hard-coded way with the address line. What we're going to do is jump over to our player class. We're going to start looking at recording the direction at which we've been hitting. Things will have been hit. And depending on how this is recorded at the time of impact, we're going to either decide whether the plaque to be taking damage or providing damage. Now in this case, to simplify things again, I'm going to put all of this in a single class. So we'll have the player completely in control whether the damage is being applied, received what doubt, again, in a larger, fuller project, you may want to have something like a damaged class at damage now to fire some communication between the classes, but we're going to try and keep all of the logic in one place in this instance. So the first thing we need to do very similar to our We'll detection setup. We're going to get the capsule component, but any colliding that is recorded in this class, we're going to use the non-compartment hit as we know that these are blocking each other. So these will be hit events, not overlap events. And the first thing I wanted to do is cast against the other thing that we're hitting and check that it is a type of enemy that we've hit. So we're doing that using the cast to BP underscore. And I'm going to use the enemy base rather than enemy. But so again, if you have a created subclasses of the base class, that means that that will account for all of the different inherited enemy types with this cast checked if that's true. So if the thing that we've hit is an enemy, we're going to need to do some things, checking some variables. Working with the data based on that class as we go through. So I won't do is rather than constantly putting from this pin or this pin light to, we're just going to promote this to a variable. And I, this also saves us the potential of needing to recast as well. I'll give this one a name, I'll just call this one hit and then the href. And then from here we want to start again pulling from some of this hit information. So we're going to split the structure pen for the hit. And we wanted to find some information about the direction in which the hit has been provided. So rather than pulling back on the hit Normal that we've used in the past. I'm going to show you another way that you may see this kind of calculation done is some very simple vector maths to find or determine which direction a collision impact has been detected. So it's very, very simple. All we need to do is we're going to get the location of ourselves, or in this case, the location of the thing that we've hit and then take away from the location of ourselves. The value returned from that vector calculation is going to be the direction in which the hit of code. So we have that information here. We can see the hit location. So that's the first part of the calculation. And a pull from this and get the vector minus a vector. And then as I mentioned, the second part of the calculation is our own location. So we can pull from this pin and we can just search for the get act at location return value. It's a nice and simple. So this is going to take the world location of what we've hit, take our location away from that. Of course, the returning value from that will be the direction in which we've been hit. Now let's do another debugging and let's print string this because this isn't going to be very readable, I suppose o make it very easy to work with this value. So in the print string, we will just drop this down would increase the duration here so that we can see why this may not work, because we wanted to find from this information from the direction we've been hit. And we want a kind of simple value that we can always test against, that we never will be within a certain range. And basically we're going to be looking to see if the hit has been detected from below the player or has been detected from the side of the planet. If it's below the player within this tolerance, then we know that that will be classified as causing damage to the enemy. So we've got, again for that kind of Mario ask, jumping on something's had will cause that damage. And if it walks into the side of us, then that will be classing as damaging ourselves. And we'll see when we test this, why this may not be the kind of value that we want to work with straightaway. Okay, so we can see a few things. Probably seeing what's happening in the background is we're getting some pretty big numbers returned. What we really wanted to do is again, we're getting very familiar with working with normalized values are between a range of 01. Just kinda what I'm trying to point out here is we need to always remember what 67 would be in relation to the x-axis is going to be 67 degrees, was working in the scale of some things. So what we're going to do is we're going to class kind of the bottom of this as being 0. And then we have a degree of between 01 to the side, or between 0 and minus one to the other side. As an example, that's really what we're going to be looking to do. So the way that we can do this is rather than using the number directly, we're going to pull from this structure here. And we're just going to normalize this value. This will give us something very similar to what we had with the hit normal wise between 01, depending on the direction that's having this information provided. The main difference here is when we plug this in, I'm going to give this a tolerance of 0. And the main difference you'll see here is that when we're doing the calculation this way will be guessing the calculation relative to the ACTA. So the thing that we're controlling. Is the direction we're going to see the hit from. So we should be expecting to see a minus number if we're jumping on top of something and a positive number, if it's hitting us from above, if we jump into it with our head and vice versa, we can then tell whether it's hitting us from the left or the right Very, very easily. Whereas with the enemy, but what we were doing is this hit Normal was actually returning the direction the objects that we hit was facing. If you remember that. I'm going to jump back in 90 press Play. Now cleared the debugs. And this one's a little bit too high for us to hit, but we can see that that is as expected. We've hit from below, so we're getting a minus value on the zed. And we hit that one from above is a little bit hard to get rid of these working. So we can see we've got another useful thing on the floor, have to say is that we're getting minus 0.15 when it's hitting us slightly from the side on the z-axis. And we're getting our between 0. So if we let it, it's us from the left is almost minus one, so we know that's from the left. And if you get hit from the right, then we are getting almost positive one. So what we want to do is work out this kind of tolerance where we can I jump on it. We can see that as I jumped on the head of the bat that we're getting almost minus 1 or just I've got exactly minus one. So that would be the ideal point to apply damage to the and class that has odometry sign for the bot to. We also want to take into account with these values that we can get my, well, we want our range to receive damage would be as well. So we can see we're getting a lot of different values here. Some of them may be just between a taking and receiving damage. So that's what we're gonna do in this step. So that's what we needed to do to get our location that we now have the information to work with. What I'll do is I'll promote this to another variable. And I'll name that new variable hit direction. Again, we're going to need this full multiple calculations as we get further and further to the right of notes that keeps things nice and tidy. Stoplights was going everywhere. We'll just be promoting these two variables as we go along. This one, I'm going to put a comments around just so we remember what this is doing. So it nice and simple just to remind us, this is getting the calculation from which direction we've been hit. And the most is just going to grab these and move this down a little bit. As I know that we're going to need to some branching logic to decide what we do with the enemy when the hit or the plant when the hits, depending on the value being returned to. So from here, we're going to do our branch check and this would be y. We first split the logic to see whether we are providing or receiving damage. And the way we'll do that because we'll get our hit direction, will split the structure pin. And the easiest way to check this is we're going to base most of this off of the z-axis. See a very simple one to begin with. We'll tweak this value as we go through. But for now I will check whether this is less than or equal to exactly 0. So we can leave this when I, this might need some tweaking as we go along. So if we get that value returned, then what we're going to do this would be classed as the damage to the enemy class. So we can pull from here. So if this is true and we got that value returned, this would be classed as the damage to the enemy. So I'm going to very simply from her pool, from the true execution pin so much for the applied damage. Remember, we don't need to know what class this is applying damage to. And we do already have at the target lice or the damage doctor in this case will be our hit enemy. The damage of mind in this case, I'm just going to guarantee that we kill the enemy. So I'll pull from this, I'll search for get health. So a little bit of a cheating way to do this, but we're just going to pass in whatever the enemies current health is as the amount of damage to apply. This at least two. Let us very quickly test this and there's going to be a few things that I want to do on top of deaths. But we've got the death system set up in the enemy. So this should kind of work as we go through and test that we got. We've got one enemy disappearing. And if we hit this one from somewhere above, less than or equal to, remember, so we've got a very broad kind of range that then we can see that the damage is being applied to the enemy and they're being destroyed because we have that functionality In the enemy, but class just here on the enemy died. Now a few things I want to do before this, and this is kind of polish and refinement. Step 2, the impact system that we're going to have. Again, when you look at things like Mario and Sonic will keep falling back on these quite a lot. They do some simple things, which is, they'll take away a momentary kind of hit of momentum, maybe stop the input for a very small millisecond, and that'll apply impulse. So it looks as I get bouncing off because at the moment, we're going through these. And as we go through the enemy, it doesn't really feel like much has happened. It just kinda fill is just disappearing. And this one is hard to know whether that was due to what we're doing, if we've actually interact with them or if they've just popped out of existence. So what we're going to do, there's a few things we want, so it kind of floats begin with. So the first thing is the velocity is always being tracked in the character movement. And I think because this isn't physics-based, this may not be an issue, but just in case we change anything in the future, we're going to get to the character movement and set the velocity to 0. So very simply getting how, why the velocity is being tracked in the character movement and whatever that is at the moment, we're going to set that to 0. I think the more important thing for the way that we have archived to set up is we're going to drag again from the character movement and we're going to stop movement immediately. Take the input that we've currently provided, whether going left to right, Sarah's out the velocity and stops any form of movement being tracked in the current Too movement component. So this is going to give us that a momentary freeze. And then the final thing before we destroy the enemy, I've said we're going to add some impulse. So again, I'm going to Control W, the character movement as it will need this again, I'm going to pull from here and call the add impulse function. I'll just hook these up in-between to ensure this does something we're going to need to take the velocity change. And just to show a very kind of extreme response to this happening, I'll add something like 500 units self impulse to be added to the player when it binds is off of the enemy hat. Oh, there we go. So I kind of touched off in the wrong spot, but you saw that we got the impulse upwards that so try this one. And then we got, I mean, she looks like, hey, I thought I was going to be a bit more extreme 500 looks as I could be a pretty good value to go with that. So we're stopping that momentum that we have. We are posing the, the character momentarily and then applying that impulse upwards. And in fact, I think that looks pretty good. I was gonna do something more complex with this. Taking in the direction that we've hit things from adding an impulse or knock back. But I think for now that looks pretty good as a response to jumping off of the enemy's head. So with that, I think this is one section almost wrapped up. So we'll put a comment around this just to again. That's what this is doing. Very simply, I'm just going to say that this is the logic, accounting what happens when we damage the enemy? Now a couple of things have come to mind here. Something that we might want to do similar to our enemy, but we're going to Festival, throw in a due once a night someone has. So I went about making sure that we're not repeating this over and over. And another thing is we want to make sure that we're tracking this less than or equal to query here. Now at the moment I'm kind of guessing it. What we're working with, a very simple thing that we could have done is left at that print string. And each time we hit something, when we're testing different things, how we can kind of make note of what feels right, which would have class does something we would have felt as kind of over lenient for classing as the planet cools damage, um, which of those may have felt better to be a receiving damage from the enemy. So I'm going to pull from here and we do a print string and very similar to before, I'm just going to set this to be much higher for the duration so that we can read this a little bit better. And what I'll do is I'll pull in the hip direction but the structure pin and rather than getting the whole information, because that looks a little bit cumbersome on screen. We're only really interested in this stage in the z-axis. So we're going to plug that into the zed. And like I've said, once we've done this, we're just going to make sure that we only do all of this once. And I don't think we even need to reset this for the moment, at least for the time being when we're just testing, this means we'll only be able to test against one enemy, but that's perfectly fine. I mean, if you wanted to, we could, whilst we don't have everything set up and ready to go, we can always pull from these. So if this is true or false, this stage will always reset this and we're just going to unhook this later because of course we never want this to be sort of production ready code that we'll be working with. So I'm gonna come in here and we can test again. We know this is working but the 0, 1, 2 felt by it, right? Maybe a little bit lenient. And of course 0.9 is definitely high enough that as well matched directly on top of the butt. It's now as we go through, we can test this, we can tweak and we can start seeing. So let's say value of minus 0.1 could feel okay. So now if we start doing some more tests with the player damage and we find that that isn't being triggered when we feel it will be, then we'll get some information being fed by care that we can work with. So for the damage, we're gonna do some very similar logic. We will once again want to stop all of the movements. So we'll go into count for the velocity and the movement from the Character Movement Component at the same time and also apply it some impulse. So we can actually copy and paste all of these dynamics pressing Control W again, to copy all of those, I'm going to take this away. So we need to really hook this up in, in just a moment. And, and what we want to do, I think this is going to be exactly the same. We will want to do a little bit of calculation for the impulse that we don't want this to go straight up. What we want when the plant is damaged. And especially because the it has been set to constantly move towards us. We don't want it to be in this state where having the movement stopped and we'll be stuck in this kind of state of constantly being hit by the enemy, which is obviously going to be pretty annoying for the plan. I'm just gonna move the bat Dine as this is very hard to test against. So if we come in to kind of demonstrate what this would look like and the bats got a little bit stuck. Okay, we're testing, it's this one, that one. So we can already see actually this is at this stage. We've got that stage where I didn't look at what those values were. But we know that this is going to be a little bit too lenient. So I wasn't trying to kill one of the best stab. Did kill it. So 0.4. And in fact, for NIH, we're going to skip the students altogether because I can see that will cause some issues. So I'm just gonna make sure that the bats lined up. And I want this one to be easy to test. So I'm going to put it down here. Okay, so we don't want the player going straight up. Because if we go straight up like that, you can see we kind of get a free kill after losing a bit of Health. We're going to get that free kill on the enemy. So not an ideal kind of response to that. And what we're going to do is we're gonna make sure that we take into account the direction that we've been hit and we're going to apply it somewhat knocked back for us. So pushing it the player away from the enemy, which is gonna give the enemy kind of catch up with us and not put us in a constant loop of losing health and being hit by the enemy without having any control over our player. So to do this, I'm going to pull from the impulse and make a vector. The main thing that we want to change here is going to be the x value that, that will be applying a force to. So what we're going to do is get the hit direction. We will split the structure pin here, will pull from here and get a float multiplied by a float. And then we're actually going to need another multiply by float. The reason being is we want to make sure we're going in a negative version the opposite direction from which we've been hit. So we're gonna take whatever this was, multiply it by minus one, and then multiply this by a value which I think is going to be roughly the same as our knock back here. So if we set this to 500, see how that feels, and we can come in and test that against the bat. Okay, so that's not going to work because we're being pushed along the floor. We will need some of that vertical push back as well. So we're going to be pushed up and backwards to make sure that we can get some velocity being accumulated here. And that is pretty much exactly what I wanted. So you can see that there as the SS kind of head on, push back and up, which gives us that velocity that we need to get away and escape the bat. And it means that we're not going to take multiple hits constantly and be in this kind of state of being stuck with the enemy. So we wanna make sure this happens from the other side as well. So because we're inverting that impulse that is working perfectly. And again, I think that's pretty much the right kind of force being applied to both sides. We get that nice hit from above there. So I think what we can do, because those working, I'll just promote this to a variable, the 500 that we have, and I'll call this our knocked back for us. We can change this for different cases if you want. Well, I think in this state they all work pretty well at the same value. So I'll also split the structure pin this one rather than using these magic numbers. Why we might forget what that's actually doing. We can control dragon, hopefully these values here, which is just not letting me do. And we can plug that in so we know that what we're doing is we're applying a knock back for us as an impulse to the character when the enemies being hit. So adding these variable names just keeps things that again, a little bit more readable and easy to maintain the code. So final step, we have our impulse calculated. Now, one other thing we wanted to do, we are going to again Control W, the damage. And like we've done in the past with our test for the health, remember we had this on the input. We know we can essentially just takes this actually. This would be a good time to cut the code from the base to Stein here, because we want to apply damage to us off again at a certain value. So we'll say it's when t is going to be perfectly fine. And like I said, we don't want this to be in the final game, so we're going to remove that. And that's a perfect time to see remember to do that. So we can come in. And if we're being hit from the side, when I starting to lose health, same if we get hit from above, something strange happened there. So we'll look into that in a moment. But that we got from the side, at least we're getting that damage taken away. If we get hit from 0, if we hit them from above, then we're taking that health away. Let's take a final look here. We're going to unhook this nine. I think we will hook the V1's backup and we need to find a good name for what this is doing. And we'll call that from both the, so we want both of these to reset that do once that will post-Civil set a comment around this. So nice and simple, just remind us this is why the plant damage is being accounted. This is kind of doing a hit check here. So what I'll do, and in fact, just to make sure that this isn't being updated more than it should. I'm just going to change the direction or the place that was, should they do once it's cooled. If this is successful, then we only want to set the hit direction once per enemy that we hit. And if that's the case, we'll create another custom events. We name this one, reset, hit check. As again, that's pretty much what we're doing. We're reassessing the ability to check whether we've hit something rewritten, note that, and we'll call that function in both cases here. And we wanted to make sure that we do this on the true and the false. Of course, if we forgot to do this once, then we might reset to after the enemies has been damaged. But if we take damage, then that's not going to get resets and we can never take damage again. Make sure we plug this backup, can probably skip the print string for now. I think what I found was working quite well, somewhere between minus 0.25. If you think about why that is on the player, that's going to be when we hissing, roam around this zone on the Class I from the bottom to our kind of corners of the player. That's going to be a sweet spot for applying damage. Anywhere else we're going to be expecting the enemies to damage us. That we're taking damage there. And that's feeling pretty good. So I think that's roughly how we want this to go and be applied. So that felt like a good spots take damage. That was me running into them. A little bit too much force applied there. There may be some oddities with the the force being applied to something for you to play around with and test that. But I think as far as the hit result responses going, and where's the sweet spots for the applying and taking damage? I'm pretty happy with those at this stage. Again, all of this is kind of intended to point you in the direction of way you can start looking to create these effects. You're already going to be expected to take this and improve upon what's being covered here. I'm really make it your own with your own kind of health damage systems and the different effects and things being played. One thing that I just came to mind actually was looking at this is this is still going to be problematic. This isn't really doing anything. So just a quick backtrack from, I just said we're going to delete the reset Jack's head because this is all happening so quickly that essentially, unless the enemies dying, that would work on the enemy dying because as soon as that's happened, we've lost our reference anyway. And any false returns, I just going to reset this to be a null value. But potentially having the play head could happen multiple times because this is happening in a minute part of the millisecond. Essentially, what we want to do is from this regardless of the response. So before we get into our branch check, we're going to throw in a sequence. And from the sequence we're going to allow it to run its logic ones, check what's being hits again. And then very similar to the enemy, back to what we actually wanted to do this from is a delay. So making sure that we do have a small pools before another check. And that was what the initial approach. So I kind of overlooked here momentarily wasn't accounting for we want this kind of delay so that for a certain period of time we're not able to take or even calculate new hit results. And then we're gonna do the same thing. And this also means we only need to do this once. So we can now do our reset hit check down here. And we can do that just once, regardless of the results here, I'm going again, we can play around and make sure that things aren't happening too fast for this 0.1 of a second to be too low. But I think that's going to be perfectly fine. So I kinda have even done, you can see that by insulin them and that was such a small delay before this gets reset that we still go hit second time. So I think this is going to be okay. The main thing, as I said, this case it would have worked. This case it wouldn't have worked because that happens so quickly, is immediately resetting it and we can still get those multiple hits being done per collision check here. 17. 17 - Player Death: With the damaged system and I fully implemented. We've got the enemy back to taking damage and actually being killed or removed from the world. We've got most of that setup and ready to go for the player. Of course at the moment the plaza only receiving damage was still going to call this default print string, which is just remind us in the play iodide function, then nothing's been set up. So let's jump over there and we can start getting this worked on. And we'll consider what needs to be done for the planet died at scenario and how we can implement this. Okay, so the first thing is we know we're already tracking this. B is dead value, which is going to be quite important to us. So we'll delete the print string to get started. We will strike in, the B is dead. And we'll just be sure to set this to be true. So again, that we know that all of our checks or whether or not we should take any further damage is based on this. We can actually remove this from, hey, we don't need to do this twice. This would probably fit a little bit more nicely inside of the function handling the iodine night. But this means that this is now tracked and we went any further damage and we went play this response that would might to set up no more than once. So inside pliers dead, apply died. We're going to set the Boolean here. This is just like I mentioned, a little bit cleaner. Now the first thing I think I want to do is take the input wave from the plaza. We don't want them to be able to carry on running at any kind of final input to that. So the very first thing we're going to do is call a function on the planet, control that. So we use the get planet controller and we'll call the disable input function. Just make sure that this is hooked up to the right place. So the player controller is going to be the PI control, the target, and the actual target for the input to be disabled is ourself. So now when we die, this means that if we're pressing forward, backwards or anything like that, we won't be able to jump or move in any direction. And again, this is very simple, just testable I'm going to do is come back to the damage and will promote this to a variable as well, the base damage for when the player is damaged. So if we promote this to a variable, we can change this from anywhere, which will again just make this a little bit easier for us. And I'll just call this one apply a damage. Now, ideally, we're going to change this based on the thing that we're hitting. But again, very simple project to get things going. This can be easily changed later, but this will just allow us to NIH very quickly changed this to a 100. And it means that when we're working inside of our planet died function. If you ever want to test this now we can come straight into the game, okay, hit by the enemy. We can see we've died. I'm not gonna keep trying to move, jump, movement, every like that is disabled. So first check is done here we have this bit working. So if you remember previously, I mentioned that I wanted to replicate again that Mario or sonic retro kind of 2D animation where you fly up into the air and off of the screen. So we already have something very similar to working. But instead of using the character movement impulse, this time I'm going to move the whole thing. So we're going to take the conceptual components. And as this is the root components, obviously everything is kind of nested below this for movement. We're going to grab that and impulse to that. We're also going to have to remember to disable all of the collision to allow us to merge through the floor. So if we control drag in our capture components, we can, first of all. To allow us to do this, we need to set the set, simulate physics to true. And we'll just hook this stroke backup. If we didn't do this, we're gonna get a warning when we tried to do anything like adding forces or impulses to something which by default doesn't have the physics simulation enabled. We can see here, simulate physics is set to false, which means if you try doing anything physics related, we get a warning or an error message come up. I'm going to press Control W to get the Capsule Component again. And now that we have that in place, we can pull from here and we'll make the ad impulse function. So very similar to what we did through our character movement. Combine them, we can do the same thing here. We're going to set the velocity change to true, will split the structure pin here. And the mimics the impulse this time a little bit more dramatic. So we'll set this up something like 800 or maybe 900. And so it's clearly higher than just being hit. So again, if we come in press Play, we can test this. And it's just not quite working. Remember I mentioned the other thing is the collision, so I think that's going to be high enough. The problem is we were immediately kind of punched out of the air because we're still taking in our hit responses. But I mean, this is fine that we get some funny results from doing these. And we're testing that things are working and how they're responding as we go along. So we're just currently running around. Not quite the response that we want, but we're definitely getting closer. Now again, we want to make sure that all of this as being accounted for in the right direction. So the first thing we want to do, we don't want all of these to be played potentially before we've disabled, I would collision. So I've just made a bit of space here. I'm going to Control W, the capital component again. Again, this is just to save y is going from multiple places. This starts looking a little bit messy. I'm going to pull from here, I'm going to set the collision response. We can set this to all channels. We're not going to need to worry about this missing anything because of course at this stage with dead, all we know is we want this to ignore collision responses on every single channel. By channels. If you're not familiar too much with the collision settings, we've got the Collision Presets. These are the channels we've got tracing, overlapping and block and the different things that we can either trace, which would be things like re-cast, check, casting into the water if you've hit something or looking at something overlapping for things which won't block the other objects, but just detect that event the same space. And then blocking, which is what we're doing while we're physically moving things out, what potentially hitting them with an almost physical response. So we're going to set all of these to ignore. So none of these will block anymore. You can see most of them are set to block. We'll set this to ignore, which means we'll also start doing things like falling through the floor. We're not even going to respond to the floors collision response, which is ideal because remember I said part of the setup is making us fall out of the level. So with jumping up and then flowing through the floor. So that is pretty good. We can see again more issues here. So what we're getting a problem with knife is the camera is colliding with things that we didn't have problems colliding with before. So what we wanted to do, if you wanted to keep the camera attached and stop this from happening. We're gonna go to the spring on and we can see we've got the collision test enabled. And basically what was happening when it was flickering, the spring on. Remember we've got this long arm here, is trying to adjust out of the way if it's facing into the world and detecting that there is something that we could potentially be colliding. So as noticing that when I clipping through this and it's trying to move the camera, which is why it looks a little bit GEC. We can stop this by undertaking the do collision test. And again, we'll try this again, see the new results. So what we should see now is we're still going to merge throw ourselves, but that's fine. We can change the Y offset something if we wanted to override that. But the main thing is we don't have the camera jumping around. Generally. This is going to kind of show that we don't have an entire level around us. This isn't what you'd be used to in those kind of old school games. So what we're going to do instead is just one fixed. The way that I'm going to approach this is we're going to grab the spring I'm component. We will pull from this and we'll use the detach from compartment. Ready knows what component it is attached to, is attached to the Capsule Component, as you can see here in the hierarchy. But this is going to take the spring on. It will detach from what it is attached to the amendment, going to keep the location and rotation, we might need to update these and it will stay where it is in the world. And this is more what you are used to saying, is the player kind of flying up and out of the screen. So this is relative. We don't want this to be relative because it is currently relative to the Capsule Component. We want this to keep its position in the world. So I've not where it was relative to its own components. If the spring arm is moved over here, we want it to stay over here when the player dies because you saw that kind of flew down to the corner of the screen. And now we go. So we now have the player jumping up the camera saying where it was. And we're avoiding all of that clipping issue. We can still kind of see the player's going through the floor. But again, in this case, not overly important if you want it to. When this happens, you could do something as simple as you can add a very small impulse on the y. So if we just add an impulsive like one or something, this will put us slightly ahead or behind of the floor. The enemies have disappeared. That one didn't kill me. And they go very small impulse. And again, if you wanted them to fly behind the floor. And you can see that the different sizes that he fell behind the hill. And if you wanted, you could get slightly creative with this. You've seen how to add different offsets. Again, it using a select, you could add something like a random Boolean select. And 50, 50% of the chance you could get them to fly forward with a select note here. And same for the x. If you find it boring that they're always just going straight up and straight down. You could add a random chance for them to fly left or right. And the final things I've been doing all these tests when I'm still perfect. Still. If we're moving towards the back, you can see something strange like that happens though. We got a little bit too much force with different forces being applied to each other. So I think what we need to do before all of this happens, we're also going to stop that movement. So we'll disable the input, stop the movement that we have. And just to say, going back to this very quickly, if you wanted to apply different impulses to the x and the y and apply that randomly. Then I'm not gonna go through that at this stage, we've done very similar things. Most times, this would be a good kind of learning tests via South between topics. Just give the videos of pulls and see if you can implement this yourself. Take some of this like nights that we've been using, some of the random chat can put those together and you pretty much have the result for some at random impulses have. So the next thing with this stopping of the momentum that we already have this being done, we're ready copying code here, which is never ideal. So what we're gonna do, probably familiar with this, not as well. We're going to select two of these. We're going to collapse this to a function, and we'll name this one that council Movement. Of course we're going to delete these Dine half. We can drag in our council movements and we'll just hook this up to the false pin. So doing exactly the same thing by the impulse is slightly different. We could pass in different overrides if we wanted. But I think in this case, these two are kind of unique enough, not one dropping this into a function. And I think that would be a little bit more of a hindrance to our code progress, then it would help us. But in this case we can take the council Movement one more time, go into play iodide, pull from here, find that the council movement function and hook these up between the two execution pins. And this just means now if we try this again, what we should have is that movement cancelled out. We can say it's not the case. So this isn't Up philosophy. I think the problem being is that we're not getting velocity from the character movement. Think instead we're getting velocity from the capsule component. So we can either replace or just to kind of fail-safe and 0 bugs, which is the option I'm going to go for. And what we want is on the capture component is a slightly different name. It's the linear velocity. It's the old physics linear velocity that we're looking for. So the easiest way is just to type linear, slightly long-winded. But we want to set all physics linear velocity to 0. And then we can try this again. And I think that should solve everything nice. So if we go and find the bat, yeah, there you go. So we're getting rid of all of the movement. The velocity was actually being calculated on the capture component, not the character movement. But again, there might be cases where there's changes suggesting case I'm going to leave this in. But we can see that my regardless of how we're moving, when it comes to that, I am going to apply that force just the fullest that we wanted to do, which is that a vertical velocity to replicate that old school dying automation. So that's pretty much everything you can, like I've mentioned a few times now you can come in. I'm already kind of stopped publishing this up. Another thing you might have noticed is that when we die, we're just entering the jumping and falling animations because that's what's being tracked. We don't really have anything as a death animation. So if you wanted to import one, you could bring that in. And like I've mentioned, adding new animation states should be as simple as adding a new movement States, which is our enums that we've exposed here, could add after the jump, before you can have a death animation and then adding this to be tracked. So again, the simple as in the player update flip book functionality, check here and you can even do another branch entirely. So rather than adding things to this stream of logic, it could be as simple as if is dead, then play the death animation or stop all animation. If it's not dead, then continue to check which movement-based animation we should be assessing. And then just adding that extra pin in here for the death animation. So again, just to recap why we've gone with this kind of automated approach, not fully automated, but you can see how much easier is to plug in just one new movement state. And it would have been to have an extra set of branching logic to the side. So between the topics again, if you wanted to pause and do that type of thing just for that kind of refined polish, then do feel free. It's not something that we'll be adding in, in the topics. But that does mean at this stage when I'm done with the enemies and the player, they're really interacting pretty much as expected. And as we wanted them to, we can now move on to the final topic, which is going to be the interactive classes, the pickups to replenish health, and that spring items to act as a kind of jump pad and provide a slightly more interesting level to maneuver around. 18. 18 - Interactive Base: To move them to the interactive classes will be looking at this in a very similar way to our enemy classes. So we're going to have a few different types of interactive classes in the project. Therefore, we can derive a lot of the general logic from a base class that says we're going to have multiple interactive classes where we only have the one enemy. We have the flip book ready for our hot and springs that whenever we have two classes available, and of course you can expand this out to get started. We will just make sure that we keep the project hierarchy, it nice and tidy. So we're going to create a new folder named interactives. Inside of this, we'll be creating our main classes. So the first one is going to be our interactive base class. And of course, what we really need this to do is exist in the world with the potential to interact with the player. So for anyone familiar with Unreal, you're probably already aware that as far as the class hierarchy guys or the class structure inside of Unreal, the most basic type of glass that can exist in the world with a transform and that kind of physical entity is an actor class. So we're just gonna come down and create a new blueprint class of type Actor. And I'll name this one that BP underscore interactive base. Like I've said inside of this class, this is where we want to take those considerations. So the things which will be generic between the different potential interactive classes for this project, I can only see two different variations that we'll be having. And between those, There's only two things I can see them needing to do. One is going to be more of an issue with the way that the flip books are set up. So it kind of work around to that. And the second is the actual interaction that we're going to need some type of collision or the player to cause that interaction to be fired off. And the issue comes from the fact that flip books are automatically set to play and that loop. So we're going to need to account for that because the heart is going to look pretty good looping. But I think the spring, of course, we don't want that playing constantly. First of all, if we said are the components that we'll need for this, all we really need is the visual representation for the animation and the colliding Act. And I'm going to separate these two Act or the colliding component. And I'll separate both of these so that we don't need to worry about providing a sprite animation on the animated flip book. And that would be some potentially extra performance cores that we don't need. What we'll do is we're going to encapsulate the entire flip book inside of a cube glider. So for the components to begin, I'm going to add a new scene component, just going to drag and drop it on top of the default component or the default seem component. This is purely so that we have like an anchor point and a transform for the other components to sit on. But we don't need that spherical billboard representations, so we're gonna get rid of that with a scene component. Then on top of the sin component will place our paper flip book. So this will be the animation for the different sprites. And then making sure that we have the paper flip book selected. We can use the drop down again and find a box collider. So this will be the thing that the player will potentially interact with. And I'll just give this one the name of interactive collider. This will just make it a lot more kind of easy to update again, come back is going to be very clear why we have a paper flip book is a 2D game. We need that visual representation. It might not be so clear what the collider is doing. So if we name this accurately now it will make things a little bit easier when we come back to the project. So the first thing to account for will be this collision setup. Looking at the paper flip book to begin with, we can see that the collision that channel is set to block all. So if we were to add a flip book and it did have some collision information, then this could potentially, again, taking into account things like the spring component when we had the US in, that would potentially block the character for moving rather than adding that impose it match you, stop you from moving around the level. What we'll do instead is we'll drop that Collision Presets option box down and we'll change this to no collision. So this will not collide a tool that wouldn't provide any collision costs. I'm also make sure that we untick overlap events just in case anything changes. So one of the collision is going to be done that from our interactive glider. If we look over here, we can see that this is set to overlap all dynamic. And we can make this a little bit cheaper if we just consider how we'll be using this. So at the moment we can see the object type is a world dynamic type itself. So this would mean at the moment the other interactive classes could potentially overlap with each other as they would with vehicles, anything destructive. It could be things like, I think the enemy class is a probably well dynamic as well. So this could be triggered by an enemy. So what we want to do is we're going to change this to custom from the drop-down here. I'm going to take this button here, the ignore the top one. If you take the top row, it will change all of the options underneath. So I'm going to make this ignore everything except the pool. So the thing that the player is controlling is the only thing we want this to interact with. So this means neither anything else in the world won't trigger this functionality will make this a little bit cheaper to run. And it also means that we don't need to consider so many different eventualities with the collisions. Okay, so that is our components setup. We can now move over to the Event Graph as we've done in the past. A few things that we can do here, we can get rid of the functions that we know we won't be using, which will be these two. And we only really have those two considerations that I've mentioned that we wanted to do, or a floor as a generic functionality for all of the potential interactive class. So the first one I think will address is that fix. So the way that this works, we'll just hop back into the viewport quickly. If you're not familiar with this, if we select a sprites for our flip, we've got the hots and we have the spring. So when we place this in the world, this will do exactly what we have here. This will kind of post and pump with the hunt, which I think looks pretty cool in the context of kind of fleshing out your world. It's quite nice to have these animated flip books and sprites, having things like foliage moving around, the enemies, pacing back and forwards the pickups kind of animating in this kind of posting way here brings your level and makes the lab already fell lively and brings it to life. So this isn't something I wanted to come together. However, if we then consider the FB spring, of course, we don't want this constantly springing nothing as we just walking by it. We want this to only react. So this is going to be very reactive, which is why we've removed the event tick. And we want this one to only react in play this animation once when it's actually adding impulse to the player. So this will be the first thing we fix. And I'm just going to undo this like with the enemies. I want to make sure that if we have a forget to change this in the derived classes, it's very clear that we haven't given this a flip book because there'll be, well, they went be showing anything. So what we're going to do is we're going to pull the paper flip book will control, drag this in. We're going to pull from here. I'm going to search for it looping. So we can do fine two things have, we could have just searched, set looping, or we can check if it's looping. All we're going to do is immediately on Begin Play Set whether or not we want this to loop. Hook this up to the execution pen from the beginning play, then the new looping, I'm going to select this and we'll promote this to a variable. And I'll just name this one be autoplay. I'll make this public as well and compile this and just make sure that by default, let's assume that we want everything to auto play and then we'll come in and we'll change this floor, the spring class. So what this will do is this will come in and it should check if it should carry on looping indefinitely or whether it should be a kind of play it once type of Sprite. We've made this public so that if we ever wanted to override something for any reason, maybe we wanted a very special type of hot to pick up. If it doesn't animate for some reason, then we could easily change that from the World Outliner. Just have when we've dropped it into our world, we could select overhead you've seen, but on other public properties. So that's the first part of the generic logic I think we need to be doing. The next thing is we're going to need this new function, which will be thing that happens when we interact with the player. I'm gonna create a new function like we did with the enemy Banks. I'll name this one interact. And very similar to the enemy base class. We're not actually going to do anything in here. Instead, I'll just set myself a reminder with a simple comment saying that the functionality is intended to be overridden in the child classes with their own kind of unique functionality. But one thing that, because this is going to be very simple, you could extend this if you wanted. Changing the interactive collider sets up, you could have this interactive things like enemies. So if you wanted to implement systems where enemies could use the springs or they could potentially pick up health and share that kind of health pool of items with the playoffs. I would give the player some extra kind of challenge to make sure that whilst damaging the enemies, they're also not recollecting Health somewhere else. You can easily change this to be accounted for in this project, what I'm going to do is I'm going to assume that we're only going to be interacting with the player. So for the input, so that we have access to all of the health information and things like that. I'm going to create a new input, have a change. The variable type had to be the BP undisclosed player base object. So we are going for this object reference. And I'll name this one that the player rough. And we're going to use this in just a moment. So we'll make sure that we compile this and save. And that's pretty much everything we need to do for our Interact function back in the event graph, we're going to get the interactive collider. And we wanted to go down here. Remember we're doing the overlap events. So the overlaps and not the hits. The hit is what we're using in the enemy classes. The main difference being is that HIS events acts like a kind of a blocker. So if you remember that the collision needed to be resolved to the stage where the player was pushed out of its line in the y-axis and it was pushed to the background. In comparison, when you're doing overlaps, you can have two things pass each other. They're not going to physically stop each other. But we can have an event fired when an overlap is triggered or noticed and that's using the online component to begin overlap. Now we're not going to need all of the information like we have in the past. But what I will do is because we want to cool our Interact function and we want our player reference, even though we know that the only thing that we should be colliding against is the player class. I'm gonna do one extra check here. So we're going to cast this to the type of BP undisclosed player. See we've got the BP underscore player base and that way the Interact function when I've only ever be cooled. If this is a successful cas stuff, the thing we hit is definitely the plan. And not only that, but we can then pass in the reference to the player base. Which means again that when it comes to adding Health, adding impulse, we have some information that we can use about the player. And that's really it. So this is the base class done. This is the generic functionality that the child classes we're about to create can all inherit and reuse very simply. 19. 19 - Interactive Health: The first class we'll get started with, we can leave the Interact base class if you still have. What we can do now is using this, we can arrive at another class from this as you've seen with the enemies. So we're going to right-click on the interactive base, select, Create a Child Blueprint class from this. And I'll name this one BP underscore interactive health. Few things I've see we're going to need to do festival is make sure that the components are setup as we need them to be inside of the child class. And all we really need to do is we can select the paper flip book and set this to be the health that book that we have already. And then we need to make sure that the interactive collide a fits pretty snugly around the image. Think of Box Extent of 25, one and 25. It should work pretty well on that. So we don't need anything in the y to be via deep. And it's pretty much a square image. So at 25, 25 radius seems to fit it pretty well. Next, we don't really need to do anything. Remember, we can set this if we wanted it to not play, we can set the autoplay to false. This will take effect in the event begin play. If you wanted that to happen sooner in the parent class, you can always put that on the construction script, but I think the Event Begin Play, it should be perfectly fine for now. The only thing that we've really left that we need to do is add functionality to the player. And that's going to be done through our override function that we drop this down and we can find the Interact function here. Well, we wanted to do is work out a few things happen on the Interact event. So this is going to be fired as soon as the parent class function of the overlap is triggered if we hit the player. So we have the player information here that we're going to need. And there's a couple of things to consider, so you can probably see how this is going to go. We want to add health to the player, and then we want to destroy the interactive health pickup so that it doesn't exist in the world any longer. And just take a moment before we go through this together and consider which order of cool you might want to do this. So we're going to add the destroy here. Yeah, um, where are we going to call this health functionality update? Okay, so of course we know that the first thing that's going to happen is we can account for anything happening on the parent cool if we wanted. So if we added the destroy cool here, of course that's going to happen before we can even call the parent functionality. Now in this case, nothing is really happening on the functionality. So we can either remove this altogether or just plug this in and do everything after this. It really doesn't matter in this case because I know that we're not going to be going back to the parent class and adding any base functionality. So in this case, I think what we can do is we'll just show how we can go through this process without even making a call to the parent class if we don't want to. Next, we have the player reference. And a handy little tip here. If you haven't seen this before, because this is now a local variable for as long as we're inside of this function, we can search for the variable by the same name. And rather than pulling this from everywhere like we've seen in the past, we wanted to really avoid having y's going everywhere. We can just use the Get play or rref, note, just hit. That's exactly the same thing. That this means that regardless of how many times a, where we need to cool this, we can reuse this variable very, very easily. And what we want to do is see if we have the health functionality setup. So we know that this is the BP underscore player base. We search for health. We can see that we have the update function and we can set the health variables manually. Now we never really want to. The variables from one class in another. This can make it very hard to track where variables being set and updated, especially if they stopped being done outside of the player class as an example. So what we really want to do, ideally, we'd make these private so we couldn't even see them from another class. But ideally without that, that being taken, we want to create another function in the player class similar to update health. But we're going to call this one AddHealth. Let's go over to the player class. Remember that the update health is quite simply just finding what the current health is and updating that to the widget. So we could probably rename this to be a little bit clearer actually. So we'll make this update health widget because that's really all it's doing. What we want to do is provide a function that we're going to create a new function. We'll name this one AddHealth. And in here we just want to provide one input, which is the minds of health, which is going to be held by our pickup. So we're going to add a new variable. Yeah, we'll make this a float and we'll change the name of this to heal it might. So they might never going to be held. And very similar to what we're doing on the damage events. If we can find that here On the only damage, we're going to want to set our health rather than being a minus here though, we're going to set this to be a positive so we can copy a lot of this. I'm just going to copy and we'll paste this into the AddHealth function that we're going to set our health to be current health. And then rather than using a minus will say plus another variable or another flight, the plug that into the value, and that will be here. So whatever the health currently is, plus our helium ion will be our new health. And again, we'll making sure to clump this so we don't do anything silly by extending, making it lower than 0. And we went make it any higher than the default health. So it nice and simple. Copy and pasting was perfectly fine. We've already kind of seen this logic, so we didn't really need to retrace this too much. Now the final thing is we can call our update health widgets. And if we do this here, this is going to take in those variables that we've just changed. And this will show on screen the new health might be shopping there, nice and simple, that didn't take very long a tool. And that is all of the health system now implemented in the plaque class. And a few things I've noticed with cleanliness though, is we have several variables at the same time, kinda separated and taking up a lot more space and they need to over here. So this can happen in some big classes. What we can do to get around this is we can actually put these in different categories. Those an example, I'll select the first flip book type, and I'll put this in a category named FB. So we can show it and this. And then we can either drag the other flip books into this. Well, we can now use the drop-down option and change the different category that we've just created. We can then drop this diamond so we can see we've saved a little bit of space on the multiple variable types there. And likewise, I'll do the same for the flights. So this is just a case of creating new category name deflects, dragging them in, and then we can collapse those one. But done. Now we've still got a few left over, but I think this will make things much easier to find an I and then those unique types and not taking up too much space. Before we head back over to the health class, just make sure that you compile and save this to make sure that this new function will be able to be located in the other class. So we're gonna go to the interactive health class. And then from here, we've now got our reference. We're ready using, we can pull from this and we can now find that that new Add Health function. So hopefully you can see why this is going to be a little bit safer, but now not setting the health value outside of the class where it's being used. Which means inside of the player class, just as a recap, we now know that this health function or this variable is only being updated either in the AddHealth function or the damage is connection of the event graph here, it means that if we have a kind of debugging through this, we know where to look if something strange is happening with the health. Whereas if you start adding these calls to set variables from other classes, it starts becoming a little bit harder to track down where multiples of house might be getting changed, something at some point in your project. The final thing is we can set this to something like ten for the helium white. And I'm going to promote this to a variable. I'll name this one health value and just drop this down and tidy the Unites up a little bit here. We can also make this public hit Compile. And the reason that we've made this public is an eye when we drag this into the wild. So I will come back a little bit. We'll find our interactive health. Drag this in, make sure that this is on the 0 axis and the y value on the y-axis. And if we drag this and add a few different health components, Law, Health pickup, sorry, we can change the value in the edit to have by making this public. So again, we can add some variety to these. So this one can be worth 50. This one can be with and we'll leave the first one at 10. We can I come in and test this? So I'm going to want to find an enemy to deal with some damage. We've set the enemy to complete the killer snow test. So make sure that we go back into the player class. If you forgot to change this back down to something a little bit more manageable. So the player damage was set to a 100. We're going to want to set this down to something like 20. Again, empower that so that we don't die immediately. And this gives us some time to test the house value. Okay? So we can see this is being picked up. We can also see the one thing we forgot to do that in the interactive class. We haven't fully finished. We can check the different values were working. That all seems pretty good for that. The final thing, of course, is once we've interacted, once we've added how, like I've said, we just want to destroy the act of being interacted with are actually no, that was wrong. Don't destroy the ice being interacted with because the one we're interacting with would be the player. Obviously, we don't want to destroy the playa. We're going to destroy ourselves so that when we come in, we can now add some house and we can see as being picked up, take a bit of damage. And then we can come over and collect our health pickups. We're getting held that being destroyed. So we have a fairly standard health pick up implemented. 20. 20 - Interactive Spring: The final interactive class and the funnel class we'll be making in this selection of videos is going to be our interactive spring. We already actually have a lot of what we need to go in here. And in fact, we have everything we need coping. So what I'm going to do rather than creating a brand new class, remember that this one, our health class here, is already inheriting it from the interactive base, which is exactly what we need. So what I'm gonna do instead, rather than completely recreating the wheel, I'm going to Control W, our interactive health. Name, this one interactive spring. Inside of, hey, again, we can see that this will take the same default values as the health side we're deriving from the parent class of the interactive base, which is the main thing here we have a variable. So this flight variable is going to be very useful in a moment. I could already kind of envision what we're going to be using. And we have our indirect function also being caught. So the main things that we're going to need adjust half, we can rework this a little bit. We don't want to destroy the spring whenever it's used. We weren't want AddHealth, but we will need two variables which are going to be the player reference. We want to do something to that and this health value, we're just going to need to change the name, but we already have it available. We really wanted to do when the spring is touched. We're going to come in here and we're going to call the launch character function. So again, this is why it's useful to know that we're interacting directly with the BPM School of plant-based because we know it's a type of character that was a let us know we can use this default built-in functionality in the character class to launch. And essentially just adding velocity to our character class is kind of like a jump, but with some different overwrites. The reason that we want our flight value, we just moved this time. We don't want to take in any x or y velocity. So we'll split the structure pin here. And we basically, we can plug this into the zed as the launch, the character. On the z-axis. We want to override these, add override. So we'll take this to be true and we can rename this to our launch flux. Um, like we've seen in the past, we can leave this public. So again, on any of the different springs that we have around the level, we can very easily update and override how much force is going to be applied. I think by default, 20 or 10, even, even dilemma is going to be quite low. So we can start with something around about 500 and have a good feeling for an impulse of 500 and it might be too low. We can update that in a level when testing. Now the next thing is to remember the way that the visuals are going to work. So the visuals festival, we want to change the paper flip book. We're going to change this from the hot to be our spring. And if we just hop over to the viewport, we can also see that I would collide is going to be a little bit small. I think really all I wanted to change is the width of this stuff. So I'm gonna go to the interactive collider, change the width, which is going to be our x to justify fit this. And then remember that we have a C9 co-host. So that allows us the freedom and flexibility to change the position of the flip book, or in this case, the interactive collider, because the interactive collider is a child of the flip book. Of course, if we move that, the collider will move with it. So what we want to do is take this collider and just move this time roughly to the bottom of the spring. But the idea is if this wasn't playing, it will be sought. Just above the top of the spring so that it will look like as soon as we hit the top of that spring, we're going to play this animation. So that's the visual side done there and updated. The final thing is back in the Interact function. Remember that we're going to set this to multiply to be false. So we're not going to be playing constantly in the level. What we will want to do is as soon as we've interacted with this, we're going to set this to play it from the stock. We do that by getting our paper flip book. So control dragging in the paper flip book and I'm finding the play from stopped function. We just took that back up and tidy the function a little bit. I'm not as pretty much all the interactive spring really needs to do. If we come back into the level, we probably have too many springs. So I'm going to grab one of these with the interactive spring selected. We can right-click on the heart. And we can choose the Replace Selected actor with. And one of the app's going to be the interactive spring because we have it selected here. So we'll replace it with that. We can see there's little dramatically change and we can come in here and move this around. Now in the editor looking at it, maybe this will be a little bit annoying that we have these automating constantly. So back in the interactive base, what I'm gonna do is grab this and just pop this into the construction script. So this should hopefully stop any looping animation. And now we go, we can see that the spring is immediately stopped animating. That lets us know that this is working is only going to change if we move that location. But that's better than having it springing constantly. And let's add a couple of these in as well so we can use one over here. When we get past this section, we can glide the planets easily, jump up and reach this section. These are also going to work as good ways to kind of test different velocities and the impasto going to be adding. So perfect, we can see that I didn't animates before we started playing. Jump on. This is going to animate once, not gonna go back to looping, we need to kill the bat. And we can jump on this again. I think the impulse is maybe a little bit too low. So it doesn't look as though we're being pushed up quite as high as we need that we can come in and we can change this to maybe 800. And then hopefully yeah. So it looks as I was actually going up with the spring rather than through it. And that's pushing us up unless distance. So we can go and play with different values. On the other ones that we could test, maybe what this would feel like with an impulse of the thighs and otherwise pretty good. But the main thing that you can see is that these are reassessing that the animation playing constantly and everything is pretty much responding as we would hope, unexpected. Hopefully, you've seen the, the kind of values of adding these public properties as well. So we can easily come in and change the house values now, the spring values so we can add some extra launch floss. And like I've said, if we really wanted, we could set one of the springs for whatever reason to automatically play, one of the hot to not play. So when we come in and play NIH, this one's gonna keep posting from no real good reason. And the hot is going to be frozen in place. So we have a little bit of flexibility with how our class is a working or derived from the same kind of base class, meaning that we needed to program. I love this only once and we can reuse it between different inherited child classes. Now the only other thing that I haven't really touched on is that we're getting a lot of different items coming in here. So you may want to start renaming some of these, especially consider the way that we changed one of the huts to be a spring component or a spring actor. It's still named the default name. So we can say it is a spring act to hear, but it's still cool. Bp underscore interactive health. So anything can be redacting. We can change this to spring and that will kind of update correctly. And we've got the same thing for this one because that was just a copy of the original one, which was really cool to health. And another thing you might want to start doing is you can create different groups. So you can have sub folders here. So we'll name one enemies, and we'll create another one, and we'll name this one interactives. Main reason being is that we can then easily drop enemies and enemies in directives. Directives, and if we have a one, clear things up and just look at the level, do a little bit more level design. We can hide certain things. Of course, when you press play, all of these are going to come back. This is only edits are related. And of course it just means as well, you're not going to have this huge hundreds and hundreds of items dropped down at all times, especially if you just wanted to find something like the light source, move something around, then it's going to make things a little bit easier to navigate through and we can drop these diamond. I'm worked with them whenever needed. With all of that done, we now have the basics of a 2D platformer set up and working inside of the Unreal Engine. Hopefully throughout the series of videos, you've come to appreciate some of the power that can be leveraged from unreal. And although there are some slight hindrances with the flip book system, the way that we can automate some of the processes of working with those really isn't that bad. We've still got this really, really useful pile editing tool really compatible with collisions and things that I've not even dived into. Like we could set up materials using the default on momentarily editor to take into things like normal so we can add lighting and essentially replicating 3D lighting techniques on these 2D sprites. If we have that information available, there's much, much more that you could do with this. But again, this is really just to bring to light a little bit more than that. This is definitely more than a suitable 2D engine as well as 3D. What we're already doing at the end of the day is taken away and access to two, again, unreal has all of these things where we can constrain different things to different axes to allow us to really easily work in a 2D world. So if you've enjoyed this content, do be sure to follow me for more content like this, we'll be looking at making bigger, more in-depth updates to similar content in the future. So do be sure to follow me on here for content like that. If this was something you find useful, I wanted to see more. So I hope you've enjoyed this series of videos. If you've gotten this far, then thank you for following along with everything and going through the entire process with me. So thank you for your time and patience and I look forward to seeing you in the future.