C# Godot 2D Platformer | Magic System Pt 2 : Potions and Magic Bars Oh Boy!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys this is mitch with fine point cgi and today we're going to talk about how to create a pickupable object inside of godot so what we're going to do is much like we did in our last video on this little series is we basically created a mana system that allowed us to dash and it would reduce our mana and it kind of regenerates slowly but it would be good to have a pickupable object to increase our mana all at once right so in this video we're going to go through the process of creating that so we're going to create our little potion object we're going to code our potion object and make it kind of extendable and then we are going to go ahead and set up our scene so that way we can have little little bars on our screen to show our stamina going down or going up so that's what i have to start for you guys today so let's go ahead and get started okay so the next major thing we need to do is we need to create a potion to restore the magic really quickly so right now we don't have an inventory or anything like that so we're not going to actually be able to build a full inventory system but what we can do is we can at least make an object that's pickupable and that's what we're going to achieve right now so what we're going to do is we're going to right click on our game manager we'll add in a child node we're going to make a node 2d object we're going to call this magic potion all right now we're going to right click this we're going to add in a child 2d we are going to add in a area 2d and we're going to right click as well add in another child node and add in a a collision shape 2d right here and we're going to go ahead and add that in and we're going to make that shape a circle shape so if we focus in on it you can see here's our little shape now we're going to right click on our magic potion we're going to add in a child node we're going to add a sprite and i don't need it to animate through the animated sprite node i'm going to animate it through the animation editor or through like an animation player so we can just go ahead and go through it that way now for the sprite i actually have a sprite with that metroidvania platformer if you actually go in there you go into your miscellaneous sprites you can see they have an antidote potion i'm going to use that as my sprite considering i don't actually maybe this fancy orb would do this looks nice let's go with the fancy orb actually i mean i don't know if it's not really a potion but it'll work so we'll go ahead and drag that fancy orbin ah no i'll go with the antidote so i'll go ahead and drag in the antidote there we go nice and fancy so if we click on that and we go to our import settings let's change that to a 2d pixel get rid of that nasty aliasing thing it's doing and then what we're going to do is we're going to add in an animation layer here and we are going to first animate this so that it can move so what we'll do is we're going to right click add in a child note and we're going to say node to d we'll take both these two and put them underneath here so that way when this moves it moves all of it including my collision and we're going to grab our animation player and we're going to add in a new animation and we're going to call it bounce and then what we're going to do is we are going to grab our node 2d and we are going to go ahead and add in a keyframe here and we will use bezier curves so i know i'm running pretty quick through these but basically what we did was we threw an animation player we threw it all under a no 2d that way we could um properly animate it moving up and down while so it can take all of the objects so if i move this you'll see it takes the whole thing instead of doing it via like the area 2d which would just move the area 2d or the sprite which would just move the sprite it's going to move all of it together and then i went over here and i clicked on this little button here and that basically throws in a keyframe so that i can start my animation so we're going to set this to i don't know a three second animation let's say we're going to drag this to about halfway through and we're gonna go up whoops i said up we're gonna go up i don't know about three we'll say so minus three it looks like and then we'll kick in a keyframe and we'll come back here set this back to zero and kick in another keyframe so now if we run this you'll see it's moving really slowly i actually think maybe we should go down to a two second animation instead so let's drag this back same thing with this one drag this to one drag this to one and it's still not quick enough for me so let's cut it down by another second or so or by i guess a little bit more let's see if that feels better that's too quick so we'll go with 1.5 i think 1.5 will be a good middle ground for them all so we'll just drag that in there there we go there we go and we're going to go ahead and click on this little button right here which will loop our animation so now if we hit play awesome simple enough right what i'm going to do is i'm also going to open up my bezier curves here i'm going to zoom in on them real quick let me see actually i think you know what i think they're probably okay if you use the middle mouse button you can pan like this so you can actually pan around and what i was thinking of doing was us thinking of messing with position y and maybe just kind of stacking it down like this to make it more linear and then having it kind of smoothly transition down i'm curious if that's gonna make it feel better yeah now it feels more like it's bouncing whereas before see how it's a smooth gradient versus a bouncing gradient i think i prefer the bouncing gradient over the two so we'll go with that so if i drag this back to something like this to this it gives a little bit more angular velocity a little bit more bounciness to it so i'll stick with that and if you like the other way go ahead and do it that way but i thought it'd be cool to show you guys kind of how this graph editor works so we'll go ahead and close that and then what we're going to do is we need to go ahead and code all of this so we're going to right click on here attach a script and what we're going to need to do is we're going to do a little bit of object inheritance here so there's going to be some fanciness that we're going to be doing so i'm actually going to right click over here or not right click i'm going to go ahead and add in a new file and i'm just going to cause potion or we'll call it pickupable i guess and i'm doing this whoops i need to make that a cs file dot cs and i'm going to grab my magic potion i'm going to control a control c i'm going to go ahead and paste that in here and i'm going to say pickupable i don't need a ready node i'm good i'm just gonna have this as a thing that exists and the reason why is because if you use class inheritance you can do a lot of really fancy tricks that allows you to inherit from this class and then you can use things in a generic way and i know that that's kind of difficult to understand but think of it kind of like if i'm looking at an object i can say is this object a pickupable it could be a potion it could be a weapon it could be anything but as long as it inherits from pickupable i can generically say this is a pickupable object and that will give you a lot of flexibility so if we go to magic potion instead of node 2d we say pick up opal that will allow us to have that little bit of flexibility that i was talking to you guys about a little bit ago so from here let's go ahead and add in a public float and we'll say magic gain amount is equal to and we'll say 20. i think 20 is a good number it's a lot but it's it's a good number we'll we'll cast that as a float to make sure it's a float and what we're going to do is first we need to animate our object so let's get that going so we'll say get node animation player and we're going to say quote and let's look at our project structure here and it looks like our animation player is right here so it's perfect that's exactly where we need it to be so we'll say animation player and then what we need to all what we need to do is we need to hook up some signals here and what i'm going to do is i'm going to go ahead and do some linking in here so we'll come over here we need to make this its own scene because if not then all this will be for naught when we switch it over to its own scene so let's go ahead and right click this save our branch as a scene and say magicpotion.tscn let's go inside of there and now make our links it's going to make things easier in the future so if we go to node and we'll go to body entered we'll right click that connect and connect it to my magic potion make sure that you copy this receiver method so that way we can make it hit connect and then let's say public void on body enter we'll say object body we'll go ahead and pass that in here and then we need to go ahead and also do the same thing on area 2d body exit so we'll click on area 2d body exit connect and then we'll go ahead and copy this connect it it'll open up visual studio code we'll say public void on 2d body exit object body and then we're going to be perfect right this works great so now from here we need to show and hide our text element now we don't actually have a text element here so let's go ahead and add one so we're going to right click add a child node rich text label and let's go ahead and set it as x seems like we're going for like a lower keyboard binding thing here so this works perfectly for us so from here now that we have this let's go back to visual studio code and then let's go ahead and say get node rich text label quote node 2d slash rich text label and it will say dot show because we want to show it when people enter it and then we also want to do the same thing here so just go ahead and control c control v dot hide awesome so that'll show and hide our rich text label so now that we've done all of that let's check our work let's see if it actually works so we'll go to player testing we'll zoom out and we will go ahead and grab our magic potion and drag it over here and also we don't really want um that x to be there at all times so let's go ahead and hide that there we go so now it's gone and now that it exists let's go ahead and hit play and let's see if it even builds it might not to be honest with you great so now if we run over to it you'll see it has x we leave it goes away perfect now you'll notice that our little animation doesn't seem to be running so let's see what we did wrong here get because i didn't tell it to play dot play and then we want to play our little bounce animation i believe we called it bounce so we'll say bounce perfect so that's how we get this to work right but we do have a bug here right if i bring this little magic potion down to this guy and i hit play oh it didn't work there we go so you see when the uh the platform passed through it you'll see that that x showed up and that's a bug right we don't want it to uh show up if the player is not over it so we need to detect if it's the player before we show the x so let's come over here and say hey if body is player controller then go ahead and do this little bit of code here and do the same thing over here there we are and if we go ahead and play it now when that platform runs through it it's not going to actually affect the potion you'll see it didn't affect it but if i jump in there it's there oh i'm bad at my own game oh no there we go so you can see that if i jump into it it works sweet that's awesome so let's drag this magic potion over here so now it's back to where we were and we should be good to go now you'll see that it's still not playing its animation so we do have a error here player animation f not found bounce i did not spell bounce correctly so let's fix that b o u n c e not b o u c there we go perfect that looks good all right so now that we have that working we need to allow the character to pick it up so here's where that generic coding stuff i threw in at the beginning of this was what we need to do is we need to go ahead and tell our magic potion to be pickupable right and it already is right it already is a pickupable object because we inherited it from pickupable but we don't have the code here for playercontroller to handle that just yet so let's go ahead and add that in now the first thing we need to do is we need to determine if the player can pick up an object and i'm going to use actually i know we said x was the button that's going to be pressed but um we already have some code to interact with the npc and i think that if we're going to do pickups and stuff like that we should probably make it all the same right so if we go back to our reference here we actually have a section here that allows you to interact with the player or with the npcs so we should probably use that little bit of code so let's go use that little bit of code so if we come up here it says hey if raycast write is colliding then show npc dialog right what we can do is we can actually kind of hijack this little bit of code and use our own little bit of uh magic to make it work so what i'm going to do is i'm going to come down to i'm actually going to come down to my show npc dialog and i think i'm going to change this to interact with item we'll go ahead and rename that so we're going to say if obj is pickupable then i want to go ahead and do my item interaction so what we'll say is if item is pickupable else if is it an npc whoops i got rid of my code there we are else if is it an npc right what we can say now is if obj is magic potion then magic potion is equal to obj as magic potion and then now from here we can go ahead and call some magic potion code right so i'm going to go ahead and go over to my magic potion and i'm going to add in a little bit of code to make our little magic potion work so we'll say public void use potion and we are going to go ahead and say game manager dot player dot all right i don't think our game manager actually has a global reference to players let's go check that out i thought it did but i don't remember it's been a minute it does not so what i'm going to say is public static player controller player and i'm going to capital p because it is a static now some people do if it's a if it's a global variable they do like player i'm going to stick with lowercase or capital p i just prefer it that way and we will go to our player controller and we will say gamemanager.player is equal to this and now we'll just go ahead and assign this to the game manager so that way we have you know our stuff is all of our ducks are in a row right so we can now use our player anywhere in the code so we're going to say gamemanager.player dot update mana and then we're going to go ahead and give it the magic gain amount and then we need to go ahead and delete ourselves so you free awesome so now if we come over here and we hit play and in our case we're gonna have to hit enter so we just run up to it hit enter and you'll notice that well nothing seems to happen right that's because our character is ray casting out but it's not able to hit an area 2d so we need to go into our player and allow it to hit area 2ds so if we come into our player we go ahead and go into our player scene we grab our two raycasts left and right we can actually tell it to collide with areas as well so now we can actually collide with areas so if we run over there now and we hit enter you'll notice that again it seems like it's doing nothing why is that well let's take a look and see why it's doing that so if we go into our player controller we scroll down to wherever we're doing our stuff here let's put a break point here and here and let's see if it's doing anything if it's actually connecting with these objects so let's go ahead and hit this hit play in editor and let's check what our breakpoints are doing hopefully we don't have any weird breakpoints sitting out there we probably do i think this one yeah it's going to say we probably have a few of them sitting out there so let's do that any other ones awesome open up our project we'll run over we'll hit enter and let's see if it hits anything yep so it's hit something it collided get collider interact with item that's good oh i think it just lost connection to the server so let's stop this and let's put a break point here let's come up here kill our two breakpoints play an editor let's see if i run up here and i hit enter if object is pickupable okay so it's not a pickupable object interesting let me see oh because we're pulling the area 2d that would make sense because it's grabbing the area 2d so what we're going to do to solve this is we're going to call for the owner of that object and it's one of my favorite things and i really should use it more often but basically what you can do is you can call your object.owner and that is your root of the scene of that object so what we're going to do is we are going to call for the scenes owner and what that means is we're literally going to call whatever object that owns this object we're going to call that object and it's a little easier if i show you so let me come over here and i can show you so our problem is that if we collide with this it says area2d right but we don't want that and we can't just say parent because that's this we can't just say parent parent because while that'll work here it might not work in other projects right so what we can do instead is we can do what's called owner an owner will fetch this node whatever is your base node of that object it will fetch that node and it's in my opinion one of the best ways of doing this so what we'll do is we'll say obj.owner is pickupable and we will say obj.owner is a magic potion and obj.owner as a magic potion and that should solve our little problem that we're running into so now let's go back here and let's actually we can just do it here play an editor let's walk through this real quick and see if it works so we'll come over here we'll hit x or i'm sorry enter i keep forgetting because i have the x prompt here but we'll hit enter we'll come over here and you'll see that we can flow right through it we can go into our magic potion and it's not happy with us because of course it's not why would it be sometimes walking through code and c-sharp is funky so we'll just go ahead and throw a break point here and we'll crash out our godot engine there we go or at least arkadel project here then we'll go ahead and hit play again it'll relaunch it so that's good so we'll come up here hit enter there we go and we're going to go ahead and step over step over hit play and it didn't seem to call oh that's because i didn't call it goodness potion dot there we are goodness just full of mistakes today all right so let's go ahead and play that i run up to it i hit x or enter it'll say use potion it updates my mana and then it q freeze and you'll see that it's now gone perfect that's exactly what we wanted so now let's go ahead and minimize this real quick and let's use some of our magic here so watch our output over here if we dash up or dash down you'll see that we start going down if i run up here and i hit enter you'll see now i'm at 70. i was at 50 now i'm at 70. so perfect that's working that's exactly what we wanted so now we just have one small bug that we got to figure out and you'll notice if you if you mess around with it you'll notice that there's a bug here if i run just straight on top of it i hit enter it doesn't seem to work now why is that raycasts raycast from the inside of an object if that makes sense like if you're inside an object and you're raycasting out it's not going to collide properly so what you need to do is you need to pull your raycasts and pull them in a little bit so if we actually pull this in side like this and we pull our raycast right inside a bit like that there we go and then we just go ahead and extend these a little bit that should solve our problem in theory at least we'll we'll see how it goes and this one is slightly too large so let's pull you back some there we go make it so it's all in line now if we run up to it and we hit enter it goes away perfect which we that's what we wanted and if we go ahead and we run up to it and we're inside of it it allows us to pick it up perfect that's exactly what we wanted all right okay so the last thing that we're going to do and i know this tutorial has been going on forever and i'm sorry for that but the last thing that we're going to do is we are going to add in some stamina and health bars and this is kind of a long time coming so we should definitely add them in we're going to right click on our interface manager add in a child node we're going to add in a control node here and then we're going to right click on that add in a child don't add in a progress node now the reason why we're adding in a control node is because that allows us to say main interface all right so we're going to grab our main interface we're going to say layout and we are going to do full rect and that's going to make it the full size of our screen here and then we're going to go ahead and grab our progress bar we're going to go to layout and we are going to say uh top right here and we're going to resize this we'll pull this back something about i don't know about yay big give or take and then we're going to go ahead and just call this health bar and we are going to duplicate this pull it down and name it mana bar all right so now that we have that we need to go ahead and go into our interface manager if you remember way back in the day we made a interface manager so we need to open that up right here oops open up the dialog manager interface manager there we go now we need to first get our objects so we'll say public static progress bar and we will say mana bar we'll say public static progress bar health bar and then we're gonna go ahead and get those nodes so we'll say mana bar health bar and we will just say as progress bar and we're going to say get node instead of dialog manager we're going to go ahead and go out to our location so we have main interface here so we'll say main interface slash whoops not slash progress bar goodness it's um slash health bar or slash mana bar actually slash mana bar and then we'll just go ahead and copy this so i don't have to retype it and then we will say slash health bar awesome so now that we have that we need of a way for us to update our health and update our mana right so what we're going to do is we're going to add in some static functions here so we'll say public static void update health we'll pass in a let's say float and we'll say max health comma and we'll pass on another flow called health and we are going to go ahead and say health bar dot value is equal to and we're gonna do a little bit of math here okay and i know math is terrifying i hate math so we'll say health divided by max health multiplied whoops multiplied by health bar dot max value now the reason why we're doing this is because it allows us to have a very flexible health bar we could make our health bar 0 to 700 we could make our health bar zero to 200 and it wouldn't matter our entire system would just work okay and same thing with health versus max health the reason why i'm doing this is because i'm getting a percentage of what health is of the max health and then i'm multiplying it by our health bar and i'm saying hey uh create this out of a normalized value and then multiply it by my max value so that way i can guarantee that it's going to properly show up on my health bar or on my my mana bar that way if i pick up man of if i pick up like let's say a mana crystal it increases my total mana i can just i don't have to change this code it just handles it so that's the reason why i want to do it this way so now we'll say public static void update manager and we're going to go with whoops float max mana comma float max or i'm sorry float mana and i'm just bumping all the keys today goodness all right so now we'll go mana bar dot max value is equal to mana divided by max mana multiplied by mana bar dot max whoops max value and what that's going to do again is it's just going to set it up so that we can get away with just not needing to touch this ever again basically it's actually really useful so from here what we can do is we can go over to our player controller and add in that little bit of functionality so if we go up to our physics process here and i'm going to first thing i'm gonna do is i'm gonna say interface manager dot update mana and i am going to make it my max mana comma mana there we go and that's just going to update it every single physics process that mana is going to be updated it's going to say hey are we good is it good does it feel good how are we doing right and then i'm going to come up here and i'm going to say interface manager dot update health max health comma health there we go and the only other time that this would need to be updated and it's mad at me doesn't exist in current oh no it should exist in current context do i oh i don't actually have a max health so let's go ahead and do that max health is equal to three for right now we'll say and we are going to make that a capital and we're going to change this to a float i know it's going to break some of my code but i want these to be floats for future stuff if if you know something does like 0.5 points of damage or something i want to keep that in there and we'll say max health and health why there we go max health and health there we go so that'll work perfect now we need to also update it when a character gets hit so we will say take damage if player has um greater than or equal to health current health is this and we'll go ahead and update their health right there and if the player dies we want to be able to reset their health right and if i remember correctly we have a section here called respawn player so we'll go ahead and set it in there as well so now that we have it in our respawn player and in our take damage code that will allow us to update our health so now we should in theory be good i think let's go ahead and hit play let's see what happens i got a feeling that we're going to have a bug first or maybe not okay not too bad our stamina for some reason is at a hundred let's see i'm just chunking down our our stuff so you can see that it didn't update it properly so that leads me to believe that something is wrong here update mana max mana mana yup interface manager that's correct my mana is correct i know my man is correct okay so i figured out what i did wrong and i feel really dumb but the reason why this is broken is because if we go into our interface manager and we look at it we say manabar dot max value not dot value is equal to mana divided by max mana times mana bar dot max value so that's my fault so now if i come over here and i attempt to dash you'll see that our stuff seems to work so now when we start gaining our mana you'll see it's slowly starting to come back awesome that's exactly what we wanted so one of the coolest things is we could actually come in here now to kind of prove a little bit let's say this is end game he has a hundred mana his end game if we actually come in here and we come up to our max mana on our player controller if we change this max mana down to something like 10 and we change the mana to 10 okay and we come over here and we dash you'll see that it's zero but you'll see that it reflows perfectly to being exactly what we want so that's one of the coolest things about this system is that you can it's flexible right so in the future you could give him an addition you just update that value to whatever you want we don't have to worry about changing these values anymore you know we could go in here go into our player and if i were to export the value which i didn't export it but if i were to export the value i could just adjust this and it would dynamically update this value so that's one of the powers of this system so if i go in here and i change this back to a hundred and a hundred and i save it and i play and we do two dashes so dash up dash down dash up we run up here we hit enter now we're at 90. you see that how that changed which is exactly what we want so what uh what did we do see it's at 60 we run over here enter now we're at 80. so what did we do today so what we did was we added in a pickup that allows them to pick it up and heal their mana and it and the same thing goes for health potions it's actually really easy we can do that in the next video maybe um and we added in the ability to see what our health and our mana is at but that's really all i have for you guys today so hey you know if you like this video go ahead and hit that like button hey if you dislike this video go ahead and hit that dislike button because i am here to make content for you guys as always this series is a viewer suggested tutorial series everything in here is stuff that you guys have asked from me to be added to it so please if you have any questions or anything that you'd like me to cover in the future put it in the comments below and i'm more than happy to get to it and hey if you have any questions about this throw some comments down below or check out my link in the description below for my discord a lot of the guys over there are pretty cool and you know we'd love to hang out with you guys but that is all i have for you guys today so thank you so much again for watching and i will see you all next time thanks [Music] you
Info
Channel: FinePointCGI
Views: 261
Rating: undefined out of 5
Keywords: godot, godot game engine, godot engine, godot platformer, godot tutorial, godot platformer shooter, magic, godot platformer tutorial, pixel platformer godot 3.2, magical potion, magic attack ing godot, godot 3, game maker potions, shooting game platformer, potions, pixel platformer engine, platformer devlog, unity 2d platformer, tutorial godot, pixel platformer games, unity pixel platformer, indie platformer devlog, devlog potions, indie devlog potions
Id: PW4gDF736Dw
Channel Id: undefined
Length: 41min 1sec (2461 seconds)
Published: Mon Nov 01 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.